0

I am looking to the setup device owner from custom setup wizard app programmatically Currently, I am testing with google sample testDpc app.

I am able to ask for provisioning mode by using the calling ACTION_GET_PROVISIONING_MODE intent, but I don't know what to do after receiving there result

Process proc = Runtime.getRuntime().exec("dpm set-device-owner com.afwsamples.testdpc/.DeviceAdminReceiver");

If I try to run the above command then I am getting the below error

Exception occurred while executing 'set-device-owner': 
java.lang.SecurityException: Calling identity is not authorized

I want to setup device as orgnization owned work profile from setup wizard (COPE profile)

Jarvis
  • 1,714
  • 2
  • 20
  • 35

2 Answers2

1

Use DevicePolicyManager's hide method: setActiveAdmin and setDeviceOwner

SetDeviceOwnerPolicyTask.run is an example.

Yong
  • 1,529
  • 12
  • 21
  • Calling these hidden methods is equivalent to running the "dpm set-device-owner ..." shell command. It also requires system signature and should be done before completing the setup wizard. This code sample is from the ManagedProvisioning app which is called by the setup wizard before it completes! – vmayorow May 21 '22 at 15:04
  • Hm, I am getting "Cannot set the device owner if the device is already set-up" when calling that method. Permissions and signature are ok. With adb it works fine, even afterwards. Maybe I need to use different UserId? (I am not using any, just calling the method with single ComponentName parameter). – Looka Sep 13 '22 at 15:58
  • Update: It has to be called early on from Setup Wizard . – Looka Sep 15 '22 at 06:48
1

To execute the dpm command successfully from within the application, two conditions should be fulfilled:

  • Your application must have android.permission.MANAGE_DEVICE_ADMINS and android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS permissions;
  • The Android setup wizard should not be completed.

To get the android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS permission, your application must be a system app, that is, you need to set the shared user as android.uid.system in AndroidManifest.xml and sign the app by platform keys.

The second condition could be ignored if your app, instead of running the dpm set-device-owner command, directly updates the system configuration XML files (since it's signed by platform keys, it is able to update them!).

Two system files should be updated. They must have the following content:

  1. /data/system/device_owner_2.xml

    <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
    <root>
        <device-owner 
            package="your.package.name" 
            name=""
            component="your.package.name/your.package.name.AdminReceiverClassName" 
            userRestrictionsMigrated="true" 
            canAccessDeviceIds="true" />
        <device-owner-context userId="0" />
    </root>
    
  2. /data/system/device_policies.xml

    <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
    <policies setup-complete="true" provisioning-state="3">
        <admin name="your.package.name/your.package.name.AdminReceiverClassName">
            <policies flags="17" />
            <strong-auth-unlock-timeout value="0" />
            <user-restrictions no_add_managed_profile="true" />
            <default-enabled-user-restrictions>
                <restriction value="no_add_managed_profile" />
            </default-enabled-user-restrictions>
            <cross-profile-calendar-packages />
        </admin>
        <password-validity value="true" />
        <lock-task-features value="16" />
    </policies>
    

To apply these changes in system configuration files, the device needs to be rebooted.

As a working sample, take a look at the source code of Headwind MDM which is the open source MDM solution able to be integrated into the AOSP (for example, LineageOS). Disclaimer: I am the owner of Headwind MDM.

The related code can be found in the following file:

app/src/main/java/com/hmdm/launcher/util/SystemUtils.java
vmayorow
  • 630
  • 5
  • 15