Merge "Implement SkiaRecordingCanvas, RenderNodeDrawable and other drawables."
diff --git a/api/current.txt b/api/current.txt
index 42be478..47968de 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1041,6 +1041,7 @@
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
     field public static final int rotation = 16843558; // 0x1010326
+    field public static final int rotationAnimation = 16843688; // 0x10103a8
     field public static final int rotationX = 16843559; // 0x1010327
     field public static final int rotationY = 16843560; // 0x1010328
     field public static final int roundIcon = 16844076; // 0x101052c
@@ -6520,6 +6521,7 @@
   public static class NetworkStats.Bucket {
     ctor public NetworkStats.Bucket();
     method public long getEndTimeStamp();
+    method public int getMetered();
     method public int getRoaming();
     method public long getRxBytes();
     method public long getRxPackets();
@@ -6529,6 +6531,9 @@
     method public long getTxBytes();
     method public long getTxPackets();
     method public int getUid();
+    field public static final int METERED_ALL = -1; // 0xffffffff
+    field public static final int METERED_NO = 1; // 0x1
+    field public static final int METERED_YES = 2; // 0x2
     field public static final int ROAMING_ALL = -1; // 0xffffffff
     field public static final int ROAMING_NO = 1; // 0x1
     field public static final int ROAMING_YES = 2; // 0x2
@@ -10057,7 +10062,7 @@
     field public static final deprecated int PROTECTION_FLAG_SYSTEM = 16; // 0x10
     field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200
     field public static final int PROTECTION_MASK_BASE = 15; // 0xf
-    field public static final int PROTECTION_MASK_FLAGS = 4080; // 0xff0
+    field public static final int PROTECTION_MASK_FLAGS = 65520; // 0xfff0
     field public static final int PROTECTION_NORMAL = 0; // 0x0
     field public static final int PROTECTION_SIGNATURE = 2; // 0x2
     field public static final deprecated int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3
@@ -11792,14 +11797,14 @@
     method public deprecated boolean clipRegion(android.graphics.Region);
     method public void concat(android.graphics.Matrix);
     method public void drawARGB(int, int, int, int);
-    method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
     method public void drawArc(float, float, float, float, float, float, boolean, android.graphics.Paint);
+    method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
     method public void drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint);
-    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint);
+    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint);
     method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint);
+    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint);
     method public deprecated void drawBitmap(int[], int, int, float, float, int, int, boolean, android.graphics.Paint);
     method public deprecated void drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint);
-    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint);
     method public void drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint);
     method public void drawCircle(float, float, float, android.graphics.Paint);
     method public void drawColor(int);
@@ -11807,28 +11812,28 @@
     method public void drawLine(float, float, float, float, android.graphics.Paint);
     method public void drawLines(float[], int, int, android.graphics.Paint);
     method public void drawLines(float[], android.graphics.Paint);
-    method public void drawOval(android.graphics.RectF, android.graphics.Paint);
     method public void drawOval(float, float, float, float, android.graphics.Paint);
+    method public void drawOval(android.graphics.RectF, android.graphics.Paint);
     method public void drawPaint(android.graphics.Paint);
     method public void drawPath(android.graphics.Path, android.graphics.Paint);
     method public void drawPicture(android.graphics.Picture);
-    method public void drawPicture(android.graphics.Picture, android.graphics.RectF);
     method public void drawPicture(android.graphics.Picture, android.graphics.Rect);
+    method public void drawPicture(android.graphics.Picture, android.graphics.RectF);
     method public void drawPoint(float, float, android.graphics.Paint);
     method public void drawPoints(float[], int, int, android.graphics.Paint);
     method public void drawPoints(float[], android.graphics.Paint);
     method public deprecated void drawPosText(char[], int, int, float[], android.graphics.Paint);
     method public deprecated void drawPosText(java.lang.String, float[], android.graphics.Paint);
     method public void drawRGB(int, int, int);
-    method public void drawRect(android.graphics.RectF, android.graphics.Paint);
-    method public void drawRect(android.graphics.Rect, android.graphics.Paint);
     method public void drawRect(float, float, float, float, android.graphics.Paint);
-    method public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint);
+    method public void drawRect(android.graphics.Rect, android.graphics.Paint);
+    method public void drawRect(android.graphics.RectF, android.graphics.Paint);
     method public void drawRoundRect(float, float, float, float, float, float, android.graphics.Paint);
+    method public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint);
     method public void drawText(char[], int, int, float, float, android.graphics.Paint);
+    method public void drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint);
     method public void drawText(java.lang.String, float, float, android.graphics.Paint);
     method public void drawText(java.lang.String, int, int, float, float, android.graphics.Paint);
-    method public void drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint);
     method public void drawTextOnPath(char[], int, int, android.graphics.Path, float, float, android.graphics.Paint);
     method public void drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint);
     method public void drawTextRun(char[], int, int, int, int, float, float, boolean, android.graphics.Paint);
diff --git a/api/system-current.txt b/api/system-current.txt
index 810d973..ff5e8735 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1147,6 +1147,7 @@
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
     field public static final int rotation = 16843558; // 0x1010326
+    field public static final int rotationAnimation = 16843688; // 0x10103a8
     field public static final int rotationX = 16843559; // 0x1010327
     field public static final int rotationY = 16843560; // 0x1010328
     field public static final int roundIcon = 16844076; // 0x101052c
@@ -6809,6 +6810,7 @@
   public static class NetworkStats.Bucket {
     ctor public NetworkStats.Bucket();
     method public long getEndTimeStamp();
+    method public int getMetered();
     method public int getRoaming();
     method public long getRxBytes();
     method public long getRxPackets();
@@ -6818,6 +6820,9 @@
     method public long getTxBytes();
     method public long getTxPackets();
     method public int getUid();
+    field public static final int METERED_ALL = -1; // 0xffffffff
+    field public static final int METERED_NO = 1; // 0x1
+    field public static final int METERED_YES = 2; // 0x2
     field public static final int ROAMING_ALL = -1; // 0xffffffff
     field public static final int ROAMING_NO = 1; // 0x1
     field public static final int ROAMING_YES = 2; // 0x2
@@ -10482,6 +10487,7 @@
     field public static final int PROTECTION_DANGEROUS = 1; // 0x1
     field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40
     field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
+    field public static final int PROTECTION_FLAG_EPHEMERAL = 4096; // 0x1000
     field public static final int PROTECTION_FLAG_INSTALLER = 256; // 0x100
     field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80
     field public static final int PROTECTION_FLAG_PREINSTALLED = 1024; // 0x400
@@ -10490,7 +10496,7 @@
     field public static final deprecated int PROTECTION_FLAG_SYSTEM = 16; // 0x10
     field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200
     field public static final int PROTECTION_MASK_BASE = 15; // 0xf
-    field public static final int PROTECTION_MASK_FLAGS = 4080; // 0xff0
+    field public static final int PROTECTION_MASK_FLAGS = 65520; // 0xfff0
     field public static final int PROTECTION_NORMAL = 0; // 0x0
     field public static final int PROTECTION_SIGNATURE = 2; // 0x2
     field public static final deprecated int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3
@@ -12239,14 +12245,14 @@
     method public deprecated boolean clipRegion(android.graphics.Region);
     method public void concat(android.graphics.Matrix);
     method public void drawARGB(int, int, int, int);
-    method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
     method public void drawArc(float, float, float, float, float, float, boolean, android.graphics.Paint);
+    method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
     method public void drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint);
-    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint);
+    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint);
     method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint);
+    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint);
     method public deprecated void drawBitmap(int[], int, int, float, float, int, int, boolean, android.graphics.Paint);
     method public deprecated void drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint);
-    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint);
     method public void drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint);
     method public void drawCircle(float, float, float, android.graphics.Paint);
     method public void drawColor(int);
@@ -12254,28 +12260,28 @@
     method public void drawLine(float, float, float, float, android.graphics.Paint);
     method public void drawLines(float[], int, int, android.graphics.Paint);
     method public void drawLines(float[], android.graphics.Paint);
-    method public void drawOval(android.graphics.RectF, android.graphics.Paint);
     method public void drawOval(float, float, float, float, android.graphics.Paint);
+    method public void drawOval(android.graphics.RectF, android.graphics.Paint);
     method public void drawPaint(android.graphics.Paint);
     method public void drawPath(android.graphics.Path, android.graphics.Paint);
     method public void drawPicture(android.graphics.Picture);
-    method public void drawPicture(android.graphics.Picture, android.graphics.RectF);
     method public void drawPicture(android.graphics.Picture, android.graphics.Rect);
+    method public void drawPicture(android.graphics.Picture, android.graphics.RectF);
     method public void drawPoint(float, float, android.graphics.Paint);
     method public void drawPoints(float[], int, int, android.graphics.Paint);
     method public void drawPoints(float[], android.graphics.Paint);
     method public deprecated void drawPosText(char[], int, int, float[], android.graphics.Paint);
     method public deprecated void drawPosText(java.lang.String, float[], android.graphics.Paint);
     method public void drawRGB(int, int, int);
-    method public void drawRect(android.graphics.RectF, android.graphics.Paint);
-    method public void drawRect(android.graphics.Rect, android.graphics.Paint);
     method public void drawRect(float, float, float, float, android.graphics.Paint);
-    method public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint);
+    method public void drawRect(android.graphics.Rect, android.graphics.Paint);
+    method public void drawRect(android.graphics.RectF, android.graphics.Paint);
     method public void drawRoundRect(float, float, float, float, float, float, android.graphics.Paint);
+    method public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint);
     method public void drawText(char[], int, int, float, float, android.graphics.Paint);
+    method public void drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint);
     method public void drawText(java.lang.String, float, float, android.graphics.Paint);
     method public void drawText(java.lang.String, int, int, float, float, android.graphics.Paint);
-    method public void drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint);
     method public void drawTextOnPath(char[], int, int, android.graphics.Path, float, float, android.graphics.Paint);
     method public void drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint);
     method public void drawTextRun(char[], int, int, int, int, float, float, boolean, android.graphics.Paint);
diff --git a/api/test-current.txt b/api/test-current.txt
index 249b339..907f9a4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1041,6 +1041,7 @@
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
     field public static final int rotation = 16843558; // 0x1010326
+    field public static final int rotationAnimation = 16843688; // 0x10103a8
     field public static final int rotationX = 16843559; // 0x1010327
     field public static final int rotationY = 16843560; // 0x1010328
     field public static final int roundIcon = 16844076; // 0x101052c
@@ -6529,6 +6530,7 @@
   public static class NetworkStats.Bucket {
     ctor public NetworkStats.Bucket();
     method public long getEndTimeStamp();
+    method public int getMetered();
     method public int getRoaming();
     method public long getRxBytes();
     method public long getRxPackets();
@@ -6538,6 +6540,9 @@
     method public long getTxBytes();
     method public long getTxPackets();
     method public int getUid();
+    field public static final int METERED_ALL = -1; // 0xffffffff
+    field public static final int METERED_NO = 1; // 0x1
+    field public static final int METERED_YES = 2; // 0x2
     field public static final int ROAMING_ALL = -1; // 0xffffffff
     field public static final int ROAMING_NO = 1; // 0x1
     field public static final int ROAMING_YES = 2; // 0x2
@@ -10065,6 +10070,7 @@
     field public static final int PROTECTION_DANGEROUS = 1; // 0x1
     field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40
     field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
+    field public static final int PROTECTION_FLAG_EPHEMERAL = 4096; // 0x1000
     field public static final int PROTECTION_FLAG_INSTALLER = 256; // 0x100
     field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80
     field public static final int PROTECTION_FLAG_PREINSTALLED = 1024; // 0x400
@@ -10073,7 +10079,7 @@
     field public static final deprecated int PROTECTION_FLAG_SYSTEM = 16; // 0x10
     field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200
     field public static final int PROTECTION_MASK_BASE = 15; // 0xf
-    field public static final int PROTECTION_MASK_FLAGS = 4080; // 0xff0
+    field public static final int PROTECTION_MASK_FLAGS = 65520; // 0xfff0
     field public static final int PROTECTION_NORMAL = 0; // 0x0
     field public static final int PROTECTION_SIGNATURE = 2; // 0x2
     field public static final deprecated int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3
@@ -11809,14 +11815,14 @@
     method public deprecated boolean clipRegion(android.graphics.Region);
     method public void concat(android.graphics.Matrix);
     method public void drawARGB(int, int, int, int);
-    method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
     method public void drawArc(float, float, float, float, float, float, boolean, android.graphics.Paint);
+    method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
     method public void drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint);
-    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint);
+    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint);
     method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint);
+    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint);
     method public deprecated void drawBitmap(int[], int, int, float, float, int, int, boolean, android.graphics.Paint);
     method public deprecated void drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint);
-    method public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint);
     method public void drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint);
     method public void drawCircle(float, float, float, android.graphics.Paint);
     method public void drawColor(int);
@@ -11824,28 +11830,28 @@
     method public void drawLine(float, float, float, float, android.graphics.Paint);
     method public void drawLines(float[], int, int, android.graphics.Paint);
     method public void drawLines(float[], android.graphics.Paint);
-    method public void drawOval(android.graphics.RectF, android.graphics.Paint);
     method public void drawOval(float, float, float, float, android.graphics.Paint);
+    method public void drawOval(android.graphics.RectF, android.graphics.Paint);
     method public void drawPaint(android.graphics.Paint);
     method public void drawPath(android.graphics.Path, android.graphics.Paint);
     method public void drawPicture(android.graphics.Picture);
-    method public void drawPicture(android.graphics.Picture, android.graphics.RectF);
     method public void drawPicture(android.graphics.Picture, android.graphics.Rect);
+    method public void drawPicture(android.graphics.Picture, android.graphics.RectF);
     method public void drawPoint(float, float, android.graphics.Paint);
     method public void drawPoints(float[], int, int, android.graphics.Paint);
     method public void drawPoints(float[], android.graphics.Paint);
     method public deprecated void drawPosText(char[], int, int, float[], android.graphics.Paint);
     method public deprecated void drawPosText(java.lang.String, float[], android.graphics.Paint);
     method public void drawRGB(int, int, int);
-    method public void drawRect(android.graphics.RectF, android.graphics.Paint);
-    method public void drawRect(android.graphics.Rect, android.graphics.Paint);
     method public void drawRect(float, float, float, float, android.graphics.Paint);
-    method public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint);
+    method public void drawRect(android.graphics.Rect, android.graphics.Paint);
+    method public void drawRect(android.graphics.RectF, android.graphics.Paint);
     method public void drawRoundRect(float, float, float, float, float, float, android.graphics.Paint);
+    method public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint);
     method public void drawText(char[], int, int, float, float, android.graphics.Paint);
+    method public void drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint);
     method public void drawText(java.lang.String, float, float, android.graphics.Paint);
     method public void drawText(java.lang.String, int, int, float, float, android.graphics.Paint);
-    method public void drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint);
     method public void drawTextOnPath(char[], int, int, android.graphics.Path, float, float, android.graphics.Paint);
     method public void drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint);
     method public void drawTextRun(char[], int, int, int, int, float, float, boolean, android.graphics.Paint);
diff --git a/core/java/android/app/ActivityManager.aidl b/core/java/android/app/ActivityManager.aidl
index 92350da..fa6481b 100644
--- a/core/java/android/app/ActivityManager.aidl
+++ b/core/java/android/app/ActivityManager.aidl
@@ -17,3 +17,4 @@
 package android.app;
 
 parcelable ActivityManager.RecentTaskInfo;
+parcelable ActivityManager.TaskDescription;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index a2f7aea..82cea8a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -964,6 +964,14 @@
             return true;
         }
 
+        case UNREGISTER_TASK_STACK_LISTENER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            unregisterTaskStackListener(ITaskStackListener.Stub.asInterface(token));
+            reply.writeNoException();
+            return true;
+        }
+
         case GET_TASK_FOR_ACTIVITY_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
@@ -4208,6 +4216,18 @@
         data.recycle();
         reply.recycle();
     }
+    @Override
+    public void unregisterTaskStackListener(ITaskStackListener listener) throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(listener.asBinder());
+        mRemote.transact(UNREGISTER_TASK_STACK_LISTENER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
     public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException
     {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 3670c58..3f11a7f 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -214,6 +214,7 @@
     public int getFocusedStackId() throws RemoteException;
     public void setFocusedTask(int taskId) throws RemoteException;
     public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException;
+    public void unregisterTaskStackListener(ITaskStackListener listener) throws RemoteException;
     public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException;
     public ContentProviderHolder getContentProvider(IApplicationThread caller,
             String name, int userId, boolean stable) throws RemoteException;
@@ -1114,4 +1115,5 @@
     int GET_DEFAULT_PICTURE_IN_PICTURE_BOUNDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 401;
     int GET_PICTURE_IN_PICTURE_MOVEMENT_BOUNDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 402;
     int UPDATE_DISPLAY_OVERRIDE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 403;
+    int UNREGISTER_TASK_STACK_LISTENER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+404;
 }
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 496ca6f..e454ae1 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -16,6 +16,9 @@
 
 package android.app;
 
+import android.app.ActivityManager;
+import android.content.ComponentName;
+
 /** @hide */
 oneway interface ITaskStackListener {
     /** Called whenever there are changes to the state of tasks in a stack. */
@@ -45,4 +48,51 @@
      * Callen when we launched an activity that is dismissed the docked stack.
      */
     void onActivityDismissingDockedStack();
+
+    /**
+     * Called when a task is added.
+     *
+     * @param taskId id of the task.
+     * @param componentName of the activity that the task is being started with.
+    */
+    void onTaskCreated(int taskId, in ComponentName componentName);
+
+    /**
+     * Called when a task is removed.
+     *
+     * @param taskId id of the task.
+    */
+    void onTaskRemoved(int taskId);
+
+    /**
+     * Called when a task is moved to the front of its stack.
+     *
+     * @param taskId id of the task.
+    */
+    void onTaskMovedToFront(int taskId);
+
+    /**
+     * Called when a task’s description is changed due to an activity calling
+     * ActivityManagerService.setTaskDescription
+     *
+     * @param taskId id of the task.
+     * @param td the new TaskDescription.
+    */
+    void onTaskDescriptionChanged(int taskId, in ActivityManager.TaskDescription td);
+
+    /**
+     * Called when a activity’s orientation is changed due to it calling
+     * ActivityManagerService.setRequestedOrientation
+     *
+     * @param taskId id of the task that the activity is in.
+     * @param requestedOrientation the new requested orientation.
+    */
+    void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation);
+
+    /**
+     * Called when the task is about to be finished but before its surfaces are
+     * removed from the window manager. This allows interested parties to
+     * perform relevant animations before the window disappears.
+     */
+    void onTaskRemovalStarted(int taskId);
 }
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
new file mode 100644
index 0000000..0639552
--- /dev/null
+++ b/core/java/android/app/TaskStackListener.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.ComponentName;
+import android.os.RemoteException;
+
+/**
+ * Classes interested in observing only a subset of changes using ITaskStackListener can extend
+ * this class to avoid having to implement all the methods.
+ * @hide
+ */
+public abstract class TaskStackListener extends ITaskStackListener.Stub {
+    @Override
+    public void onTaskStackChanged() throws RemoteException {
+    }
+
+    @Override
+    public void onActivityPinned() throws RemoteException {
+    }
+
+    @Override
+    public void onPinnedActivityRestartAttempt() throws RemoteException {
+    }
+
+    @Override
+    public void onPinnedStackAnimationEnded() throws RemoteException {
+    }
+
+    @Override
+    public void onActivityForcedResizable(String packageName, int taskId) throws RemoteException {
+    }
+
+    @Override
+    public void onActivityDismissingDockedStack() throws RemoteException {
+    }
+
+    @Override
+    public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
+    }
+
+    @Override
+    public void onTaskRemoved(int taskId) throws RemoteException {
+    }
+
+    @Override
+    public void onTaskMovedToFront(int taskId) throws RemoteException {
+    }
+
+    @Override
+    public void onTaskRemovalStarted(int taskId) {
+    }
+
+    @Override
+    public void onTaskDescriptionChanged(int taskId, ActivityManager.TaskDescription td)
+            throws RemoteException {
+    }
+
+    @Override
+    public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation)
+            throws RemoteException {
+    }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9ce9dec..118e1f3 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1095,7 +1095,7 @@
      * names.  If there are no administrators {@code null} may be
      * returned.
      */
-    public List<ComponentName> getActiveAdmins() {
+    public @Nullable List<ComponentName> getActiveAdmins() {
         throwIfParentInstance("getActiveAdmins");
         return getActiveAdminsAsUser(myUserId());
     }
@@ -1104,7 +1104,7 @@
      * @see #getActiveAdmins()
      * @hide
      */
-    public List<ComponentName> getActiveAdminsAsUser(int userId) {
+    public @Nullable List<ComponentName> getActiveAdminsAsUser(int userId) {
         if (mService != null) {
             try {
                 return mService.getActiveAdmins(userId);
@@ -2500,7 +2500,7 @@
      *            of the device admin that sets the proxy.
      * @hide
      */
-    public ComponentName setGlobalProxy(@NonNull ComponentName admin, Proxy proxySpec,
+    public @Nullable ComponentName setGlobalProxy(@NonNull ComponentName admin, Proxy proxySpec,
             List<String> exclusionList ) {
         throwIfParentInstance("setGlobalProxy");
         if (proxySpec == null) {
@@ -2584,7 +2584,7 @@
      *         if no admin has set the proxy.
      * @hide
      */
-    public ComponentName getGlobalProxyAdmin() {
+    public @Nullable ComponentName getGlobalProxyAdmin() {
         if (mService != null) {
             try {
                 return mService.getGlobalProxyAdmin(myUserId());
@@ -2894,8 +2894,8 @@
      * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
      *         owner.
      */
-    public List<byte[]> getInstalledCaCerts(@Nullable ComponentName admin) {
-        List<byte[]> certs = new ArrayList<byte[]>();
+    public @NonNull List<byte[]> getInstalledCaCerts(@Nullable ComponentName admin) {
+        final List<byte[]> certs = new ArrayList<byte[]>();
         throwIfParentInstance("getInstalledCaCerts");
         if (mService != null) {
             try {
@@ -3108,7 +3108,8 @@
      *         none is set.
      * @throws SecurityException if {@code admin} is not a device or a profile owner.
      */
-    public String getCertInstallerPackage(@NonNull ComponentName admin) throws SecurityException {
+    public @Nullable String getCertInstallerPackage(@NonNull ComponentName admin)
+            throws SecurityException {
         throwIfParentInstance("getCertInstallerPackage");
         if (mService != null) {
             try {
@@ -3177,7 +3178,7 @@
      *         is set.
      * @throws SecurityException if {@code admin} is not a device or a profile owner.
      */
-    public String getAlwaysOnVpnPackage(@NonNull ComponentName admin) {
+    public @Nullable String getAlwaysOnVpnPackage(@NonNull ComponentName admin) {
         throwIfParentInstance("getAlwaysOnVpnPackage");
         if (mService != null) {
             try {
@@ -3798,7 +3799,7 @@
      * @hide
      */
     @SystemApi
-    public String getDeviceOwner() {
+    public @Nullable String getDeviceOwner() {
         throwIfParentInstance("getDeviceOwner");
         final ComponentName name = getDeviceOwnerComponentOnCallingUser();
         return name != null ? name.getPackageName() : null;
@@ -3843,7 +3844,7 @@
      */
     @Deprecated
     @SystemApi
-    public String getDeviceInitializerApp() {
+    public @Nullable String getDeviceInitializerApp() {
         return null;
     }
 
@@ -3854,7 +3855,7 @@
      */
     @Deprecated
     @SystemApi
-    public ComponentName getDeviceInitializerComponent() {
+    public @Nullable ComponentName getDeviceInitializerComponent() {
         return null;
     }
 
@@ -4020,8 +4021,8 @@
      *         this method.
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
-    public String[] setPackagesSuspended(@NonNull ComponentName admin, String[] packageNames,
-            boolean suspended) {
+    public @NonNull String[] setPackagesSuspended(@NonNull ComponentName admin,
+            @NonNull String[] packageNames, boolean suspended) {
         throwIfParentInstance("setPackagesSuspended");
         if (mService != null) {
             try {
@@ -4128,7 +4129,7 @@
      * @throws IllegalArgumentException if the userId is invalid.
      */
     @SystemApi
-    public ComponentName getProfileOwner() throws IllegalArgumentException {
+    public @Nullable ComponentName getProfileOwner() throws IllegalArgumentException {
         throwIfParentInstance("getProfileOwner");
         return getProfileOwnerAsUser(Process.myUserHandle().getIdentifier());
     }
@@ -4137,7 +4138,8 @@
      * @see #getProfileOwner()
      * @hide
      */
-    public ComponentName getProfileOwnerAsUser(final int userId) throws IllegalArgumentException {
+    public @Nullable ComponentName getProfileOwnerAsUser(final int userId)
+            throws IllegalArgumentException {
         if (mService != null) {
             try {
                 return mService.getProfileOwner(userId);
@@ -4154,7 +4156,7 @@
      *         if one is not set.
      * @throws IllegalArgumentException if the userId is invalid.
      */
-    public String getProfileOwnerName() throws IllegalArgumentException {
+    public @Nullable String getProfileOwnerName() throws IllegalArgumentException {
         if (mService != null) {
             try {
                 return mService.getProfileOwnerName(Process.myUserHandle().getIdentifier());
@@ -4173,7 +4175,7 @@
      * @throws IllegalArgumentException if the userId is invalid.
      */
     @SystemApi
-    public String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException {
+    public @Nullable String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException {
         throwIfParentInstance("getProfileOwnerNameAsUser");
         if (mService != null) {
             try {
@@ -4278,7 +4280,8 @@
      *         {@code null} if none is set.
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
-    public String getApplicationRestrictionsManagingPackage(@NonNull ComponentName admin) {
+    public @Nullable String getApplicationRestrictionsManagingPackage(
+            @NonNull ComponentName admin) {
         throwIfParentInstance("getApplicationRestrictionsManagingPackage");
         if (mService != null) {
             try {
@@ -4416,14 +4419,14 @@
      * @param agent Which component to get enabled features for.
      * @return configuration for the given trust agent.
      */
-    public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin,
-            @NonNull ComponentName agent) {
+    public @Nullable List<PersistableBundle> getTrustAgentConfiguration(
+            @Nullable ComponentName admin, @NonNull ComponentName agent) {
         return getTrustAgentConfiguration(admin, agent, myUserId());
     }
 
     /** @hide per-user version */
-    public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin,
-            @NonNull ComponentName agent, int userHandle) {
+    public @Nullable List<PersistableBundle> getTrustAgentConfiguration(
+            @Nullable ComponentName admin, @NonNull ComponentName agent, int userHandle) {
         if (mService != null) {
             try {
                 return mService.getTrustAgentConfiguration(admin, agent, userHandle,
@@ -4738,7 +4741,7 @@
      * @return List of accessiblity service package names.
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
-    public List<String> getPermittedAccessibilityServices(@NonNull ComponentName admin) {
+    public @Nullable List<String> getPermittedAccessibilityServices(@NonNull ComponentName admin) {
         throwIfParentInstance("getPermittedAccessibilityServices");
         if (mService != null) {
             try {
@@ -4786,7 +4789,7 @@
      * @hide
      */
      @SystemApi
-     public List<String> getPermittedAccessibilityServices(int userId) {
+     public @Nullable List<String> getPermittedAccessibilityServices(int userId) {
         throwIfParentInstance("getPermittedAccessibilityServices");
         if (mService != null) {
             try {
@@ -4840,7 +4843,7 @@
      * @return List of input method package names.
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
-    public List<String> getPermittedInputMethods(@NonNull ComponentName admin) {
+    public @Nullable List<String> getPermittedInputMethods(@NonNull ComponentName admin) {
         throwIfParentInstance("getPermittedInputMethods");
         if (mService != null) {
             try {
@@ -4886,7 +4889,7 @@
      * @hide
      */
     @SystemApi
-    public List<String> getPermittedInputMethodsForCurrentUser() {
+    public @Nullable List<String> getPermittedInputMethodsForCurrentUser() {
         throwIfParentInstance("getPermittedInputMethodsForCurrentUser");
         if (mService != null) {
             try {
@@ -4907,7 +4910,7 @@
      * @return List of package names to keep cached.
      * @hide
      */
-    public List<String> getKeepUninstalledPackages(@NonNull ComponentName admin) {
+    public @Nullable List<String> getKeepUninstalledPackages(@NonNull ComponentName admin) {
         throwIfParentInstance("getKeepUninstalledPackages");
         if (mService != null) {
             try {
@@ -4959,7 +4962,7 @@
      * @removed From {@link android.os.Build.VERSION_CODES#N}
      */
     @Deprecated
-    public UserHandle createUser(@NonNull ComponentName admin, String name) {
+    public @Nullable UserHandle createUser(@NonNull ComponentName admin, String name) {
         return null;
     }
 
@@ -4992,7 +4995,7 @@
      * @removed From {@link android.os.Build.VERSION_CODES#N}
      */
     @Deprecated
-    public UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name,
+    public @Nullable UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name,
             String ownerName, @NonNull ComponentName profileOwnerComponent, Bundle adminExtras) {
         return null;
     }
@@ -5037,7 +5040,8 @@
      *         user could not be created.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public UserHandle createAndManageUser(@NonNull ComponentName admin, @NonNull String name,
+    public @Nullable UserHandle createAndManageUser(@NonNull ComponentName admin,
+            @NonNull String name,
             @NonNull ComponentName profileOwner, @Nullable PersistableBundle adminExtras,
             int flags) {
         throwIfParentInstance("createAndManageUser");
@@ -5104,7 +5108,8 @@
      * @see {@link #setApplicationRestrictionsManagingPackage}
      */
     @WorkerThread
-    public Bundle getApplicationRestrictions(@Nullable ComponentName admin, String packageName) {
+    public @NonNull Bundle getApplicationRestrictions(
+            @Nullable ComponentName admin, String packageName) {
         throwIfParentInstance("getApplicationRestrictions");
         if (mService != null) {
             try {
@@ -5171,7 +5176,7 @@
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
-    public Bundle getUserRestrictions(@NonNull ComponentName admin) {
+    public @NonNull Bundle getUserRestrictions(@NonNull ComponentName admin) {
         throwIfParentInstance("getUserRestrictions");
         Bundle ret = null;
         if (mService != null) {
@@ -5311,7 +5316,7 @@
      *
      * @see #setAccountManagementDisabled
      */
-    public String[] getAccountTypesWithManagementDisabled() {
+    public @Nullable String[] getAccountTypesWithManagementDisabled() {
         throwIfParentInstance("getAccountTypesWithManagementDisabled");
         return getAccountTypesWithManagementDisabledAsUser(myUserId());
     }
@@ -5320,7 +5325,7 @@
      * @see #getAccountTypesWithManagementDisabled()
      * @hide
      */
-    public String[] getAccountTypesWithManagementDisabledAsUser(int userId) {
+    public @Nullable String[] getAccountTypesWithManagementDisabledAsUser(int userId) {
         if (mService != null) {
             try {
                 return mService.getAccountTypesWithManagementDisabledAsUser(userId);
@@ -5366,7 +5371,7 @@
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @hide
      */
-    public String[] getLockTaskPackages(@NonNull ComponentName admin) {
+    public @NonNull String[] getLockTaskPackages(@NonNull ComponentName admin) {
         throwIfParentInstance("getLockTaskPackages");
         if (mService != null) {
             try {
@@ -5651,7 +5656,7 @@
      * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String)
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
-    public List<String> getCrossProfileWidgetProviders(@NonNull ComponentName admin) {
+    public @NonNull List<String> getCrossProfileWidgetProviders(@NonNull ComponentName admin) {
         throwIfParentInstance("getCrossProfileWidgetProviders");
         if (mService != null) {
             try {
@@ -5709,7 +5714,7 @@
      *
      * @return The current policy object, or {@code null} if no policy is set.
      */
-    public SystemUpdatePolicy getSystemUpdatePolicy() {
+    public @Nullable SystemUpdatePolicy getSystemUpdatePolicy() {
         throwIfParentInstance("getSystemUpdatePolicy");
         if (mService != null) {
             try {
@@ -5948,7 +5953,7 @@
      *         The address will be in the {@code XX:XX:XX:XX:XX:XX} format.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public String getWifiMacAddress(@NonNull ComponentName admin) {
+    public @Nullable String getWifiMacAddress(@NonNull ComponentName admin) {
         throwIfParentInstance("getWifiMacAddress");
         try {
             return mService.getWifiMacAddress(admin);
@@ -6057,7 +6062,7 @@
      *         null if no message has been set.
      * @throws SecurityException if {@code admin} is not an active administrator.
      */
-    public CharSequence getLongSupportMessage(@NonNull ComponentName admin) {
+    public @Nullable CharSequence getLongSupportMessage(@NonNull ComponentName admin) {
         throwIfParentInstance("getLongSupportMessage");
         if (mService != null) {
             try {
@@ -6078,7 +6083,7 @@
      *
      * @hide
      */
-    public CharSequence getShortSupportMessageForUser(@NonNull ComponentName admin,
+    public @Nullable CharSequence getShortSupportMessageForUser(@NonNull ComponentName admin,
             int userHandle) {
         if (mService != null) {
             try {
@@ -6100,7 +6105,8 @@
      *
      * @hide
      */
-    public CharSequence getLongSupportMessageForUser(@NonNull ComponentName admin, int userHandle) {
+    public @Nullable CharSequence getLongSupportMessageForUser(
+            @NonNull ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
                 return mService.getLongSupportMessageForUser(admin, userHandle);
@@ -6155,7 +6161,7 @@
      * @return a new instance of {@link DevicePolicyManager} that acts on the parent profile.
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
-    public DevicePolicyManager getParentProfileInstance(@NonNull ComponentName admin) {
+    public @NonNull DevicePolicyManager getParentProfileInstance(@NonNull ComponentName admin) {
         throwIfParentInstance("getParentProfileInstance");
         try {
             if (!mService.isManagedProfile(admin)) {
@@ -6225,7 +6231,7 @@
      * or {@code null} if rate limitation is exceeded or if logging is currently disabled.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
+    public @Nullable List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
         throwIfParentInstance("retrieveSecurityLogs");
         try {
             ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
@@ -6246,7 +6252,7 @@
      *
      * @hide
      */
-    public DevicePolicyManager getParentProfileInstance(UserInfo uInfo) {
+    public @NonNull DevicePolicyManager getParentProfileInstance(UserInfo uInfo) {
         mContext.checkSelfPermission(
                 android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
         if (!uInfo.isManagedProfile()) {
@@ -6272,7 +6278,8 @@
      *         is not supported on the device.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public List<SecurityEvent> retrievePreRebootSecurityLogs(@NonNull ComponentName admin) {
+    public @Nullable List<SecurityEvent> retrievePreRebootSecurityLogs(
+            @NonNull ComponentName admin) {
         throwIfParentInstance("retrievePreRebootSecurityLogs");
         try {
             ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
@@ -6391,7 +6398,7 @@
      * @return The organization name or {@code null} if none is set.
      * @throws SecurityException if {@code admin} is not a profile owner.
      */
-    public CharSequence getOrganizationName(@NonNull ComponentName admin) {
+    public @Nullable CharSequence getOrganizationName(@NonNull ComponentName admin) {
         throwIfParentInstance("getOrganizationName");
         try {
             return mService.getOrganizationName(admin);
@@ -6408,7 +6415,7 @@
      *
      * @hide
      */
-    public CharSequence getOrganizationNameForUser(int userHandle) {
+    public @Nullable CharSequence getOrganizationNameForUser(int userHandle) {
         try {
             return mService.getOrganizationNameForUser(userHandle);
         } catch (RemoteException re) {
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index 226aa8f..f64bec7 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -164,6 +164,29 @@
         public static final int UID_TETHERING = TrafficStats.UID_TETHERING;
 
         /** @hide */
+        @IntDef({METERED_ALL, METERED_NO, METERED_YES})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Metered {}
+
+        /**
+         * Combined usage across all metered states. Covers metered and unmetered usage.
+         */
+        public static final int METERED_ALL = -1;
+
+        /**
+         * Usage that occurs on an unmetered network.
+         */
+        public static final int METERED_NO = 0x1;
+
+        /**
+         * Usage that occurs on a metered network.
+         *
+         * <p>A network is classified as metered when the user is sensitive to heavy data usage on
+         * that connection.
+         */
+        public static final int METERED_YES = 0x2;
+
+        /** @hide */
         @IntDef({ROAMING_ALL, ROAMING_NO, ROAMING_YES})
         @Retention(RetentionPolicy.SOURCE)
         public @interface Roaming {}
@@ -200,6 +223,7 @@
         private int mUid;
         private int mTag;
         private int mState;
+        private int mMetered;
         private int mRoaming;
         private long mBeginTimeStamp;
         private long mEndTimeStamp;
@@ -279,6 +303,21 @@
         }
 
         /**
+         * Metered state. One of the following values:<p/>
+         * <ul>
+         * <li>{@link #METERED_ALL}</li>
+         * <li>{@link #METERED_NO}</li>
+         * <li>{@link #METERED_YES}</li>
+         * </ul>
+         * <p>A network is classified as metered when the user is sensitive to heavy data usage on
+         * that connection. Apps may warn before using these networks for large downloads. The
+         * metered state can be set by the user within data usage network restrictions.
+         */
+        public @Metered int getMetered() {
+            return mMetered;
+        }
+
+        /**
          * Roaming state. One of the following values:<p/>
          * <ul>
          * <li>{@link #ROAMING_ALL}</li>
@@ -491,6 +530,8 @@
         bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
         bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag);
         bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
+        // TODO: Implement metered tracking.
+        bucketOut.mMetered = Bucket.METERED_ALL;
         bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming);
         bucketOut.mBeginTimeStamp = mStartTimeStamp;
         bucketOut.mEndTimeStamp = mEndTimeStamp;
@@ -539,6 +580,7 @@
                 bucketOut.mUid = Bucket.convertUid(getUid());
                 bucketOut.mTag = Bucket.convertTag(mTag);
                 bucketOut.mState = Bucket.STATE_ALL;
+                bucketOut.mMetered = Bucket.METERED_ALL;
                 bucketOut.mRoaming = Bucket.ROAMING_ALL;
                 bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
                 bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart +
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 4cbff5f..e2ebd46 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -26,6 +26,8 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
+
 /**
  * Information you can retrieve about a particular application
  * activity or receiver. This corresponds to information collected
@@ -763,6 +765,13 @@
      */
     public String parentActivityName;
 
+    /**
+     * Screen rotation animation desired by the activity, with values as defined
+     * for {@link android.view.WindowManager.LayoutParams#rotationAnimation}.
+     * @hide
+     */
+    public int rotationAnimation = ROTATION_ANIMATION_ROTATE;
+
     /** @hide */
     public static final int LOCK_TASK_LAUNCH_MODE_DEFAULT = 0;
     /** @hide */
@@ -822,6 +831,7 @@
         windowLayout = orig.windowLayout;
         resizeMode = orig.resizeMode;
         requestedVrComponent = orig.requestedVrComponent;
+        rotationAnimation = orig.rotationAnimation;
     }
 
     /**
@@ -972,6 +982,7 @@
         }
         dest.writeInt(resizeMode);
         dest.writeString(requestedVrComponent);
+        dest.writeInt(rotationAnimation);
     }
 
     public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -1006,6 +1017,7 @@
         }
         resizeMode = source.readInt();
         requestedVrComponent = source.readString();
+        rotationAnimation = source.readInt();
     }
 
     /**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 12e8d487..13c8ab1 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -98,6 +98,7 @@
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
 
 /**
  * Parser for package files (APKs) on disk. This supports apps packaged either
@@ -2599,9 +2600,10 @@
         perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
 
         if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
-            if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
+            if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_EPHEMERAL) == 0
+                    && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
                     PermissionInfo.PROTECTION_SIGNATURE) {
-                outError[0] = "<permission>  protectionLevel specifies a flag but is "
+                outError[0] = "<permission>  protectionLevel specifies a non-ephemeral flag but is "
                         + "not based on signature type";
                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                 return null;
@@ -3572,6 +3574,9 @@
 
             a.info.requestedVrComponent =
                 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
+
+            a.info.rotationAnimation =
+                sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_ROTATE);
         } else {
             a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
             a.info.configChanges = 0;
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 65e0b92..6901ba1 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -119,6 +120,17 @@
      */
     public static final int PROTECTION_FLAG_SETUP = 0x800;
 
+
+    /**
+     * Additional flag for {@link #protectionLevel}, corresponding
+     * to the <code>ephemeral</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int PROTECTION_FLAG_EPHEMERAL = 0x1000;
+
     /**
      * Mask for {@link #protectionLevel}: the basic protection type.
      */
@@ -127,7 +139,7 @@
     /**
      * Mask for {@link #protectionLevel}: additional flag bits.
      */
-    public static final int PROTECTION_MASK_FLAGS = 0xff0;
+    public static final int PROTECTION_MASK_FLAGS = 0xfff0;
 
     /**
      * The level of access this permission is protecting, as per
@@ -236,6 +248,9 @@
         if ((level&PermissionInfo.PROTECTION_FLAG_SETUP) != 0) {
             protLevel += "|setup";
         }
+        if ((level&PermissionInfo.PROTECTION_FLAG_EPHEMERAL) != 0) {
+            protLevel += "|ephemeral";
+        }
         return protLevel;
     }
 
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index e399be0..7b63b62 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -442,7 +442,6 @@
         // note that docsui treats this as *force* show advanced. So sending
         // false permits advanced to be shown based on user preferences.
         intent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, isPrimary());
-        intent.putExtra(DocumentsContract.EXTRA_FANCY_FEATURES, true);
         return intent;
     }
 
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 8bf57a7..20c7073 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -103,9 +103,6 @@
     public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
 
     /** {@hide} */
-    public static final String EXTRA_FANCY_FEATURES = "android.content.extra.FANCY";
-
-    /** {@hide} */
     public static final String EXTRA_TARGET_URI = "android.content.extra.TARGET_URI";
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d3a978c..03e0ebf 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8287,6 +8287,9 @@
         /** {@hide} */
         public static final String
                 BLUETOOTH_SAP_PRIORITY_PREFIX = "bluetooth_sap_priority_";
+        /** {@hide} */
+        public static final String
+                BLUETOOTH_PAN_PRIORITY_PREFIX = "bluetooth_pan_priority_";
 
         /**
          * Device Idle (Doze) specific settings.
@@ -8464,6 +8467,14 @@
         }
 
         /**
+         * Get the key that retrieves a bluetooth pan client priority.
+         * @hide
+         */
+        public static final String getBluetoothPanPriorityKey(String address) {
+            return BLUETOOTH_PAN_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
+        }
+
+        /**
          * Get the key that retrieves a bluetooth map priority.
          * @hide
          */
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 8023201..71c1d62 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -860,32 +860,35 @@
             android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;  // 0x00000001
 
     /**
-     * Called by the input method to commit a content such as PNG image to the editor.
+     * Called by the input method to commit content such as a PNG image to the editor.
      *
-     * <p>In order to avoid variety of compatibility issues, this focuses on a simple use case,
-     * where we expect editors and IMEs work cooperatively as follows:</p>
+     * <p>In order to avoid a variety of compatibility issues, this focuses on a simple use case,
+     * where editors and IMEs are expected to work cooperatively as follows:</p>
      * <ul>
-     *     <li>Editor must keep {@link EditorInfo#contentMimeTypes} to be {@code null} if it does
+     *     <li>Editor must keep {@link EditorInfo#contentMimeTypes} equal to {@code null} if it does
      *     not support this method at all.</li>
      *     <li>Editor can ignore this request when the MIME type specified in
-     *     {@code inputContentInfo} does not match to any of {@link EditorInfo#contentMimeTypes}.
+     *     {@code inputContentInfo} does not match any of {@link EditorInfo#contentMimeTypes}.
      *     </li>
-     *     <li>Editor can ignore the cursor position when inserting the provided context.</li>
+     *     <li>Editor can ignore the cursor position when inserting the provided content.</li>
      *     <li>Editor can return {@code true} asynchronously, even before it starts loading the
      *     content.</li>
-     *     <li>Editor should provide a way to delete the content inserted by this method, or revert
-     *     the effect caused by this method.</li>
+     *     <li>Editor should provide a way to delete the content inserted by this method or to
+     *     revert the effect caused by this method.</li>
      *     <li>IME should not call this method when there is any composing text, in case calling
-     *     this method causes focus change.</li>
+     *     this method causes a focus change.</li>
      *     <li>IME should grant a permission for the editor to read the content. See
      *     {@link EditorInfo#packageName} about how to obtain the package name of the editor.</li>
      * </ul>
      *
      * @param inputContentInfo Content to be inserted.
-     * @param flags {@code 0} or {@link #INPUT_CONTENT_GRANT_READ_URI_PERMISSION}.
+     * @param flags {@link #INPUT_CONTENT_GRANT_READ_URI_PERMISSION} if the content provider
+     * allows {@link android.R.styleable#AndroidManifestProvider_grantUriPermissions
+     * grantUriPermissions} or {@code 0} if the application does not need to call
+     * {@link InputContentInfo#requestPermission()}.
      * @param opts optional bundle data. This can be {@code null}.
-     * @return {@code true} if this request is accepted by the application, no matter if the request
-     * is already handled or still being handled in background.
+     * @return {@code true} if this request is accepted by the application, whether the request
+     * is already handled or still being handled in background, {@code false} otherwise.
      */
     public boolean commitContent(@NonNull InputContentInfo inputContentInfo, int flags,
             @Nullable Bundle opts);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index de6f2c5..b38bb1e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -723,7 +723,7 @@
         android:permissionGroup="android.permission-group.LOCATION"
         android:label="@string/permlab_accessFineLocation"
         android:description="@string/permdesc_accessFineLocation"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="dangerous|ephemeral" />
 
     <!-- Allows an app to access approximate location.
          <p>Protection level: dangerous
@@ -732,7 +732,7 @@
         android:permissionGroup="android.permission-group.LOCATION"
         android:label="@string/permlab_accessCoarseLocation"
         android:description="@string/permdesc_accessCoarseLocation"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="dangerous|ephemeral" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device telephony                         -->
@@ -763,7 +763,7 @@
         android:permissionGroup="android.permission-group.PHONE"
         android:label="@string/permlab_readPhoneState"
         android:description="@string/permdesc_readPhoneState"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="dangerous|ephemeral" />
 
     <!-- Allows an application to initiate a phone call without going through
         the Dialer user interface for the user to confirm the call.
@@ -1164,7 +1164,7 @@
     <permission android:name="android.permission.INTERNET"
         android:description="@string/permdesc_createNetworkSockets"
         android:label="@string/permlab_createNetworkSockets"
-        android:protectionLevel="normal" />
+        android:protectionLevel="normal|ephemeral" />
 
     <!-- Allows applications to access information about networks.
          <p>Protection level: normal
@@ -1354,7 +1354,7 @@
     <permission android:name="android.permission.VIBRATE"
         android:label="@string/permlab_vibrate"
         android:description="@string/permdesc_vibrate"
-        android:protectionLevel="normal" />
+        android:protectionLevel="normal|ephemeral" />
 
     <!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
          from dimming.
@@ -1363,7 +1363,7 @@
     <permission android:name="android.permission.WAKE_LOCK"
         android:label="@string/permlab_wakeLock"
         android:description="@string/permdesc_wakeLock"
-        android:protectionLevel="normal" />
+        android:protectionLevel="normal|ephemeral" />
 
     <!-- Allows using the device's IR transmitter, if available.
          <p>Protection level: normal
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index cad5854..967c4ad 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -242,6 +242,9 @@
         <!-- Additional flag from base permission type: this permission can be automatically
             granted to the setup wizard app -->
         <flag name="setup" value="0x800" />
+        <!-- Additional flag from base permission type: this permission can be granted to ephemeral
+             apps -->
+        <flag name="ephemeral" value="0x1000" />
     </attr>
 
     <!-- Flags indicating more context for a permission group. -->
@@ -575,6 +578,20 @@
          transtion from one VR activity to another. -->
     <attr name="enableVrMode" format="string" />
 
+    <!-- Flag allowing the activity to specify which screen rotation animation
+         it desires.  Valid values are "rotate", "crossfade", and "jumpcut"
+         as described in {@link android.view.WindowManager.LayoutParams#rotationAnimation}.
+         Specifying your Rotation animation in the WindowManager.LayoutParams
+         may be racy with app startup and updattransitions occuring during application startup and thusly
+         the manifest attribute is preferred.
+    -->
+    <attr name="rotationAnimation">
+      <flag name="rotate" value= "0" />
+      <flag name="crossfade" value = "1" />
+      <flag name="jumpcut" value = "2" />
+      <flag name="seamless" value = "3" />
+    </attr>
+
     <!-- Specify the order in which content providers hosted by a process
          are instantiated when that process is created.  Not needed unless
          you have providers with dependencies between each other, to make
@@ -1923,6 +1940,7 @@
         <!-- @hide This activity is a launcher which should always show up on the top of others.
              This attribute is ignored if the activity isn't a launcher. -->
         <attr name="onTopLauncher" format="boolean" />
+        <attr name="rotationAnimation"/>
     </declare-styleable>
 
     <!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5df33bd..567e920 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1368,6 +1368,9 @@
     <!-- Whether supported profiles should be reloaded upon enabling bluetooth -->
     <bool name="config_bluetooth_reload_supported_profiles_when_enabled">false</bool>
 
+    <!-- Enabling autoconnect over pan -->
+    <bool name="config_bluetooth_pan_enable_autoconnect">false</bool>
+
     <!-- The default data-use polling period. -->
     <integer name="config_datause_polling_period_sec">600</integer>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7999e7e..c06a93d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2765,4 +2765,5 @@
     </public-group>
 
     <public type="attr" name="min" />
+    <public type="attr" name="rotationAnimation" />
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 48cea84..e946136 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -368,6 +368,7 @@
   <java-symbol type="integer" name="config_bluetooth_rx_cur_ma" />
   <java-symbol type="integer" name="config_bluetooth_tx_cur_ma" />
   <java-symbol type="integer" name="config_bluetooth_operating_voltage_mv" />
+  <java-symbol type="bool" name="config_bluetooth_pan_enable_autoconnect" />
   <java-symbol type="bool" name="config_bluetooth_reload_supported_profiles_when_enabled" />
   <java-symbol type="integer" name="config_cursorWindowSize" />
   <java-symbol type="integer" name="config_drawLockTimeoutMillis" />
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java b/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java
index 366add0b..84745b2 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java
@@ -49,7 +49,6 @@
                 final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
                 intent.setData(uri);
                 intent.addCategory(Intent.CATEGORY_DEFAULT);
-                intent.putExtra(DocumentsContract.EXTRA_FANCY_FEATURES, true);
                 this.startActivity(intent);
             } catch (IOException exception) {
                 Log.e(MtpDocumentsProvider.TAG, "Failed to open device", exception);
diff --git a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
index b04948b..ebb5d19 100644
--- a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
@@ -82,11 +82,10 @@
 
         final String PROC_VERSION_REGEX =
                 "Linux version (\\S+) " + /* group 1: "3.0.31-g6fb96c9" */
-                "\\((\\S+?)\\) " +        /* group 2: "x@y.com" (kernel builder) */
-                "(?:\\(gcc.+? \\)) " +    /* ignore: GCC version information */
-                "(#\\d+) " +              /* group 3: "#1" */
-                "(?:.*?)?" +              /* ignore: optional SMP, PREEMPT, and any CONFIG_FLAGS */
-                "((Sun|Mon|Tue|Wed|Thu|Fri|Sat).+)"; /* group 4: "Thu Jun 28 11:02:39 PDT 2012" */
+                "\\((\\S+)\\)" +          /* group 2: "x@y.com" (kernel builder) */
+                ".*(#\\d+)" +             /* group 3: "#1" */
+                /* group 4: "Thu Jun 28 11:02:39 PDT 2012" */
+                ".*((?:Sun|Mon|Tue|Wed|Thu|Fri|Sat).+)";
 
         Matcher m = Pattern.compile(PROC_VERSION_REGEX).matcher(rawKernelVersion);
         if (!m.matches()) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 6a1b477..c91b060 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -160,7 +160,7 @@
      * ActivityManagerNative.
      * This simply passes callbacks to listeners through {@link H}.
      * */
-    private ITaskStackListener.Stub mTaskStackListener = new ITaskStackListener.Stub() {
+    private android.app.TaskStackListener mTaskStackListener = new android.app.TaskStackListener() {
         @Override
         public void onTaskStackChanged() throws RemoteException {
             mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f9121c3..41d07f2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -76,6 +76,7 @@
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManager.StackId;
 import android.app.ActivityManager.StackInfo;
+import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityManager.TaskThumbnailInfo;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerInternal.SleepToken;
@@ -524,9 +525,6 @@
     static final int ALLOW_NON_FULL_IN_PROFILE = 1;
     static final int ALLOW_FULL_ONLY = 2;
 
-    // Delay in notifying task stack change listeners (in millis)
-    static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
-
     // Necessary ApplicationInfo flags to mark an app as persistent
     private static final int PERSISTENT_MASK =
             ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
@@ -554,9 +552,7 @@
 
     final ActivityStarter mActivityStarter;
 
-    /** Task stack change listeners. */
-    private final RemoteCallbackList<ITaskStackListener> mTaskStackListeners =
-            new RemoteCallbackList<ITaskStackListener>();
+    final TaskChangeNotificationController mTaskChangeNotificationController;
 
     final InstrumentationReporter mInstrumentationReporter = new InstrumentationReporter();
 
@@ -1526,29 +1522,23 @@
     static final int START_USER_SWITCH_UI_MSG = 46;
     static final int SEND_LOCALE_TO_MOUNT_DAEMON_MSG = 47;
     static final int DISMISS_DIALOG_UI_MSG = 48;
-    static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 49;
-    static final int NOTIFY_CLEARTEXT_NETWORK_MSG = 50;
-    static final int POST_DUMP_HEAP_NOTIFICATION_MSG = 51;
-    static final int DELETE_DUMPHEAP_MSG = 52;
-    static final int FOREGROUND_PROFILE_CHANGED_MSG = 53;
-    static final int DISPATCH_UIDS_CHANGED_UI_MSG = 54;
-    static final int REPORT_TIME_TRACKER_MSG = 55;
-    static final int REPORT_USER_SWITCH_COMPLETE_MSG = 56;
-    static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 57;
-    static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 59;
-    static final int IDLE_UIDS_MSG = 60;
-    static final int SYSTEM_USER_UNLOCK_MSG = 61;
-    static final int LOG_STACK_STATE = 62;
-    static final int VR_MODE_CHANGE_MSG = 63;
-    static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 64;
-    static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 65;
-    static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 66;
-    static final int NOTIFY_FORCED_RESIZABLE_MSG = 67;
-    static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 68;
-    static final int VR_MODE_APPLY_IF_NEEDED_MSG = 69;
-    static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 70;
-    static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 71;
-    static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 72;
+    static final int NOTIFY_CLEARTEXT_NETWORK_MSG = 49;
+    static final int POST_DUMP_HEAP_NOTIFICATION_MSG = 50;
+    static final int DELETE_DUMPHEAP_MSG = 51;
+    static final int FOREGROUND_PROFILE_CHANGED_MSG = 52;
+    static final int DISPATCH_UIDS_CHANGED_UI_MSG = 53;
+    static final int REPORT_TIME_TRACKER_MSG = 54;
+    static final int REPORT_USER_SWITCH_COMPLETE_MSG = 55;
+    static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 56;
+    static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 57;
+    static final int IDLE_UIDS_MSG = 58;
+    static final int SYSTEM_USER_UNLOCK_MSG = 59;
+    static final int LOG_STACK_STATE = 60;
+    static final int VR_MODE_CHANGE_MSG = 61;
+    static final int VR_MODE_APPLY_IF_NEEDED_MSG = 62;
+    static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 63;
+    static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 64;
+    static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 65;
     static final int START_USER_SWITCH_FG_MSG = 712;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -2105,92 +2095,6 @@
                 }
                 break;
             }
-            case NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG: {
-                synchronized (ActivityManagerService.this) {
-                    for (int i = mTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
-                        try {
-                            // Make a one-way callback to the listener
-                            mTaskStackListeners.getBroadcastItem(i).onTaskStackChanged();
-                        } catch (RemoteException e){
-                            // Handled by the RemoteCallbackList
-                        }
-                    }
-                    mTaskStackListeners.finishBroadcast();
-                }
-                break;
-            }
-            case NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG: {
-                synchronized (ActivityManagerService.this) {
-                    for (int i = mTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
-                        try {
-                            // Make a one-way callback to the listener
-                            mTaskStackListeners.getBroadcastItem(i).onActivityPinned();
-                        } catch (RemoteException e){
-                            // Handled by the RemoteCallbackList
-                        }
-                    }
-                    mTaskStackListeners.finishBroadcast();
-                }
-                break;
-            }
-            case NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG: {
-                synchronized (ActivityManagerService.this) {
-                    for (int i = mTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
-                        try {
-                            // Make a one-way callback to the listener
-                            mTaskStackListeners.getBroadcastItem(i).onPinnedActivityRestartAttempt();
-                        } catch (RemoteException e){
-                            // Handled by the RemoteCallbackList
-                        }
-                    }
-                    mTaskStackListeners.finishBroadcast();
-                }
-                break;
-            }
-            case NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG: {
-                synchronized (ActivityManagerService.this) {
-                    for (int i = mTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
-                        try {
-                            // Make a one-way callback to the listener
-                            mTaskStackListeners.getBroadcastItem(i).onPinnedStackAnimationEnded();
-                        } catch (RemoteException e){
-                            // Handled by the RemoteCallbackList
-                        }
-                    }
-                    mTaskStackListeners.finishBroadcast();
-                }
-                break;
-            }
-            case NOTIFY_FORCED_RESIZABLE_MSG: {
-                synchronized (ActivityManagerService.this) {
-                    for (int i = mTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
-                        try {
-                            // Make a one-way callback to the listener
-                            mTaskStackListeners.getBroadcastItem(i).onActivityForcedResizable(
-                                    (String) msg.obj, msg.arg1);
-                        } catch (RemoteException e){
-                            // Handled by the RemoteCallbackList
-                        }
-                    }
-                    mTaskStackListeners.finishBroadcast();
-                }
-                break;
-            }
-                case NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG: {
-                    synchronized (ActivityManagerService.this) {
-                        for (int i = mTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
-                            try {
-                                // Make a one-way callback to the listener
-                                mTaskStackListeners.getBroadcastItem(i)
-                                        .onActivityDismissingDockedStack();
-                            } catch (RemoteException e){
-                                // Handled by the RemoteCallbackList
-                            }
-                        }
-                        mTaskStackListeners.finishBroadcast();
-                    }
-                    break;
-                }
             case NOTIFY_CLEARTEXT_NETWORK_MSG: {
                 final int uid = msg.arg1;
                 final byte[] firstPacket = (byte[]) msg.obj;
@@ -2322,11 +2226,6 @@
             case IDLE_UIDS_MSG: {
                 idleUids();
             } break;
-            case LOG_STACK_STATE: {
-                synchronized (ActivityManagerService.this) {
-                    mStackSupervisor.logStackState();
-                }
-            } break;
             case VR_MODE_CHANGE_MSG: {
                 VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
                 if (vrService == null) {
@@ -2730,6 +2629,8 @@
         mStackSupervisor.onConfigurationChanged(mTempConfig);
         mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
         mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
+        mTaskChangeNotificationController =
+                new TaskChangeNotificationController(this, mStackSupervisor, mHandler);
         mActivityStarter = new ActivityStarter(this, mStackSupervisor);
         mRecentTasks = new RecentTasks(this, mStackSupervisor);
 
@@ -3104,13 +3005,18 @@
     @Override
     public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException {
         enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "registerTaskStackListener()");
-        synchronized (this) {
-            if (listener != null) {
-                mTaskStackListeners.register(listener);
-            }
-        }
+        mTaskChangeNotificationController.registerTaskStackListener(listener);
     }
 
+    /**
+     * Unregister a task stack listener so that it stops receiving callbacks.
+     */
+    @Override
+    public void unregisterTaskStackListener(ITaskStackListener listener) throws RemoteException {
+         enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "unregisterTaskStackListener()");
+         mTaskChangeNotificationController.unregisterTaskStackListener(listener);
+     }
+
     @Override
     public void notifyActivityDrawn(IBinder token) {
         if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY, "notifyActivityDrawn: token=" + token);
@@ -7753,7 +7659,8 @@
             try {
                 PermissionInfo info = mActivityManagerService.mContext.getPackageManager()
                         .getPermissionInfo(permission, 0);
-                return info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS;
+                return (info.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+                        == PermissionInfo.PROTECTION_DANGEROUS;
             } catch (NameNotFoundException nnfe) {
                 Slog.e(TAG, "No such permission: "+ permission, nnfe);
             }
@@ -9411,7 +9318,6 @@
 
                 task.setLastThumbnailLocked(thumbnail);
                 task.freeLastThumbnail();
-
                 return task.taskId;
             }
         } finally {
@@ -9433,6 +9339,7 @@
             if (r != null) {
                 r.setTaskDescription(td);
                 r.task.updateTaskDescription();
+                mTaskChangeNotificationController.notifyTaskDescriptionChanged(r.task.taskId, td);
             }
         }
     }
@@ -11714,38 +11621,10 @@
         mRecentTasks.notifyTaskPersisterLocked(task, flush);
     }
 
-    /** Notifies all listeners when the task stack has changed. */
-    void notifyTaskStackChangedLocked() {
-        mHandler.sendEmptyMessage(LOG_STACK_STATE);
-        mHandler.removeMessages(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG);
-        Message nmsg = mHandler.obtainMessage(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG);
-        mHandler.sendMessageDelayed(nmsg, NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY);
-    }
-
-    /** Notifies all listeners when an Activity is pinned. */
-    void notifyActivityPinnedLocked() {
-        mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG);
-        mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG).sendToTarget();
-    }
-
-    /**
-     * Notifies all listeners when an attempt was made to start an an activity that is already
-     * running in the pinned stack and the activity was not actually started, but the task is
-     * either brought to the front or a new Intent is delivered to it.
-     */
-    void notifyPinnedActivityRestartAttemptLocked() {
-        mHandler.removeMessages(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
-        mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG).sendToTarget();
-    }
-
     /** Notifies all listeners when the pinned stack animation ends. */
     @Override
     public void notifyPinnedStackAnimationEnded() {
-        synchronized (this) {
-            mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG);
-            mHandler.obtainMessage(
-                    NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG).sendToTarget();
-        }
+        mTaskChangeNotificationController.notifyPinnedStackAnimationEnded();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index abe4f30..df03af2 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -664,10 +664,18 @@
         hasBeenLaunched = false;
         mStackSupervisor = supervisor;
         mInitialActivityContainer = container;
+
+        mRotationAnimationHint = aInfo.rotationAnimation;
+
         if (options != null) {
             pendingOptions = options;
             mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind();
-            mRotationAnimationHint = pendingOptions.getRotationAnimationHint();
+
+            final int rotationAnimation = pendingOptions.getRotationAnimationHint();
+            // Only override manifest supplied option if set.
+            if (rotationAnimation >= 0) {
+                mRotationAnimationHint = rotationAnimation;
+            }
             PendingIntent usageReport = pendingOptions.getUsageTimeReport();
             if (usageReport != null) {
                 appTimeTracker = new AppTimeTracker(usageReport);
@@ -932,6 +940,10 @@
             if (stopped) {
                 clearOptionsLocked();
             }
+
+            if (service != null) {
+                service.mTaskChangeNotificationController.notifyTaskStackChanged();
+            }
         }
     }
 
@@ -1733,6 +1745,8 @@
                 mStackSupervisor.resumeFocusedStackTopActivityLocked();
             }
         }
+        service.mTaskChangeNotificationController.notifyActivityRequestedOrientationChanged(
+                task.taskId, requestedOrientation);
     }
 
     // TODO: now used only in one place to address race-condition. Remove when that will be fixed.
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3dbbb13..fc41fd3 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1279,7 +1279,7 @@
         // task stack changes, because its positioning may depend on it.
         if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause
                 || mService.mStackSupervisor.getStack(PINNED_STACK_ID) != null) {
-            mService.notifyTaskStackChangedLocked();
+            mService.mTaskChangeNotificationController.notifyTaskStackChanged();
             mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
         }
 
@@ -3314,9 +3314,11 @@
         final boolean endTask = index <= 0;
         final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
         if (mResumedActivity == r) {
-
             if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                     "Prepare close transition: finishing " + r);
+            if (endTask) {
+                mService.mTaskChangeNotificationController.notifyTaskRemovalStarted(task.taskId);
+            }
             mWindowManager.prepareAppTransition(transit, false);
 
             // Tell window manager to prepare for this one to be removed.
@@ -4138,6 +4140,8 @@
 
         mStackSupervisor.resumeFocusedStackTopActivityLocked();
         EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
+
+        mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
     }
 
     /**
@@ -4690,6 +4694,7 @@
                 // default configuration the next time it launches.
                 task.updateOverrideConfiguration(null);
             }
+            mService.mTaskChangeNotificationController.notifyTaskRemoved(task.taskId);
         }
 
         final ActivityRecord r = mResumedActivity;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 99c5b06..e55c1e4 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -157,8 +157,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityManagerService.ANIMATE;
 import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
-import static com.android.server.am.ActivityManagerService.NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG;
-import static com.android.server.am.ActivityManagerService.NOTIFY_FORCED_RESIZABLE_MSG;
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
@@ -2582,7 +2580,7 @@
         resumeFocusedStackTopActivityLocked();
 
         mWindowManager.animateResizePinnedStack(bounds, -1);
-        mService.notifyActivityPinnedLocked();
+        mService.mTaskChangeNotificationController.notifyActivityPinned();
     }
 
     boolean moveFocusableActivityStackToFrontLocked(ActivityRecord r, String reason) {
@@ -2904,7 +2902,7 @@
         r.mLaunchTaskBehind = false;
         task.setLastThumbnailLocked(r.screenshotActivityLocked());
         mRecentTasks.addLocked(task);
-        mService.notifyTaskStackChangedLocked();
+        mService.mTaskChangeNotificationController.notifyTaskStackChanged();
         mWindowManager.setAppVisibility(r.appToken, false);
 
         // When launching tasks behind, update the last active time of the top task after the new
@@ -3588,7 +3586,7 @@
         final ActivityRecord topActivity = task.getTopActivity();
         if (!task.canGoInDockedStack() || forceNonResizable) {
             // Display a warning toast that we tried to put a non-dockable task in the docked stack.
-            mService.mHandler.sendEmptyMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
+            mService.mTaskChangeNotificationController.notifyActivityDismissingDockedStack();
 
             // Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
             // we need to move it to top of fullscreen stack, otherwise it will be covered.
@@ -3596,8 +3594,8 @@
         } else if (topActivity != null && topActivity.isNonResizableOrForced()
                 && !topActivity.noDisplay) {
             String packageName = topActivity.appInfo.packageName;
-            mService.mHandler.obtainMessage(NOTIFY_FORCED_RESIZABLE_MSG, task.taskId, 0,
-                    packageName).sendToTarget();
+            mService.mTaskChangeNotificationController.notifyActivityForcedResizable(
+                    task.taskId, packageName);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 20a14d3..006c13d 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -631,7 +631,7 @@
             // The activity was already running in the pinned stack so it wasn't started, but either
             // brought to the front or the new intent was delivered to it since it was already in
             // front. Notify anyone interested in this piece of information.
-            mService.notifyPinnedActivityRestartAttemptLocked();
+            mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt();
             return;
         }
     }
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
new file mode 100644
index 0000000..b6e35d2
--- /dev/null
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.ITaskStackListener;
+import android.app.ActivityManager.TaskDescription;
+import android.content.ComponentName;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+
+class TaskChangeNotificationController {
+    static final int LOG_STACK_STATE_MSG = 1;
+    static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 2;
+    static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 3;
+    static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 4;
+    static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 5;
+    static final int NOTIFY_FORCED_RESIZABLE_MSG = 6;
+    static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 7;
+    static final int NOTIFY_TASK_ADDED_LISTENERS_MSG = 8;
+    static final int NOTIFY_TASK_REMOVED_LISTENERS_MSG = 9;
+    static final int NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG = 10;
+    static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11;
+    static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12;
+    static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
+
+    // Delay in notifying task stack change listeners (in millis)
+    static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
+
+    private final ActivityManagerService mService;
+    private final ActivityStackSupervisor mStackSupervisor;
+    private final Handler mHandler;
+
+    /** Task stack change listeners. */
+    private final RemoteCallbackList<ITaskStackListener> mTaskStackListeners =
+            new RemoteCallbackList<ITaskStackListener>();
+
+    @FunctionalInterface
+    public interface ConsumerWithRemoteException<T> {
+        void accept(T t) throws RemoteException;
+    }
+
+    private class MainHandler extends Handler {
+        public MainHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case LOG_STACK_STATE_MSG: {
+                    synchronized (mService) {
+                        mStackSupervisor.logStackState();
+                    }
+                    break;
+                }
+                case NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG:
+                    forAllListeners((listener) -> listener.onTaskStackChanged());
+                    break;
+                case NOTIFY_TASK_ADDED_LISTENERS_MSG:
+                    forAllListeners((listener) -> listener.onTaskCreated(msg.arg1,
+                            (ComponentName) msg.obj));
+                    break;
+                case NOTIFY_TASK_REMOVED_LISTENERS_MSG:
+                    forAllListeners((listener) -> listener.onTaskRemoved(msg.arg1));
+                    break;
+                case NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG:
+                    forAllListeners((listener) -> listener.onTaskMovedToFront(msg.arg1));
+                    break;
+                case NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG:
+                    forAllListeners((listener) -> listener.onTaskDescriptionChanged(msg.arg1,
+                            (TaskDescription) msg.obj));
+                    break;
+                case NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS:
+                    forAllListeners((listener) -> listener.onActivityRequestedOrientationChanged(
+                            msg.arg1, msg.arg2));
+                case NOTIFY_TASK_REMOVAL_STARTED_LISTENERS:
+                    forAllListeners((listener) -> listener.onTaskRemovalStarted(msg.arg1));
+                    break;
+                case NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG:
+                    forAllListeners((listener) -> listener.onActivityPinned());
+                    break;
+                case NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG:
+                    forAllListeners((listener) -> listener.onPinnedActivityRestartAttempt());
+                    break;
+                case NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG:
+                    forAllListeners((listener) -> listener.onPinnedStackAnimationEnded());
+                    break;
+                case NOTIFY_FORCED_RESIZABLE_MSG:
+                    forAllListeners((listener) -> listener.onActivityForcedResizable(
+                            (String) msg.obj, msg.arg1));
+                    break;
+                case NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG:
+                    forAllListeners((listener) -> listener.onActivityDismissingDockedStack());
+                    break;
+            }
+        }
+    }
+
+    public TaskChangeNotificationController(ActivityManagerService service,
+            ActivityStackSupervisor stackSupervisor, Handler handler) {
+        mService = service;
+        mStackSupervisor = stackSupervisor;
+        mHandler = new MainHandler(handler.getLooper());
+    }
+
+    public void registerTaskStackListener(ITaskStackListener listener) {
+        synchronized (mService) {
+            if (listener != null) {
+                mTaskStackListeners.register(listener);
+            }
+        }
+    }
+
+    public void unregisterTaskStackListener(ITaskStackListener listener) {
+        synchronized (mService) {
+            if (listener != null) {
+                mTaskStackListeners.unregister(listener);
+            }
+        }
+    }
+
+    void forAllListeners(ConsumerWithRemoteException<ITaskStackListener> callback) {
+        synchronized (mService) {
+            for (int i = mTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
+                try {
+                    // Make a one-way callback to the listener
+                    callback.accept(mTaskStackListeners.getBroadcastItem(i));
+                } catch (RemoteException e) {
+                    // Handled by the RemoteCallbackList.
+                }
+            }
+            mTaskStackListeners.finishBroadcast();
+         }
+      }
+
+    /** Notifies all listeners when the task stack has changed. */
+    void notifyTaskStackChanged() {
+        mHandler.sendEmptyMessage(LOG_STACK_STATE_MSG);
+        mHandler.removeMessages(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG);
+        Message msg = mHandler.obtainMessage(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG);
+        // Only the main task stack change notification requires a delay.
+        mHandler.sendMessageDelayed(msg, NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY);
+    }
+
+    /** Notifies all listeners when an Activity is pinned. */
+    void notifyActivityPinned() {
+        mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG);
+        mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG).sendToTarget();
+    }
+
+    /**
+     * Notifies all listeners when an attempt was made to start an an activity that is already
+     * running in the pinned stack and the activity was not actually started, but the task is
+     * either brought to the front or a new Intent is delivered to it.
+     */
+    void notifyPinnedActivityRestartAttempt() {
+        mHandler.removeMessages(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
+        mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG).sendToTarget();
+    }
+
+    /** Notifies all listeners when the pinned stack animation ends. */
+    void notifyPinnedStackAnimationEnded() {
+        mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG);
+        mHandler.obtainMessage(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG)
+                .sendToTarget();
+    }
+
+    void notifyActivityDismissingDockedStack() {
+        mHandler.removeMessages(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
+        mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG).sendToTarget();
+    }
+
+    void notifyActivityForcedResizable(int taskId, String packageName) {
+        mHandler.removeMessages(NOTIFY_FORCED_RESIZABLE_MSG);
+        mHandler.obtainMessage(NOTIFY_FORCED_RESIZABLE_MSG, taskId, 0 /* unused */, packageName)
+                .sendToTarget();
+    }
+
+    void notifyTaskCreated(int taskId, ComponentName componentName) {
+        mHandler.obtainMessage(NOTIFY_TASK_ADDED_LISTENERS_MSG, taskId, 0 /* unused */,
+                componentName).sendToTarget();
+    }
+
+    void notifyTaskRemoved(int taskId) {
+        mHandler.obtainMessage(NOTIFY_TASK_REMOVED_LISTENERS_MSG, taskId, 0 /* unused */)
+                .sendToTarget();
+    }
+
+    void notifyTaskMovedToFront(int taskId) {
+        mHandler.obtainMessage(NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG, taskId, 0 /* unused */)
+                .sendToTarget();
+    }
+
+    void notifyTaskDescriptionChanged(int taskId, TaskDescription taskDescription) {
+        mHandler.obtainMessage(NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG, taskId,
+                0 /* unused */, taskDescription).sendToTarget();
+    }
+
+    void notifyActivityRequestedOrientationChanged(int taskId, int orientation) {
+        mHandler.obtainMessage(NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS, taskId,
+                orientation).sendToTarget();
+    }
+
+    /**
+     * Notify listeners that the task is about to be finished before its surfaces are removed from
+     * the window manager. This allows interested parties to perform relevant animations before
+     * the window disappears.
+     */
+    void notifyTaskRemovalStarted(int taskId) {
+        mHandler.obtainMessage(NOTIFY_TASK_REMOVAL_STARTED_LISTENERS, taskId, 0 /* unused */)
+                .sendToTarget();
+    }
+}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 9d97dd3..b37b3f0 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -298,6 +298,7 @@
         setIntent(_intent, info);
         setMinDimensions(info);
         touchActiveTime();
+        mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
     }
 
     TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
@@ -329,6 +330,7 @@
         mTaskToReturnTo = HOME_ACTIVITY_TYPE;
         lastTaskDescription = _taskDescription;
         touchActiveTime();
+        mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
     }
 
     private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
@@ -383,6 +385,7 @@
         mPrivileged = privileged;
         mMinWidth = minWidth;
         mMinHeight = minHeight;
+        mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
     }
 
     void touchActiveTime() {
@@ -861,7 +864,7 @@
             // We normally notify listeners of task stack changes on pause, however pinned stack
             // activities are normally in the paused state so no notification will be sent there
             // before the activity is removed. We send it here so instead.
-            mService.notifyTaskStackChangedLocked();
+            mService.mTaskChangeNotificationController.notifyTaskStackChanged();
         }
 
         if (mActivities.isEmpty()) {
diff --git a/services/core/java/com/android/server/pm/BasePermission.java b/services/core/java/com/android/server/pm/BasePermission.java
index 52d0928..8948fa3 100644
--- a/services/core/java/com/android/server/pm/BasePermission.java
+++ b/services/core/java/com/android/server/pm/BasePermission.java
@@ -94,4 +94,8 @@
                 == PermissionInfo.PROTECTION_SIGNATURE
                 && (protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0;
     }
+
+    public boolean isEphemeral() {
+        return (protectionLevel & PermissionInfo.PROTECTION_FLAG_EPHEMERAL) != 0;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 974d95d..59c4fb9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4083,6 +4083,11 @@
                 return;
             }
 
+            if (pkg.applicationInfo.isEphemeralApp() && !bp.isEphemeral()) {
+                throw new SecurityException("Cannot grant non-ephemeral permission"
+                        + name + " for package " + packageName);
+            }
+
             if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
                 Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
                 return;
@@ -10109,6 +10114,14 @@
                 continue;
             }
 
+
+            // Limit ephemeral apps to ephemeral allowed permissions.
+            if (pkg.applicationInfo.isEphemeralApp() && !bp.isEphemeral()) {
+                Log.i(TAG, "Denying non-ephemeral permission " + bp.name + " for package "
+                        + pkg.packageName);
+                continue;
+            }
+
             final String perm = bp.name;
             boolean allowedSig = false;
             int grant = GRANT_DENIED;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 270488c..1ecb3d3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -179,7 +179,7 @@
  */
 public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
 
-    private static final String LOG_TAG = "DevicePolicyManagerService";
+    private static final String LOG_TAG = "DevicePolicyManager";
 
     private static final boolean VERBOSE_LOG = false; // DO NOT SUBMIT WITH TRUE
 
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 3548f28..4165467 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -4,9 +4,9 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -30,6 +30,7 @@
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
     <uses-permission android:name="android.permission.REAL_GET_TASKS" />
     <uses-permission android:name="android.permission.GET_DETAILED_TASKS" />
+    <uses-permission android:name="android.permission.REORDER_TASKS" />
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
     <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
     <uses-permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING" />
@@ -159,6 +160,9 @@
 
         <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityA" />
         <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityB" />
+        <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityRequestedOrientationChange" />
+        <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityTaskChangeCallbacks" />
+        <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityTaskDescriptionChange" />
 
     </application>
 
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java b/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java
index b47d17e..c9c691d 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java
@@ -17,21 +17,33 @@
 package com.android.server.am;
 
 import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
+import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
 import android.app.ITaskStackListener;
+import android.app.Instrumentation.ActivityMonitor;
+import android.app.TaskStackListener;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources.Theme;
 import android.os.RemoteException;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
-
+import android.text.TextUtils;
+import android.util.Pair;
 import com.android.internal.annotations.GuardedBy;
-
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -39,9 +51,10 @@
 
 @MediumTest
 @RunWith(AndroidJUnit4.class)
-public class TaskStackChangedListenerTest extends ITaskStackListener.Stub {
+public class TaskStackChangedListenerTest {
 
     private IActivityManager mService;
+    private ITaskStackListener mTaskStackListener;
 
     private static final Object sLock = new Object();
     @GuardedBy("sLock")
@@ -51,11 +64,25 @@
     @Before
     public void setUp() throws Exception {
         mService = ActivityManagerNative.getDefault();
-        mService.registerTaskStackListener(this);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mService.unregisterTaskStackListener(mTaskStackListener);
+        mTaskStackListener = null;
     }
 
     @Test
     public void testTaskStackChanged_afterFinish() throws Exception {
+        registerTaskStackChangedListener(new TaskStackListener() {
+            @Override
+            public void onTaskStackChanged() throws RemoteException {
+                synchronized (sLock) {
+                    sTaskStackChangedCalled = true;
+                }
+            }
+        });
+
         Context ctx = InstrumentationRegistry.getContext();
         ctx.startActivity(new Intent(ctx, ActivityA.class));
         UiDevice.getInstance(getInstrumentation()).waitForIdle();
@@ -65,31 +92,151 @@
         Assert.assertTrue(sActivityBResumed);
     }
 
-    @Override
-    public void onTaskStackChanged() throws RemoteException {
-        synchronized (sLock) {
-            sTaskStackChangedCalled = true;
+    @Test
+    public void testTaskDescriptionChanged() throws Exception {
+        final Object[] params = new Object[2];
+        final CountDownLatch latch = new CountDownLatch(1);
+        registerTaskStackChangedListener(new TaskStackListener() {
+            int taskId = -1;
+
+            @Override
+            public void onTaskCreated(int taskId, ComponentName componentName)
+                    throws RemoteException {
+                this.taskId = taskId;
+            }
+            @Override
+            public void onTaskDescriptionChanged(int taskId, TaskDescription td)
+                    throws RemoteException {
+                if (this.taskId == taskId && !TextUtils.isEmpty(td.getLabel())) {
+                    params[0] = taskId;
+                    params[1] = td;
+                    latch.countDown();
+                }
+            }
+        });
+        final Activity activity = startTestActivity(ActivityTaskDescriptionChange.class);
+        waitForCallback(latch);
+        assertEquals(activity.getTaskId(), params[0]);
+        assertEquals("Test Label", ((TaskDescription) params[1]).getLabel());
+    }
+
+    @Test
+    public void testActivityRequestedOrientationChanged() throws Exception {
+        final int[] params = new int[2];
+        final CountDownLatch latch = new CountDownLatch(1);
+        registerTaskStackChangedListener(new TaskStackListener() {
+            @Override
+            public void onActivityRequestedOrientationChanged(int taskId,
+                    int requestedOrientation) {
+                params[0] = taskId;
+                params[1] = requestedOrientation;
+                latch.countDown();
+            }
+        });
+        final Activity activity = startTestActivity(ActivityRequestedOrientationChange.class);
+        waitForCallback(latch);
+        assertEquals(activity.getTaskId(), params[0]);
+        assertEquals(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, params[1]);
+    }
+
+    @Test
+    /**
+     * Tests for onTaskCreated, onTaskMovedToFront, onTaskRemoved and onTaskRemovalStarted.
+     */
+    public void testTaskChangeCallBacks() throws Exception {
+        final Object[] params = new Object[2];
+        final CountDownLatch taskCreatedLaunchLatch = new CountDownLatch(1);
+        final CountDownLatch taskMovedToFrontLatch = new CountDownLatch(1);
+        final CountDownLatch taskRemovedLatch = new CountDownLatch(1);
+        final CountDownLatch taskRemovalStartedLatch = new CountDownLatch(1);
+        final CountDownLatch onDetachedFromWindowLatch = new CountDownLatch(1);
+        registerTaskStackChangedListener(new TaskStackListener() {
+            @Override
+            public void onTaskCreated(int taskId, ComponentName componentName)
+                    throws RemoteException {
+                params[0] = taskId;
+                params[1] = componentName;
+                taskCreatedLaunchLatch.countDown();
+            }
+
+            @Override
+            public void onTaskMovedToFront(int taskId) throws RemoteException {
+                params[0] = taskId;
+                taskMovedToFrontLatch.countDown();
+            }
+
+            @Override
+            public void onTaskRemovalStarted(int taskId) {
+                params[0] = taskId;
+                taskRemovalStartedLatch.countDown();
+            }
+
+            @Override
+            public void onTaskRemoved(int taskId) throws RemoteException {
+                params[0] = taskId;
+                taskRemovedLatch.countDown();
+            }
+        });
+
+        final ActivityTaskChangeCallbacks activity =
+                (ActivityTaskChangeCallbacks) startTestActivity(ActivityTaskChangeCallbacks.class);
+        final int id = activity.getTaskId();
+
+        // Test for onTaskCreated.
+        waitForCallback(taskCreatedLaunchLatch);
+        assertEquals(id, params[0]);
+        ComponentName componentName = (ComponentName) params[1];
+        assertEquals(ActivityTaskChangeCallbacks.class.getName(), componentName.getClassName());
+
+        // Test for onTaskMovedToFront.
+        assertEquals(1, taskMovedToFrontLatch.getCount());
+        mService.moveTaskToFront(id, 0, null);
+        waitForCallback(taskMovedToFrontLatch);
+        assertEquals(activity.getTaskId(), params[0]);
+
+        // Test for onTaskRemovalStarted.
+        assertEquals(1, taskRemovalStartedLatch.getCount());
+        activity.finishAndRemoveTask();
+        waitForCallback(taskRemovalStartedLatch);
+        // onTaskRemovalStarted happens before the activity's window is removed.
+        assertFalse(activity.onDetachedFromWindowCalled);
+        assertEquals(id, params[0]);
+
+        // Test for onTaskRemoved.
+        assertEquals(1, taskRemovedLatch.getCount());
+        waitForCallback(taskRemovedLatch);
+        assertEquals(id, params[0]);
+        assertTrue(activity.onDetachedFromWindowCalled);
+    }
+
+    /**
+     * Starts the provided activity and returns the started instance.
+     */
+    private Activity startTestActivity(Class<?> activityClass) {
+        final Context context = InstrumentationRegistry.getContext();
+        final ActivityMonitor monitor =
+                new ActivityMonitor(activityClass.getName(), null, false);
+        InstrumentationRegistry.getInstrumentation().addMonitor(monitor);
+        context.startActivity(new Intent(context, activityClass));
+        final Activity activity = monitor.waitForActivityWithTimeout(1000);
+        if (activity == null) {
+            throw new RuntimeException("Timed out waiting for Activity");
         }
+        return activity;
     }
 
-    @Override
-    public void onActivityPinned() throws RemoteException {
+    private void registerTaskStackChangedListener(ITaskStackListener listener) throws Exception {
+        mTaskStackListener = listener;
+        mService.registerTaskStackListener(listener);
     }
 
-    @Override
-    public void onPinnedActivityRestartAttempt() throws RemoteException {
-    }
-
-    @Override
-    public void onPinnedStackAnimationEnded() throws RemoteException {
-    }
-
-    @Override
-    public void onActivityForcedResizable(String packageName, int taskId) throws RemoteException {
-    }
-
-    @Override
-    public void onActivityDismissingDockedStack() throws RemoteException {
+    private void waitForCallback(CountDownLatch latch) {
+        try {
+        final boolean result = latch.await(2, TimeUnit.SECONDS);
+            if (!result) {
+                throw new RuntimeException("Timed out waiting for task stack change notification");
+            }
+        }catch (InterruptedException e) {}
     }
 
     public static class ActivityA extends Activity {
@@ -120,4 +267,31 @@
             finish();
         }
     }
+
+    public static class ActivityRequestedOrientationChange extends Activity {
+        @Override
+        protected void onPostResume() {
+            super.onPostResume();
+            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+            finish();
+        }
+    }
+
+    public static class ActivityTaskDescriptionChange extends Activity {
+        @Override
+        protected void onPostResume() {
+            super.onPostResume();
+            setTaskDescription(new TaskDescription("Test Label"));
+            finish();
+        }
+    }
+
+    public static class ActivityTaskChangeCallbacks extends Activity {
+        public boolean onDetachedFromWindowCalled = false;;
+
+        @Override
+        public void onDetachedFromWindow() {
+            onDetachedFromWindowCalled = true;
+        }
+    }
 }