I'm trying to disable a component during app OTA on my secondary profile. I'm writing a receiver to disable the component by capturing “android.intent.action.MY_PACKAGE_REPLACED”. Adding my AndroidManifest.xml change here,
<receiver android:name=".receivers.OTAUpdateReceiver"android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
along with adding these permission,
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
And here is my receiver code,
private static final int PRIMARY_USER_ID = 0;
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Entering here into ota update receiver");
packageManager = context.getPackageManager();
myComponent = new ComponentName(MY_PKG, MY_CLASS);
if (mPackageManager.hasSystemFeature("com.abc.xyz") && !isPrimaryProfile()) {
packageManager.setComponentEnabledSetting(
myComponent,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
}
public boolean isPrimaryProfile() {
int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
return (userId == PRIMARY_USER_ID) ? true : false;
}
I'm facing the following runtime exception when I'm receiving this MY_PACKAGE_REPLACED intent,
E/AndroidRuntime(13492): FATAL EXCEPTION: main E/AndroidRuntime(13492): Process: com.abc.project, PID: 13492 E/AndroidRuntime(13492): java.lang.RuntimeException: Unable to start receiver com.abc.project.receivers.OTAUpdateReceiver: java.lang.SecurityException: PermissionDenial: getCurrentUser() from pid=13492, uid=1032112 requires android.permission.INTERACT_ACROSS_USERS E/AndroidRuntime(13492): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2776) E/AndroidRuntime(13492): at android.app.ActivityThread.access$1700(ActivityThread.java:160) E/AndroidRuntime(13492): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1398) E/AndroidRuntime(13492): at android.os.Handler.dispatchMessage(Handler.java:102) E/AndroidRuntime(13492): at android.os.Looper.loop(Looper.java:135) E/AndroidRuntime(13492): at android.app.ActivityThread.main(ActivityThread.java:5597) E/AndroidRuntime(13492): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(13492): at java.lang.reflect.Method.invoke(Method.java:372) E/AndroidRuntime(13492): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:984) E/AndroidRuntime(13492): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) E/AndroidRuntime(13492): Caused by: java.lang.SecurityException: Permission Denial:getCurrentUser() from pid=13492, uid=1032112 requires android.permission.INTERACT_ACROSS_USERS E/AndroidRuntime(13492): at android.os.Parcel.readException(Parcel.java:1566) E/AndroidRuntime(13492): at android.os.Parcel.readException(Parcel.java:1519) E/AndroidRuntime(13492): at android.app.ActivityManagerProxy.getCurrentUser(ActivityManagerNative.java:4816) E/AndroidRuntime(13492): at
Though this permission "INTERACT_ACROSS_USERS" is defined in AndroidManifest.xml it is not getting reflected. Am I missing out something? Or is there any alternative way to achieve this?
My primary goal is to differentiate between primary and secondary profile or make sure the user is not in primary profile.
Able to differentiate between primary and secondary profile with the help of UserManager's getSerialNumberForUser api,
public boolean isPrimaryProfile(final Context context) {
UserHandle userHandle = Process.myUserHandle();
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
return (userManager != null) ? userManager.getSerialNumberForUser(userHandle) == PRIMARY_USER_ID : false;
}
The value of PRIMARY_USER_ID is 0 for primary user/owner.