通过DeviceAdminSettings.java的addAc。设备管理应用"界面列表中应用的激活状态是通过DevicePolicyManager的isAdminActiveAsUser()方法获取的。" />
- 首页 > it技术 > >
设备管理应用"界面列表中应用的激活状态是通过DevicePolicyManager的isAdminActiveAsUser()方法获取的
"设备管理应用"界面列表中应用的激活状态是通过DevicePolicyManager的isAdminActiveAsUser()方法获取的设置中,"设备管理应用"界面应用列表数据加载逻辑如下:> 通过DeviceAdminSettings.java的addActiveAdminsForProfile()和addDeviceAdminBroadcastReceiversForProfile()方法获取应用列表:packages/apps/Settings/src/com/android/settings/DeviceAdminSettings.javaprivate 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) {
1609if (mService != null) {
1610try {
1611return mService.getActiveAdmins(userId);
1612} catch (RemoteException e) {
1613throw e.rethrowFromSystemServer();
1614}> 跟踪mService.getActiveAdmins(userId)进入frameworks/base/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@SuppressWarnings("unchecked")
3280public List getActiveAdmins(int userHandle) {
3281if (!mHasFeature) {
3282return Collections.EMPTY_LIST;
3283}
3284
3285enforceFullCrossUsersPermission(userHandle);
3286synchronized (this) {
3287DevicePolicyData policy = getUserData(userHandle);
3288final int N = policy.mAdminList.size();
3289if (N <= 0) {
3290return null;
3291}
3292ArrayList res = new ArrayList(N);
3293for (int i=0;
i从本地的List里面复制了一份给返回,在这个文件里就找到了两处add:一处在 setActiveAdmin,一致在 loadSettingsLocked ,setActiveAdmin发现他是一个hide的借口存在于Manager类上,第三发的应用是不能调到的,在loadSettingsLocked。在这个函数里面在做xml的parser.代码比较长,不全列出来
private void saveSettingsLocked(int userHandle) {
2511DevicePolicyData policy = getUserData(userHandle);
2512JournaledFile journal = makeJournaledFile(userHandle);
2513FileOutputStream stream = null;
2514try {
2515stream = new FileOutputStream(journal.chooseForWrite(), false);
2516XmlSerializer out = new FastXmlSerializer();
2517out.setOutput(stream, StandardCharsets.UTF_8.name());
2518out.startDocument(null, true);
2519
2520out.startTag(null, "policies");
2521if (policy.mRestrictionsProvider != null) {
2522out.attribute(null, ATTR_PERMISSION_PROVIDER,
2523policy.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) {
2500final String base = userHandle == UserHandle.USER_SYSTEM
2501? mInjector.getDevicePolicyFilePathForSystemUser() + DEVICE_POLICIES_XML
2502: new File(mInjector.environmentGetUserSystemDirectory(userHandle),
2503DEVICE_POLICIES_XML).getAbsolutePath();
2504if (VERBOSE_LOG) {
2505Log.v(LOG_TAG, "Opening " + base);
2506}
2507return 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.java567public boolean isAdminActiveAsUser(@NonNull ComponentName admin, int userId) {
1568if (mService != null) {
1569try {
1570return mService.isAdminActive(admin, userId);
1571} catch (RemoteException e) {
1572throw e.rethrowFromSystemServer();
1573}
1574}
1575return false;
1576}>同理,通过Binder机制,进入DeviceMangerService.java文件中发现调用的是getActiveAdminUncheckedLocked(adminReceiver, userHandle)接口,进一步跟踪进入.
3241public boolean isAdminActive(ComponentName adminReceiver, int userHandle) {
3242if (!mHasFeature) {
3243return false;
3244}
3245enforceFullCrossUsersPermission(userHandle);
3246synchronized (this) {
3247return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;
3248}
3249}> 查看传入的参数在mAdminMap中是否存在.
9ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) {
2250ActiveAdmin admin = getUserData(userHandle).mAdminMap.get(who);
2251if (admin != null
2252&& who.getPackageName().equals(admin.info.getActivityInfo().packageName)
2253&& who.getClassName().equals(admin.info.getActivityInfo().name)) {
2254return admin;
2255}
2256return null;
2257}> 我们来查看谁向mAdminMap中写入参数.查看在 loadSettingsLocked接口中有mAdminMap.put操作,由如下代码来看,是通过解析device_policy.xml来决定是否默认选中的.
private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
2708JournaledFile journal = makeJournaledFile(userHandle);
2709FileInputStream stream = null;
2710File file = journal.chooseForRead();
2711boolean needsRewrite = false;
2712try {
2713stream = new FileInputStream(file);
2714XmlPullParser parser = Xml.newPullParser();
2715parser.setInput(stream, StandardCharsets.UTF_8.name());
2716
...
...
+ userHandle);
2810}
2811if (dai != null) {
2812ActiveAdmin ap = new ActiveAdmin(dai, /* parent */ false);
2813ap.readFromXml(parser);
2814policy.mAdminMap.put(ap.info.getComponent(), ap);
2815}
2816} catch (RuntimeException e) {
2817Slog.w(LOG_TAG, "Failed loading admin " + name, e);
2818}> 综上所述,该界面显示的列表已经相应列表是否默认选中,都是通过解析device_policy.xml文件来决定的,并非是某个配置文件通过简单修改即可.
该机制为Android 原生机制,强制修改存在不可控风险
推荐阅读