summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt3
-rw-r--r--core/java/android/app/admin/DeviceAdminReceiver.java51
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl2
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java30
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java22
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();