How configure GCM for an Android Device Policy Controller (DPC)

438 views Asked by At

I want to use the demo application TestDPC released by Google to create a Work Profile with my own device policy controller so I added some code to this app in order to connect to GCM service to receive cloud messages to start some actions on my device.
To connect to GCM I used some example code that I tested separately and it works, the only thing I added is a boot listener (ReceiverStarter) in order to activate GCM listener everytime the user reboot his device.
The strange thing is that when I install my app on device (Samsung Note 4 with Android 5.1.1 API 22) without create a managed profile the GCM client works properly.
If with the app early installed I create a work profile and the app itslef take control over the new profile the same code for GCM doesn't work anymore. I can see (using notifications) that in this case my dpc app can register to GCM and fetch GCM ID and I can read it in my console but the listener (MyGcmListenerService) doesn't receive any cloud messages as if the listener is not up and running, I cannot see any errors and/or logs in my console.
Maybe I need some more permissions?
Here my manifest

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<permission android:name="com.xxx.emmagent.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.xxx.emmagent.permission.C2D_MESSAGE" />

<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:theme="@style/AppTheme"
        android:label="@string/app_name">

    <activity
        android:name=".LaunchActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

    <activity
        android:name=".gcm.MainActivity"
        android:label="@string/app_name"
        android:theme="@style/SetupTheme"/>

    <activity
            android:name=".PolicyManagementActivity"
            android:label="@string/app_name"
            android:windowSoftInputMode="adjustPan"/>

    <activity
            android:name=".AddAccountActivity"
            android:label="@string/app_name"
            android:theme="@style/SetupTheme"/>

    <activity
            android:name=".EnableProfileActivity"
            android:label="@string/app_name"
            android:theme="@style/SetupTheme"/>

    <activity
            android:name=".EnableDeviceOwnerActivity"
            android:label="@string/app_name"
            android:theme="@style/SetupTheme"/>

    <activity
            android:name=".cosu.EnableCosuActivity"
            android:label="@string/app_name"
            android:theme="@style/SetupTheme"/>

    <activity
            android:name=".syncauth.SetupSyncAuthManagement"
            android:label="@string/app_name"
            android:theme="@style/SetupTheme"/>

    <activity
            android:name=".syncauth.FinishSyncAuthDeviceOwnerActivity"
            android:label="@string/app_name"
            android:theme="@style/SetupTheme"/>

    <activity
            android:name=".syncauth.FinishSyncAuthProfileOwnerActivity"
            android:label="@string/app_name"
            android:theme="@style/SetupTheme"/>

    <activity
            android:name=".policy.locktask.KioskModeActivity"
            android:label="@string/kiosk_mode"
            android:launchMode="singleInstance"
            android:lockTaskMode="if_whitelisted"
            android:enabled="false">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.HOME"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>

    <receiver
            android:name=".DeviceAdminReceiver"
            android:description="@string/app_name"
            android:label="@string/app_name"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
        <meta-data
                android:name="android.app.device_admin"
                android:resource="@xml/device_admin_receiver"/>
        <intent-filter>
            <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
            <action android:name="android.app.action.PROFILE_PROVISIONING_COMPLETE"/>
        </intent-filter>
    </receiver>

    <provider
            android:authorities="com.xxx.emmagent.fileprovider"
            android:name="android.support.v4.content.FileProvider"
            android:grantUriPermissions="true"
            android:exported="false">
        <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
    </provider>


    <!-- GCM messagging -->
    <!-- [START gcm_receiver] -->
    <receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="com.xxx.emmagent" />
        </intent-filter>
    </receiver>
    <!-- [END gcm_receiver] -->

    <!-- [START gcm_listener] -->
    <service
        android:name=".gcm.MyGcmListenerService"
        android:exported="true" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </service>
    <!-- [END gcm_listener] -->
    <!-- [START instanceId_listener] -->
    <service
        android:name=".gcm.MyInstanceIDListenerService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.iid.InstanceID"/>
        </intent-filter>
    </service>
    <!-- [END instanceId_listener] -->
    <service
        android:name=".gcm.RegistrationIntentService"
        android:exported="false">
    </service>

    <receiver android:name=".gcm.ReceiverStarter" android:enabled="true" android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>

</application>

I don't think it depends by code, as I said the same app and the same code without a work profile works well.
Any ideas?
Thanks in advance

EDIT: here the same problem

1

There are 1 answers

3
PasinduJay On

according my knowledge the OS avoid triggering any managed profile intents from the personal profile as well (unless grant privileges). So although the request is reserved to the device from GCM, the device is unable to trigger your app's activities when the app is in the managed profile.

What you have to do is keep a separate unit in the personal profile which handles receiving GCM operations. You can grant privileges to certain intents to be cross share to the managed profile. In that way you can send the trigger though an intent to the app in the managed profile with relevant information to the operation. Let me know if it is not clear.

Please go through this link (Ensuring Compatibility with Managed Profiles) to understand enabling cross profile intents.