设备管理应用"界面列表中应用的激活状态是通过DevicePolicyManager的isAdminActiveAsUser()方法获取的

"设备管理应用"界面列表中应用的激活状态是通过DevicePolicyManager的isAdminActiveAsUser()方法获取的

设置中,"设备管理应用"界面应用列表数据加载逻辑如下:

> 通过DeviceAdminSettings.java的addActiveAdminsForProfile()和addDeviceAdminBroadcastReceiversForProfile()方法获取应用列表:

packages/apps/Settings/src/com/android/settings/DeviceAdminSettings.java

    private void updateAvailableAdminsForProfile(final int profileId) {
        // We are adding the union of two sets 'A' and 'B' of device admins to mAvailableAdmins.
        // Set 'A' is the set of active admins for the profile whereas set 'B' is the set of
        // listeners to DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED for the profile.

        // Add all of set 'A' to mAvailableAdmins.
        List activeAdminsListForProfile = mDPM.getActiveAdminsAsUser(profileId);
        addActiveAdminsForProfile(activeAdminsListForProfile, profileId);

        // Collect set 'B' and add B-A to mAvailableAdmins.
        addDeviceAdminBroadcastReceiversForProfile(activeAdminsListForProfile, profileId);
    }

>获取显示的应用列表.

    private void addActiveAdminsForProfile(final List activeAdmins,
            final int profileId) {
        if (activeAdmins != null) {
            final PackageManager packageManager = getActivity().getPackageManager();
            final IPackageManager iPackageManager = AppGlobals.getPackageManager();
            final int n = activeAdmins.size();
            for (int i = 0; i < n; ++i) {
                final ComponentName activeAdmin = activeAdmins.get(i);
                final ActivityInfo ai;
                try {
                    ai = iPackageManager.getReceiverInfo(activeAdmin,
                            PackageManager.GET_META_DATA |
                            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
                            PackageManager.MATCH_DIRECT_BOOT_UNAWARE |
                            PackageManager.MATCH_DIRECT_BOOT_AWARE, profileId);
                } catch (RemoteException e) {
                    Log.w(TAG, "Unable to load component: " + activeAdmin);
                    continue;
                }
                final DeviceAdminInfo deviceAdminInfo = createDeviceAdminInfo(ai);
                if (deviceAdminInfo == null) {
                    continue;
                }
                // Don't do the applicationInfo.isInternal() check here; if an active
                // admin is already on SD card, just show it.
                final DeviceAdminListItem item = new DeviceAdminListItem();
                item.info = deviceAdminInfo;
                item.name = deviceAdminInfo.loadLabel(packageManager).toString();
                item.active = true;
                mAdmins.add(item);
            }
        }
    }

    private void addDeviceAdminBroadcastReceiversForProfile(
            Collection alreadyAddedComponents, final int profileId) {
        final PackageManager pm = getActivity().getPackageManager();
        List enabledForProfile = pm.queryBroadcastReceiversAsUser(
                new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
                profileId);
        if (enabledForProfile == null) {
            enabledForProfile = Collections.emptyList();
        }
        final int n = enabledForProfile.size();
        for (int i = 0; i < n; ++i) {
            ResolveInfo resolveInfo = enabledForProfile.get(i);
            ComponentName riComponentName =
                    new ComponentName(resolveInfo.activityInfo.packageName,
                            resolveInfo.activityInfo.name);
            if (alreadyAddedComponents == null
                    || !alreadyAddedComponents.contains(riComponentName)) {
                DeviceAdminInfo deviceAdminInfo =  createDeviceAdminInfo(resolveInfo.activityInfo);
                // add only visible ones (note: active admins are added regardless of visibility)
                if (deviceAdminInfo != null && deviceAdminInfo.isVisible()) {
                    if (!deviceAdminInfo.getActivityInfo().applicationInfo.isInternal()) {
                        continue;
                    }
                    DeviceAdminListItem item = new DeviceAdminListItem();
                    item.info = deviceAdminInfo;
                    item.name = deviceAdminInfo.loadLabel(pm).toString();
                    // Active ones already added.
                    item.active = false;
                    mAdmins.add(item);
                }
            }
        }
    }

> 通过DeviceAdminSettings.java的isActiveAdmin()方法获取应用激活状态:

    private boolean isActiveAdmin(DeviceAdminInfo item) {
        return mDPM.isAdminActiveAsUser(item.getComponent(), getUserId(item));
    }

> 设置中调用mDPM.getActiveAdminsAsUser(profileId)来确定列表的数目,该接口是DevicePolicyManager通过Binder调用DeviceManagerService.java中的接口
进入frameworks/base/core/java/android/app/admin/DevicePolicyManager.java
    public @Nullable List getActiveAdminsAsUser(int userId) {
1609        if (mService != null) {
1610            try {
1611                return mService.getActiveAdmins(userId);
1612            } catch (RemoteException e) {
1613                throw e.rethrowFromSystemServer();
1614            }

> 跟踪mService.getActiveAdmins(userId)进入frameworks/base/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
    @SuppressWarnings("unchecked")
3280    public List getActiveAdmins(int userHandle) {
3281        if (!mHasFeature) {
3282            return Collections.EMPTY_LIST;
3283        }
3284
3285        enforceFullCrossUsersPermission(userHandle);
3286        synchronized (this) {
3287            DevicePolicyData policy = getUserData(userHandle);
3288            final int N = policy.mAdminList.size();
3289            if (N <= 0) {
3290                return null;
3291            }
3292            ArrayList res = new ArrayList(N);
3293            for (int i=0; i从本地的List里面复制了一份给返回,在这个文件里就找到了两处add:一处在 setActiveAdmin,一致在 loadSettingsLocked ,setActiveAdmin发现他是一个hide的借口存在于Manager类上,第三发的应用是不能调到的,在loadSettingsLocked。在这个函数里面在做xml的parser.代码比较长,不全列出来
private void saveSettingsLocked(int userHandle) {
2511        DevicePolicyData policy = getUserData(userHandle);
2512        JournaledFile journal = makeJournaledFile(userHandle);
2513        FileOutputStream stream = null;
2514        try {
2515            stream = new FileOutputStream(journal.chooseForWrite(), false);
2516            XmlSerializer out = new FastXmlSerializer();
2517            out.setOutput(stream, StandardCharsets.UTF_8.name());
2518            out.startDocument(null, true);
2519
2520            out.startTag(null, "policies");
2521            if (policy.mRestrictionsProvider != null) {
2522                out.attribute(null, ATTR_PERMISSION_PROVIDER,
2523                        policy.mRestrictionsProvider.flattenToString());

>从上面代码可以看出,JournaledFile journal = makeJournaledFile(userHandle)加载需要解析的xml文件,进入该函数发现需要解析的xml文件为device_policies.xml
 private static final String DEVICE_POLICIES_XML = "device_policies.xml";
    private JournaledFile makeJournaledFile(int userHandle) {
2500        final String base = userHandle == UserHandle.USER_SYSTEM
2501                ? mInjector.getDevicePolicyFilePathForSystemUser() + DEVICE_POLICIES_XML
2502                : new File(mInjector.environmentGetUserSystemDirectory(userHandle),
2503                        DEVICE_POLICIES_XML).getAbsolutePath();
2504        if (VERBOSE_LOG) {
2505            Log.v(LOG_TAG, "Opening " + base);
2506        }
2507        return new JournaledFile(new File(base), new File(base + ".tmp"));
2508    }
>综上,显示列表是DeviceManagerService.java来解析device_policies.xml文件,并非通过配置文件或者增加功能来显示的.


>列表选项是否默认,Settings中通过DeviceAdminSettings.java的isActiveAdmin()方法获取应用激活状态:
    private boolean isActiveAdmin(DeviceAdminInfo item) {
        return mDPM.isAdminActiveAsUser(item.getComponent(), getUserId(item));
    }
> 跟踪mDPM.isAdminActiveAsUser(item.getComponent(), getUserId(item));进入frameworks/base/core/java/android/app/admin/DevicePolicyManager.java

567    public boolean isAdminActiveAsUser(@NonNull ComponentName admin, int userId) {
1568        if (mService != null) {
1569            try {
1570                return mService.isAdminActive(admin, userId);
1571            } catch (RemoteException e) {
1572                throw e.rethrowFromSystemServer();
1573            }
1574        }
1575        return false;
1576    }

>同理,通过Binder机制,进入DeviceMangerService.java文件中发现调用的是getActiveAdminUncheckedLocked(adminReceiver, userHandle)接口,进一步跟踪进入.
3241    public boolean isAdminActive(ComponentName adminReceiver, int userHandle) {
3242        if (!mHasFeature) {
3243            return false;
3244        }
3245        enforceFullCrossUsersPermission(userHandle);
3246        synchronized (this) {
3247            return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;
3248        }
3249    }

> 查看传入的参数在mAdminMap中是否存在.
9    ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) {
2250        ActiveAdmin admin = getUserData(userHandle).mAdminMap.get(who);
2251        if (admin != null
2252                && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
2253                && who.getClassName().equals(admin.info.getActivityInfo().name)) {
2254            return admin;
2255        }
2256        return null;
2257    }

> 我们来查看谁向mAdminMap中写入参数.查看在 loadSettingsLocked接口中有mAdminMap.put操作,由如下代码来看,是通过解析device_policy.xml来决定是否默认选中的.
 private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
2708        JournaledFile journal = makeJournaledFile(userHandle);
2709        FileInputStream stream = null;
2710        File file = journal.chooseForRead();
2711        boolean needsRewrite = false;
2712        try {
2713            stream = new FileInputStream(file);
2714            XmlPullParser parser = Xml.newPullParser();
2715            parser.setInput(stream, StandardCharsets.UTF_8.name());
2716
...
...
                           + userHandle);
2810                        }
2811                        if (dai != null) {
2812                            ActiveAdmin ap = new ActiveAdmin(dai, /* parent */ false);
2813                            ap.readFromXml(parser);
2814                            policy.mAdminMap.put(ap.info.getComponent(), ap);
2815                        }
2816                    } catch (RuntimeException e) {
2817                        Slog.w(LOG_TAG, "Failed loading admin " + name, e);
2818                    }


> 综上所述,该界面显示的列表已经相应列表是否默认选中,都是通过解析device_policy.xml文件来决定的,并非是某个配置文件通过简单修改即可.
该机制为Android 原生机制,强制修改存在不可控风险

你可能感兴趣的:(Android系统)