summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--core/java/android/app/ActivityManagerNative.java23
-rw-r--r--core/java/android/app/IActivityManager.java3
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java17
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl2
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java41
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java57
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);