目录
1.ProfileOwner
2.DeviceOwner
3.DO或PO授权后获取设备信息:
3.1.获取设备IMEI(Android10及以上版本)
3.2.获取IMSI,ICCID及电话号码
ProfileOwner是Android5.0系统推出.ProfileOwner包含了所有DeviceAdmin用户的管理能力.系统只能设置一个Profile Owner程序,并且设置为ProfileOwner后应用无法卸载.
设置ProfileOwner
具有MANAGE_PROFILE_AND_DEVICE_OWNERS权限和shell uid的应用程序才能调用此方法
public boolean setProfileOwner(ComponentName, String, int) {}
应用反射调用:
public void setProfileOwner(){
try {
Method setDeviceOwner = mDevicePolicyManager.getClass().getDeclaredMethod("setActiveProfileOwner", ComponentName.class,String.class);
setDeviceOwner.setAccessible(true);
setDeviceOwner.invoke(mDevicePolicyManager,admin,"ansen");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
// APP需要系统签名和如下权限
<uses-permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS" />
<uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
DPMS接口:
public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) {
if (!mHasFeature) {
return false;
}
if (who == null
|| !isPackageInstalledForUser(who.getPackageName(), userHandle)) {
throw new IllegalArgumentException("Component " + who
+ " not installed for userId:" + userHandle);
}
final boolean hasIncompatibleAccountsOrNonAdb =
hasIncompatibleAccountsOrNonAdbNoLock(userHandle, who);
synchronized (getLockObject()) {
enforceCanSetProfileOwnerLocked(who, userHandle, hasIncompatibleAccountsOrNonAdb);
final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
if (admin == null || getUserData(userHandle).mRemovingAdmins.contains(who)) {
throw new IllegalArgumentException("Not active admin: " + who);
}
if (isAdb()) {
// Log profile owner provisioning was started using adb.
MetricsLogger.action(mContext, PROVISIONING_ENTRY_POINT_ADB, LOG_TAG_PROFILE_OWNER);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.PROVISIONING_ENTRY_POINT_ADB)
.setAdmin(who)
.setStrings(LOG_TAG_PROFILE_OWNER)
.write();
}
// Shutting down backup manager service permanently.
toggleBackupServiceActive(userHandle, /* makeActive= */ false);
mOwners.setProfileOwner(who, ownerName, userHandle);
mOwners.writeProfileOwner(userHandle);
Slog.i(LOG_TAG, "Profile owner set: " + who + " on user " + userHandle);
final long id = mInjector.binderClearCallingIdentity();
try {
if (mUserManager.isManagedProfile(userHandle)) {
maybeSetDefaultRestrictionsForAdminLocked(userHandle, admin,
UserRestrictionsUtils.getDefaultEnabledForManagedProfiles());
ensureUnknownSourcesRestrictionForProfileOwnerLocked(userHandle, admin,
true /* newOwner */);
}
sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED,
userHandle);
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
mDeviceAdminServiceController.startServiceForOwner(
who.getPackageName(), userHandle, "set-profile-owner");
return true;
}
}
ProfileOwner支持的管控能力:
是否为ProfileOwner
mDevicePolicyManager.isProfileOwnerApp(mComponentName.getPackageName());
隐藏应用
可停用制定应用并且不再界面显示,除非调用相应API恢复可用,否则该应用永远无法运行.可以用来开发应用黑白名单功能
mDevicePolicyManager.setApplicationHidden(admin, "packageName", true);
// 应用是否隐藏
mDevicePolicyManager.isApplicationHidden(admin, "packageName");
禁止卸载应用
被设置为禁止卸载的应用将成为受保护应用,无法被用户卸载,除非取消保护
mDevicePolicyManager.setUninstallBlocked(admin, "packageName", true);
mDevicePolicyManager.isUninstallBlocked(admin, "packageName");
DPMS实现
public void setUninstallBlocked(ComponentName who, String callerPackage, String packageName,
boolean uninstallBlocked) {
final int userId = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or a block uninstall delegate
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_BLOCK_UNINSTALL); // 调用者权限检查
long id = mInjector.binderClearCallingIdentity(); //清空远程调用端的uid和pid,用当前本地进程的uid和pid替代
try {
mIPackageManager.setBlockUninstallForUser(packageName, uninstallBlocked, userId); // 通过binder调用PMS来设置
} catch (RemoteException re) {
// Shouldn't happen.
Slog.e(LOG_TAG, "Failed to setBlockUninstallForUser", re);
} finally {
mInjector.binderRestoreCallingIdentity(id);// 恢复远程调用端的uid和pid信息
}
}
final boolean isDelegate = (who == null);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_UNINSTALL_BLOCKED)
.setAdmin(callerPackage)
.setBoolean(isDelegate)
.setStrings(packageName)
.write();
}
首先对调用者权限检查,只有device owner,profile owner或指定DELEGATION_BLOCK_UNINSTALL作用域的委托调用,然后使用SystemServer的权限来调用PMS的setBlockUninstallForUser()方法来设置调用者用户的应用是否可卸载.
修改系统设置
mDevicePolicyManager.setSecureSetting(admin, "setting", "value");
public void setSecureSetting(ComponentName who, String setting, String value) {
Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = mInjector.userHandleGetCallingUserId();
// ... ...
// 对调用者的权限判断
long id = mInjector.binderClearCallingIdentity(); //清空远程调用端的uid和pid,用当前本地进程的uid和pid替代
try {
if (Settings.Secure.DEFAULT_INPUT_METHOD.equals(setting)) {
final String currentValue = mInjector.settingsSecureGetStringForUser(
Settings.Secure.DEFAULT_INPUT_METHOD, callingUserId);
if (!TextUtils.equals(currentValue, value)) {
// Tell the content observer that the next change will be due to the owner
// changing the value. There is a small race condition here that we cannot
// avoid: Change notifications are sent asynchronously, so it is possible
// that there are prior notifications queued up before the one we are about
// to trigger. This is a corner case that will have no impact in practice.
mSetupContentObserver.addPendingChangeByOwnerLocked(callingUserId);
}
getUserData(callingUserId).mCurrentInputMethodSet = true;
saveSettingsLocked(callingUserId);
}
mInjector.settingsSecurePutStringForUser(setting, value, callingUserId); //调用Settings.Secure.putStringForUser()执行逻辑
} finally {
mInjector.binderRestoreCallingIdentity(id); // 恢复远程调用端的uid和pid信息
}
// ... ...
}
首先也是对调用者的权限进行一系列判断,随后以SystemServer的权限来调用Settings.Secure.putStringForUser()方法传入需要设置的值和调用user.
设置静音
mDevicePolicyManager.setMasterVolumeMuted(admin, true);
mDevicePolicyManager.isMasterVolumeMuted(admin); //是否静音
public void setMasterVolumeMuted(ComponentName who, boolean on) {
Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
setUserRestriction(who, UserManager.DISALLOW_UNMUTE_DEVICE, on);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_MASTER_VOLUME_MUTED)
.setAdmin(who)
.setBoolean(on)
.write();
}
}
首先也是权限判断,随后调用 用户限制管理的方法setUserRestriction传入SET_MASTER_VOLUME_MUTED设置静音的指令完成.
用户限制管理
mDevicePolicyManager.addUserRestriction(admin, key); // 添加用户限制
mDevicePolicyManager.clearUserRestriction(admin, key); // 清除用户限制
mDevicePolicyManager.getUserRestrictions(admin); // 获取用户限制
DPM中的addUserRestriction会调用到DPMS的setUserRestriction方法,具体如下
public void setUserRestriction(ComponentName who, String key, boolean enabledFromThisOwner) {
Preconditions.checkNotNull(who, "ComponentName is null");
if (!UserRestrictionsUtils.isValidRestriction(key)) {
return;
}
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
final ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); // 调用者权限检查
final boolean isDeviceOwner = isDeviceOwner(who, userHandle);
if (isDeviceOwner) {
if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) { //判断当前用户是否限制了DeviceOwner设置
throw new SecurityException("Device owner cannot set user restriction " + key);
}
} else { // profile owner
if (!UserRestrictionsUtils.canProfileOwnerChange(key, userHandle)) { //判断当前用户是否限制了ProfileOwner设置
throw new SecurityException("Profile owner cannot set user restriction " + key);
}
}
// 把当前的限制策略保存到activeAdmin的一个bundle对象中
final Bundle restrictions = activeAdmin.ensureUserRestrictions();
if (enabledFromThisOwner) {
restrictions.putBoolean(key, true);
} else {
restrictions.remove(key);
}
saveUserRestrictionsLocked(userHandle); //保存并应用该限制
}
final int eventId = enabledFromThisOwner
? DevicePolicyEnums.ADD_USER_RESTRICTION
: DevicePolicyEnums.REMOVE_USER_RESTRICTION;
DevicePolicyEventLogger
.createEvent(eventId)
.setAdmin(who)
.setStrings(key)
.write();
if (SecurityLog.isLoggingEnabled()) {
final int eventTag = enabledFromThisOwner
? SecurityLog.TAG_USER_RESTRICTION_ADDED
: SecurityLog.TAG_USER_RESTRICTION_REMOVED;
SecurityLog.writeEvent(eventTag, who.getPackageName(), userHandle, key);
}
}
private void saveUserRestrictionsLocked(int userId) {
saveSettingsLocked(userId); // 获取当前最新的DevicePolicyData,然后保存到xml文件中
pushUserRestrictions(userId); // 调用UserManagerService,传入之前保存在Bundle中的限制策略key
sendChangedNotification(userId); // 发送策略状态改变的广播
}
在setUserRestriction方法中对调用者权限检查,然后判断当前user是否有不能修改的限制,接着把当前的限制策略key保存到activeAdmin的一个bundle对象中.
最后
设置用户图标
mDevicePolicyManager.setUserIcon(admin, icon);
修改权限申请的策略
mDevicePolicyManager.setPermissionPolicy(admin, DevicePolicyManager.PERMISSION_POLICY_PROMPT);
// 修改指定权限的策略
mDevicePolicyManager.setPermissionGrantState(admin, "packageName", "permission", DevicePolicyManager.PERMISSION_POLICY_PROMPT);
有如下三种策略,这些策略都不影响已经允许过拒绝的权限
PERMISSION_POLICY_PROMPT
每次都提醒是否允许
PERMISSION_POLICY_AUTO_GRANT
自动允许
PERMISSION_POLICY_AUTO_DENY
自动拒绝
设置应用限制
mDevicePolicyManager.setApplicationRestrictions(admin, "packageName", null);
mDevicePolicyManager.getApplicationRestrictions(admin, packageName); // 获取应用程序受限信息
主要是调用UserManager来实现应用限制.
public void setApplicationRestrictions(ComponentName who, String callerPackage,
String packageName, Bundle settings) {
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_APP_RESTRICTIONS); // 调用者权限检查
final UserHandle userHandle = mInjector.binderGetCallingUserHandle();
final long id = mInjector.binderClearCallingIdentity(); // 清空远程调用端的uid和pid
try {
mUserManager.setApplicationRestrictions(packageName, settings, userHandle); //调用UserManager方法实现
// ...
} finally {
mInjector.binderRestoreCallingIdentity(id);// 恢复远程调用端的uid和pid
}
}
启用或禁用备份服务
DeviceOwner调用此API来控制设备上所有用户的备份服务。ProfileOwner可以使用此API启用或禁用Profile的备份服务
mDevicePolicyManager.setBackupServiceEnabled(admin, enabled);
mDevicePolicyManager.isBackupServiceEnabled(admin); // 备份服务是否开启
这主要是调用IBackupManager的实现类Trampoline类创建当前用户的BackupManagerService
public void setBackupServiceEnabled(ComponentName admin, boolean enabled) {
if (!mHasFeature) {
return;
}
Preconditions.checkNotNull(admin); // 不为空检查
enforceProfileOrDeviceOwner(admin); // 检查调用者是否为ProfileOwner
int userId = mInjector.userHandleGetCallingUserId();
toggleBackupServiceActive(userId, enabled); // 通过userid来控制当前用户备份服务启用和禁止
}
private void toggleBackupServiceActive(int userId, boolean makeActive) {
long ident = mInjector.binderClearCallingIdentity();
try {
if (mInjector.getIBackupManager() != null) {
mInjector.getIBackupManager()
.setBackupServiceActive(userId, makeActive);// 如果makeActive为true,则创建一个BackupManagerService,创建用户的激活文件
}
} catch (RemoteException e) {
throw new IllegalStateException("Failed deactivating backup service.", e);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
}
设置状态栏的禁用或启用
mDevicePolicyManager.setStatusBarDisabled(admin, disabled);
public boolean setStatusBarDisabled(ComponentName who, boolean disabled) {
int userId = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); //检查调用者权限
if (!isUserAffiliatedWithDeviceLocked(userId)) {
throw new SecurityException("Admin " + who +
" is neither the device owner or affiliated user's profile owner.");
}
if (isManagedProfile(userId)) {
throw new SecurityException("Managed profile cannot disable status bar");
}
DevicePolicyData policy = getUserData(userId); // 获取当前用户的设备策略数据对象
if (policy.mStatusBarDisabled != disabled) {
boolean isLockTaskMode = false;
try {
isLockTaskMode = mInjector.getIActivityTaskManager().getLockTaskModeState()
!= LOCK_TASK_MODE_NONE;
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to get LockTask mode");
}
if (!isLockTaskMode) {
if (!setStatusBarDisabledInternal(disabled, userId)) {
return false;
}
}
policy.mStatusBarDisabled = disabled; // 禁用状态栏的值在policy中设置
saveSettingsLocked(userId); // 保存当前策略xml中,并发送更改策略的广播
}
}
// ...
return true;
}
设置输入法权限
默认情况下,用户可以使用任何输入法.当添加了零个或多个包时,用户无法启用不在列表中的输入法
mDevicePolicyManager.setPermittedInputMethods(admin, new ArrayList
mDevicePolicyManager.getPermittedInputMethods(admin); // 获取受信任的输入法包列表
设置是否禁止截图
mDevicePolicyManager.setScreenCaptureDisabled(admin, true);
mDevicePolicyManager.getScreenCaptureDisabled(admin); // 是否禁止截图
禁止蓝牙访问联系人
mDevicePolicyManager.setBluetoothContactSharingDisabled(admin, true);
mDevicePolicyManager.getBluetoothContactSharingDisabled(admin); // 获取蓝牙访问联系人状态
通过包名添加删除应用程序小部件
mDevicePolicyManager.addCrossProfileWidgetProvider(admin, packageName); // 添加小部件
mDevicePolicyManager.removeCrossProfileWidgetProvider(admin, packageName); // 删除小部件
mDevicePolicyManager.getCrossProfileWidgetProviders(admin); // 获取所有可用小部件
管理应用程序消息通知
默认允许所有应用的通知消息,当添加了零个或多个包时,不在列表中且不是当前用户上的应用通知将不接收
mDevicePolicyManager.setPermittedCrossProfileNotificationListeners(admin, packageList);
mDevicePolicyManager.getPermittedCrossProfileNotificationListeners(admin); // 获取可显示消息通知的包列表
运行时权限控制
mDevicePolicyManager.getPermissionGrantState(admin, packageName, permission); // 获取应用程序的运行时权限状态
mDevicePolicyManager.setPermissionPolicy(admin, policy); // 允许应用程序自动授予或拒绝运行时权限请求
mDevicePolicyManager.getPermissionPolicy(admin); // 返回设备或配置文件所有者设置的当前运行时权限策略
设置特定的服务组件作为内容提供者
用于向用户的本地或远程管理员发出权限请求
mDevicePolicyManager.setRestrictionsProvider(admin, provider);
禁用特定类型的帐户
mDevicePolicyManager.setAccountManagementDisabled(admin, "accountType", true);
mDevicePolicyManager.getAccountTypesWithManagementDisabled();// 获取禁用的账户列表
重新启用用户初始化时默认禁用的系统应用程序
mDevicePolicyManager.enableSystemApp(admin, packageName);
设置辅助权限
默认情况下,用户可以使用任何可访问性服务.当添加了零个或多个包时,用户无法启用列表中非系统部分的可访问性服务
mDevicePolicyManager.setPermittedAccessibilityServices(admin, new ArrayList
mDevicePolicyManager.getPermittedAccessibilityServices(admin);
设置组织名
mDevicePolicyManager.setOrganizationName(admin, title); //设置组织名
mDevicePolicyManager.getOrganizationName(admin);// 获取组织名
禁止或者开启搜索联系人功能
mDevicePolicyManager.setCrossProfileContactsSearchDisabled(admin, disabled);
mDevicePolicyManager.getCrossProfileContactsSearchDisabled(admin); // 获取搜索联系人状态
禁止或者开启来电显示功能
mDevicePolicyManager.setCrossProfileCallerIdDisabled(admin, disabled);
mDevicePolicyManager.getCrossProfileCallerIdDisabled(admin); // 获取禁止来电显示状态
设置应用程序挂起
挂起的程序将无法启动任何活动
mDevicePolicyManager.setPackagesSuspended(admin, packageNames, suspended);
mDevicePolicyManager.isPackageSuspended(admin, packageName); // 是否为挂起应用
指定特定应用程序始终打开的VPN连接
此连接在重新启动后自动授予并持久化
mDevicePolicyManager.setAlwaysOnVpnPackage(admin, Package, lockdownEnabled);
获取打开VPN连接的应用
mDevicePolicyManager.getAlwaysOnVpnPackage(admin);
授予对另一个应用程序的特权API的访问权
mDevicePolicyManager.setDelegatedScopes(admin, delegatePackage, scopes);
mDevicePolicyManager.getDelegatedScopes(admin, delegatedPackage); // 获取特权应用的所有权限
安装证书和相应的私钥
mDevicePolicyManager.installKeyPair(admin, privKey, cert, alias);
mDevicePolicyManager.removeKeyPair(admin, alias); // 删除密匙
CA证书管理
mDevicePolicyManager.uninstallAllUserCaCerts(admin); // 卸载所有自定义的可信CA证书,除系统CA证书外,通过设备策略以外的方式安装的证书也将被删除
mDevicePolicyManager.uninstallCaCert(admin, certBuffer); // 从可信用户CAs卸载给定的证书
mDevicePolicyManager.installCaCert(admin, certBuffer); // 将给定证书安装为用户可信CA
mDevicePolicyManager.hasCaCertInstalled(admin, certBuffer); // 此证书是否安装为可信CA
mDevicePolicyManager.getInstalledCaCerts(admin); // 返回当前受信任的所有CA证书,不包括系统CA证书.如果用户通过除设备策略之外的其他方式安装了任何证书,这些证书也将包括在内
锁屏管理
mDevicePolicyManager.setRequiredStrongAuthTimeout(admin, timeoutMs); // 超时后用户必须使用身份验证才能进入系统,比如指纹、密码等
mDevicePolicyManager.setResetPasswordToken(admin, token); // 重置设备锁屏密码
mDevicePolicyManager.clearResetPasswordToken(admin); // 清除重置设备密码Token
mDevicePolicyManager.resetPasswordWithToken(admin, password, token, flags); // 重置设备锁屏密码,在Token激活的状态下有效
Android 5.0 引入了部署DeviceOwner应用的功能.DeviceOwner(设备所有者)是一种专业化类型的设备管理员.DeviceOwner包含了ProfileOwner的所有管理能力,并且在这些基础上额外添加了一些管理权限,如重启设备、禁用状态栏、创建和移除二级用户以及配置全局设置的能力等.一台设备在同一时间只能有一名活动的DeviceOwner.并且系统同时只能有一个DeviceOwner应用或者ProfileOwner应用
2.1.设置DeviceOwner
adb shell dpm set-device-owner --name Test com.example.myapplication/.AdminReciver
adb shell dpm remove-active-admin com.example.myapplication/.AdminReciver
可以通过如上adb命令设置DeviceOwner,同时也可以使用如下接口设置,该接口为hide api,需要系统应用才可调用.
APP反射调用:
public void setDeviceOwner(){
try {
Method setDeviceOwner = mDevicePolicyManager.getClass().getDeclaredMethod("setDeviceOwner", ComponentName.class);
setDeviceOwner.setAccessible(true);
setDeviceOwner.invoke(mDevicePolicyManager,admin);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
// APP需要系统签名和如下权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS" />
<uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
应用层接口:
mDevicePolicyManager.setDeviceOwner(ComponentName who, String ownerName, int userId); // 设置DeviceOwner
mDevicePolicyManager.isDeviceOwnerApp(mComponentName.getPackageName()); // 是否为DeviceOwner
2.2.DeviceOwner的主要能力:
用户管理
mDevicePolicyManager.createAndManageUser(admin, name, profileOwner, adminExtras, flags); // 创建用户
mDevicePolicyManager.switchUser(admin, userHandle); // 切换用户
mDevicePolicyManager.removeUser(admin, userHandle); // 删除用户
由DeviceOwner调用,创建指定名称的用户并将传入的组件包作为profile owner.
这个方法主要做了两件事,首先是创建用户,然后设置ProfileOwner,设置ProfileOwner前提是需要先设置device admin.
public UserHandle createAndManageUser(ComponentName admin, String name,
ComponentName profileOwner, PersistableBundle adminExtras, int flags) {
//参数不为空判断
Preconditions.checkNotNull(admin, "admin is null");
Preconditions.checkNotNull(profileOwner, "profileOwner is null");
if (!admin.getPackageName().equals(profileOwner.getPackageName())) {
throw new IllegalArgumentException("profileOwner " + profileOwner + " and admin "
+ admin + " are not in the same package");
}
// 只允许系统用户使用本方法
if (!mInjector.binderGetCallingUserHandle().isSystem()) {
throw new SecurityException("createAndManageUser was called from non-system user");
}
final boolean ephemeral = (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0;
final boolean demo = (flags & DevicePolicyManager.MAKE_USER_DEMO) != 0
&& UserManager.isDeviceInDemoMode(mContext);
final boolean leaveAllSystemAppsEnabled = (flags & LEAVE_ALL_SYSTEM_APPS_ENABLED) != 0;
final int targetSdkVersion;
// 创建用户
UserHandle user = null;
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);// 权限检查,只允许DeviceOwner调用
final int callingUid = mInjector.binderGetCallingUid();
final long id = mInjector.binderClearCallingIdentity(); //清除调用者的PID UID并保存到id变量中
try {
targetSdkVersion = mInjector.getPackageManagerInternal().getUidTargetSdkVersion(
callingUid);
// 对设备的存储大小和创建用户数限制进行检查
DeviceStorageMonitorInternal deviceStorageMonitorInternal =
LocalServices.getService(DeviceStorageMonitorInternal.class);
if (deviceStorageMonitorInternal.isMemoryLow()) {
if (targetSdkVersion >= Build.VERSION_CODES.P) {
throw new ServiceSpecificException(
UserManager.USER_OPERATION_ERROR_LOW_STORAGE, "low device storage");
} else {
return null;
}
}
if (!mUserManager.canAddMoreUsers()) {
if (targetSdkVersion >= Build.VERSION_CODES.P) {
throw new ServiceSpecificException(
UserManager.USER_OPERATION_ERROR_MAX_USERS, "user limit reached");
} else {
return null;
}
}
int userInfoFlags = 0;
if (ephemeral) {
userInfoFlags |= UserInfo.FLAG_EPHEMERAL;
}
if (demo) {
userInfoFlags |= UserInfo.FLAG_DEMO;
}
String[] disallowedPackages = null;
if (!leaveAllSystemAppsEnabled) {
disallowedPackages = mOverlayPackagesProvider.getNonRequiredApps(admin,
UserHandle.myUserId(), ACTION_PROVISION_MANAGED_USER).toArray(
new String[0]);
}
//调用UserManagerService的方法创建用户,和调用UserManager.createuser()相同,
//但绕过了UserManager#DISALLOW_ADD_USER和UserManager#DISALLOW_ADD_MANAGED_PROFILE的检查
UserInfo userInfo = mUserManagerInternal.createUserEvenWhenDisallowed(name,
userInfoFlags, disallowedPackages);
if (userInfo != null) {
user = userInfo.getUserHandle();
}
} finally {
mInjector.binderRestoreCallingIdentity(id); //从id变量中恢复调用者的PID UID
}
}
// ...
final int userHandle = user.getIdentifier();
// 发送用户创建的广播
final Intent intent = new Intent(DevicePolicyManager.ACTION_MANAGED_USER_CREATED)
.putExtra(Intent.EXTRA_USER_HANDLE, userHandle)
.putExtra(
DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED,
leaveAllSystemAppsEnabled)
.setPackage(getManagedProvisioningPackage(mContext))
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
final long id = mInjector.binderClearCallingIdentity();
try {
final String adminPkg = admin.getPackageName();
try {
// Install the profile owner if not present.
if (!mIPackageManager.isPackageAvailable(adminPkg, userHandle)) {
mIPackageManager.installExistingPackageAsUser(adminPkg, userHandle,
PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS,
PackageManager.INSTALL_REASON_POLICY, null);
}
} catch (RemoteException e) {
// Does not happen, same process
}
// 激活admin
setActiveAdmin(profileOwner, true, userHandle);
final String ownerName = getProfileOwnerName(Process.myUserHandle().getIdentifier());
// 设置ProfileOwner
setProfileOwner(profileOwner, ownerName, userHandle);
synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(userHandle);
policyData.mInitBundle = adminExtras;
policyData.mAdminBroadcastPending = true;
saveSettingsLocked(userHandle); // 保存该用户配置的策略到xml并发送状态改变广播
}
// 保存新建用户的userId(该id可用来移除和切换用户)
if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 1, userHandle);
}
return user;
} catch (Throwable re) {
mUserManager.removeUser(userHandle);
if (targetSdkVersion >= Build.VERSION_CODES.P) {
throw new ServiceSpecificException(UserManager.USER_OPERATION_ERROR_UNKNOWN,
re.getMessage());
} else {
return null;
}
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
}
重启设备
调用PowerManager的reboot方法来来重启设备,该方法只有DeviceOwner可以调用
mDevicePolicyManager.reboot(admin);
获取wifi Mac地址
调用WifiManager的getFactoryMacAddresses方法获取mac地址,该方法只有DeviceOwner可以调用
mDevicePolicyManager.getWifiMacAddress(admin);
将锁屏模式设置为None,当用户设置了密码时无效
mDevicePolicyManager.setKeyguardDisabled(admin, disabled);
系统更新策略
mDevicePolicyManager.setSystemUpdatePolicy(admin, policy); // 设置系统更新策略
mDevicePolicyManager.getSystemUpdatePolicy(); // 获取系统更新策略
设置系统设置中Global相关的属性
mDevicePolicyManager.setGlobalSetting(admin, setting, value);
锁屏管理
mDevicePolicyManager.setDeviceOwnerLockScreenInfo(admin, info); // 设置锁屏界面显示的提示消息
mDevicePolicyManager.getDeviceOwnerLockScreenInfo();// 获取锁屏界面显示消息
设置一个独立于网络的全局HTTP代理
mDevicePolicyManager.setRecommendedGlobalProxy(admin, proxyInfo);
固定屏幕的指定应用
需要device owner调用,然后调用Activity的startLockTask()方法
mDevicePolicyManager.setLockTaskPackages(mComponentName, new String[]{"packages"});
mDevicePolicyManager.getLockTaskPackages(admin); // 获取允许在锁定界面显示的包列表
mDevicePolicyManager.isLockTaskPermitted(packageName); // 查询一个应用是否能够在锁定界面显示
(1).应用必须动态获取android.permission.READ_PHONE_STATE 权限
(2).应用必须具有DeviceOwner或者ProfileOwner权限。或者由具有这两个权限的应用通过setDelegatedScopes(ComponentName admin,String delegatePackage,List
(3).调用TelephonyManager.getImei(int slotIndex)
例:
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
DevicePolicyManager dpm = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
ArrayList
dpm.setDelegatedScopes(new ComponentName("com.example.deviceadmin","com.example.deviceadmin.DeviceAdminSampleReceiver"),"com.xx.xxx",strings);
}else{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, 1);
}
(1).应用必须动态获取android.permission.READ_PHONE_STATE 权限,且具有android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE权限(该权限需系统应用或者deviceAdmin和ProflieOwner才能使用)
(2).反射调用SubscriptionManager.getActiveSubscriptionInfoList,返回值为List
[{id=1 iccId=89860042191833126825 simSlotIndex=1 carrierId=1435 displayName=移动 carrierName=中国移动 nameSource=0 iconTint=-16746133 number= dataRoaming=0 iconBitmap=android.graphics.Bitmap@7f33c3b mcc=460 mnc=07 countryIso=cn isEmbedded=false nativeAccessRules=null cardString=89860042191833126825 cardId=0 isOpportunistic=false groupUUID=null isGroupDisabled=false profileClass=-1 ehplmns=[46000, 46007, 46002, 46008] hplmns=[46000, 46000, 46000] subscriptionType=0 groupOwner=null carrierConfigAccessRules=null areUiccApplicationsEnabled=true}]
(3).通过SubscriptionInfo.getIccId(),SubscriptionInfo.getNumber()方法获取Iccid和电话号码。
(4).通过SubscriptionInfo.getSubscriptionId() 获取SubscriberId,然后反射调用TelephonyManager.getSubscriberId(int SubscriberId)获取IMSI