diff options
-rw-r--r-- | api/current.txt | 1 | ||||
-rw-r--r-- | api/system-current.txt | 1 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 23 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 3 | ||||
-rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 17 | ||||
-rw-r--r-- | core/java/android/app/admin/IDevicePolicyManager.aidl | 2 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 41 | ||||
-rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java | 57 |
8 files changed, 138 insertions, 7 deletions
diff --git a/api/current.txt b/api/current.txt index eb69ed6..df77416 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5781,6 +5781,7 @@ package android.app.admin { method public void setPasswordQuality(android.content.ComponentName, int); method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>); method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>); + method public void setPreferredSetupActivity(android.content.ComponentName, android.content.ComponentName); method public void setProfileEnabled(android.content.ComponentName); method public void setProfileName(android.content.ComponentName, java.lang.String); method public void setRecommendedGlobalProxy(android.content.ComponentName, android.net.ProxyInfo); diff --git a/api/system-current.txt b/api/system-current.txt index b8c7fa2..e10a8b2 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5886,6 +5886,7 @@ package android.app.admin { method public void setPasswordQuality(android.content.ComponentName, int); method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>); method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>); + method public void setPreferredSetupActivity(android.content.ComponentName, android.content.ComponentName); method public void setProfileEnabled(android.content.ComponentName); method public void setProfileName(android.content.ComponentName, java.lang.String); method public void setRecommendedGlobalProxy(android.content.ComponentName, android.net.ProxyInfo); diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index b11c509..a71a258 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2521,6 +2521,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case UPDATE_PREFERRED_SETUP_ACTIVITY_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + ComponentName preferredActivity = ComponentName.readFromParcel(data); + int userId = data.readInt(); + updatePreferredSetupActivity(preferredActivity, userId); + reply.writeNoException(); + return true; + } + case GET_PACKAGE_PROCESS_STATE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String pkg = data.readString(); @@ -5821,6 +5830,20 @@ class ActivityManagerProxy implements IActivityManager } @Override + public void updatePreferredSetupActivity(ComponentName preferredActivity, int userId) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + ComponentName.writeToParcel(preferredActivity, data); + data.writeInt(userId); + mRemote.transact(UPDATE_PREFERRED_SETUP_ACTIVITY_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override public int getPackageProcessState(String packageName) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 00558fe..5829fbe 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -496,6 +496,8 @@ public interface IActivityManager extends IInterface { throws RemoteException; public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException; public void updateDeviceOwner(String packageName) throws RemoteException; + public void updatePreferredSetupActivity(ComponentName preferredActivity, int userId) + throws RemoteException; public int getPackageProcessState(String packageName) throws RemoteException; @@ -839,4 +841,5 @@ public interface IActivityManager extends IInterface { int GET_PACKAGE_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+293; int SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+294; int UPDATE_DEVICE_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+295; + int UPDATE_PREFERRED_SETUP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+296; } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 47133d4..ed814c3 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -4325,4 +4325,21 @@ public class DevicePolicyManager { } } } + + /** + * Called by a device initializer to set the activity to be launched on device boot or after a + * user switch during user setup. This activity will be started regardless of the priority of + * other 'home' activities. Once user setup is complete, the preferred setup activity will be + * ignored. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param activity The Activity to be started by default during user setup. + */ + public void setPreferredSetupActivity(ComponentName admin, ComponentName activity) { + try { + mService.setPreferredSetupActivity(admin, activity); + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); + } + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 087fc88..a678c51 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -216,6 +216,8 @@ interface IDevicePolicyManager { String getDeviceInitializer(); ComponentName getDeviceInitializerComponent(); + void setPreferredSetupActivity(in ComponentName admin, in ComponentName activity); + void setUserIcon(in ComponentName admin, in Bitmap icon); void sendDeviceInitializerStatus(int statusCode, String description); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4970e0f..15d7367 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -442,6 +442,12 @@ public final class ActivityManagerService extends ActivityManagerNative */ String mDeviceOwnerName; + /** + * Preferred activities to start on boot/user switch, as set by DevicePolicyManager. Indexed + * by userId. + */ + SparseArray<ComponentName> mPreferredSetupActivities = new SparseArray<>(); + public class PendingAssistExtras extends Binder implements Runnable { public final ActivityRecord activity; public final Bundle extras; @@ -3334,15 +3340,22 @@ public final class ActivityManagerService extends ActivityManagerNative ComponentName comp = intent.getComponent(); try { if (comp != null) { + // Factory test. ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId); } else { - ResolveInfo info = AppGlobals.getPackageManager().resolveIntent( - intent, - intent.resolveTypeIfNeeded(mContext.getContentResolver()), - flags, userId); + ComponentName preferredComponent = mPreferredSetupActivities.get(userId); + if (preferredComponent != null) { + ai = AppGlobals.getPackageManager().getActivityInfo( + preferredComponent, flags, userId); + } else { + ResolveInfo info = AppGlobals.getPackageManager().resolveIntent( + intent, + intent.resolveTypeIfNeeded(mContext.getContentResolver()), + flags, userId); - if (info != null) { - ai = info.activityInfo; + if (info != null) { + ai = info.activityInfo; + } } } } catch (RemoteException e) { @@ -8574,6 +8587,22 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override + public void updatePreferredSetupActivity(ComponentName preferredActivity, int userId) { + final int callingUid = Binder.getCallingUid(); + if (callingUid != 0 && callingUid != Process.SYSTEM_UID) { + throw new SecurityException( + "updatePreferredSetupActivity called from non-system process"); + } + synchronized (this) { + if (preferredActivity == null) { + mPreferredSetupActivities.delete(userId); + } else { + mPreferredSetupActivities.put(userId, preferredActivity); + } + } + } + + @Override public void updateDeviceOwner(String packageName) { final int callingUid = Binder.getCallingUid(); if (callingUid != 0 && callingUid != Process.SYSTEM_UID) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 2b88158..31d7f74 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -181,6 +181,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final String ATTR_PERMISSION_PROVIDER = "permission-provider"; private static final String ATTR_SETUP_COMPLETE = "setup-complete"; + private static final String ATTR_PREFERRED_SETUP_ACTIVITY = "setup-activity"; private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer"; @@ -315,6 +316,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { boolean doNotAskCredentialsOnBoot = false; + ComponentName mPreferredSetupActivity; + public DevicePolicyData(int userHandle) { mUserHandle = userHandle; } @@ -1410,7 +1413,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, ATTR_DELEGATED_CERT_INSTALLER, policy.mDelegatedCertInstallerPackage); } - + if (policy.mPreferredSetupActivity != null) { + out.attribute(null, ATTR_PREFERRED_SETUP_ACTIVITY, + policy.mPreferredSetupActivity.flattenToString()); + } else { + out.attribute(null, ATTR_PREFERRED_SETUP_ACTIVITY, ""); + } final int N = policy.mAdminList.size(); for (int i=0; i<N; i++) { @@ -1531,6 +1539,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } policy.mDelegatedCertInstallerPackage = parser.getAttributeValue(null, ATTR_DELEGATED_CERT_INSTALLER); + String preferredSetupActivity = + parser.getAttributeValue(null, ATTR_PREFERRED_SETUP_ACTIVITY); + if (preferredSetupActivity != null) { + policy.mPreferredSetupActivity = + ComponentName.unflattenFromString(preferredSetupActivity); + } type = parser.next(); int outerDepth = parser.getDepth(); @@ -1654,6 +1668,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!policy.mStatusBarEnabledState) { setStatusBarEnabledStateInternal(policy.mStatusBarEnabledState, userHandle); } + updatePreferredSetupActivityLocked(userHandle); } private void updateLockTaskPackagesLocked(List<String> packages, int userId) { @@ -4632,6 +4647,43 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override + public void setPreferredSetupActivity(ComponentName who, ComponentName activity) { + if (!mHasFeature) { + return; + } + Preconditions.checkNotNull(who, "ComponentName is null"); + synchronized (this) { + ActiveAdmin activeAdmin = + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + if (!isDeviceInitializer(activeAdmin.info.getPackageName())) { + throw new SecurityException( + "This method can only be called by device initializers"); + } + int userHandle = UserHandle.getCallingUserId(); + DevicePolicyData userData = getUserData(userHandle); + userData.mPreferredSetupActivity = activity; + saveSettingsLocked(userHandle); + updatePreferredSetupActivityLocked(userHandle); + } + } + + private void updatePreferredSetupActivityLocked(int userHandle) { + if (!mHasFeature) { + return; + } + IActivityManager am = ActivityManagerNative.getDefault(); + long ident = Binder.clearCallingIdentity(); + try { + am.updatePreferredSetupActivity( + getUserData(userHandle).mPreferredSetupActivity, userHandle); + } catch (RemoteException e) { + // Not gonna happen. + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override public void setApplicationRestrictions(ComponentName who, String packageName, Bundle settings) { Preconditions.checkNotNull(who, "ComponentName is null"); final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); @@ -6000,6 +6052,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!policy.mUserSetupComplete) { policy.mUserSetupComplete = true; synchronized (this) { + // Clear the preferred setup activity. + policy.mPreferredSetupActivity = null; + updatePreferredSetupActivityLocked(userHandle); // The DeviceInitializer was whitelisted but now should be removed. removeDeviceInitializerFromLockTaskPackages(userHandle); saveSettingsLocked(userHandle); |