精华内容
下载资源
问答
  • 一、准备工作 配置DeviceAdmin ...Google没有提供类似获取设备管理器权限那样的api,所以个人设备的deviceowner权限一般是通过adb shell命令赋予的,而一些大公司是采用批量订购设备,定制room的方式获取DeviceOwner
  • vaScript(@ octokit / core.js)等待octokit.request('GET / repos / {owner} / {repo} / actions / runs / {run_id} / jobs',{owner:'octocat',repo:'hello- world',run_id:42})响应状态:200 OK {“ ...
  •   因为Work Profile在体验上与Device Owner和Device admin有很大的差别,所以在讲怎么开启profileOwner之前先讲一下什么是Work Profile。   ProfileOwner/WorkProfile,是google为了Android在企业中运用推出的...
  • dell笔记本电脑m7510 操作手册 dell笔记本电脑m7510 操作手册 dell笔记本电脑m7510 操作手册 dell笔记本电脑m7510 操作手册 dell笔记本电脑m7510 操作手册 英文版
  • OWNER 是一个简单的 Java 对 Properties 文件的封装库,假设 properties 配置如下: port=80 hostname=foobar.com maxThreads=100 只需要简单的封装: public interface ServerConfig extends Config { int port...
  • Device owner调研

    2020-10-24 01:32:14
    什么是Device owner? Device Owner 是在设备上以管理员身份运行的应用程序. 此应用可以使用 DevicePolicyManager类中的编程方法来控制设备上的配置,安全性和其他应用程序。 可以将Device owner视为具有特殊权限...

    一.什么是Device owner?

    Device Owner 是在设备上以管理员身份运行的应用程序.
     此应用可以使用 DevicePolicyManager类中 的编程方法 来控制设备上的配置,安全性和其他应用程序。 可以将Device owner视为具有特殊权限的Device Admin。
     
     
    Android提供了三种设备管理方案,Device Administration(设备管理员), Profile Owner(配置文件所有者)和 Device Owner(设备所有者)。这三种权限管理策略的能力大小依次增加 为 DeviceAdmin < ProfileOwner < DeviceOwner。 同样的,要将一个应用设置成为这些管理设备,需要的权限也依次增加。应用需要最大的授权才能成为Device Owner,Device Owner具有设备的最高权限.
     
     
    1.DeviceAdmin是Android2.2引入的方案,通过用户授权自己的应用设备管理权限后,可以在代码中修改一些系统设置,主要的功能是围绕锁屏这一块对权限比较“敏感”的区域。Android系统在同一时间可以拥有多个Device Admin程序,并且可以有多个同时处于激活状态。
    由于设备管理员不太适合支持当今的企业要求,因此我们建议客户和合作伙伴从现在开始采用托管设备和工作资料模式来管理其设备。为了支持此过渡并将资源集中于Android当前的管理功能,官方在Android 9.0版本中弃用了用于企业的设备管理员,并在Android 10.0版本中删除了这些功能。Device Administration 在Android9.0(Android Pie)被废弃,Google推荐企业管理使用Profile Owner或Device Owner。
    DeviceAdmin功能有 比如设置锁屏方式、恢复出厂设置、设置密码、强制清除密码,修改密码等操作。
     
     
    2.ProfileOwner 译为配置文件所有者,在Android5.0系统推出。ProfileOwner涵盖了所有DeviceAdmin用户的管理能力,并且额外添加了很多管理权限。Android系统只能设置一个Profile Owner程序,并且该程序在设置为ProfileOwner后不能取消,应用不能卸载,唯一可以取消的途径是恢复出厂设置。
    ProfileOwner 具有功能有: 包含DeviceAdmin的功能 截屏截图\设置组织名\应用授权\设置应用是否可以卸载\静音\设置内容提供者\禁用特定用户\隐藏应用\清除应用限制\开启和禁止来电\挂起应用\获取应用所有权限\安装与卸载证书\锁屏密码重置
     
     
    3.DeviceOwner 译为设备所有者,在Android5.0系统推出。DeviceOwner涵盖了DeviceAdmin用户的所有管理能力,也涵盖了ProfileOwner的所有管理能力,并且额外拥有在设备上创建和移除二级用户以及配置全局设置的能力。您的设备所有者应用可以使用 DevicePolicyManager 类中的方法对托管设备上的配置、安全性和应用进行精细控制。一台设备在同一时间只能有一名活动的设备所有者。 要部署和激活设备所有者,您必须在设备处于未配置状态.
     

     

    二.Device owner的功能

     
    功能有: 包含Device Admin和Profile Owner的功能, 连带有重启设备/获取wifi/设置状态栏/设置系统更新策略/创建切换删除用户/设置全局HTTP代理/蓝牙获取联系人等.
     
    总的来说就是:
    启用或禁用硬件功能,例如相机或指纹传感器
    启用或禁用软件功能,例如锁屏(键盘锁),通知,小部件,可见的应用程序(将它们隐藏或取消隐藏),设备启动时使用的凭据或设备加密
    配置密码策略
    在设备上配置用户帐户
    配置网络参数,CA证书和VPN信息
    擦除设备(恢复出厂设置)或外部存储设备上的内容
    设置全局设置,例如飞行模式,GPS,蓝牙,漫游等。
    切换用户
    清除当前设备所有者
     
     
     

     

    Device Admin, Profile Owner 和 Device Owner的功能区别?

    The Android Device Administrator was introduced back in Android 2.2. It included support for the DevicePolicyManager class, along with the DeviceAdminReceiver and DeviceAdminInfo classes. The Device Owner app is a Device Administrator. A Profile Owner app is also a Device Administrator. But, the Device Owner can perform functions that a Profile Owner cannot. You can think of a Device Owner as a Device Administrator with special privileges. Even the semantics of some normal API methods change for a Device Owner. For example, any activity can call startLockTask(), but it only enables full kiosk mode for the Device Owner.
     
    Android Device Admin 是在Android 2.2中引入的。它包括对DevicePolicyManager类以及DeviceAdminReceiver和DeviceAdminInfo类的支持。Device Owner应用是设备管理员。Profile Owner应用程序也是设备管理员。但是,Device Owner可以执行Profile Owner无法执行的功能。您可以将Device Owner视为具有特殊特权的设备管理员。甚至某些常规API方法的语义对于Device Owner 也会发生变化。例如,任何活动都可以调用startLockTask(),但它仅为设备所有者启用完全信息亭模式。
     
     
     
    A Device Owner and a Profile Owner can perform many of the same functions, and the functionality of both may indeed be provided by a single app (like a Device Policy Controller (DPC) from your EMM provider). Profile Owner functionality is usually utilized on a device that has both work and personal data. The Profile Owner app creates a user profile on the device that separates the work data from personal data. The apps that are installed on the device in the work profile contain the Android for Work “briefcase” badge in order to distinguish those work apps from personal apps. Devices with both personal and work profiles fall into either the BYOD (Bring Your Own Device) or COPE (Corporate Owned, Personally Enabled) device classes.
     
    A Device Owner can perform some functions that a Profile Owner cannot. It can disable Wi-Fi and Bluetooth, wipe device data, configure kiosk applications (whitelist “lock task” packages), and more. In other words, for corporate-liable devices that have no personal data, you want to configure a Device Owner, rather than a Profile Owner. Some apps, like EMM Agents (DPCs), may be written to function as both Device Owner and Profile Owner. See this Google developer information for more details on Profile and Device Owner.
     
    设备所有者和配置文件所有者可以执行许多相同的功能,并且两者的功能确实可以由单个应用程序提供(例如,您的EMM提供程序中的设备策略控制器(DPC))。配置文件所有者功能通常在同时具有工作和个人数据的设备上使用。Profile Owner应用程序在设备上创建一个用户配置文件,以将工作数据与个人数据分开。在工作资料中设备上安装的应用程序包含Android for Work“公文包”徽章,以便将这些工作应用程序与个人应用程序区分开。
     设备所有者可以执行配置文件所有者无法执行的某些功能。它可以禁用Wi-Fi和蓝牙,擦除设备数据,配置信息亭应用程序(白名单“锁定任务”软件包)等。换句话说,对于没有个人数据的企业责任设备,您需要配置设备所有者而不是配置文件所有者。某些应用程序(例如EMM代理(DPC))可能会编写为既充当设备所有者又充当配置文件所有者。有关个人资料和设备所有者的更多详细信息,请参见此Google开发者信息。
     
    什么是设备策略控制器(DPC)?
    设备策略控制器是在Android设备上管理公司策略的应用程序。 它可以实现配置文件所有者,设备所有者或两者。 有时称为设备EMM代理,它是EMM提供程序中的应用程序,对设备实施安全性和使用限制。
     
     

    .创建Device Owner

    1.基本配置

    在res/xml目录下新建device_admin.xml文件;
     
    注册一个广播继承DeviceAdminReceiver;
     
    在清单文件里注册广播;
     
     

    2.激活DeviceOwner的三种方式

        a. 利用NFC功能在手机初始化的时候发送一个DeviceOwner应用到手机上。
     
        b. 利用ADB命令。
        adb shell dpm set-device-owner com.xjli.deviceownerdemo/.MyDeviceOwnerReceiver
     
        c. 在已root设备上进行,先在/data/system/目录下创建一个device_owner.xml文件。
        内容如下 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
        <device-owner package="your owner app packagename" />
        然后重启设备,一定要注意在重启设备之前安装好你的DeviceOwner应用,否则会出现无法启动的BUG
     
     
     

    四.DevicePolicyManager

     
    种设备管理方案 都是调用 DevicePolicyManager 类 从而调用 IDevicePolicyManager .aidl 设备 策略服务的内部 IPC 接口。
     
    获取DevicePolicyManager实例对象
    (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
     
    reboot(ComponentName admin);重启设备
    getWifiMacAddress( ComponentName admin);获取wifi Mac地址
    setStatusBarDisabled(ComponentName admin, boolean disabled);禁用或启用状态栏
    setKeyguardDisabled(ComponentName admin, boolean disabled) 将锁屏模式设置为None,当用户设置了密码时无效
    resetPassword(String password, int flags);修改锁屏密码
    setSystemUpdatePolicy(ComponentName admin, SystemUpdatePolicy policy)  设置系统更新策略
    SystemUpdatePolicy getSystemUpdatePolicy(); 获取系统更新策略
    setGlobalSetting(ComponentName admin, String setting, String value) 设置系统设置中Global相关的属性 如:Settings.BLUETOOTH_ON 蓝牙是否启用/禁用
    setCameraDisabled(@NonNull ComponentName admin, boolean disabled) 停用相机 禁止使用所有设备摄像头
    createUser(@NonNull ComponentName admin, String name) 用户管理
    setUninstallBlocked(@NonNull ComponentName admin, String packageName, boolean uninstallBlocked) 禁止卸载应用
    setScreenCaptureDisabled(@NonNull ComponentName admin, boolean disabled); 禁止截图
    等....
     

     

    五.Device Owner的代码展示

     
    见DeviceOwnerDemo ,参考DeviceAdmin简单实践  http://floatingmuseum.github.io/2016/07/device-admin-practice
     

     
    参考链接:
    Android DeviceOwner 应用的能力  https://blog.csdn.net/visionliao/article/details/84767383
    一键设置 DeviceAdmin/ProfileOwner/DeviceOwner 应用  https://blog.csdn.net/visionliao/article/details/84768035
    Android Device Administration 应用的能力 https://blog.csdn.net/visionliao/article/details/84766876
    Android ProfileOwner 应用的能力 https://blog.csdn.net/visionliao/article/details/84767136
    什么是设备策略控制器(DPC)? https://support.google.com/work/android/answer/6192678?hl=en
    Android极速开发之设备管理器(DevicePolicyManager) https://www.jianshu.com/p/8934d47aed3b
    DeviceOwner设备所有者配置   https://www.jianshu.com/p/5b1a552b5040
     
     
    更多Android系统和应用开发的讨论,可以加入我
     
     
    展开全文
  • 一键设置 DeviceAdmin/ProfileOwner/DeviceOwner 应用

    万次阅读 热门讨论 2018-12-03 15:36:53
    一键设置DeviceOwner 概述 Android提供了三种设备管理方案,Device Administration(设备管理员), ProfileOwner(配置文件所有者)和 DeviceOwner(设备所有者)。这三种管理方案对应三种等级的管理权限,相对的,等级越...

    一键设置 DeviceAdmin/ProfileOwner/DeviceOwner 应用


    概述

    Android提供了三种设备管理方案,Device Administration(设备管理员), ProfileOwner(配置文件所有者)和 DeviceOwner(设备所有者)。这三种管理方案对应三种等级的管理权限,相对的,等级越高所拥有的管理权限越高,面临的风险也对大,所以,要将一个应用设置成为这些管理设备,也需要不同的权限等级。

    设置 Device Administration

    要设置一个DeviceAdmin 所需要权限相对来说是最小的,Android系统提供了一种方案:

    Intent intent = new Intent(
    	DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
    intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
    	mComponentName);
    intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "提示文字");
    startActivityForResult(intent, 1);
    

    该方法将激活DeviceAdmin的动作委托给系统Settings,有界面提示用户是否激活/停用/卸载一个设备管理应用。这种方案其实是一种动态权限,由用户决定是否启用设备管理。在特殊行业中,有些操作不应该让用户决定,由管理平台在后台一键设置。
    如果一个应用的进程所属system,那么就和系统Settings具有相同的权限,我们可以在系统中添加一个这样的程序,用来一键设置自己的DeviceAdmin程序。

    /**
     * 设置DeviceAdmin
     * packageName: 应用程序包名
     * policyReceiver: 继承了DeviceAdminReceiver的类名
     */
    public static void setActiveAdmin(String packageName, String policyReceiver) {
        // 1. 将包名和类名转换为ComponentName
        ComponentName component = new ComponentName(packageName, policyReceiver);
        // 2. 通过ComponentName获取ActivityInfo,如果为空,说明参数传递有误,系统中根本不存在这个应用,直接返回
        ActivityInfo ai = null;
        try {
            ai = iPackageManager.getReceiverInfo(component,
                    PackageManager.GET_META_DATA |
                    PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
                    PackageManager.MATCH_DIRECT_BOOT_UNAWARE |
                    PackageManager.MATCH_DIRECT_BOOT_AWARE, getMyUserId());
        } catch (RemoteException e) {
            debug("Unable to load component: " + component);
        }
        // 3. 调用DevicePolicyManager的现有方法setActiveAdmin(系统级应用有权限)
        mDevicePolicyManager.setActiveAdmin(component, true /*refreshing*/, mUserId);
    }
    
    /**
     * 通过包名判断一个程序是否为激活的DeviceAdmin
     * packageName: 应用程序包名
     * return
     *      true: 是
     *      false: 不是
     */
    public static boolean packageHasActiveAdmins(String packageName) {
        // packageHasActiveAdmins方法标记为@hide,只有系统应用可以调用
        DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
        return devicePolicyManager.packageHasActiveAdmins(packageName);
    }
    

    了解更多DeviceAdmin的权限以及API的使用详情,请转到往期文章Android Device Administration 应用的能力

    设置 ProfileOwner

    之前介绍过,ProfileOwner 在国内可能不适用(Android DevicePolicyManager 设备管理中已做出说明),所以设置一个ProfileOwner程序有几条途径不做深入讲解,这里只给出一个方案:
    属于system进程的系统应用,有设置ProfileOwner程序的能力,可以在系统中实现一个系统应用,暴露一个一键设置ProfileOwner的接口:

    /**
     * 设置ProfileOwner
     * packageName: 应用程序包名
     * policyReceiver: 继承了DeviceAdminReceiver的类
     * deviceUserName: 为ProfileOwner设置一个名字,如不设置传null
     * return
     *      true:  设置成功
     *      false: 设置失败
     * (限于篇幅这里只给出了关键代码,一部分逻辑、变量代码省略)
     */
    public static boolean setProfileOwner(String packageName, String policyReceiver, String deviceUserName) {
        // 1. 将包名和类名转换为ComponentName
        ComponentName component = new ComponentName(packageName, policyReceiver);
        // 2. 通过ComponentName获取ActivityInfo,如果为空,说明参数传递有误,系统中根本不存在这个应用,直接返回
        ActivityInfo ai = null;
        try {
            ai = iPackageManager.getReceiverInfo(component,
                    PackageManager.GET_META_DATA |
                    PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
                    PackageManager.MATCH_DIRECT_BOOT_UNAWARE |
                    PackageManager.MATCH_DIRECT_BOOT_AWARE, getMyUserId());
        } catch (RemoteException e) {
            debug("Unable to load component: " + component);
        }
        // 3. 调用DevicePolicyManager的现有方法setActiveAdmin(系统级应用有权限)
        mDevicePolicyManager.setActiveAdmin(component, true /*refreshing*/, mUserId);
        // 4. 设置setProfileOwner
        try {
            result = mDevicePolicyManager.setProfileOwner(component, deviceUserName, mUserId);
            debug("set package " + component + " as profile owner result: " + result);
        } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
            debug("Error: setProfileOwner failed to " + component.flattenToShortString() + " Error Info: " + e);
            // 如果设置ProfileOwner异常,则将设置的DeviceAdmin程序也一并取消
            try {
                mDevicePolicyManager.removeActiveAdmin(component, mUserId);
            } catch (RemoteException e2) {
                debug("Error: removeActiveAdmin failed to " + component.toString() + " Error Info: " + e2);
            }
        }
        if (result) {
            try {
                mDevicePolicyManager.setUserProvisioningState(DevicePolicyManager.STATE_USER_SETUP_FINALIZED, mUserId);
            } catch (RemoteException e) {
                debug("Error: setUserProvisioningState failed to " + component.toString() + " Error Info: " + e);
            }
            debug("Success: Active admin and profile owner set to " + component.toShortString() + " for user " + mUserId);
        }
    }
    

    当一个应用成为了ProfileOwner应用,它就拥有了所有的ProfileOwner的能力。了解更多ProfileOwner的权限以及API的使用详情,请转至往期文章Android ProfileOwner 应用的能力

    设置 DeviceOwner

    DeviceOwner可以使一个第三方应用程序拥有系统最高管理权限,面临的风险也是最大的。 要设置一个DeviceOwner程序, 需要很高的权限,系统提供两种方式:

    adb shell

    msm8953_64:/ # 
    msm8953_64:/ # dpm set-device-owner --name Test com.action.deviceadmin/.DPMTestReceiver
    -----------------------mName Test
    mComponent: {com.action.deviceadmin/com.action.deviceadmin.DPMTestReceiver}, mName: Test, mUserId: 0
    Success: Device owner set to package ComponentInfo{com.action.deviceadmin/com.action.deviceadmin.DPMTestReceiver}
    Active admin set to component {com.action.deviceadmin/com.action.deviceadmin.DPMTestReceiver}
    msm8953_64:/ # 
    

    通过dpm命令设置一个DeviceOwner。

    使用NFC方式

    以下内容摘录自 https://mp.weixin.qq.com/s?__biz=MzAxMTE3MDkyMA==&mid=506926154&idx=1&sn=55ea2cfc894db74dcf296233a3e74a6f#rd 的文章内容。


    用NFC传输的方式来使一个App成为DeviceOwner(设备所有者),我们需要两部手机。

    首先,两台设备都要支持NFC并激活了NFC,并且激活了Android Beam功能(在设置里的NFC and payment里)。

    第一台设备(Mobile A)是要在其上安装App,并使这个App成为Device Owner的。这个App可以是任意的一个App(我们的例子中是一个叫作Kiosk Mode Demo的App。

    第二台设备(Mobile B)是要provision那台Mobile A的(使Mobile A上的App成为Device Owner),算是数据传输方/服务提供方。Mobile B上安装了我们的SetDeviceOwner这个App。

    然后,在那个SetDeviceOwner的App里的源码中,比较关键的设置是下面几个:
    EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME

    对应要成为Device Owner的App的完整包名,例如:com.enmingx.test

    EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LOCATION

    对应要成为Device Owner的App的下载URL,例如:http://www.dropbox.com/xxx

    EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM

    对应要成为Device Owner的App的checksum(校验码),要计算校验码,可以用adb命令:

    cat MY_APP.apk | openssl dgst -binary -sha1 | openssl base64 | tr ‘+/’ ‘-_’ | tr -d ‘=’

    EXTRA_PROVISIONING_WIFI_SSID

    对应用于下载要成为Device Owner的App的WiFi的名称

    EXTRA_PROVISIONING_WIFI_SECURITY_TYPE

    对应用于下载要成为Device Owner的App的安全类型,比如WPA或WPA2

    最后,在那个SetDeviceOwner的App源码里,把这些数据都“打包”到一个NFC Bundle中,用NFC技术来传输到另一台手机。

    你应该知道如何使用NFC来进行数据传输吧:

    让两个手机足够接近,背靠背,然后会听到清脆的一声“叮”,显示"Touch to beam",然后你轻触作为传输方的那台设备的屏幕,就开始传输了。

    为了成功使一台设备上的App成为Device Owner,这台设备必须从来没被配置过(当然更不能被Root过),也不能被设置过Device Owner或Profile Owner。如果已经配置过了,可以恢复出场设置。

    开始操作:

    1. 对Mobile A恢复出厂设置(Factory Reset),一般在Settings(设置)里就可以选择(比较文明的方式);也可以用比较粗暴的方式,按键的方式(一般是同时按住 音量向上键+Home键+电源键 几秒,然后会出现选项,可以选择)。

    2. 当Mobile A的恢复出厂设置结束后,Mobile A会出现初始设置的界面。此时,Mobile A就是处于unprovisioned(还没被设置)的状态。

    3. 在Mobile B上,安装我们的SetDeviceOwner这个App,也就是要使其他设备的App成为Device Owner的,术语叫做“Device owner provisioning”。

    4. 在Mobile B上开启SetDeviceOwner这个App,点击“Generate checksum”按钮,会生成checksum(校验码)。

    5. Mobile A处于初始配置状态,两台设备的屏幕都是打开的。将两台设备(Mobile A和Mobile B)背靠背,足够近,直到听到清脆的“叮”的声响,然后在Mobile B上轻触屏幕,即开始从Mobile B向Mobile A进行NFC的数据传输。

    6. 当NFC传输完成后(一般瞬间就完成了),Mobile A上会显示配置Device Owner的界面,标题貌似是Set up your profile(记不清了…),点击Set up按钮之后会问你要不要Encrypt设备(对数据加密),点击“是”(OK),然后选择快速Encrypt还是对所有数据Encrypt(加密所有数据会很慢),一般都选Fast Encryption就好。然后开始对手机的数据加密,不要问为什么,就是必须要这步。

    7. 加密完成后,Mobile A会重启。然后,因为之前我们传输过去的数据里面指定了WiFi的SSID和密码,而且也指定了那个要成为Device Owner的App的下载链接(URL),因此,会显示让你配置选择WiFi,请选择你之前指定的那个WiFi,并连接。

    8. 一旦WiFi成功连接上Internet,就会开始下载指定的App。下载完成后会开始安装,然后会使这个App成为Device Owner。

    9. 如果你看到一个Toast跳出来说:Device Owner enabled,那么就OK了。恭喜,你的App已经成为了Mobile A的Device Owner了。


    可以看到,按照官方的方法设置一个DeviceOwner程序,要么得拥有Shell这种级别的权限,要么就使用NFC传输的这种繁杂的方式。对于行业需求,NFC的方式显然不可行。
    跟踪dpm的源码,设置DeviceOwner 的方法最终调用到DevicePolicyManagerService.java中:

    @Override
    public boolean setDeviceOwner(ComponentName admin, String ownerName, int userId) {
        if (!mHasFeature) {
            return false;
        }
        if (admin == null
                || !isPackageInstalledForUser(admin.getPackageName(), userId)) {
                throw new IllegalArgumentException("Invalid component " + admin
                    + " for device owner");
        }
        final boolean hasIncompatibleAccountsOrNonAdb =
                hasIncompatibleAccountsOrNonAdbNoLock(userId, admin);
        synchronized (this) {
            enforceCanSetDeviceOwnerLocked(admin, userId, hasIncompatibleAccountsOrNonAdb);
            
            ...
            省略大量其它代码
            ...
        }
    }
    

    setDeviceOwner方法在正在设置DeviceOwenr之前会做很多权限检查,以保证安全性,只要调用方法enforceCanSetDeviceOwnerLockedcheckDeviceOwnerProvisioningPreConditionLocked

    enforceCanSetDeviceOwnerLocked

    private void enforceCanSetDeviceOwnerLocked(@Nullable ComponentName owner, int userId,
                boolean hasIncompatibleAccountsOrNonAdb) {
            if (!isAdb()) {
                enforceCanManageProfileAndDeviceOwners();
            }
    
            final int code = checkDeviceOwnerProvisioningPreConditionLocked(
                    owner, userId, isAdb(), hasIncompatibleAccountsOrNonAdb);
            switch (code) {
                case CODE_OK:
                    return;
                case CODE_HAS_DEVICE_OWNER:
                    throw new IllegalStateException(
                            "Trying to set the device owner, but device owner is already set.");
                case CODE_USER_HAS_PROFILE_OWNER:
                    throw new IllegalStateException("Trying to set the device owner, but the user "
                            + "already has a profile owner.");
                case CODE_USER_NOT_RUNNING:
                    throw new IllegalStateException("User not running: " + userId);
                case CODE_NOT_SYSTEM_USER:
                    throw new IllegalStateException("User is not system user");
                case CODE_USER_SETUP_COMPLETED:
                    throw new IllegalStateException(
                            "Cannot set the device owner if the device is already set-up");
                case CODE_NONSYSTEM_USER_EXISTS:
                    throw new IllegalStateException("Not allowed to set the device owner because there "
                            + "are already several users on the device");
                case CODE_ACCOUNTS_NOT_EMPTY:
                    throw new IllegalStateException("Not allowed to set the device owner because there "
                            + "are already some accounts on the device");
                case CODE_HAS_PAIRED:
                    throw new IllegalStateException("Not allowed to set the device owner because this "
                            + "device has already paired");
                default:
                    throw new IllegalStateException("Unexpected @ProvisioningPreCondition " + code);
            }
        }
    

    checkDeviceOwnerProvisioningPreConditionLocked

    private int checkDeviceOwnerProvisioningPreConditionLocked(@Nullable ComponentName owner,
                int deviceOwnerUserId, boolean isAdb, boolean hasIncompatibleAccountsOrNonAdb) {
            if (mOwners.hasDeviceOwner()) {
                return CODE_HAS_DEVICE_OWNER;
            }
            if (mOwners.hasProfileOwner(deviceOwnerUserId)) {
                return CODE_USER_HAS_PROFILE_OWNER;
            }
            if (!mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
                return CODE_USER_NOT_RUNNING;
            }
            if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
                return CODE_HAS_PAIRED;
            }
            if (isAdb) {
                // if shell command runs after user setup completed check device status. Otherwise, OK.
                if (mIsWatch || hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
                    if (!mInjector.userManagerIsSplitSystemUser()) {
                        if (mUserManager.getUserCount() > 1) {
                            return CODE_NONSYSTEM_USER_EXISTS;
                        }
                        if (hasIncompatibleAccountsOrNonAdb) {
                            return CODE_ACCOUNTS_NOT_EMPTY;
                        }
                    } else {
                        // STOPSHIP Do proper check in split user mode
                    }
                }
                return CODE_OK;
            } else {
                if (!mInjector.userManagerIsSplitSystemUser()) {
                    // In non-split user mode, DO has to be user 0
                    if (deviceOwnerUserId != UserHandle.USER_SYSTEM) {
                        return CODE_NOT_SYSTEM_USER;
                    }
                    // In non-split user mode, only provision DO before setup wizard completes
                    if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
                        return CODE_USER_SETUP_COMPLETED;
                    }
                } else {
                    // STOPSHIP Do proper check in split user mode
                }
                return CODE_OK;
            }
        }
    

    细看以上两个方法的权限检测,很多权限在检测之前会先判断 isAdb,如果是adb,很多权限都会跳过。让我们看看这个isAdb 是怎么来的。

    private boolean isAdb() {
        final int callingUid = mInjector.binderGetCallingUid();
    
        return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
        }
    

    判断流程非常简单,就是获得调用方进程的Uid,如果是SHELL_UID 或者 ROOT_UID,那么就认为有设置DeviceOwner 的权限,跳过权限检查,直接设置。

    **
     * Defines the root UID.
     * @hide
     */
    public static final int ROOT_UID = 0;
    
    /**
     * Defines the UID/GID under which system code runs.
     */
    public static final int SYSTEM_UID = 1000;
    
    /**
     * Defines the UID/GID under which the telephony code runs.
     */
    public static final int PHONE_UID = 1001;
    
    /**
     * Defines the UID/GID for the user shell.
     * @hide
     */
    public static final int SHELL_UID = 2000;
    
    

    以上是系统中定义的各大内部专属进程的UID值。属于system进程的应用的UID值为1000,没有权限设置DeviceOwner。而Android系统中设置DeviceOwner 的入口也只有这里。
    要实现一键设置DeviceOwner程序的功能,只能修改DevicePolicyManagerService 的代码。我们可以制定一个方案,既然 SHELL 和 ROOT进程能够设置DeviceOwner,那么我们添加的系统进程也可以“冒充SHELL进程”, 只需要添加如下几行代码即可:

    private boolean isAdb() {
        final int callingUid = mInjector.binderGetCallingUid();
        
        // 获取调用放的进程id -- pid
        final int callingPid = mInjector.binderGetCallingPid();
        
        return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID || fixedProcess(callingPid);
    }
    

    fixedProcess(callingPid) 方法比较 我们自定义的系统进程的PID 和调用方的PID是否一致,如果一致则认为有权限设置DeviceOwner,也即是说,只有ROOT、SHEL 和 自定义系统进程 拥有设置DeviceOwner 的权限。应用进程的PID是系统生成的,不同的应用程序进程ID不可能重复,同一个应用被杀死后再开起来,进程ID也会不同,系统会以递增的形式分配进程ID。所以不用担心该ID被冒名顶替。fixedProcess方法会取得自定义系统进程事先保存好的PID。

    添加了上述规避权限的流程,接下来只需要在自定义系统进程中添加一个设置DeviceOwner的接口即可:

    /**
     * 设置DeviceOwner
     * packageName: 应用程序包名
     * policyReceiver: 继承了DeviceAdminReceiver的类
     * deviceUserName: 为DeviceOwner设置一个名字,如不设置传null
     * return
     *      true:  设置成功
     *      false: 设置失败
     * (限于篇幅这里只给出了关键代码,一部分逻辑、变量代码省略)
     */
    public static boolean setDeviceOwner(String packageName, String policyReceiver, String deviceUserName) {
         // 1. 保存本应用的进程号,在设置DeviceOwner时的权限检测中取出,视为Shell、Root。
         saveMdmPid(android.os.Process.myPid());
         // 2. 将包名和类名转换为ComponentName
        ComponentName component = new ComponentName(packageName, policyReceiver);
        // 3. 通过ComponentName获取ActivityInfo,如果为空,说明参数传递有误,系统中根本不存在这个应用,直接返回
        ActivityInfo ai = null;
        try {
            ai = iPackageManager.getReceiverInfo(component,
                    PackageManager.GET_META_DATA |
                    PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
                    PackageManager.MATCH_DIRECT_BOOT_UNAWARE |
                    PackageManager.MATCH_DIRECT_BOOT_AWARE, getMyUserId());
        } catch (RemoteException e) {
            debug("Unable to load component: " + component);
        }
        // 4. 调用DevicePolicyManager的现有方法setActiveAdmin(需要系统级应用有权限)
        mDevicePolicyManager.setActiveAdmin(component, true /*refreshing*/, mUserId);
        // 5. 调用DevicePolicyManager的setDeviceOwner接口
        try {
            result = mDevicePolicyManager.setDeviceOwner(component, deviceUserName, mUserId);
            debug("set package " + component + " as device owner result: " + result);
        } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
            debug("Error: setDeviceOwner failed to " + component.flattenToShortString() + " Error Info: " + e);
            // Need to remove the admin that we just added.
            try {
                mDevicePolicyManager.removeActiveAdmin(component, mUserId);
            } catch (RemoteException e2) {
                debug("Error: removeActiveAdmin failed to " + component.toString() + " Error Info: " + e2);
            }
        }
        if (result) {
            try {
                mDevicePolicyManager.setUserProvisioningState(DevicePolicyManager.STATE_USER_SETUP_FINALIZED, mUserId);
            } catch (RemoteException e) {
                debug("Error: setUserProvisioningState failed to " + component.toString() + " Error Info: " + e);
            }
            debug("Success: Device owner set to package " + component);
            debug("Active admin set to component " + component.toShortString());
        }
    }
    

    如此,一键设置DeviceOwner 应用的接口就实现了。

    对于一个应用程序来说,成为DeviceOwner应用即拥有了系统最高软件管理权限。了解更多DeviceOwner的权限以及API的使用详情,请回顾往期博客Android DeviceOwner 应用的能力


    上一篇 Android DeviceOwner 应用的能力
    下一篇 微信小程序入门级实战开发指南
    展开全文
  • OWNER

    千次阅读 2018-07-15 21:06:52
    Owner 概述 主人公的精神 团队中的每一个人都要把自己当做集体中的一员,任务不是我们为了别人而去完成的,是为了我们自己,我们是一个集体,一个整体,我们每个人的所作都会影响到集体的利益 其他 记得有...

    Owner


    概述

    • 主人公的精神
    • 团队中的每一个人都要把自己当做集体中的一员,任务不是我们为了别人而去完成的,是为了我们自己,我们是一个集体,一个整体,我们每个人的所作都会影响到集体的利益

    其他

    记得有这样一则寓言,洞房花烛夜新娘对新郎说,看啊,老鼠在吃你家的大米呢,只是说而没有任何其他动作;第二天,新娘又看到了老鼠在吃大米,此时她大叫老鼠你怎么可以吃我们家的大米,拿起扫帚去赶走老鼠

    • 这就是明显的区别,每个人都要把任务当做自己分内的事情,而不是为了其他人而去完成的
    展开全文
  • LVDS Owner Manual 2008 中英文版本 前面是中文 后面是英文 比较全
  • Android device owner简述

    千次阅读 2018-08-29 15:41:50
    一 、设置device owner命令: adb shell dpm set-device-owner 'packagename/ReceiverClass' dpm主要是和DevicePolicyManage进行交互,通过用户授权应用设备管理权限后,可以在代码修改很多系统设置。 激活命令: ...

    一 、设置device owner命令:

    adb shell dpm set-device-owner 'packagename/ReceiverClass'


    dpm主要是和DevicePolicyManage进行交互,通过用户授权应用设备管理权限后,可以在代码修改很多系统设置。

    激活命令:

    DevicePolicyManager.setActiveAdmin

    源码路径frameworks/base/core/java/android/app/admin/DevicePolicyManager.java,代码如下:

        /**
         * @hide
         */
        public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing,
                int userHandle) {
            if (mService != null) {
                try {
                    mService.setActiveAdmin(policyReceiver, refreshing, userHandle);
                } catch (RemoteException e) {
                    Log.w(TAG, "Failed talking with device policy service", e);
                }
            }
        }
    

     这里的setActiveAdmin调用的是DevicePolicyManagerService中的setActiveAdmin

    DevicePolicyManagerService中setActiveAdmin实现代码如下:

     /**
         * @param adminReceiver The admin to add
         * @param refreshing true = update an active admin, no error
         */
        @Override
        public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle) {
            if (!mHasFeature) {
                return;
            }
            setActiveAdmin(adminReceiver, refreshing, userHandle, null);    //这里调用的是私有方法setActiveAdmin
        }
     
     private void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle,
                Bundle onEnableData) {
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);    //权限检查,这里检查的是用户是否有android.Manifest.permission.MANAGE_DEVICE_ADMINS权限,这个权限是需要签名权限或者priv-app下的应用才能使用
            enforceFullCrossUsersPermission(userHandle);    //权限检查,这里检查的是不同用户之间的权限
     
            DevicePolicyData policy = getUserData(userHandle);    //获取当前用户的DevicePolicyData
            DeviceAdminInfo info = findAdmin(adminReceiver, userHandle,
                    /* throwForMissionPermission= */ true);    //获取当前用户的ComponentName获取DeviceAdminInfo
            if (info == null) {
                throw new IllegalArgumentException("Bad admin: " + adminReceiver);
            }
            if (!info.getActivityInfo().applicationInfo.isInternal()) {
                throw new IllegalArgumentException("Only apps in internal storage can be active admin: "
                        + adminReceiver);
            }
            synchronized (this) {
                long ident = mInjector.binderClearCallingIdentity();
                try {
                    final ActiveAdmin existingAdmin
                            = getActiveAdminUncheckedLocked(adminReceiver, userHandle);    //取出系统当前默认的设备管理器
                    if (!refreshing && existingAdmin != null) {
                        throw new IllegalArgumentException("Admin is already added");    //如果refreshing为false,并且不存在默认设备管理器,直接报错~
                    }
                    if (policy.mRemovingAdmins.contains(adminReceiver)) {    //如果设置当前用户DevicePolicyData中已经移除过的设备管理器,直接报错
                        throw new IllegalArgumentException(
                                "Trying to set an admin which is being removed");
                    }
                    ActiveAdmin newAdmin = new ActiveAdmin(info, /* parent */ false);    //新创建一个设备管理器
                    newAdmin.testOnlyAdmin =
                            (existingAdmin != null) ? existingAdmin.testOnlyAdmin
                                    : isPackageTestOnly(adminReceiver.getPackageName(), userHandle);
                    policy.mAdminMap.put(adminReceiver, newAdmin);    //把componentName和ActiveAdmin放到当前用户的DevicePolicyData的ArrayMap中
                    int replaceIndex = -1;
                    final int N = policy.mAdminList.size();    //获取当前DevicePolicyData中的mAdminList的大小
                    for (int i=0; i < N; i++) {
                        ActiveAdmin oldAdmin = policy.mAdminList.get(i);
                        if (oldAdmin.info.getComponent().equals(adminReceiver)) {    //找到默认设备管理器的位置,并将位置标记
                            replaceIndex = i;
                            break;
                        }
                    }
                    if (replaceIndex == -1) {
                        policy.mAdminList.add(newAdmin);    //如果替换位置没有找到,添加新的AdminActive到mAdminList中
                        enableIfNecessary(info.getPackageName(), userHandle);
                    } else {
                        policy.mAdminList.set(replaceIndex, newAdmin);    //如果替换位置已经找到,就将当前的ActiveAdmin插入到该位置,替换为新的默认设备管理器
                    }
                    saveSettingsLocked(userHandle);    //保存当前用户的设置
                    sendAdminCommandLocked(newAdmin,     DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
                            onEnableData, null);    //发送通知给新的默认设备管理器
                } finally {
                    mInjector.binderRestoreCallingIdentity(ident);
                }
            }
        }
     
    

    设置设备权限命令:

    DevicePolicyManager.setDeviceOwner

    源码路径frameworks/base/core/java/android/app/admin/DevicePolicyManager.java,代码如下:

        /**
         * @hide
         * Sets the given package as the device owner. The package must already be installed. There
         * must not already be a device owner.
         * Only apps with the MANAGE_PROFILE_AND_DEVICE_OWNERS permission and the shell uid can call
         * this method.
         * Calling this after the setup phase of the primary user has completed is allowed only if
         * the caller is the shell uid, and there are no additional users and no accounts.
         * @param packageName the package name of the application to be registered as the device owner.
         * @param ownerName the human readable name of the institution that owns this device.
         * @return whether the package was successfully registered as the device owner.
         * @throws IllegalArgumentException if the package name is null or invalid
         * @throws IllegalStateException If the preconditions mentioned are not met.
         */
        public boolean setDeviceOwner(String packageName, String ownerName)
                throws IllegalArgumentException, IllegalStateException {
            if (mService != null) {
                try {
                    return mService.setDeviceOwner(packageName, ownerName);
                } catch (RemoteException re) {
                    Log.w(TAG, "Failed to set device owner");
                }
            }
            return false;
        }
    

     这里的setDeviceOwner调用的是DevicePolicyManagerService中的setDeviceOwner

    DevicePolicyManagerService中setDeviceOwner实现代码如下:

     @Override
        public boolean setDeviceOwner(String packageName, String ownerName) {
            if (!mHasFeature) {
                return false;
            }
            if (packageName == null
                    || !DeviceOwner.isInstalled(packageName, mContext.getPackageManager())) {
                throw new IllegalArgumentException("Invalid package name " + packageName
                        + " for device owner");
            }
            synchronized (this) {
                enforceCanSetDeviceOwner();
    
                // Shutting down backup manager service permanently.
                long ident = Binder.clearCallingIdentity();
                try {
                    IBackupManager ibm = IBackupManager.Stub.asInterface(
                            ServiceManager.getService(Context.BACKUP_SERVICE));
                    ibm.setBackupServiceActive(UserHandle.USER_OWNER, false);
                } catch (RemoteException e) {
                    throw new IllegalStateException("Failed deactivating backup service.", e);
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
    
                if (mDeviceOwner == null) {
                    // Device owner is not set and does not exist, set it.
                    mDeviceOwner = DeviceOwner.createWithDeviceOwner(packageName, ownerName);  //如果现在没有设置默认设备管理器,就新建一个
                } else {
                    // Device owner state already exists, update it.
                    mDeviceOwner.setDeviceOwner(packageName, ownerName);    //如果已经存在,就更新一下
                }
                mDeviceOwner.writeOwnerFile();
                updateDeviceOwnerLocked();    //更新并锁定新的DeviceOwner
                Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED);
    
                ident = Binder.clearCallingIdentity();
                try {
                    mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
                return true;
            }
        }

    文件权限:

    DevicePolicyManager.setProfileOwner 

    源码路径frameworks/base/core/java/android/app/admin/DevicePolicyManager.java,代码如下:

        /**
         * @hide
         * @deprecated Use #ACTION_SET_PROFILE_OWNER
         * Sets the given component as an active admin and registers the package as the profile
         * owner for this user. The package must already be installed and there shouldn't be
         * an existing profile owner registered for this user. Also, this method must be called
         * before the user setup has been completed.
         * <p>
         * This method can only be called by system apps that hold MANAGE_USERS permission and
         * MANAGE_DEVICE_ADMINS permission.
         * @param admin The component to register as an active admin and profile owner.
         * @param ownerName The user-visible name of the entity that is managing this user.
         * @return whether the admin was successfully registered as the profile owner.
         * @throws IllegalArgumentException if packageName is null, the package isn't installed, or
         *         the user has already been set up.
         */
        @SystemApi
       
        public boolean setProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName,
                int userHandle) throws IllegalArgumentException {
            if (admin == null) {
                throw new NullPointerException("admin cannot be null");
            }
            if (mService != null) {
                try {
                    if (ownerName == null) {
                        ownerName = "";
                    }
                    return mService.setProfileOwner(admin, ownerName, userHandle);
                } catch (RemoteException re) {
                    Log.w(TAG, "Failed to set profile owner", re);
                    throw new IllegalArgumentException("Couldn't set profile owner.", re);
                }
            }
            return false;
        }
    

     这里的setProfileOwner 调用的是DevicePolicyManagerService中的setProfileOwner 

    DevicePolicyManagerService中setProfileOwner 实现代码如下:

     @Override
        public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) {
            if (!mHasFeature) {
                return false;
            }
            if (who == null
                    || !DeviceOwner.isInstalledForUser(who.getPackageName(), userHandle)) {
                throw new IllegalArgumentException("Component " + who
                        + " not installed for userId:" + userHandle);
            }
            synchronized (this) {
                enforceCanSetProfileOwner(userHandle);
                if (mDeviceOwner == null) {
                    // Device owner state does not exist, create it.
                    mDeviceOwner = DeviceOwner.createWithProfileOwner(who, ownerName,
                            userHandle);
                } else {
                    // Device owner state already exists, update it.
                    mDeviceOwner.setProfileOwner(who, ownerName, userHandle);
                }
                mDeviceOwner.writeOwnerFile();
                return true;
            }
        }

     这些命令都是DevicePolicyManager隐藏的api,三方应用没有权限进行调用的.

    对adb shell中dpm命令进行处理的是Dpm,路径为framework/base/cmds/dpm/src/com/android/commands/dpm/Dpm.java
    android Dpm源码如下:

    /*
     * Copyright (C) 2014 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.android.commands.dpm;
    
    import android.app.admin.IDevicePolicyManager;
    import android.content.ComponentName;
    import android.content.Context;
    import android.os.RemoteException;
    import android.os.ServiceManager;
    import android.os.UserHandle;
    
    import com.android.internal.os.BaseCommand;
    
    import java.io.PrintStream;
    
    public final class Dpm extends BaseCommand {
    
        /**
         * Command-line entry point.
         *
         * @param args The command-line arguments
         */
        public static void main(String[] args) {
          (new Dpm()).run(args);
        }
    
        private static final String COMMAND_SET_ACTIVE_ADMIN = "set-active-admin";
        private static final String COMMAND_SET_DEVICE_OWNER = "set-device-owner";
        private static final String COMMAND_SET_PROFILE_OWNER = "set-profile-owner";
    
        private IDevicePolicyManager mDevicePolicyManager;
        private int mUserId = UserHandle.USER_OWNER;
        private ComponentName mComponent = null;
    
        @Override
        public void onShowUsage(PrintStream out) {
            out.println(
                    "usage: dpm [subcommand] [options]\n" +
                    "usage: dpm set-active-admin [ --user <USER_ID> ] <COMPONENT>\n" +
                    "usage: dpm set-device-owner <COMPONENT>\n" +
                    "usage: dpm set-profile-owner [ --user <USER_ID> ] <COMPONENT>\n" +
                    "\n" +
                    "dpm set-active-admin: Sets the given component as active admin" +
                    " for an existing user.\n" +
                    "\n" +
                    "dpm set-device-owner: Sets the given component as active admin, and its\n" +
                    "  package as device owner.\n" +
                    "\n" +
                    "dpm set-profile-owner: Sets the given component as active admin and profile" +
                    "  owner for an existing user.\n");
        }
    
        @Override
        public void onRun() throws Exception {
            mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface(
                    ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
            if (mDevicePolicyManager == null) {
                showError("Error: Could not access the Device Policy Manager. Is the system running?");
                return;
            }
    
            String command = nextArgRequired();
            switch (command) {
                case COMMAND_SET_ACTIVE_ADMIN:
                    runSetActiveAdmin();
                    break;
                case COMMAND_SET_DEVICE_OWNER:
                    runSetDeviceOwner();
                    break;
                case COMMAND_SET_PROFILE_OWNER:
                    runSetProfileOwner();
                    break;
                default:
                    throw new IllegalArgumentException ("unknown command '" + command + "'");
            }
        }
    
        private void parseArgs(boolean canHaveUser) {
            String nextArg = nextArgRequired();
            if (canHaveUser && "--user".equals(nextArg)) {
                mUserId = parseInt(nextArgRequired());
                nextArg = nextArgRequired();
            }
            mComponent = parseComponentName(nextArg);
        }
    
        private void runSetActiveAdmin() throws RemoteException {
            parseArgs(true);
            mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId);
    
            System.out.println("Success: Active admin set to component " + mComponent.toShortString());
        }
    
        private void runSetDeviceOwner() throws RemoteException {
            ComponentName component = parseComponentName(nextArgRequired());
            mDevicePolicyManager.setActiveAdmin(component, true /*refreshing*/, UserHandle.USER_OWNER);
    
            String packageName = component.getPackageName();
            try {
                if (!mDevicePolicyManager.setDeviceOwner(packageName, null /*ownerName*/)) {
                    throw new RuntimeException(
                            "Can't set package " + packageName + " as device owner.");
                }
            } catch (Exception e) {
                // Need to remove the admin that we just added.
                mDevicePolicyManager.removeActiveAdmin(component, UserHandle.USER_OWNER);
                throw e;
            }
            System.out.println("Success: Device owner set to package " + packageName);
            System.out.println("Active admin set to component " + component.toShortString());
        }
    
        private void runSetProfileOwner() throws RemoteException {
            parseArgs(true);
            mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId);
    
            try {
                if (!mDevicePolicyManager.setProfileOwner(mComponent, "" /*ownerName*/, mUserId)) {
                    throw new RuntimeException("Can't set component " + mComponent.toShortString() +
                            " as profile owner for user " + mUserId);
                }
            } catch (Exception e) {
                // Need to remove the admin that we just added.
                mDevicePolicyManager.removeActiveAdmin(mComponent, mUserId);
                throw e;
            }
            System.out.println("Success: Active admin and profile owner set to "
                    + mComponent.toShortString() + " for user " + mUserId);
        }
    
        private ComponentName parseComponentName(String component) {
            ComponentName cn = ComponentName.unflattenFromString(component);
            if (cn == null) {
                throw new IllegalArgumentException ("Invalid component " + component);
            }
            return cn;
        }
    
        private int parseInt(String argument) {
            try {
                return Integer.parseInt(argument);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException ("Invalid integer argument '" + argument + "'", e);
            }
        }
    }


    device_admin 管理的权限:

    <limit-password />    //设置密码规则

    <watch-login />       //监控屏幕解锁尝试次数

    <reset-password />    //更改屏幕解锁密码

    <force-lock />        //设备自动解锁

    <wipe-data />         //清除数据

    <expire-password />   //激活密码

    <encrypted-storage />   //数据加密  

    <disable-camera />    //禁用摄像头


    DeviceOwner权限相关

    1、设置壁纸

    2、获得硬件属性(cpu使用情况、温度、转速)

    3、静默卸载、设置某用户隐藏/停止某应用

    4、静默安装

    5、网络状态

    ..............

    展开全文
  • Mssql Db_owner角色注入直接获得系统权限.txt
  • owner:java属性文件配置

    千次阅读 2017-12-04 11:07:54
    一.OWNER入门 1.什么是OWNEROWNER是一个java库,其目标是通过Java属性文件来最小化处理应用程序配置所需的代码。 2.OWNER的特点 (1)简单:不需要代码来加载、转换和管理属性文件,仅仅只需要用最简单的方式使用...
  • Android DeviceOwner 应用的能力

    千次阅读 2018-12-03 15:26:07
    Device Owner 概述 DeviceOwner 译为设备所有者,在Android5.0系统推出。DeviceOwner涵盖了DeviceAdmin用户的所有管理能力,也涵盖了ProfileOwner的所有管理能力,并且在这些基础上额外添加了一些管理权限,如重启...
  • Android ProfileOwner 应用的能力

    千次阅读 2018-12-03 15:22:08
    Profile Owner 概述 ProfileOwner 译为配置文件所有者,在Android5.0系统推出。ProfileOwner涵盖了所有DeviceAdmin用户的管理能力,并且额外添加了很多管理权限。Android系统只能设置一个Profile Owner程序,并且该...
  • EMC超融合设备VxRail E系列手册,EMC VxRail E Series Appliance Owner's manual
  • XP128XP1024 Owner's Guide

    2016-02-02 01:09:06
    XP128XP1024 Owner's Guide
  • LVDS Owner’s Manual

    2017-04-10 14:40:53
    LVDS Owner’s Manual Low-Voltage Differential Signaling Spring 2004 3rd Edition
  • 成员的owner意识

    千次阅读 2020-04-26 08:28:16
    大家都看得到,Owner意识的宣传无处不在,无论是对国家的爱国主义,或是对公司的感恩主义,还是对所处团队的团队荣誉感,这些都是Owner意识的体现。其中最关键的就是激情和责任感!前提就是团队成员具有很强的Owner...
  • 工程师一定要有 “Owner 意识”

    千次阅读 2020-05-23 00:37:13
    Owner 意识”主要体现在两个层面:一是认真负责的态度,二是积极主动的精 神。 认真负责是工作的底线,积极主动是“Owner 意识”更高一级的要求。 自私确实是人的天性,不是自己的东西,很难谈什么责任感,更不用...
  • Acts as owner 是 Ruby on Rails 的一个插件,它为所有者对象提供了自我查询可拥有对象的所有权的能力。 可拥有对象可以是属于所有者对象的任何对象和属于可拥有对象的任何对象。 属于拥有的可拥有的父代的任何可...
  • 执行如下脚本,其中database为需要修改owner的库,username为需要修改的新owner名称,schema1可以去掉: \c database; DO $$ DECLARE r record; i int; v_schema text[] := '{public,schema1}'; v_new_owner ...
  • filecoin-将多签钱包设置为owner地址

    千次阅读 2021-09-02 10:46:37
    第一步:准备多签钱包 此处使用上篇生成好的多签钱包; 第二步:创建miner ...这里使用已经新创建好的miner ...命令:lotus-miner actor set-owner --really-do-it <newOwner> <oldOwner> 执行:(ne.
  • 客户写了一个apk要成为device owner; 之后apk联网更新升级; 强制卸载安装,导致无法再次成为DeviceOwner。 原因:当一个app成为DeviceOwner后,这个app是不能被卸载,但是由于应用更新,强制卸载之前没有注销...
  • 原文:SQL Server修改数据库对象所有者(Owner)浅析在SQL Server数据库中如何修改数据库对象(表、视图、存储过程..)的所有者(Owner)呢?一般我们可以使用系统提供的系统存储过程sp_changeobjectowner来修改。 我们...
  • Linux 中的 owner,group,others

    千次阅读 2020-02-12 21:52:16
    背景 Linux 比较强大的一点就是它的多人多...Linux 中将文件的身份分为三个类别,分别是文件拥有者(owner),所属群组(group),其他人(others),每个文件都可单独地对不同的身份执行不同的权限(read,write,execute...
  • 研发Owner的职责

    千次阅读 2019-12-06 12:29:01
    概述 技术组长或者PMO,可能在同一个上线周期里,需要跟多个项目,有时候会跟不过来,这个时候可以指派一个owner,分担一些压力。...且这里说的owner,是指单端的owner,例如:后端侧owner,前端侧owner。 对内 ...
  • Gitlab用户在组中有五种权限:Guest、Reporter、Developer、Master、Owner Gitlab权限管理 Gitlab用户在组中有五种权限:Guest、Reporter、Developer、Master、Owner Guest:可以创建issue、发表评论,不能读写版本...
  • 父窗口parent和所有者owner的区别

    千次阅读 2018-01-11 16:08:53
     一、概念和区别  在windows系统中,每个窗口对象都对应有一个数据结构,形成一个list链表。系统的窗口管理器通过这个list...这个数据结构中有四个数据用来构建list,即child、sibling、parent、owner四个域。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 344,521
精华内容 137,808
关键字:

owner