Add Lock Task Mode.

When in lock task mode only the specified task may run. All
attempts to switch to another task are ignored until the task
finishes or a call to stopLockTaskMode() is made.

Change-Id: I6cfe92fe1bcf22cd47b5398c08e23c52a4092dda
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 287c463..606d803 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5606,6 +5606,22 @@
         }
     }
 
+    /** @hide */
+    public void startLockTask() {
+        try {
+            ActivityManagerNative.getDefault().startLockTaskMode(mToken);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** @hide */
+    public void stopLockTask() {
+        try {
+            ActivityManagerNative.getDefault().stopLockTaskMode();
+        } catch (RemoteException e) {
+        }
+    }
+
     /**
      * Interface for informing a translucent {@link Activity} once all visible activities below it
      * have completed drawing. This is necessary only after an {@link Activity} has been made
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7f7616f..a2183e6 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -155,6 +155,13 @@
     public static final int START_SWITCHES_CANCELED = 4;
 
     /**
+     * Result for IActivityManaqer.startActivity: a new activity was attempted to be started
+     * while in Lock Task Mode.
+     * @hide
+     */
+    public static final int START_RETURN_LOCK_TASK_MODE_VIOLATION = 5;
+
+    /**
      * Flag for IActivityManaqer.startActivity: do special start mode where
      * a new activity is launched only if it is needed.
      * @hide
@@ -2232,4 +2239,35 @@
             e.printStackTrace(pw);
         }
     }
+
+    /**
+     * @hide
+     */
+    public void startLockTaskMode(int taskId) {
+        try {
+            ActivityManagerNative.getDefault().startLockTaskMode(taskId);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void stopLockTaskMode() {
+        try {
+            ActivityManagerNative.getDefault().stopLockTaskMode();
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public boolean isInLockTaskMode() {
+        try {
+            return ActivityManagerNative.getDefault().isInLockTaskMode();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
 }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index c7c81dd..373a8a3 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2097,6 +2097,37 @@
             reply.writeStrongBinder(homeActivityToken);
             return true;
         }
+
+        case START_LOCK_TASK_BY_TASK_ID_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            final int taskId = data.readInt();
+            startLockTaskMode(taskId);
+            reply.writeNoException();
+            return true;
+        }
+
+        case START_LOCK_TASK_BY_TOKEN_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            startLockTaskMode(token);
+            reply.writeNoException();
+            return true;
+        }
+
+        case STOP_LOCK_TASK_MODE_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            stopLockTaskMode();
+            reply.writeNoException();
+            return true;
+        }
+
+        case IS_IN_LOCK_TASK_MODE_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            final boolean isInLockTaskMode = isInLockTaskMode();
+            reply.writeNoException();
+            reply.writeInt(isInLockTaskMode ? 1 : 0);
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -4820,5 +4851,53 @@
         return res;
     }
 
+    @Override
+    public void startLockTaskMode(int taskId) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(taskId);
+        mRemote.transact(START_LOCK_TASK_BY_TASK_ID_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
+    @Override
+    public void startLockTaskMode(IBinder token) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        mRemote.transact(START_LOCK_TASK_BY_TOKEN_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
+    @Override
+    public void stopLockTaskMode() throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(STOP_LOCK_TASK_MODE_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
+    @Override
+    public boolean isInLockTaskMode() throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(IS_IN_LOCK_TASK_MODE_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean isInLockTaskMode = reply.readInt() == 1;
+        data.recycle();
+        reply.recycle();
+        return isInLockTaskMode;
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index f2cabf4..cb06a42 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -424,6 +424,18 @@
 
     public IBinder getHomeActivityToken() throws RemoteException;
 
+    /** @hide */
+    public void startLockTaskMode(int taskId) throws RemoteException;
+
+    /** @hide */
+    public void startLockTaskMode(IBinder token) throws RemoteException;
+
+    /** @hide */
+    public void stopLockTaskMode() throws RemoteException;
+
+    /** @hide */
+    public boolean isInLockTaskMode() throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -719,4 +731,8 @@
     int GET_TAG_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+210;
     int START_USER_IN_BACKGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+211;
     int IS_IN_HOME_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+212;
+    int START_LOCK_TASK_BY_TASK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+213;
+    int START_LOCK_TASK_BY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+214;
+    int STOP_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+215;
+    int IS_IN_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+216;
 }