Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 010cfd45 authored by Adam Connors's avatar Adam Connors
Browse files

Add enableSystemApp methods to DevicePolicyManager

These methods allow profile or device owners to enable
systems apps pre-installed in the primary user in the
managed profile. Apps can be specified by either package
name or intent.

Bug: 13587051

Change-Id: Ifcbc68c139308506b6c18cf3c0ea62b8026ff75f
parent 10a38c06
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -5013,6 +5013,8 @@ package android.app.admin {
    method public void clearForwardingIntentFilters(android.content.ComponentName);
    method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
    method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
    method public void enableSystemApp(android.content.ComponentName, java.lang.String);
    method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
    method public java.util.List<android.content.ComponentName> getActiveAdmins();
    method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
    method public boolean getCameraDisabled(android.content.ComponentName);
@@ -20506,9 +20508,17 @@ package android.os {
    method public void setUserRestriction(java.lang.String, boolean);
    method public void setUserRestrictions(android.os.Bundle);
    method public void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
    field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
    field public static final java.lang.String DISALLOW_CONFIG_APPS = "no_config_apps";
    field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
    field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
    field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
    field public static final java.lang.String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks";
    field public static final java.lang.String DISALLOW_CONFIG_TETHERING = "no_config_tethering";
    field public static final java.lang.String DISALLOW_CONFIG_VPN = "no_config_vpn";
    field public static final java.lang.String DISALLOW_CONFIG_WIFI = "no_config_wifi";
    field public static final java.lang.String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features";
    field public static final java.lang.String DISALLOW_FACTORY_RESET = "no_factory_reset";
    field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
    field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
    field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
@@ -20516,15 +20526,7 @@ package android.os {
    field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
    field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
    field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
    field public static final java.lang.String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features";
    field public static final java.lang.String DISALLOW_CONFIG_VPN = "no_config_vpn";
    field public static final java.lang.String DISALLOW_CONFIG_TETHERING = "no_config_tethering";
    field public static final java.lang.String DISALLOW_FACTORY_RESET = "no_factory_reset";
    field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
    field public static final java.lang.String ENSURE_VERIFY_APPS = "ensure_verify_apps";
    field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
    field public static final java.lang.String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks";
    field public static final java.lang.String DISALLOW_CONFIG_APPS = "no_config_apps";
  }
  public abstract class Vibrator {
+40 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -2041,4 +2042,43 @@ public class DevicePolicyManager {
            }
        }
    }

    /**
     * Called by profile or device owner to re-enable a system app that was disabled by default
     * when the managed profile was created. This should only be called from a profile or device
     * owner running within a managed profile.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param packageName The package to be re-enabled in the current profile.
     */
    public void enableSystemApp(ComponentName admin, String packageName) {
        if (mService != null) {
            try {
                mService.enableSystemApp(admin, packageName);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed to install package: " + packageName);
            }
        }
    }

    /**
     * Called by profile or device owner to re-enable system apps by intent that were disabled
     * by default when the managed profile was created. This should only be called from a profile
     * or device owner running within a managed profile.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param intent An intent matching the app(s) to be installed. All apps that resolve for this
     *               intent will be re-enabled in the current profile.
     * @returns int The number of activities that matched the intent and were installed.
     */
    public int enableSystemApp(ComponentName admin, Intent intent) {
        if (mService != null) {
            try {
                return mService.enableSystemAppWithIntent(admin, intent);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed to install packages matching filter: " + intent);
            }
        }
        return 0;
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
package android.app.admin;

import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.RemoteCallback;
@@ -122,4 +123,7 @@ interface IDevicePolicyManager {
    void setUserRestriction(in ComponentName who, in String key, boolean enable);
    void addForwardingIntentFilter(in ComponentName admin, in IntentFilter filter, int flags);
    void clearForwardingIntentFilters(in ComponentName admin);

    void enableSystemApp(in ComponentName admin, in String packageName);
    int enableSystemAppWithIntent(in ComponentName admin, in Intent intent);
}
+1 −5
Original line number Diff line number Diff line
@@ -7479,11 +7479,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                null);
        PackageSetting pkgSetting;
        final int uid = Binder.getCallingUid();
        if (UserHandle.getUserId(uid) != userId) {
            mContext.enforceCallingPermission(
                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
                    "installExistingPackage for user " + userId);
        }
        enforceCrossUserPermission(uid, userId, true, "installExistingPackage for user " + userId);
        if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
            return PackageManager.INSTALL_FAILED_USER_RESTRICTED;
        }
+109 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -3023,6 +3024,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    @Override
    public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
            ComponentName activity) {
        synchronized (this) {
@@ -3043,6 +3045,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    @Override
    public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
        synchronized (this) {
            if (who == null) {
@@ -3168,4 +3171,110 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
        }
    }

    @Override
    public void enableSystemApp(ComponentName who, String packageName) {
        synchronized (this) {
            if (who == null) {
                throw new NullPointerException("ComponentName is null");
            }

            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);

            int userId = UserHandle.getCallingUserId();
            long id = Binder.clearCallingIdentity();

            try {
                UserManager um = UserManager.get(mContext);
                if (!um.getUserInfo(userId).isManagedProfile()) {
                    throw new IllegalStateException(
                            "Only call this method from a managed profile.");
                }

                // TODO: Use UserManager::getProfileParent when available.
                UserInfo primaryUser = um.getUserInfo(UserHandle.USER_OWNER);

                if (DBG) {
                    Slog.v(LOG_TAG, "installing " + packageName + " for "
                            + userId);
                }

                IPackageManager pm = AppGlobals.getPackageManager();
                if (!isSystemApp(pm, packageName, primaryUser.id)) {
                    throw new IllegalArgumentException("Only system apps can be enabled this way.");
                }

                // Install the app.
                pm.installExistingPackageAsUser(packageName, userId);

            } catch (RemoteException re) {
                // shouldn't happen
                Slog.wtf(LOG_TAG, "Failed to install " + packageName, re);
            } finally {
                restoreCallingIdentity(id);
            }
        }
    }

    @Override
    public int enableSystemAppWithIntent(ComponentName who, Intent intent) {
        synchronized (this) {
            if (who == null) {
                throw new NullPointerException("ComponentName is null");
            }

            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);

            int userId = UserHandle.getCallingUserId();
            long id = Binder.clearCallingIdentity();

            try {
                UserManager um = UserManager.get(mContext);
                if (!um.getUserInfo(userId).isManagedProfile()) {
                    throw new IllegalStateException(
                            "Only call this method from a managed profile.");
                }

                // TODO: Use UserManager::getProfileParent when available.
                UserInfo primaryUser = um.getUserInfo(UserHandle.USER_OWNER);

                IPackageManager pm = AppGlobals.getPackageManager();
                List<ResolveInfo> activitiesToEnable = pm.queryIntentActivities(intent,
                        intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                        0, // no flags
                        primaryUser.id);

                if (DBG) Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
                int numberOfAppsInstalled = 0;
                if (activitiesToEnable != null) {
                    for (ResolveInfo info : activitiesToEnable) {
                        if (info.activityInfo != null) {

                            if (!isSystemApp(pm, info.activityInfo.packageName, primaryUser.id)) {
                                throw new IllegalArgumentException(
                                        "Only system apps can be enabled this way.");
                            }


                            numberOfAppsInstalled++;
                            pm.installExistingPackageAsUser(info.activityInfo.packageName, userId);
                        }
                    }
                }
                return numberOfAppsInstalled;
            } catch (RemoteException e) {
                // shouldn't happen
                Slog.wtf(LOG_TAG, "Failed to resolve intent for: " + intent);
                return 0;
            } finally {
                restoreCallingIdentity(id);
            }
        }
    }

    private boolean isSystemApp(IPackageManager pm, String packageName, int userId)
            throws RemoteException {
        ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0, userId);
        return (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0;
    }
}