关于android的设备管理器-DevicePolicyManager
Posted cynchanpin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于android的设备管理器-DevicePolicyManager相关的知识,希望对你有一定的参考价值。
在Andorid的设置->安全里面有个设备管理器的选项,相信大部分android用户都不太会去注意这个东西。近期在安装了一个应用之后发现这个里面的东西变了。怎么回事呢,研究研究看看。</span>
老思路,从已有的最明显的线索開始分析。“设备管理器”这几个字就是最好的线索,在Setting的package里面搜搜,一大堆多语言话的字符串,这个不是我要找的,我要找的是谁在用这个字符串。在一个布局文件中找到了:
res/xml/security_settings.xml
<Preference android:title="@string/manage_device_admin" android:summary="@string/manage_device_admin_summary" android:persistent="false" android:fragment="com.android.settings.DeviceAdminSettings"/>那就要详细看DeviceAdminSettings这个fragment了。这是一个比較正规的fragment。非常easy理解。关键在当中的updateList这个函数:
void updateList() { mActiveAdmins.clear(); List<ComponentName> cur = mDPM.getActiveAdmins(); if (cur != null) { for (int i=0; i<cur.size(); i++) { mActiveAdmins.add(cur.get(i)); } } mAvailableAdmins.clear(); List<ResolveInfo> avail = getActivity().getPackageManager().queryBroadcastReceivers( new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED), PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS); if (avail == null) { avail = Collections.emptyList(); } // Some admins listed in mActiveAdmins may not have been found by the above query. // We thus add them separately. Set<ComponentName> activeAdminsNotInAvail = new HashSet<ComponentName>(mActiveAdmins); for (ResolveInfo ri : avail) { ComponentName riComponentName = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name); activeAdminsNotInAvail.remove(riComponentName); } if (!activeAdminsNotInAvail.isEmpty()) { avail = new ArrayList<ResolveInfo>(avail); PackageManager packageManager = getActivity().getPackageManager(); for (ComponentName unlistedActiveAdmin : activeAdminsNotInAvail) { List<ResolveInfo> resolved = packageManager.queryBroadcastReceivers( new Intent().setComponent(unlistedActiveAdmin), PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS); if (resolved != null) { avail.addAll(resolved); } } } for (int i = 0, count = avail.size(); i < count; i++) { ResolveInfo ri = avail.get(i); try { DeviceAdminInfo dpi = new DeviceAdminInfo(getActivity(), ri); if (dpi.isVisible() || mActiveAdmins.contains(dpi.getComponent())) { mAvailableAdmins.add(dpi); } } catch (XmlPullParserException e) { Log.w(TAG, "Skipping " + ri.activityInfo, e); } catch (IOException e) { Log.w(TAG, "Skipping " + ri.activityInfo, e); } } getListView().setAdapter(new PolicyListAdapter()); }这个函数本身不复杂。可是还是看不出来所谓的设备管理器是个什么东东。
这里的线索就须要细致分析了,这里貌似有两个列表:
一个Active的列表和一个Available的列表,ok。
和在UI上看到的确实是一致的。那么能够说明列表的每一个项应该就是一个所谓的 设备管理器。两个列表的区别就是是否是active的。
那就看看Active的列表,它是怎么来的呢:
mActiveAdmins.clear(); List<ComponentName> cur = mDPM.getActiveAdmins(); if (cur != null) { for (int i=0; i<cur.size(); i++) { mActiveAdmins.add(cur.get(i)); } }ok,从mDPM里get的,mDPM是DevicePolicyManager对象。看到这里要吐槽下了,android的framework里XXXManager基本都是会相应一个XXXService的,都是通过典型的AIDL来实现的进程间的通信。
这里也不错所料:
/** * Return a list of all currently active device administrator‘s component * names. Note that if there are no administrators than null may be * returned. */ public List<ComponentName> getActiveAdmins() { if (mService != null) { try { return mService.getActiveAdmins(UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } } return null; }
mService必定是IDevicePolicyManager的对象,要找详细实现肯定要找到详细的service。DevicePolicyManagerService。
public List<ComponentName> getActiveAdmins(int userHandle) { enforceCrossUserPermission(userHandle); synchronized (this) { DevicePolicyData policy = getUserData(userHandle); final int N = policy.mAdminList.size(); if (N <= 0) { return null; } ArrayList<ComponentName> res = new ArrayList<ComponentName>(N); for (int i=0; i<N; i++) { res.add(policy.mAdminList.get(i).info.getComponent()); } return res; } }首先看到enforceCrossUserPermission这个应该是要求权限的。非常多Service的方法都会先检查权限,这是Android安全机制的一种体现。不多说这个了。
看逻辑是比較简单的,从本地的List里面复制了一份给返回。
看到这里,还是不知道这个东西究竟是什么。但至少知道他是以一个list的形式保存在这个service里面的。那就看怎么来add这个list吧。
在这个文件中就找到了两处add:一处在 setActiveAdmin,一致在 loadSettingsLocked
最踪下setActiveAdmin发现他是一个hide的借口存在于Manager类上,看来第三发的应该是不能调到的,那就看loadSettingsLocked吧。不能看到这个函数里面在做xml的parser,那么大概能够猜到了,应该是有一个xml的文件存在的。
private static JournaledFile makeJournaledFile(int userHandle) { final String base = userHandle == 0 ? "/data/system/" + DEVICE_POLICIES_XML : new File(Environment.getUserSystemDirectory(userHandle), DEVICE_POLICIES_XML) .getAbsolutePath(); return new JournaledFile(new File(base), new File(base + ".tmp")); }查看这个函数就大概找到了。/data/system下device_policies.xml 详细先不看这个xml的内容。我们关心的是谁回去写这个文件呢?与他相应有个saveSettingsLocked,追踪它能够发现,在handlePackagesChanged里面调用了。其它有非常多调用。可是看起来不像。
能够发现时在package发生变化的时候调用到的。那之前看到在有新应用安装以后page发生变化,这个现象也是符合的。
现象是解释通了,可是还是不明确,它究竟是干什么用的。下回再分析吧。
以上是关于关于android的设备管理器-DevicePolicyManager的主要内容,如果未能解决你的问题,请参考以下文章
安卓开发,如何点击按钮打开应用程序管理器里关于自己软件信息的页面?代码怎么写,谢谢
如何使用 android 的帐户管理器获取多个范围的身份验证令牌
使用 Android 帐户管理器在我的服务器上验证使用 FB 登录的用户
使用 Android 帐户管理器在我的服务器上验证使用 FB 登录的用户