DevicePolicyManagerService之DeviceOwner和ProfileOwner

目录

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 {
            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激活的状态下有效

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

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

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

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

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

(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 strings = new ArrayList(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内容示例如下:

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

你可能感兴趣的:(Android,#,Framework,framework,android)