目录

1.ProfileOwner

2.DeviceOwner

3.DO或PO授权后获取设备信息:

3.1.获取设备IMEI(Android10及以上版本)

3.2.获取IMSI,ICCID及电话号码


1.ProfileOwner

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 {
            MethodsetDeviceOwner =mDevicePolicyManager.getClass().getDeclaredMethod("setActiveProfileOwner", ComponentName.class,String.class);
setDeviceOwner.setAccessible(true);
setDeviceOwner.invoke(mDevicePolicyManager,admin,"ansen");
        } catch (IllegalAccessExceptione) {
e.printStackTrace();
        } catch (InvocationTargetExceptione) {
e.printStackTrace();
        } catch (NoSuchMethodExceptione) {
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(ComponentNamewho, StringownerName, intuserHandle) {
        if (!mHasFeature) {
            return false;
        }
        if (who == null
                || !isPackageInstalledForUser(who.getPackageName(),userHandle)) {
            throw new IllegalArgumentException("Component " +who
                    + " not installed for userId:" +userHandle);
        }

final booleanhasIncompatibleAccountsOrNonAdb =
                hasIncompatibleAccountsOrNonAdbNoLock(userHandle,who);
        synchronized (getLockObject()) {
            enforceCanSetProfileOwnerLocked(who,userHandle,hasIncompatibleAccountsOrNonAdb);

final ActiveAdminadmin = 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 longid =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(ComponentNamewho, StringcallerPackage, StringpackageName,
            booleanuninstallBlocked) {
        final intuserId = 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); // 调用者权限检查

longid =mInjector.binderClearCallingIdentity(); //清空远程调用端的uid和pid,用当前本地进程的uid和pid替代
            try {
mIPackageManager.setBlockUninstallForUser(packageName,uninstallBlocked,userId); // 通过binder调用PMS来设置
            } catch (RemoteExceptionre) {
                // Shouldn't happen.
                Slog.e(LOG_TAG, "Failed to setBlockUninstallForUser",re);
            } finally {
mInjector.binderRestoreCallingIdentity(id);// 恢复远程调用端的uid和pid信息
            }
        }
        final booleanisDelegate = (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(ComponentNamewho, Stringsetting, Stringvalue) {
        Preconditions.checkNotNull(who, "ComponentName is null");
        intcallingUserId =mInjector.userHandleGetCallingUserId();
  // ... ...
// 对调用者的权限判断
            longid =mInjector.binderClearCallingIdentity(); //清空远程调用端的uid和pid,用当前本地进程的uid和pid替代
            try {
                if (Settings.Secure.DEFAULT_INPUT_METHOD.equals(setting)) {
                    final StringcurrentValue =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(ComponentNamewho, booleanon) {
        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(ComponentNamewho, Stringkey, booleanenabledFromThisOwner) {
        Preconditions.checkNotNull(who, "ComponentName is null");
        if (!UserRestrictionsUtils.isValidRestriction(key)) {
            return;
        }

final intuserHandle =mInjector.userHandleGetCallingUserId();
        synchronized (getLockObject()) {
            final ActiveAdminactiveAdmin =
                    getActiveAdminForCallerLocked(who,
                            DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); // 调用者权限检查
            final booleanisDeviceOwner = 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 Bundlerestrictions =activeAdmin.ensureUserRestrictions();
            if (enabledFromThisOwner) {
restrictions.putBoolean(key, true);
            } else {
restrictions.remove(key);
            }
            saveUserRestrictionsLocked(userHandle); //保存并应用该限制
        }
        final inteventId =enabledFromThisOwner
                ? DevicePolicyEnums.ADD_USER_RESTRICTION
                : DevicePolicyEnums.REMOVE_USER_RESTRICTION;
        DevicePolicyEventLogger
                .createEvent(eventId)
                .setAdmin(who)
                .setStrings(key)
                .write();
        if (SecurityLog.isLoggingEnabled()) {
            final inteventTag =enabledFromThisOwner
                    ? SecurityLog.TAG_USER_RESTRICTION_ADDED
                    : SecurityLog.TAG_USER_RESTRICTION_REMOVED;
            SecurityLog.writeEvent(eventTag,who.getPackageName(),userHandle,key);
        }
    }
    private void saveUserRestrictionsLocked(intuserId) {
        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(ComponentNamewho, StringcallerPackage,
            StringpackageName, Bundlesettings) {
        enforceCanManageScope(who,callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_APP_RESTRICTIONS); // 调用者权限检查

final UserHandleuserHandle =mInjector.binderGetCallingUserHandle();
        final longid =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(ComponentNameadmin, booleanenabled) {
        if (!mHasFeature) {
            return;
        }
        Preconditions.checkNotNull(admin); // 不为空检查
        enforceProfileOrDeviceOwner(admin); // 检查调用者是否为ProfileOwner
        intuserId =mInjector.userHandleGetCallingUserId();
        toggleBackupServiceActive(userId,enabled); // 通过userid来控制当前用户备份服务启用和禁止
    }
    private void toggleBackupServiceActive(intuserId, booleanmakeActive) {
        longident =mInjector.binderClearCallingIdentity();
        try {
            if (mInjector.getIBackupManager() != null) {
mInjector.getIBackupManager()
                        .setBackupServiceActive(userId,makeActive);// 如果makeActive为true,则创建一个BackupManagerService,创建用户的激活文件
            }
        } catch (RemoteExceptione) {
            throw new IllegalStateException("Failed deactivating backup service.",e);
        } finally {
mInjector.binderRestoreCallingIdentity(ident);
        }
    }

设置状态栏的禁用或启用

mDevicePolicyManager.setStatusBarDisabled(admin,disabled);

public boolean setStatusBarDisabled(ComponentNamewho, booleandisabled) {
        intuserId = 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");
            }
            DevicePolicyDatapolicy = getUserData(userId); // 获取当前用户的设备策略数据对象
            if (policy.mStatusBarDisabled !=disabled) {
                booleanisLockTaskMode = false;
                try {
isLockTaskMode =mInjector.getIActivityTaskManager().getLockTaskModeState()
                            !=LOCK_TASK_MODE_NONE;
                } catch (RemoteExceptione) {
                    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<String>(){});
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<String>(){});
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,vpnPackage,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激活的状态下有效

2.DeviceOwner

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 {
            MethodsetDeviceOwner =mDevicePolicyManager.getClass().getDeclaredMethod("setDeviceOwner", ComponentName.class);
setDeviceOwner.setAccessible(true);
setDeviceOwner.invoke(mDevicePolicyManager,admin);
        } catch (IllegalAccessExceptione) {
e.printStackTrace();
        } catch (InvocationTargetExceptione) {
e.printStackTrace();
        } catch (NoSuchMethodExceptione) {
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(ComponentNamewho, StringownerName, intuserId); // 设置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(ComponentNameadmin, Stringname,
            ComponentNameprofileOwner, PersistableBundleadminExtras, intflags) {
//参数不为空判断
        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 booleanephemeral = (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0;
        final booleandemo = (flags & DevicePolicyManager.MAKE_USER_DEMO) != 0
                && UserManager.isDeviceInDemoMode(mContext);
        final booleanleaveAllSystemAppsEnabled = (flags &LEAVE_ALL_SYSTEM_APPS_ENABLED) != 0;
        final inttargetSdkVersion;

// 创建用户
        UserHandleuser = null;
        synchronized (getLockObject()) {
            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);// 权限检查,只允许DeviceOwner调用

final intcallingUid =mInjector.binderGetCallingUid();
            final longid =mInjector.binderClearCallingIdentity(); //清除调用者的PID UID并保存到id变量中
            try {
targetSdkVersion =mInjector.getPackageManagerInternal().getUidTargetSdkVersion(
callingUid);
// 对设备的存储大小和创建用户数限制进行检查
                DeviceStorageMonitorInternaldeviceStorageMonitorInternal =
                        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;
                    }
                }

intuserInfoFlags = 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的检查
                UserInfouserInfo =mUserManagerInternal.createUserEvenWhenDisallowed(name,
userInfoFlags,disallowedPackages);
                if (userInfo != null) {
user =userInfo.getUserHandle();
                }
            } finally {
mInjector.binderRestoreCallingIdentity(id); //从id变量中恢复调用者的PID UID
            }
        }
// ...
        final intuserHandle =user.getIdentifier();
// 发送用户创建的广播
        final Intentintent = 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 longid =mInjector.binderClearCallingIdentity();
        try {
            final StringadminPkg =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 (RemoteExceptione) {
                // Does not happen, same process
            }
            // 激活admin
            setActiveAdmin(profileOwner, true,userHandle);
            final StringownerName = getProfileOwnerName(Process.myUserHandle().getIdentifier());
// 设置ProfileOwner
            setProfileOwner(profileOwner,ownerName,userHandle);

synchronized (getLockObject()) {
                DevicePolicyDatapolicyData = 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);
            }

returnuser;
        } catch (Throwablere) {
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); // 查询一个应用是否能够在锁定界面显示

3.DO或PO授权后获取设备信息:

3.1.获取设备IMEI(Android10及以上版本)

(1).应用必须动态获取android.permission.READ_PHONE_STATE 权限

(2).应用必须具有DeviceOwner或者ProfileOwner权限。或者由具有这两个权限的应用通过setDelegatedScopes(ComponentName admin,String delegatePackage,List<String> scopes)方法进行授权。scopes需要包含DevicePolicyManager.DELEGATION_CERT_INSTALL

(3).调用TelephonyManager.getImei(int slotIndex)

例:

if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
    DevicePolicyManagerdpm = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
    ArrayList<String> strings = new ArrayList<String>(Arrays.asList("delegation-cert-install"));
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);
}

3.2.获取IMSI,ICCID及电话号码

(1).应用必须动态获取android.permission.READ_PHONE_STATE 权限,且具有android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE权限(该权限需系统应用或者deviceAdmin和ProflieOwner才能使用)

(2).反射调用SubscriptionManager.getActiveSubscriptionInfoList,返回值为List<SubscriptionInfo>内容示例如下:

[{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

DevicePolicyManagerService之DeviceOwner和ProfileOwner相关推荐

  1. DevicePolicyManagerService之DeviceAdmin

    目录 1.DevicePolicyManagerService的初始化 2.DeviceAdmin DevicePolicyManagerService是Android提供的一个可管理和操作设备的系统 ...

  2. Android之解决Gigaset手机不能设置DeviceOwner权限提示already provisioned问题

    客户那里有Gigaset手机,安装我们的产品需要注入DeviceOwner,但是刚恢复默认出厂的Gigaset手机很奇葩,注入权限的提示下面错误,导致不能使用我们的产品 设置DeviceOwner权限 ...

  3. Android DeviceOwner

    1:DeviceAdminReceiver 首先注册deviceAdminReceiver广播接收者. public class MyDeviceAdminReceiver extends Devic ...

  4. Android如何设置为设备拥有者device-owner?

    首先条件为android5.0及以上,执行命令adb shell dpm set-device-owner com.test/com.test.receiver.TestDeviceAdminRece ...

  5. 给Android应用设置DeviceOwner权限遇到的问题及解决方案

    原文作者:岛哥的质量效能笔记 原文链接:https://juejin.cn/post/6995906975477432357 背景 Android手机品牌和型号众多,特别是国产手机系统时常添加各种中国 ...

  6. android手机deviceowner,删除 androidDeviceOwnerWiFiConfiguration

    删除 androidDeviceOwnerWiFiConfigurationDelete androidDeviceOwnerWiFiConfiguration 2021/3/24 本文内容 命名空间 ...

  7. Vivo x9s设置deviceOwner后,无法使用应用分身

    1:排除掉应用分身app被禁用的问题 adb shell pm list package -d(查询被disable掉的package) 2:查看vivo应用分身对应的包名等信息 adb shell ...

  8. 微信小程序入门级实战开发指南

    微信小程序入门级实战开发指南 概述 微信小程序,简称小程序,英文名Mini Program,是一种"不需要下载安装"即可使用的应用(实际上是需要下载安装的,只是整个过程被简化到可以 ...

  9. android权限级别探索(四),Work Profile/Profile Owner的开启与功能

    一.什么是Work Profile   因为Work Profile在体验上与Device Owner和Device admin有很大的差别,所以在讲怎么开启profileOwner之前先讲一下什么是 ...

  10. Octavia 项目加速 OpenStack LBaaS 落地大规模应用场景

    目录 文章目录 目录 OpenStack LBaaS Octavia 软件架构 网络架构 操作对象基本概念 功能实现基本概念 Ocatvia Daemon 列表 部署 Ocatvia 手动方式集成 O ...

最新文章

  1. 硅谷产品实战-总结:14、如何用数据做出产品决定?
  2. Web 2.0技术对SEO的影响
  3. Java程序员必备!Redis面试复习大纲在手面试不慌
  4. 你可以去学python_你是怎么学好Python的?
  5. 你不知道的Node.js性能优化,读了之后水平直线上升
  6. 《进化——我们在互联网上奋斗的故事》一一1.1 靠谱工程师向管理者的转变...
  7. Linux中打包和解压到的方法
  8. 使用Kubernetes和Docker将Spring Boot与MongoDB作为容器部署
  9. 带UpdatePanel页面返回js问题
  10. 一阶电路暂态响应的结果分析。_【2020考研】南京邮电大学813《电路分析》考试大纲...
  11. [转]Error: SQL BPA command line has encountered a problem and needs to close
  12. 《浪潮之巅》吴军:特斯拉自动驾驶堪比中甲水平,全球5G看好华为
  13. 第9章 SportsStorePeta 完成购物车
  14. java request含嵌套_使用 RxJava 进行嵌套串行网络请求的一种方法
  15. ucGUI/emWin 自定义中文字库(汉字字库)
  16. 100以内奇数的平方和
  17. 从HttpClient3迁移到HttpClient4
  18. GAMS系列分享20—GAMS电力系统—目标函数增量线性化
  19. b2b平台和b2b网站一样吗?B2B是什么意思?
  20. CodeFun-UI 设计稿智能生成前端源代码

热门文章

  1. notempty注解属于哪个依赖_@NotEmpty、@NotNull、@NotBlank注解解析
  2. 木瓜移动每日快讯0511:谷歌Chrome引入新隐私功能fenced frame
  3. 【华为云·云筑2020】DevCloud考卷答案
  4. 邮箱大佬告诉你电子邮箱格式如何正确书写
  5. ansiblea基本使用
  6. 电源管理IC的分类及智能变化
  7. 【RDMA】qp数量和RDMA性能(节选)|连接数
  8. Unipus-writing exercise Expository_Text_09
  9. 招商银行软件开发笔试知识汇总
  10. matlab的persistent,MATLAB局部静态变量类型persistent