diff options
5 files changed, 107 insertions, 1 deletions
diff --git a/api/current.txt b/api/current.txt index 2912882..6175c38 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5194,6 +5194,7 @@ package android.app.admin { method public java.lang.CharSequence onDisableRequested(android.content.Context, android.content.Intent); method public void onDisabled(android.content.Context, android.content.Intent); method public void onEnabled(android.content.Context, android.content.Intent); + method public void onLockTaskModeChanged(android.content.Context, android.content.Intent); method public void onPasswordChanged(android.content.Context, android.content.Intent); method public void onPasswordExpiring(android.content.Context, android.content.Intent); method public void onPasswordFailed(android.content.Context, android.content.Intent); @@ -5203,6 +5204,7 @@ package android.app.admin { field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED"; field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED"; field public static final java.lang.String ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED"; + field public static final java.lang.String ACTION_LOCK_TASK_CHANGED = "android.app.action.ACTION_LOCK_TASK_CHANGED"; field public static final java.lang.String ACTION_PASSWORD_CHANGED = "android.app.action.ACTION_PASSWORD_CHANGED"; field public static final java.lang.String ACTION_PASSWORD_EXPIRING = "android.app.action.ACTION_PASSWORD_EXPIRING"; field public static final java.lang.String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED"; @@ -5210,6 +5212,7 @@ package android.app.admin { field public static final java.lang.String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.ACTION_PROFILE_PROVISIONING_COMPLETE"; field public static final java.lang.String DEVICE_ADMIN_META_DATA = "android.app.device_admin"; field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING"; + field public static final java.lang.String EXTRA_LOCK_TASK_ENTERING = "android.app.extra.LOCK_TASK_ENTERING"; } public class DevicePolicyManager { diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index 45a2625..0d514a5 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -166,6 +166,40 @@ public class DeviceAdminReceiver extends BroadcastReceiver { = "android.app.action.ACTION_PASSWORD_EXPIRING"; /** + * Action sent to a device administrator to notify that the device is entering + * or exiting lock task mode from an authorized package. The extra + * {@link #EXTRA_LOCK_TASK_ENTERING} will describe whether entering or exiting + * the mode. If entering, the extra {@link #EXTRA_LOCK_TASK_PACKAGE} will describe + * the authorized package using lock task mode. + * + * @see DevicePolicyManager#isLockTaskPermitted + * + * <p>The calling device admin must be the device owner or profile + * owner to receive this broadcast. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_LOCK_TASK_CHANGED + = "android.app.action.ACTION_LOCK_TASK_CHANGED"; + + /** + * A boolean describing whether the device is currently entering or exiting + * lock task mode. + * + * @see #ACTION_LOCK_TASK_CHANGED + */ + public static final String EXTRA_LOCK_TASK_ENTERING = + "android.app.extra.LOCK_TASK_ENTERING"; + + /** + * A boolean describing whether the device is currently entering or exiting + * lock task mode. + * + * @see #ACTION_LOCK_TASK_CHANGED + */ + public static final String EXTRA_LOCK_TASK_PACKAGE = + "android.app.extra.LOCK_TASK_PACKAGE"; + + /** * Broadcast Action: This broadcast is sent to indicate that provisioning of a managed profile * or managed device has completed successfully. * @@ -341,6 +375,19 @@ public class DeviceAdminReceiver extends BroadcastReceiver { } /** + * Called when a device is entering or exiting lock task mode by a package + * authorized by {@link DevicePolicyManager#isLockTaskPermitted(ComponentName)} + * + * @param context The running context as per {@link #onReceive}. + * @param intent The received intent as per {@link #onReceive}. + * @param isEnteringLockTask Whether the device is entering or exiting lock task mode. + * @param pkg If entering, the authorized package using lock task mode, otherwise null. + */ + public void onLockTaskModeChanged(Context context, Intent intent, boolean isEnteringLockTask, + String pkg) { + } + + /** * Intercept standard device administrator broadcasts. Implementations * should not override this method; it is better to implement the * convenience callbacks for each action. @@ -369,6 +416,10 @@ public class DeviceAdminReceiver extends BroadcastReceiver { onPasswordExpiring(context, intent); } else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) { onProfileProvisioningComplete(context, intent); + } else if (ACTION_LOCK_TASK_CHANGED.equals(action)) { + boolean isEntering = intent.getBooleanExtra(EXTRA_LOCK_TASK_ENTERING, false); + String pkg = intent.getStringExtra(EXTRA_LOCK_TASK_PACKAGE); + onLockTaskModeChanged(context, intent, isEntering, pkg); } } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 8272c07..e7b77d8 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -151,4 +151,6 @@ interface IDevicePolicyManager { void setMasterVolumeMuted(in ComponentName admin, boolean on); boolean isMasterVolumeMuted(in ComponentName admin); + + void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userId); } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 9b1d0e3..e07463d 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -46,6 +46,8 @@ import android.app.ActivityManager.RunningTaskInfo; import android.app.IActivityManager.WaitResult; import android.app.ResultInfo; import android.app.StatusBarManager; +import android.app.admin.DevicePolicyManager; +import android.app.admin.IDevicePolicyManager; import android.content.ComponentName; import android.content.Context; import android.content.IIntentSender; @@ -143,6 +145,7 @@ public final class ActivityStackSupervisor implements DisplayListener { /** Status Bar Service **/ private IBinder mToken = new Binder(); private IStatusBarService mStatusBarService; + private IDevicePolicyManager mDevicePolicyManager; // For debugging to make sure the caller when acquiring/releasing our // wake lock is the system process. @@ -285,6 +288,19 @@ public final class ActivityStackSupervisor implements DisplayListener { } } + private IDevicePolicyManager getDevicePolicyManager() { + synchronized (mService) { + if (mDevicePolicyManager == null) { + mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface( + ServiceManager.checkService(Context.DEVICE_POLICY_SERVICE)); + if (mDevicePolicyManager == null) { + Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE"); + } + } + return mDevicePolicyManager; + } + } + void setWindowManager(WindowManagerService wm) { synchronized (mService) { mWindowManager = wm; @@ -2992,8 +3008,9 @@ public final class ActivityStackSupervisor implements DisplayListener { final Message lockTaskMsg = Message.obtain(); if (task == null) { // Take out of lock task mode. - mLockTaskModeTask = null; + lockTaskMsg.arg1 = mLockTaskModeTask.userId; lockTaskMsg.what = LOCK_TASK_END_MSG; + mLockTaskModeTask = null; mHandler.sendMessage(lockTaskMsg); return; } @@ -3004,6 +3021,8 @@ public final class ActivityStackSupervisor implements DisplayListener { mLockTaskModeTask = task; findTaskToMoveToFrontLocked(task, 0, null); resumeTopActivitiesLocked(); + lockTaskMsg.obj = mLockTaskModeTask.intent.getComponent().getPackageName(); + lockTaskMsg.arg1 = mLockTaskModeTask.userId; lockTaskMsg.what = LOCK_TASK_START_MSG; mHandler.sendMessage(lockTaskMsg); } @@ -3112,6 +3131,11 @@ public final class ActivityStackSupervisor implements DisplayListener { (StatusBarManager.DISABLE_MASK ^ StatusBarManager.DISABLE_BACK, mToken, mService.mContext.getPackageName()); } + if (getDevicePolicyManager() != null) { + getDevicePolicyManager().notifyLockTaskModeChanged(true, + (String)msg.obj, + msg.arg1); + } } catch (RemoteException ex) { throw new RuntimeException(ex); } @@ -3124,6 +3148,10 @@ public final class ActivityStackSupervisor implements DisplayListener { (StatusBarManager.DISABLE_NONE, mToken, mService.mContext.getPackageName()); } + if (getDevicePolicyManager() != null) { + getDevicePolicyManager().notifyLockTaskModeChanged(false, null, + msg.arg1); + } } catch (RemoteException ex) { throw new RuntimeException(ex); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 765a33d..5cf5713 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3796,6 +3796,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override + public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + throw new SecurityException("notifyLockTaskModeChanged can only be called by system"); + } + synchronized (this) { + final DevicePolicyData policy = getUserData(userHandle); + Bundle adminExtras = new Bundle(); + adminExtras.putBoolean(DeviceAdminReceiver.EXTRA_LOCK_TASK_ENTERING, isEnabled); + adminExtras.putString(DeviceAdminReceiver.EXTRA_LOCK_TASK_PACKAGE, pkg); + for (ActiveAdmin admin : policy.mAdminList) { + boolean ownsDevice = isDeviceOwner(admin.info.getPackageName()); + boolean ownsProfile = (getProfileOwner(userHandle) != null + && getProfileOwner(userHandle).equals(admin.info.getPackageName())); + if (ownsDevice || ownsProfile) { + sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_LOCK_TASK_CHANGED, + adminExtras, null); + } + } + } + } + + @Override public void setGlobalSetting(ComponentName who, String setting, String value) { final ContentResolver contentResolver = mContext.getContentResolver(); |