Merge "Provide an API to make USSD calls and read the responses."
diff --git a/Android.mk b/Android.mk
index 44dd3dc..6f96803 100644
--- a/Android.mk
+++ b/Android.mk
@@ -68,6 +68,7 @@
 	core/java/android/app/IActivityContainer.aidl \
 	core/java/android/app/IActivityContainerCallback.aidl \
 	core/java/android/app/IActivityController.aidl \
+	core/java/android/app/IActivityManager.aidl \
 	core/java/android/app/IActivityPendingResult.aidl \
 	core/java/android/app/IAlarmCompleteListener.aidl \
 	core/java/android/app/IAlarmListener.aidl \
@@ -466,9 +467,9 @@
 	telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
 	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
-	wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl \
-	wifi/java/android/net/wifi/nan/IWifiNanManager.aidl \
-	wifi/java/android/net/wifi/nan/IWifiNanDiscoverySessionCallback.aidl \
+	wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl \
+	wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl \
+	wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl \
 	wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
 	wifi/java/android/net/wifi/IWifiScanner.aidl \
 	wifi/java/android/net/wifi/IRttManager.aidl \
@@ -561,9 +562,9 @@
 	frameworks/base/media/java/android/media/tv/TvTrackInfo.aidl \
 	frameworks/base/media/java/android/media/browse/MediaBrowser.aidl \
 	frameworks/base/wifi/java/android/net/wifi/ScanSettings.aidl \
-	frameworks/base/wifi/java/android/net/wifi/nan/ConfigRequest.aidl \
-	frameworks/base/wifi/java/android/net/wifi/nan/PublishConfig.aidl \
-	frameworks/base/wifi/java/android/net/wifi/nan/SubscribeConfig.aidl \
+	frameworks/base/wifi/java/android/net/wifi/aware/ConfigRequest.aidl \
+	frameworks/base/wifi/java/android/net/wifi/aware/PublishConfig.aidl \
+	frameworks/base/wifi/java/android/net/wifi/aware/SubscribeConfig.aidl \
 	frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pInfo.aidl \
 	frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.aidl \
 	frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pConfig.aidl \
@@ -586,6 +587,9 @@
 	frameworks/base/graphics/java/android/graphics/drawable/Icon.aidl \
 	frameworks/base/core/java/android/accounts/AuthenticatorDescription.aidl \
 	frameworks/base/core/java/android/accounts/Account.aidl \
+	frameworks/base/core/java/android/app/admin/ConnectEvent.aidl \
+	frameworks/base/core/java/android/app/admin/DnsEvent.aidl \
+	frameworks/base/core/java/android/app/admin/NetworkEvent.aidl \
 	frameworks/base/core/java/android/app/admin/SystemUpdatePolicy.aidl \
 	frameworks/base/core/java/android/app/admin/PasswordMetrics.aidl \
 	frameworks/base/core/java/android/print/PrintDocumentInfo.aidl \
@@ -612,6 +616,7 @@
 	frameworks/base/core/java/android/os/DropBoxManager.aidl \
 	frameworks/base/core/java/android/os/Bundle.aidl \
 	frameworks/base/core/java/android/os/Debug.aidl \
+	frameworks/base/core/java/android/os/StrictMode.aidl \
 	frameworks/base/core/java/android/accessibilityservice/AccessibilityServiceInfo.aidl \
 	frameworks/base/core/java/android/net/Network.aidl \
 	frameworks/base/core/java/android/net/RouteInfo.aidl \
@@ -692,6 +697,7 @@
 	frameworks/base/core/java/android/content/pm/ApplicationInfo.aidl \
 	frameworks/base/core/java/android/content/pm/PermissionInfo.aidl \
 	frameworks/base/core/java/android/content/pm/ActivityInfo.aidl \
+	frameworks/base/core/java/android/content/pm/ConfigurationInfo.aidl \
 	frameworks/base/core/java/android/content/pm/PackageInfo.aidl \
 	frameworks/base/core/java/android/content/pm/ResolveInfo.aidl \
 	frameworks/base/core/java/android/content/pm/ProviderInfo.aidl \
diff --git a/apct-tests/perftests/core/res/layout/test_simple_view.xml b/apct-tests/perftests/core/res/layout/test_simple_view.xml
new file mode 100644
index 0000000..9bc29a8
--- /dev/null
+++ b/apct-tests/perftests/core/res/layout/test_simple_view.xml
@@ -0,0 +1,20 @@
+<!--
+ 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.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/simple_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
index 19047d3..922a475 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
@@ -31,11 +31,38 @@
 
     @Test
     public void testMeasureRenderNodeJniOverhead() {
-        RenderNode node = RenderNode.create("benchmark", null);
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final RenderNode node = RenderNode.create("benchmark", null);
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
 
         while (state.keepRunning()) {
             node.setTranslationX(1.0f);
         }
     }
+
+    @Test
+    public void testCreateRenderNodeNoName() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            RenderNode node = RenderNode.create(null, null);
+            node.destroy();
+        }
+    }
+
+    @Test
+    public void testCreateRenderNode() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            RenderNode node = RenderNode.create("LinearLayout", null);
+            node.destroy();
+        }
+    }
+
+    @Test
+    public void testIsValid() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        RenderNode node = RenderNode.create("LinearLayout", null);
+        while (state.keepRunning()) {
+            node.isValid();
+        }
+    }
 }
diff --git a/apct-tests/perftests/core/src/android/view/ViewPerfTest.java b/apct-tests/perftests/core/src/android/view/ViewPerfTest.java
new file mode 100644
index 0000000..5503ca9
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/view/ViewPerfTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.view;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.widget.FrameLayout;
+
+import com.android.perftests.core.R;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@LargeTest
+public class ViewPerfTest {
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void testSimpleViewInflate() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        LayoutInflater inflater = LayoutInflater.from(context);
+        FrameLayout root = new FrameLayout(context);
+        while (state.keepRunning()) {
+            inflater.inflate(R.layout.test_simple_view, root, false);
+        }
+    }
+}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
index 519d524..fd393e9 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
@@ -19,8 +19,11 @@
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.os.Bundle;
+import android.os.Debug;
+import android.support.test.InstrumentationRegistry;
 import android.util.Log;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.concurrent.TimeUnit;
@@ -45,6 +48,7 @@
 public final class BenchmarkState {
 
     private static final String TAG = "BenchmarkState";
+    private static final boolean ENABLE_PROFILING = false;
 
     private static final int NOT_STARTED = 0;  // The benchmark has not started yet.
     private static final int WARMUP = 1; // The benchmark is warming up.
@@ -146,6 +150,11 @@
     }
 
     private void beginBenchmark(long warmupDuration, int iterations) {
+        if (ENABLE_PROFILING) {
+            File f = new File(InstrumentationRegistry.getContext().getDataDir(), "benchprof");
+            Log.d(TAG, "Tracing to: " + f.getAbsolutePath());
+            Debug.startMethodTracingSampling(f.getAbsolutePath(), 16 * 1024 * 1024, 100);
+        }
         mMaxIterations = (int) (TARGET_TEST_DURATION_NS / (warmupDuration / iterations));
         mMaxIterations = Math.min(MAX_TEST_ITERATIONS,
                 Math.max(mMaxIterations, MIN_TEST_ITERATIONS));
@@ -161,6 +170,9 @@
         mResults.add((currentTime - mStartTimeNs - mPausedDurationNs) / mMaxIterations);
         mRepeatCount++;
         if (mRepeatCount >= REPEAT_COUNT) {
+            if (ENABLE_PROFILING) {
+                Debug.stopMethodTracing();
+            }
             calculateSatistics();
             mState = FINISHED;
             return false;
diff --git a/api/current.txt b/api/current.txt
index b993070..bef8604 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28490,6 +28490,7 @@
     field public static final int M = 23; // 0x17
     field public static final int N = 24; // 0x18
     field public static final int N_MR1 = 25; // 0x19
+    field public static final int O = 10000; // 0x2710
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -32059,6 +32060,7 @@
     method public static android.net.Uri copyDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri);
     method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
     method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
+    method public static java.util.List<java.lang.String> findDocumentPath(android.content.ContentResolver, android.net.Uri);
     method public static java.lang.String getDocumentId(android.net.Uri);
     method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
     method public static java.lang.String getRootId(android.net.Uri);
@@ -32101,6 +32103,15 @@
     field public static final java.lang.String MIME_TYPE_DIR = "vnd.android.document/directory";
   }
 
+  public static final class DocumentsContract.Path implements android.os.Parcelable {
+    ctor public DocumentsContract.Path(java.lang.String, java.util.List<java.lang.String>);
+    method public int describeContents();
+    method public java.util.List<java.lang.String> getPath();
+    method public java.lang.String getRootId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.provider.DocumentsContract.Path> CREATOR;
+  }
+
   public static final class DocumentsContract.Root {
     field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
     field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
@@ -32124,6 +32135,7 @@
     method public java.lang.String createDocument(java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
     method public void deleteDocument(java.lang.String) throws java.io.FileNotFoundException;
+    method public android.provider.DocumentsContract.Path findDocumentPath(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public java.lang.String[] getDocumentStreamTypes(java.lang.String, java.lang.String);
     method public java.lang.String getDocumentType(java.lang.String) throws java.io.FileNotFoundException;
     method public final java.lang.String getType(android.net.Uri);
diff --git a/api/system-current.txt b/api/system-current.txt
index 3f6edd9..e352b57 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3819,6 +3819,7 @@
 
   public class ActivityManager {
     method public int addAppTask(android.app.Activity, android.content.Intent, android.app.ActivityManager.TaskDescription, android.graphics.Bitmap);
+    method public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
     method public boolean clearApplicationUserData();
     method public void clearWatchHeapLimit();
     method public void dumpPackageState(java.io.FileDescriptor, java.lang.String);
@@ -3849,6 +3850,7 @@
     method public void killUid(int, java.lang.String);
     method public void moveTaskToFront(int, int);
     method public void moveTaskToFront(int, int, android.os.Bundle);
+    method public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
     method public deprecated void restartPackage(java.lang.String);
     method public static void setVrThread(int);
     method public void setWatchHeapLimit(long);
@@ -3883,6 +3885,10 @@
     field public long totalMem;
   }
 
+  public static abstract interface ActivityManager.OnUidImportanceListener {
+    method public abstract void onUidImportance(int, int);
+  }
+
   public static class ActivityManager.ProcessErrorStateInfo implements android.os.Parcelable {
     ctor public ActivityManager.ProcessErrorStateInfo();
     method public int describeContents();
@@ -30984,6 +30990,7 @@
     field public static final int M = 23; // 0x17
     field public static final int N = 24; // 0x18
     field public static final int N_MR1 = 25; // 0x19
+    field public static final int O = 10000; // 0x2710
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -34716,6 +34723,7 @@
     method public static android.net.Uri copyDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri);
     method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
     method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
+    method public static java.util.List<java.lang.String> findDocumentPath(android.content.ContentResolver, android.net.Uri);
     method public static java.lang.String getDocumentId(android.net.Uri);
     method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
     method public static java.lang.String getRootId(android.net.Uri);
@@ -34758,6 +34766,15 @@
     field public static final java.lang.String MIME_TYPE_DIR = "vnd.android.document/directory";
   }
 
+  public static final class DocumentsContract.Path implements android.os.Parcelable {
+    ctor public DocumentsContract.Path(java.lang.String, java.util.List<java.lang.String>);
+    method public int describeContents();
+    method public java.util.List<java.lang.String> getPath();
+    method public java.lang.String getRootId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.provider.DocumentsContract.Path> CREATOR;
+  }
+
   public static final class DocumentsContract.Root {
     field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
     field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
@@ -34781,6 +34798,7 @@
     method public java.lang.String createDocument(java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
     method public void deleteDocument(java.lang.String) throws java.io.FileNotFoundException;
+    method public android.provider.DocumentsContract.Path findDocumentPath(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public java.lang.String[] getDocumentStreamTypes(java.lang.String, java.lang.String);
     method public java.lang.String getDocumentType(java.lang.String) throws java.io.FileNotFoundException;
     method public final java.lang.String getType(android.net.Uri);
diff --git a/api/test-current.txt b/api/test-current.txt
index 019a67e..6f8d308 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3699,6 +3699,7 @@
 
   public class ActivityManager {
     method public int addAppTask(android.app.Activity, android.content.Intent, android.app.ActivityManager.TaskDescription, android.graphics.Bitmap);
+    method public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
     method public boolean clearApplicationUserData();
     method public void clearWatchHeapLimit();
     method public void dumpPackageState(java.io.FileDescriptor, java.lang.String);
@@ -3712,6 +3713,7 @@
     method public int getMemoryClass();
     method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo);
     method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo);
+    method public int getPackageImportance(java.lang.String);
     method public android.os.Debug.MemoryInfo[] getProcessMemoryInfo(int[]);
     method public java.util.List<android.app.ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState();
     method public deprecated java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException;
@@ -3726,6 +3728,7 @@
     method public void killBackgroundProcesses(java.lang.String);
     method public void moveTaskToFront(int, int);
     method public void moveTaskToFront(int, int, android.os.Bundle);
+    method public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
     method public deprecated void restartPackage(java.lang.String);
     method public static void setVrThread(int);
     method public void setWatchHeapLimit(long);
@@ -3760,6 +3763,10 @@
     field public long totalMem;
   }
 
+  public static abstract interface ActivityManager.OnUidImportanceListener {
+    method public abstract void onUidImportance(int, int);
+  }
+
   public static class ActivityManager.ProcessErrorStateInfo implements android.os.Parcelable {
     ctor public ActivityManager.ProcessErrorStateInfo();
     method public int describeContents();
@@ -28564,6 +28571,7 @@
     field public static final int M = 23; // 0x17
     field public static final int N = 24; // 0x18
     field public static final int N_MR1 = 25; // 0x19
+    field public static final int O = 10000; // 0x2710
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -32138,6 +32146,7 @@
     method public static android.net.Uri copyDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri);
     method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
     method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
+    method public static java.util.List<java.lang.String> findDocumentPath(android.content.ContentResolver, android.net.Uri);
     method public static java.lang.String getDocumentId(android.net.Uri);
     method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
     method public static java.lang.String getRootId(android.net.Uri);
@@ -32180,6 +32189,15 @@
     field public static final java.lang.String MIME_TYPE_DIR = "vnd.android.document/directory";
   }
 
+  public static final class DocumentsContract.Path implements android.os.Parcelable {
+    ctor public DocumentsContract.Path(java.lang.String, java.util.List<java.lang.String>);
+    method public int describeContents();
+    method public java.util.List<java.lang.String> getPath();
+    method public java.lang.String getRootId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.provider.DocumentsContract.Path> CREATOR;
+  }
+
   public static final class DocumentsContract.Root {
     field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
     field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
@@ -32203,6 +32221,7 @@
     method public java.lang.String createDocument(java.lang.String, java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
     method public void deleteDocument(java.lang.String) throws java.io.FileNotFoundException;
+    method public android.provider.DocumentsContract.Path findDocumentPath(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public java.lang.String[] getDocumentStreamTypes(java.lang.String, java.lang.String);
     method public java.lang.String getDocumentType(java.lang.String) throws java.io.FileNotFoundException;
     method public final java.lang.String getType(android.net.Uri);
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index c7474a11..132a4f8 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -17,8 +17,8 @@
 package com.android.commands.content;
 
 import android.app.ActivityManagerNative;
+import android.app.ContentProviderHolder;
 import android.app.IActivityManager;
-import android.app.IActivityManager.ContentProviderHolder;
 import android.content.ContentValues;
 import android.content.IContentProvider;
 import android.database.Cursor;
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 7bf073b..a41f122 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -177,7 +177,7 @@
         if (png) {
             const SkImageInfo info = SkImageInfo::Make(w, h, flinger2skia(f),
                                                        kPremul_SkAlphaType);
-            SkAutoTUnref<SkData> data(SkImageEncoder::EncodeData(info, base, s*bytesPerPixel(f),
+            sk_sp<SkData> data(SkImageEncoder::EncodeData(info, base, s*bytesPerPixel(f),
                     SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality));
             if (data.get()) {
                 write(fd, data->data(), data->size());
diff --git a/cmds/settings/Android.mk b/cmds/settings/Android.mk
index 05deb99..8a8d1bb 100644
--- a/cmds/settings/Android.mk
+++ b/cmds/settings/Android.mk
@@ -3,11 +3,6 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_MODULE := settings
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_JAVA_LIBRARY)
-
 include $(CLEAR_VARS)
 LOCAL_MODULE := settings
 LOCAL_SRC_FILES := settings
diff --git a/cmds/settings/settings b/cmds/settings/settings
index ef459ca..d41ccc62 100755
--- a/cmds/settings/settings
+++ b/cmds/settings/settings
@@ -1,5 +1,2 @@
-# Script to start "settings" on the device
-#
-base=/system
-export CLASSPATH=$base/framework/settings.jar
-exec app_process $base/bin com.android.commands.settings.SettingsCmd "$@"
+#!/system/bin/sh
+cmd settings "$@"
diff --git a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
deleted file mode 100644
index e63a1f5..0000000
--- a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (C) 2012 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.commands.settings;
-
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
-import android.app.IActivityManager.ContentProviderHolder;
-import android.content.IContentProvider;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public final class SettingsCmd {
-
-    enum CommandVerb {
-        UNSPECIFIED,
-        GET,
-        PUT,
-        DELETE,
-        LIST,
-    }
-
-    static String[] mArgs;
-    int mNextArg;
-    int mUser = -1;     // unspecified
-    CommandVerb mVerb = CommandVerb.UNSPECIFIED;
-    String mTable = null;
-    String mKey = null;
-    String mValue = null;
-
-    public static void main(String[] args) {
-        if (args == null || args.length < 2) {
-            printUsage();
-            return;
-        }
-
-        mArgs = args;
-        try {
-            new SettingsCmd().run();
-        } catch (Exception e) {
-            System.err.println("Unable to run settings command");
-        }
-    }
-
-    public void run() {
-        boolean valid = false;
-        String arg;
-        try {
-            while ((arg = nextArg()) != null) {
-                if ("--user".equals(arg)) {
-                    if (mUser != -1) {
-                        // --user specified more than once; invalid
-                        break;
-                    }
-                    arg = nextArg();
-                    if ("current".equals(arg) || "cur".equals(arg)) {
-                        mUser = UserHandle.USER_CURRENT;
-                    } else {
-                        mUser = Integer.parseInt(arg);
-                    }
-                } else if (mVerb == CommandVerb.UNSPECIFIED) {
-                    if ("get".equalsIgnoreCase(arg)) {
-                        mVerb = CommandVerb.GET;
-                    } else if ("put".equalsIgnoreCase(arg)) {
-                        mVerb = CommandVerb.PUT;
-                    } else if ("delete".equalsIgnoreCase(arg)) {
-                        mVerb = CommandVerb.DELETE;
-                    } else if ("list".equalsIgnoreCase(arg)) {
-                        mVerb = CommandVerb.LIST;
-                    } else {
-                        // invalid
-                        System.err.println("Invalid command: " + arg);
-                        break;
-                    }
-                } else if (mTable == null) {
-                    if (!"system".equalsIgnoreCase(arg)
-                            && !"secure".equalsIgnoreCase(arg)
-                            && !"global".equalsIgnoreCase(arg)) {
-                        System.err.println("Invalid namespace '" + arg + "'");
-                        break;  // invalid
-                    }
-                    mTable = arg.toLowerCase();
-                    if (mVerb == CommandVerb.LIST) {
-                        valid = true;
-                        break;
-                    }
-                } else if (mVerb == CommandVerb.GET || mVerb == CommandVerb.DELETE) {
-                    mKey = arg;
-                    if (mNextArg >= mArgs.length) {
-                        valid = true;
-                    } else {
-                        System.err.println("Too many arguments");
-                    }
-                    break;
-                } else if (mKey == null) {
-                    mKey = arg;
-                    // keep going; there's another PUT arg
-                } else {    // PUT, final arg
-                    mValue = arg;
-                    if (mNextArg >= mArgs.length) {
-                        valid = true;
-                    } else {
-                        System.err.println("Too many arguments");
-                    }
-                    break;
-                }
-            }
-        } catch (Exception e) {
-            valid = false;
-        }
-
-        if (valid) {
-            try {
-                IActivityManager activityManager = ActivityManagerNative.getDefault();
-                if (mUser == UserHandle.USER_CURRENT) {
-                    mUser = activityManager.getCurrentUser().id;
-                }
-                if (mUser < 0) {
-                    mUser = UserHandle.USER_SYSTEM;
-                }
-                IContentProvider provider = null;
-                IBinder token = new Binder();
-                try {
-                    ContentProviderHolder holder = activityManager.getContentProviderExternal(
-                            "settings", UserHandle.USER_SYSTEM, token);
-                    if (holder == null) {
-                        throw new IllegalStateException("Could not find settings provider");
-                    }
-                    provider = holder.provider;
-
-                    switch (mVerb) {
-                        case GET:
-                            System.out.println(getForUser(provider, mUser, mTable, mKey));
-                            break;
-                        case PUT:
-                            putForUser(provider, mUser, mTable, mKey, mValue);
-                            break;
-                        case DELETE:
-                            System.out.println("Deleted "
-                                    + deleteForUser(provider, mUser, mTable, mKey) + " rows");
-                            break;
-                        case LIST:
-                            for (String line : listForUser(provider, mUser, mTable)) {
-                                System.out.println(line);
-                            }
-                            break;
-                        default:
-                            System.err.println("Unspecified command");
-                            break;
-                    }
-
-                } finally {
-                    if (provider != null) {
-                        activityManager.removeContentProviderExternal("settings", token);
-                    }
-                }
-            } catch (Exception e) {
-                System.err.println("Error while accessing settings provider");
-                e.printStackTrace();
-            }
-
-        } else {
-            printUsage();
-        }
-    }
-
-    private List<String> listForUser(IContentProvider provider, int userHandle, String table) {
-        final Uri uri = "system".equals(table) ? Settings.System.CONTENT_URI
-                : "secure".equals(table) ? Settings.Secure.CONTENT_URI
-                : "global".equals(table) ? Settings.Global.CONTENT_URI
-                : null;
-        final ArrayList<String> lines = new ArrayList<String>();
-        if (uri == null) {
-            return lines;
-        }
-        try {
-            final Cursor cursor = provider.query(resolveCallingPackage(), uri, null, null, null,
-                    null, null);
-            try {
-                while (cursor != null && cursor.moveToNext()) {
-                    lines.add(cursor.getString(1) + "=" + cursor.getString(2));
-                }
-            } finally {
-                if (cursor != null) {
-                    cursor.close();
-                }
-            }
-            Collections.sort(lines);
-        } catch (RemoteException e) {
-            System.err.println("List failed in " + table + " for user " + userHandle);
-        }
-        return lines;
-    }
-
-    private String nextArg() {
-        if (mNextArg >= mArgs.length) {
-            return null;
-        }
-        String arg = mArgs[mNextArg];
-        mNextArg++;
-        return arg;
-    }
-
-    String getForUser(IContentProvider provider, int userHandle,
-            final String table, final String key) {
-        final String callGetCommand;
-        if ("system".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SYSTEM;
-        else if ("secure".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SECURE;
-        else if ("global".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_GLOBAL;
-        else {
-            System.err.println("Invalid table; no put performed");
-            throw new IllegalArgumentException("Invalid table " + table);
-        }
-
-        String result = null;
-        try {
-            Bundle arg = new Bundle();
-            arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-            Bundle b = provider.call(resolveCallingPackage(), callGetCommand, key, arg);
-            if (b != null) {
-                result = b.getPairValue();
-            }
-        } catch (RemoteException e) {
-            System.err.println("Can't read key " + key + " in " + table + " for user " + userHandle);
-        }
-        return result;
-    }
-
-    void putForUser(IContentProvider provider, int userHandle,
-            final String table, final String key, final String value) {
-        final String callPutCommand;
-        if ("system".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
-        else if ("secure".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SECURE;
-        else if ("global".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_GLOBAL;
-        else {
-            System.err.println("Invalid table; no put performed");
-            return;
-        }
-
-        try {
-            Bundle arg = new Bundle();
-            arg.putString(Settings.NameValueTable.VALUE, value);
-            arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-            provider.call(resolveCallingPackage(), callPutCommand, key, arg);
-        } catch (RemoteException e) {
-            System.err.println("Can't set key " + key + " in " + table + " for user " + userHandle);
-        }
-    }
-
-    int deleteForUser(IContentProvider provider, int userHandle,
-            final String table, final String key) {
-        Uri targetUri;
-        if ("system".equals(table)) targetUri = Settings.System.getUriFor(key);
-        else if ("secure".equals(table)) targetUri = Settings.Secure.getUriFor(key);
-        else if ("global".equals(table)) targetUri = Settings.Global.getUriFor(key);
-        else {
-            System.err.println("Invalid table; no delete performed");
-            throw new IllegalArgumentException("Invalid table " + table);
-        }
-
-        int num = 0;
-        try {
-            num = provider.delete(resolveCallingPackage(), targetUri, null, null);
-        } catch (RemoteException e) {
-            System.err.println("Can't clear key " + key + " in " + table + " for user "
-                    + userHandle);
-        }
-        return num;
-    }
-
-    private static void printUsage() {
-        System.err.println("usage:  settings [--user <USER_ID> | current] get namespace key");
-        System.err.println("        settings [--user <USER_ID> | current] put namespace key value");
-        System.err.println("        settings [--user <USER_ID> | current] delete namespace key");
-        System.err.println("        settings [--user <USER_ID> | current] list namespace");
-        System.err.println("\n'namespace' is one of {system, secure, global}, case-insensitive");
-        System.err.println("If '--user <USER_ID> | current' is not given, the operations are "
-                + "performed on the system user.");
-    }
-
-    public static String resolveCallingPackage() {
-        switch (android.os.Process.myUid()) {
-            case Process.ROOT_UID: {
-                return "root";
-            }
-
-            case Process.SHELL_UID: {
-                return "com.android.shell";
-            }
-
-            default: {
-                return null;
-            }
-        }
-    }
-}
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index cb39e37..8681166 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -17,8 +17,8 @@
 package com.android.uiautomator.core;
 
 import android.app.ActivityManagerNative;
+import android.app.ContentProviderHolder;
 import android.app.IActivityManager;
-import android.app.IActivityManager.ContentProviderHolder;
 import android.app.UiAutomation;
 import android.content.Context;
 import android.content.IContentProvider;
diff --git a/compiled-classes-phone b/compiled-classes-phone
index 661ff95..8428e41 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -245,6 +245,8 @@
 android.app.BackStackState
 android.app.BackStackState$1
 android.app.BroadcastOptions
+android.app.ContentProviderHolder
+android.app.ContentProviderHolder$1
 android.app.ContextImpl
 android.app.ContextImpl$1
 android.app.ContextImpl$ApplicationContentResolver
@@ -298,9 +300,8 @@
 android.app.IActivityContainerCallback
 android.app.IActivityController
 android.app.IActivityManager
-android.app.IActivityManager$ContentProviderHolder
-android.app.IActivityManager$ContentProviderHolder$1
-android.app.IActivityManager$WaitResult
+android.app.IActivityManager$Stub
+android.app.IActivityManager$Stub$Proxy
 android.app.IAlarmCompleteListener
 android.app.IAlarmCompleteListener$Stub
 android.app.IAlarmListener
@@ -521,6 +522,7 @@
 android.app.TimePickerDialog
 android.app.TimePickerDialog$OnTimeSetListener
 android.app.UiModeManager
+android.app.WaitResult;
 android.app.WallpaperInfo
 android.app.WallpaperManager
 android.app.WallpaperManager$Globals
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 163e7d2..b311c21 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -334,7 +334,8 @@
     public static final int GLOBAL_ACTION_HOME = 2;
 
     /**
-     * Action to toggle showing the overview of recent apps
+     * Action to toggle showing the overview of recent apps. Will fail on platforms that don't
+     * show recent apps.
      */
     public static final int GLOBAL_ACTION_RECENTS = 3;
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index cb3eba6..b3e2f57 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -6047,8 +6047,8 @@
         boolean drawComplete;
         try {
             mTranslucentCallback = callback;
-            mChangeCanvasToTranslucent =
-                    ActivityManagerNative.getDefault().convertToTranslucent(mToken, options);
+            mChangeCanvasToTranslucent = ActivityManagerNative.getDefault().convertToTranslucent(
+                    mToken, options == null ? null : options.toBundle());
             WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, false);
             drawComplete = true;
         } catch (RemoteException e) {
@@ -6092,7 +6092,8 @@
      */
     ActivityOptions getActivityOptions() {
         try {
-            return ActivityManagerNative.getDefault().getActivityOptions(mToken);
+            return ActivityOptions.fromBundle(
+                    ActivityManagerNative.getDefault().getActivityOptions(mToken));
         } catch (RemoteException e) {
         }
         return null;
@@ -6988,7 +6989,7 @@
      */
     public void startLockTask() {
         try {
-            ActivityManagerNative.getDefault().startLockTaskMode(mToken);
+            ActivityManagerNative.getDefault().startLockTaskModeByToken(mToken);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/ActivityManager.aidl b/core/java/android/app/ActivityManager.aidl
index fa6481b..5672f6b 100644
--- a/core/java/android/app/ActivityManager.aidl
+++ b/core/java/android/app/ActivityManager.aidl
@@ -16,5 +16,14 @@
 
 package android.app;
 
+parcelable ActivityManager.MemoryInfo;
+parcelable ActivityManager.ProcessErrorStateInfo;
 parcelable ActivityManager.RecentTaskInfo;
 parcelable ActivityManager.TaskDescription;
+parcelable ActivityManager.RunningAppProcessInfo;
+parcelable ActivityManager.RunningServiceInfo;
+parcelable ActivityManager.RunningTaskInfo;
+/** @hide */
+parcelable ActivityManager.StackInfo;
+/** @hide */
+parcelable ActivityManager.TaskThumbnail;
\ No newline at end of file
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4066f1c..9af7d8b 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
@@ -61,7 +62,9 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.DisplayMetrics;
+import android.util.Singleton;
 import android.util.Size;
 
 import org.xmlpull.v1.XmlSerializer;
@@ -86,6 +89,49 @@
     private final Context mContext;
     private final Handler mHandler;
 
+    static final class UidObserver extends IUidObserver.Stub {
+        final OnUidImportanceListener mListener;
+        final int mImportanceCutpoint;
+        int mLastImportance;
+
+        UidObserver(OnUidImportanceListener listener, int importanceCutpoint) {
+            mListener = listener;
+            mImportanceCutpoint = importanceCutpoint;
+        }
+
+        @Override
+        public void onUidStateChanged(int uid, int procState) {
+            final boolean lastAboveCut = mLastImportance <= mImportanceCutpoint;
+            final int importance = RunningAppProcessInfo.procStateToImportance(procState);
+            final boolean newAboveCut = importance <= mImportanceCutpoint;
+            /*
+            Log.d(TAG, "Uid " + uid + " state change from " + mLastImportance + " to "
+                    + importance + " @ cut " + mImportanceCutpoint
+                    + ": lastAbove=" + lastAboveCut + " newAbove=" + newAboveCut);
+            */
+            mLastImportance = importance;
+            if (lastAboveCut != newAboveCut) {
+                mListener.onUidImportance(uid, importance);
+            }
+        }
+
+        @Override
+        public void onUidGone(int uid) {
+            mLastImportance = RunningAppProcessInfo.IMPORTANCE_GONE;
+            mListener.onUidImportance(uid, RunningAppProcessInfo.IMPORTANCE_GONE);
+        }
+
+        @Override
+        public void onUidActive(int uid) {
+        }
+
+        @Override
+        public void onUidIdle(int uid) {
+        }
+    }
+
+    final ArrayMap<OnUidImportanceListener, UidObserver> mImportanceListeners = new ArrayMap<>();
+
     /**
      * Defines acceptable types of bugreports.
      * @hide
@@ -1687,7 +1733,7 @@
      */
     public List<ActivityManager.AppTask> getAppTasks() {
         ArrayList<AppTask> tasks = new ArrayList<AppTask>();
-        List<IAppTask> appTasks;
+        List<IBinder> appTasks;
         try {
             appTasks = ActivityManagerNative.getDefault().getAppTasks(mContext.getPackageName());
         } catch (RemoteException e) {
@@ -1695,7 +1741,7 @@
         }
         int numAppTasks = appTasks.size();
         for (int i = 0; i < numAppTasks; i++) {
-            tasks.add(new AppTask(appTasks.get(i)));
+            tasks.add(new AppTask(IAppTask.Stub.asInterface(appTasks.get(i))));
         }
         return tasks;
     }
@@ -3044,11 +3090,11 @@
      * running its code, {@link RunningAppProcessInfo#IMPORTANCE_GONE} is returned.
      * @hide
      */
-    @SystemApi
+    @SystemApi @TestApi
     @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
     public int getPackageImportance(String packageName) {
         try {
-            int procState = ActivityManagerNative.getDefault().getPackageProcessState(packageName,
+            int procState = getService().getPackageProcessState(packageName,
                     mContext.getOpPackageName());
             return RunningAppProcessInfo.procStateToImportance(procState);
         } catch (RemoteException e) {
@@ -3057,6 +3103,83 @@
     }
 
     /**
+     * Callback to get reports about changes to the importance of a uid.  Use with
+     * {@link #addOnUidImportanceListener}.
+     * @hide
+     */
+    @SystemApi @TestApi
+    public interface OnUidImportanceListener {
+        /**
+         * The importance if a given uid has changed.  Will be one of the importance
+         * values in {@link RunningAppProcessInfo};
+         * {@link RunningAppProcessInfo#IMPORTANCE_GONE IMPORTANCE_GONE} will be reported
+         * when the uid is no longer running at all.  This callback will happen on a thread
+         * from a thread pool, not the main UI thread.
+         * @param uid The uid whose importance has changed.
+         * @param importance The new importance value as per {@link RunningAppProcessInfo}.
+         */
+        void onUidImportance(int uid, int importance);
+    }
+
+    /**
+     * Start monitoring changes to the imoportance of uids running in the system.
+     * @param listener The listener callback that will receive change reports.
+     * @param importanceCutpoint The level of importance in which the caller is interested
+     * in differences.  For example, if {@link RunningAppProcessInfo#IMPORTANCE_PERCEPTIBLE}
+     * is used here, you will receive a call each time a uids importance transitions between
+     * being <= {@link RunningAppProcessInfo#IMPORTANCE_PERCEPTIBLE} and
+     * > {@link RunningAppProcessInfo#IMPORTANCE_PERCEPTIBLE}.
+     *
+     * <p>The caller must hold the {@link android.Manifest.permission#PACKAGE_USAGE_STATS}
+     * permission to use this feature.</p>
+     *
+     * @throws IllegalArgumentException If the listener is already registered.
+     * @throws SecurityException If the caller does not hold
+     * {@link android.Manifest.permission#PACKAGE_USAGE_STATS}.
+     * @hide
+     */
+    @SystemApi @TestApi
+    public void addOnUidImportanceListener(OnUidImportanceListener listener,
+            int importanceCutpoint) {
+        synchronized (this) {
+            if (mImportanceListeners.containsKey(listener)) {
+                throw new IllegalArgumentException("Listener already registered: " + listener);
+            }
+            // TODO: implement the cut point in the system process to avoid IPCs.
+            UidObserver observer = new UidObserver(listener, importanceCutpoint);
+            try {
+                getService().registerUidObserver(observer,
+                        UID_OBSERVER_PROCSTATE | UID_OBSERVER_GONE, mContext.getOpPackageName());
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+            mImportanceListeners.put(listener, observer);
+        }
+    }
+
+    /**
+     * Remove an importance listener that was previously registered with
+     * {@link #addOnUidImportanceListener}.
+     *
+     * @throws IllegalArgumentException If the listener is not registered.
+     * @hide
+     */
+    @SystemApi @TestApi
+    public void removeOnUidImportanceListener(OnUidImportanceListener listener) {
+        synchronized (this) {
+            UidObserver observer = mImportanceListeners.remove(listener);
+            if (observer == null) {
+                throw new IllegalArgumentException("Listener not registered: " + listener);
+            }
+            try {
+                getService().unregisterUidObserver(observer);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
      * Return global memory state information for the calling process.  This
      * does not fill in all fields of the {@link RunningAppProcessInfo}.  The
      * only fields that will be filled in are
@@ -3520,6 +3643,76 @@
         pw.flush();
     }
 
+    /**
+     * @hide
+     */
+    public static void broadcastStickyIntent(Intent intent, int userId) {
+        broadcastStickyIntent(intent, AppOpsManager.OP_NONE, userId);
+    }
+
+    /**
+     * Convenience for sending a sticky broadcast.  For internal use only.
+     *
+     * @hide
+     */
+    public static void broadcastStickyIntent(Intent intent, int appOp, int userId) {
+        try {
+            getService().broadcastIntent(
+                    null, intent, null, null, Activity.RESULT_OK, null, null,
+                    null /*permission*/, appOp, null, false, true, userId);
+        } catch (RemoteException ex) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static void noteWakeupAlarm(PendingIntent ps, int sourceUid, String sourcePkg,
+            String tag) {
+        try {
+            getService().noteWakeupAlarm((ps != null) ? ps.getTarget() : null,
+                    sourceUid, sourcePkg, tag);
+        } catch (RemoteException ex) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static void noteAlarmStart(PendingIntent ps, int sourceUid, String tag) {
+        try {
+            getService().noteAlarmStart((ps != null) ? ps.getTarget() : null, sourceUid, tag);
+        } catch (RemoteException ex) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static void noteAlarmFinish(PendingIntent ps, int sourceUid, String tag) {
+        try {
+            getService().noteAlarmFinish((ps != null) ? ps.getTarget() : null, sourceUid, tag);
+        } catch (RemoteException ex) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static IActivityManager getService() {
+        return IActivityManagerSingleton.get();
+    }
+
+    private static final Singleton<IActivityManager> IActivityManagerSingleton =
+            new Singleton<IActivityManager>() {
+                @Override
+                protected IActivityManager create() {
+                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
+                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
+                    return am;
+                }
+            };
+
     private static void dumpService(PrintWriter pw, FileDescriptor fd, String name, String[] args) {
         pw.print("DUMP OF SERVICE "); pw.print(name); pw.println(":");
         IBinder service = ServiceManager.checkService(name);
@@ -3593,7 +3786,7 @@
      */
     public void startLockTaskMode(int taskId) {
         try {
-            ActivityManagerNative.getDefault().startLockTaskMode(taskId);
+            ActivityManagerNative.getDefault().startLockTaskModeById(taskId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 1ee31d8..e56fe0f 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -189,4 +189,9 @@
      *                 guaranteed that all apps have their visibility updated accordingly.
      */
     public abstract void notifyKeyguardFlagsChanged(@Nullable Runnable callback);
+
+    /**
+     * @return {@code true} if system is ready, {@code false} otherwise.
+     */
+    public abstract boolean isSystemReady();
 }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 15f6361..199fda4 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -15,88 +15,64 @@
  */
 
 package android.app;
-
-import android.annotation.UserIdInt;
-import android.app.ActivityManager.StackInfo;
-import android.app.assist.AssistContent;
-import android.app.assist.AssistStructure;
-import android.content.ComponentName;
-import android.content.IIntentReceiver;
-import android.content.IIntentSender;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.content.UriPermission;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.ParceledListSlice;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
 import android.os.Debug;
 import android.os.IBinder;
-import android.os.IProgressListener;
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.StrictMode;
-import android.service.voice.IVoiceInteractionSession;
-import android.text.TextUtils;
 import android.util.Log;
-import android.util.Singleton;
-import com.android.internal.app.IVoiceInteractor;
-import com.android.internal.os.IResultReceiver;
 
-import java.util.ArrayList;
-import java.util.List;
+import com.android.server.LocalServices;
 
-/** {@hide} */
-public abstract class ActivityManagerNative extends Binder implements IActivityManager
-{
+/**
+ * {@hide}
+ * @deprecated will be removed soon. See individual methods for alternatives.
+ */
+@Deprecated
+public abstract class ActivityManagerNative {
+    private final static String TAG = "ActivityManagerNative";
+
     /**
      * Cast a Binder object into an activity manager interface, generating
      * a proxy if needed.
+     *
+     * @deprecated use IActivityManager.Stub.asInterface instead.
      */
     static public IActivityManager asInterface(IBinder obj) {
-        if (obj == null) {
-            return null;
-        }
-        IActivityManager in =
-            (IActivityManager)obj.queryLocalInterface(descriptor);
-        if (in != null) {
-            return in;
-        }
-
-        return new ActivityManagerProxy(obj);
+        return IActivityManager.Stub.asInterface(obj);
     }
 
     /**
      * Retrieve the system's default/global activity manager.
+     *
+     * @deprecated use ActivityManager.getService instead.
      */
     static public IActivityManager getDefault() {
-        return gDefault.get();
+        return ActivityManager.getService();
     }
 
     /**
      * Convenience for checking whether the system is ready.  For internal use only.
+     *
+     * @deprecated use ActivityManagerInternal.isSystemReady instead.
      */
     static public boolean isSystemReady() {
         if (!sSystemReady) {
-            sSystemReady = getDefault().testIsSystemReady();
+            if (ActivityThread.isSystem()) {
+                sSystemReady =
+                        LocalServices.getService(ActivityManagerInternal.class).isSystemReady();
+            } else {
+                // Since this is being called from outside system server, system should be
+                // ready by now.
+                sSystemReady = true;
+            }
         }
         return sSystemReady;
     }
+
     static volatile boolean sSystemReady = false;
 
+    /**
+     * @deprecated use ActivityManager.broadcastStickyIntent instead.
+     */
     static public void broadcastStickyIntent(Intent intent, String permission, int userId) {
         broadcastStickyIntent(intent, permission, AppOpsManager.OP_NONE, userId);
     }
@@ -104,7039 +80,33 @@
     /**
      * Convenience for sending a sticky broadcast.  For internal use only.
      * If you don't care about permission, use null.
+     *
+     * @deprecated use ActivityManager.broadcastStickyIntent instead.
      */
     static public void broadcastStickyIntent(Intent intent, String permission, int appOp,
             int userId) {
-        try {
-            getDefault().broadcastIntent(
-                    null, intent, null, null, Activity.RESULT_OK, null, null,
-                    null /*permission*/, appOp, null, false, true, userId);
-        } catch (RemoteException ex) {
-        }
+        ActivityManager.broadcastStickyIntent(intent, appOp, userId);
     }
 
+    /**
+     * @deprecated use ActivityManager.noteWakeupAlarm instead.
+     */
     static public void noteWakeupAlarm(PendingIntent ps, int sourceUid, String sourcePkg,
             String tag) {
-        try {
-            getDefault().noteWakeupAlarm((ps != null) ? ps.getTarget() : null,
-                    sourceUid, sourcePkg, tag);
-        } catch (RemoteException ex) {
-        }
+        ActivityManager.noteWakeupAlarm(ps, sourceUid, sourcePkg, tag);
     }
 
+    /**
+     * @deprecated use ActivityManager.noteAlarmStart instead.
+     */
     static public void noteAlarmStart(PendingIntent ps, int sourceUid, String tag) {
-        try {
-            getDefault().noteAlarmStart((ps != null) ? ps.getTarget() : null, sourceUid, tag);
-        } catch (RemoteException ex) {
-        }
+        ActivityManager.noteAlarmStart(ps, sourceUid, tag);
     }
 
+    /**
+     * @deprecated use ActivityManager.noteAlarmFinish instead.
+     */
     static public void noteAlarmFinish(PendingIntent ps, int sourceUid, String tag) {
-        try {
-            getDefault().noteAlarmFinish((ps != null) ? ps.getTarget() : null, sourceUid, tag);
-        } catch (RemoteException ex) {
-        }
+        ActivityManager.noteAlarmFinish(ps, sourceUid, tag);
     }
-
-    public ActivityManagerNative() {
-        attachInterface(this, descriptor);
-    }
-
-    @Override
-    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
-            throws RemoteException {
-        switch (code) {
-        case START_ACTIVITY_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            String callingPackage = data.readString();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            IBinder resultTo = data.readStrongBinder();
-            String resultWho = data.readString();
-            int requestCode = data.readInt();
-            int startFlags = data.readInt();
-            ProfilerInfo profilerInfo = data.readInt() != 0
-                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int result = startActivity(app, callingPackage, intent, resolvedType,
-                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
-        case START_ACTIVITY_AS_USER_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            String callingPackage = data.readString();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            IBinder resultTo = data.readStrongBinder();
-            String resultWho = data.readString();
-            int requestCode = data.readInt();
-            int startFlags = data.readInt();
-            ProfilerInfo profilerInfo = data.readInt() != 0
-                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int userId = data.readInt();
-            int result = startActivityAsUser(app, callingPackage, intent, resolvedType,
-                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options, userId);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
-        case START_ACTIVITY_AS_CALLER_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            String callingPackage = data.readString();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            IBinder resultTo = data.readStrongBinder();
-            String resultWho = data.readString();
-            int requestCode = data.readInt();
-            int startFlags = data.readInt();
-            ProfilerInfo profilerInfo = data.readInt() != 0
-                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            boolean ignoreTargetSecurity = data.readInt() != 0;
-            int userId = data.readInt();
-            int result = startActivityAsCaller(app, callingPackage, intent, resolvedType,
-                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options,
-                    ignoreTargetSecurity, userId);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
-        case START_ACTIVITY_AND_WAIT_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            String callingPackage = data.readString();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            IBinder resultTo = data.readStrongBinder();
-            String resultWho = data.readString();
-            int requestCode = data.readInt();
-            int startFlags = data.readInt();
-            ProfilerInfo profilerInfo = data.readInt() != 0
-                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int userId = data.readInt();
-            WaitResult result = startActivityAndWait(app, callingPackage, intent, resolvedType,
-                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options, userId);
-            reply.writeNoException();
-            result.writeToParcel(reply, 0);
-            return true;
-        }
-
-        case START_ACTIVITY_WITH_CONFIG_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            String callingPackage = data.readString();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            IBinder resultTo = data.readStrongBinder();
-            String resultWho = data.readString();
-            int requestCode = data.readInt();
-            int startFlags = data.readInt();
-            Configuration config = Configuration.CREATOR.createFromParcel(data);
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int userId = data.readInt();
-            int result = startActivityWithConfig(app, callingPackage, intent, resolvedType,
-                    resultTo, resultWho, requestCode, startFlags, config, options, userId);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
-        case START_ACTIVITY_INTENT_SENDER_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            IntentSender intent = IntentSender.CREATOR.createFromParcel(data);
-            Intent fillInIntent = null;
-            if (data.readInt() != 0) {
-                fillInIntent = Intent.CREATOR.createFromParcel(data);
-            }
-            String resolvedType = data.readString();
-            IBinder resultTo = data.readStrongBinder();
-            String resultWho = data.readString();
-            int requestCode = data.readInt();
-            int flagsMask = data.readInt();
-            int flagsValues = data.readInt();
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int result = startActivityIntentSender(app, intent,
-                    fillInIntent, resolvedType, resultTo, resultWho,
-                    requestCode, flagsMask, flagsValues, options);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
-        case START_VOICE_ACTIVITY_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            String callingPackage = data.readString();
-            int callingPid = data.readInt();
-            int callingUid = data.readInt();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            IVoiceInteractionSession session = IVoiceInteractionSession.Stub.asInterface(
-                    data.readStrongBinder());
-            IVoiceInteractor interactor = IVoiceInteractor.Stub.asInterface(
-                    data.readStrongBinder());
-            int startFlags = data.readInt();
-            ProfilerInfo profilerInfo = data.readInt() != 0
-                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int userId = data.readInt();
-            int result = startVoiceActivity(callingPackage, callingPid, callingUid, intent,
-                    resolvedType, session, interactor, startFlags, profilerInfo, options, userId);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
-        case START_LOCAL_VOICE_INTERACTION_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Bundle options = data.readBundle();
-            startLocalVoiceInteraction(token, options);
-            reply.writeNoException();
-            return true;
-        }
-
-        case STOP_LOCAL_VOICE_INTERACTION_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            stopLocalVoiceInteraction(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SUPPORTS_LOCAL_VOICE_INTERACTION_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            boolean result = supportsLocalVoiceInteraction();
-            reply.writeNoException();
-            reply.writeInt(result? 1 : 0);
-            return true;
-        }
-
-        case START_NEXT_MATCHING_ACTIVITY_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder callingActivity = data.readStrongBinder();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            boolean result = startNextMatchingActivity(callingActivity, intent, options);
-            reply.writeNoException();
-            reply.writeInt(result ? 1 : 0);
-            return true;
-        }
-
-        case START_ACTIVITY_FROM_RECENTS_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int taskId = data.readInt();
-            final Bundle options =
-                    data.readInt() == 0 ? null : Bundle.CREATOR.createFromParcel(data);
-            final int result = startActivityFromRecents(taskId, options);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
-        case FINISH_ACTIVITY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Intent resultData = null;
-            int resultCode = data.readInt();
-            if (data.readInt() != 0) {
-                resultData = Intent.CREATOR.createFromParcel(data);
-            }
-            int finishTask = data.readInt();
-            boolean res = finishActivity(token, resultCode, resultData, finishTask);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case FINISH_SUB_ACTIVITY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            String resultWho = data.readString();
-            int requestCode = data.readInt();
-            finishSubActivity(token, resultWho, requestCode);
-            reply.writeNoException();
-            return true;
-        }
-
-        case FINISH_ACTIVITY_AFFINITY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            boolean res = finishActivityAffinity(token);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case FINISH_VOICE_TASK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IVoiceInteractionSession session = IVoiceInteractionSession.Stub.asInterface(
-                    data.readStrongBinder());
-            finishVoiceTask(session);
-            reply.writeNoException();
-            return true;
-        }
-
-        case REQUEST_ACTIVITY_RELAUNCH: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            requestActivityRelaunch(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case RELEASE_ACTIVITY_INSTANCE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            boolean res = releaseActivityInstance(token);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case RELEASE_SOME_ACTIVITIES_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IApplicationThread app = IApplicationThread.Stub.asInterface(data.readStrongBinder());
-            releaseSomeActivities(app);
-            reply.writeNoException();
-            return true;
-        }
-
-        case WILL_ACTIVITY_BE_VISIBLE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            boolean res = willActivityBeVisible(token);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case REGISTER_RECEIVER_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app =
-                b != null ? IApplicationThread.Stub.asInterface(b) : null;
-            String packageName = data.readString();
-            b = data.readStrongBinder();
-            IIntentReceiver rec
-                = b != null ? IIntentReceiver.Stub.asInterface(b) : null;
-            IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data);
-            String perm = data.readString();
-            int userId = data.readInt();
-            Intent intent = registerReceiver(app, packageName, rec, filter, perm, userId);
-            reply.writeNoException();
-            if (intent != null) {
-                reply.writeInt(1);
-                intent.writeToParcel(reply, 0);
-            } else {
-                reply.writeInt(0);
-            }
-            return true;
-        }
-
-        case UNREGISTER_RECEIVER_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            if (b == null) {
-                return true;
-            }
-            IIntentReceiver rec = IIntentReceiver.Stub.asInterface(b);
-            unregisterReceiver(rec);
-            reply.writeNoException();
-            return true;
-        }
-
-        case BROADCAST_INTENT_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app =
-                b != null ? IApplicationThread.Stub.asInterface(b) : null;
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            b = data.readStrongBinder();
-            IIntentReceiver resultTo =
-                b != null ? IIntentReceiver.Stub.asInterface(b) : null;
-            int resultCode = data.readInt();
-            String resultData = data.readString();
-            Bundle resultExtras = data.readBundle();
-            String[] perms = data.readStringArray();
-            int appOp = data.readInt();
-            Bundle options = data.readBundle();
-            boolean serialized = data.readInt() != 0;
-            boolean sticky = data.readInt() != 0;
-            int userId = data.readInt();
-            int res = broadcastIntent(app, intent, resolvedType, resultTo,
-                    resultCode, resultData, resultExtras, perms, appOp,
-                    options, serialized, sticky, userId);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case UNBROADCAST_INTENT_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = b != null ? IApplicationThread.Stub.asInterface(b) : null;
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            int userId = data.readInt();
-            unbroadcastIntent(app, intent, userId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case FINISH_RECEIVER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder who = data.readStrongBinder();
-            int resultCode = data.readInt();
-            String resultData = data.readString();
-            Bundle resultExtras = data.readBundle();
-            boolean resultAbort = data.readInt() != 0;
-            int intentFlags = data.readInt();
-            if (who != null) {
-                finishReceiver(who, resultCode, resultData, resultExtras, resultAbort, intentFlags);
-            }
-            reply.writeNoException();
-            return true;
-        }
-
-        case ATTACH_APPLICATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IApplicationThread app = IApplicationThread.Stub.asInterface(
-                    data.readStrongBinder());
-            if (app != null) {
-                attachApplication(app);
-            }
-            reply.writeNoException();
-            return true;
-        }
-
-        case ACTIVITY_IDLE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Configuration config = null;
-            if (data.readInt() != 0) {
-                config = Configuration.CREATOR.createFromParcel(data);
-            }
-            boolean stopProfiling = data.readInt() != 0;
-            if (token != null) {
-                activityIdle(token, config, stopProfiling);
-            }
-            reply.writeNoException();
-            return true;
-        }
-
-        case ACTIVITY_RESUMED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            activityResumed(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case ACTIVITY_PAUSED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            activityPaused(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case ACTIVITY_STOPPED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Bundle map = data.readBundle();
-            PersistableBundle persistentState = data.readPersistableBundle();
-            CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
-            activityStopped(token, map, persistentState, description);
-            reply.writeNoException();
-            return true;
-        }
-
-        case ACTIVITY_SLEPT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            activitySlept(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case ACTIVITY_DESTROYED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            activityDestroyed(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case ACTIVITY_RELAUNCHED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            activityRelaunched(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_CALLING_PACKAGE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            String res = token != null ? getCallingPackage(token) : null;
-            reply.writeNoException();
-            reply.writeString(res);
-            return true;
-        }
-
-        case GET_CALLING_ACTIVITY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            ComponentName cn = getCallingActivity(token);
-            reply.writeNoException();
-            ComponentName.writeToParcel(cn, reply);
-            return true;
-        }
-
-        case GET_APP_TASKS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String callingPackage = data.readString();
-            List<IAppTask> list = getAppTasks(callingPackage);
-            reply.writeNoException();
-            int N = list != null ? list.size() : -1;
-            reply.writeInt(N);
-            int i;
-            for (i=0; i<N; i++) {
-                IAppTask task = list.get(i);
-                reply.writeStrongBinder(task.asBinder());
-            }
-            return true;
-        }
-
-        case ADD_APP_TASK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder activityToken = data.readStrongBinder();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            ActivityManager.TaskDescription descr
-                    = ActivityManager.TaskDescription.CREATOR.createFromParcel(data);
-            Bitmap thumbnail = Bitmap.CREATOR.createFromParcel(data);
-            int res = addAppTask(activityToken, intent, descr, thumbnail);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Point size = getAppTaskThumbnailSize();
-            reply.writeNoException();
-            size.writeToParcel(reply, 0);
-            return true;
-        }
-
-        case GET_TASKS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int maxNum = data.readInt();
-            int fl = data.readInt();
-            List<ActivityManager.RunningTaskInfo> list = getTasks(maxNum, fl);
-            reply.writeNoException();
-            int N = list != null ? list.size() : -1;
-            reply.writeInt(N);
-            int i;
-            for (i=0; i<N; i++) {
-                ActivityManager.RunningTaskInfo info = list.get(i);
-                info.writeToParcel(reply, 0);
-            }
-            return true;
-        }
-
-        case GET_RECENT_TASKS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int maxNum = data.readInt();
-            int fl = data.readInt();
-            int userId = data.readInt();
-            ParceledListSlice<ActivityManager.RecentTaskInfo> list = getRecentTasks(maxNum,
-                    fl, userId);
-            reply.writeNoException();
-            list.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            return true;
-        }
-
-        case GET_TASK_THUMBNAIL_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int id = data.readInt();
-            ActivityManager.TaskThumbnail taskThumbnail = getTaskThumbnail(id);
-            reply.writeNoException();
-            if (taskThumbnail != null) {
-                reply.writeInt(1);
-                taskThumbnail.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            } else {
-                reply.writeInt(0);
-            }
-            return true;
-        }
-
-        case GET_SERVICES_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int maxNum = data.readInt();
-            int fl = data.readInt();
-            List<ActivityManager.RunningServiceInfo> list = getServices(maxNum, fl);
-            reply.writeNoException();
-            int N = list != null ? list.size() : -1;
-            reply.writeInt(N);
-            int i;
-            for (i=0; i<N; i++) {
-                ActivityManager.RunningServiceInfo info = list.get(i);
-                info.writeToParcel(reply, 0);
-            }
-            return true;
-        }
-
-        case GET_PROCESSES_IN_ERROR_STATE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            List<ActivityManager.ProcessErrorStateInfo> list = getProcessesInErrorState();
-            reply.writeNoException();
-            reply.writeTypedList(list);
-            return true;
-        }
-
-        case GET_RUNNING_APP_PROCESSES_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            List<ActivityManager.RunningAppProcessInfo> list = getRunningAppProcesses();
-            reply.writeNoException();
-            reply.writeTypedList(list);
-            return true;
-        }
-
-        case GET_RUNNING_EXTERNAL_APPLICATIONS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            List<ApplicationInfo> list = getRunningExternalApplications();
-            reply.writeNoException();
-            reply.writeTypedList(list);
-            return true;
-        }
-
-        case MOVE_TASK_TO_FRONT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int task = data.readInt();
-            int fl = data.readInt();
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            moveTaskToFront(task, fl, options);
-            reply.writeNoException();
-            return true;
-        }
-
-        case MOVE_ACTIVITY_TASK_TO_BACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            boolean nonRoot = data.readInt() != 0;
-            boolean res = moveActivityTaskToBack(token, nonRoot);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case MOVE_TASK_BACKWARDS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int task = data.readInt();
-            moveTaskBackwards(task);
-            reply.writeNoException();
-            return true;
-        }
-
-        case MOVE_TASK_TO_STACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int taskId = data.readInt();
-            int stackId = data.readInt();
-            boolean toTop = data.readInt() != 0;
-            moveTaskToStack(taskId, stackId, toTop);
-            reply.writeNoException();
-            return true;
-        }
-
-        case MOVE_TASK_TO_DOCKED_STACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int taskId = data.readInt();
-            int createMode = data.readInt();
-            boolean toTop = data.readInt() != 0;
-            boolean animate = data.readInt() != 0;
-            Rect bounds = null;
-            boolean hasBounds = data.readInt() != 0;
-            if (hasBounds) {
-                bounds = Rect.CREATOR.createFromParcel(data);
-            }
-            final boolean moveHomeStackFront = data.readInt() != 0;
-            final boolean res = moveTaskToDockedStack(
-                    taskId, createMode, toTop, animate, bounds, moveHomeStackFront);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case MOVE_TOP_ACTIVITY_TO_PINNED_STACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int stackId = data.readInt();
-            final Rect r = Rect.CREATOR.createFromParcel(data);
-            final boolean res = moveTopActivityToPinnedStack(stackId, r);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case RESIZE_STACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int stackId = data.readInt();
-            final boolean hasRect = data.readInt() != 0;
-            Rect r = null;
-            if (hasRect) {
-                r = Rect.CREATOR.createFromParcel(data);
-            }
-            final boolean allowResizeInDockedMode = data.readInt() == 1;
-            final boolean preserveWindows = data.readInt() == 1;
-            final boolean animate = data.readInt() == 1;
-            final int animationDuration = data.readInt();
-            resizeStack(stackId,
-                    r, allowResizeInDockedMode, preserveWindows, animate, animationDuration);
-            reply.writeNoException();
-            return true;
-        }
-        case RESIZE_PINNED_STACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final boolean hasBounds = data.readInt() != 0;
-            Rect bounds = null;
-            if (hasBounds) {
-                bounds = Rect.CREATOR.createFromParcel(data);
-            }
-            final boolean hasTempPinnedTaskBounds = data.readInt() != 0;
-            Rect tempPinnedTaskBounds = null;
-            if (hasTempPinnedTaskBounds) {
-                tempPinnedTaskBounds = Rect.CREATOR.createFromParcel(data);
-            }
-            resizePinnedStack(bounds, tempPinnedTaskBounds);
-            return true;
-        }
-        case SWAP_DOCKED_AND_FULLSCREEN_STACK: {
-            data.enforceInterface(IActivityManager.descriptor);
-            swapDockedAndFullscreenStack();
-            reply.writeNoException();
-            return true;
-        }
-        case RESIZE_DOCKED_STACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final boolean hasBounds = data.readInt() != 0;
-            Rect bounds = null;
-            if (hasBounds) {
-                bounds = Rect.CREATOR.createFromParcel(data);
-            }
-            final boolean hasTempDockedTaskBounds = data.readInt() != 0;
-            Rect tempDockedTaskBounds = null;
-            if (hasTempDockedTaskBounds) {
-                tempDockedTaskBounds = Rect.CREATOR.createFromParcel(data);
-            }
-            final boolean hasTempDockedTaskInsetBounds = data.readInt() != 0;
-            Rect tempDockedTaskInsetBounds = null;
-            if (hasTempDockedTaskInsetBounds) {
-                tempDockedTaskInsetBounds = Rect.CREATOR.createFromParcel(data);
-            }
-            final boolean hasTempOtherTaskBounds = data.readInt() != 0;
-            Rect tempOtherTaskBounds = null;
-            if (hasTempOtherTaskBounds) {
-                tempOtherTaskBounds = Rect.CREATOR.createFromParcel(data);
-            }
-            final boolean hasTempOtherTaskInsetBounds = data.readInt() != 0;
-            Rect tempOtherTaskInsetBounds = null;
-            if (hasTempOtherTaskInsetBounds) {
-                tempOtherTaskInsetBounds = Rect.CREATOR.createFromParcel(data);
-            }
-            resizeDockedStack(bounds, tempDockedTaskBounds, tempDockedTaskInsetBounds,
-                    tempOtherTaskBounds, tempOtherTaskInsetBounds);
-            reply.writeNoException();
-            return true;
-        }
-
-        case POSITION_TASK_IN_STACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int taskId = data.readInt();
-            int stackId = data.readInt();
-            int position = data.readInt();
-            positionTaskInStack(taskId, stackId, position);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_ALL_STACK_INFOS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            List<StackInfo> list = getAllStackInfos();
-            reply.writeNoException();
-            reply.writeTypedList(list);
-            return true;
-        }
-
-        case GET_STACK_INFO_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int stackId = data.readInt();
-            StackInfo info = getStackInfo(stackId);
-            reply.writeNoException();
-            if (info != null) {
-                reply.writeInt(1);
-                info.writeToParcel(reply, 0);
-            } else {
-                reply.writeInt(0);
-            }
-            return true;
-        }
-
-        case IS_IN_HOME_STACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int taskId = data.readInt();
-            boolean isInHomeStack = isInHomeStack(taskId);
-            reply.writeNoException();
-            reply.writeInt(isInHomeStack ? 1 : 0);
-            return true;
-        }
-
-        case SET_FOCUSED_STACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int stackId = data.readInt();
-            setFocusedStack(stackId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_FOCUSED_STACK_ID_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int focusedStackId = getFocusedStackId();
-            reply.writeNoException();
-            reply.writeInt(focusedStackId);
-            return true;
-        }
-
-        case SET_FOCUSED_TASK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int taskId = data.readInt();
-            setFocusedTask(taskId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case REGISTER_TASK_STACK_LISTENER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            registerTaskStackListener(ITaskStackListener.Stub.asInterface(token));
-            reply.writeNoException();
-            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();
-            boolean onlyRoot = data.readInt() != 0;
-            int res = token != null
-                ? getTaskForActivity(token, onlyRoot) : -1;
-                reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case GET_CONTENT_PROVIDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            String name = data.readString();
-            int userId = data.readInt();
-            boolean stable = data.readInt() != 0;
-            ContentProviderHolder cph = getContentProvider(app, name, userId, stable);
-            reply.writeNoException();
-            if (cph != null) {
-                reply.writeInt(1);
-                cph.writeToParcel(reply, 0);
-            } else {
-                reply.writeInt(0);
-            }
-            return true;
-        }
-
-        case GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String name = data.readString();
-            int userId = data.readInt();
-            IBinder token = data.readStrongBinder();
-            ContentProviderHolder cph = getContentProviderExternal(name, userId, token);
-            reply.writeNoException();
-            if (cph != null) {
-                reply.writeInt(1);
-                cph.writeToParcel(reply, 0);
-            } else {
-                reply.writeInt(0);
-            }
-            return true;
-        }
-
-        case PUBLISH_CONTENT_PROVIDERS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            ArrayList<ContentProviderHolder> providers =
-                data.createTypedArrayList(ContentProviderHolder.CREATOR);
-            publishContentProviders(app, providers);
-            reply.writeNoException();
-            return true;
-        }
-
-        case REF_CONTENT_PROVIDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            int stable = data.readInt();
-            int unstable = data.readInt();
-            boolean res = refContentProvider(b, stable, unstable);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case UNSTABLE_PROVIDER_DIED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            unstableProviderDied(b);
-            reply.writeNoException();
-            return true;
-        }
-
-        case APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            appNotRespondingViaProvider(b);
-            reply.writeNoException();
-            return true;
-        }
-
-        case REMOVE_CONTENT_PROVIDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            boolean stable = data.readInt() != 0;
-            removeContentProvider(b, stable);
-            reply.writeNoException();
-            return true;
-        }
-
-        case REMOVE_CONTENT_PROVIDER_EXTERNAL_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String name = data.readString();
-            IBinder token = data.readStrongBinder();
-            removeContentProviderExternal(name, token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            ComponentName comp = ComponentName.CREATOR.createFromParcel(data);
-            PendingIntent pi = getRunningServiceControlPanel(comp);
-            reply.writeNoException();
-            PendingIntent.writePendingIntentOrNullToParcel(pi, reply);
-            return true;
-        }
-
-        case START_SERVICE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            Intent service = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            String callingPackage = data.readString();
-            int userId = data.readInt();
-            ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);
-            reply.writeNoException();
-            ComponentName.writeToParcel(cn, reply);
-            return true;
-        }
-
-        case STOP_SERVICE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            Intent service = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            int userId = data.readInt();
-            int res = stopService(app, service, resolvedType, userId);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case STOP_SERVICE_TOKEN_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            ComponentName className = ComponentName.readFromParcel(data);
-            IBinder token = data.readStrongBinder();
-            int startId = data.readInt();
-            boolean res = stopServiceToken(className, token, startId);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case SET_SERVICE_FOREGROUND_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            ComponentName className = ComponentName.readFromParcel(data);
-            IBinder token = data.readStrongBinder();
-            int id = data.readInt();
-            Notification notification = null;
-            if (data.readInt() != 0) {
-                notification = Notification.CREATOR.createFromParcel(data);
-            }
-            int sflags = data.readInt();
-            setServiceForeground(className, token, id, notification, sflags);
-            reply.writeNoException();
-            return true;
-        }
-
-        case BIND_SERVICE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            IBinder token = data.readStrongBinder();
-            Intent service = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            b = data.readStrongBinder();
-            int fl = data.readInt();
-            String callingPackage = data.readString();
-            int userId = data.readInt();
-            IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
-            int res = bindService(app, token, service, resolvedType, conn, fl,
-                    callingPackage, userId);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case UNBIND_SERVICE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
-            boolean res = unbindService(conn);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case PUBLISH_SERVICE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            IBinder service = data.readStrongBinder();
-            publishService(token, intent, service);
-            reply.writeNoException();
-            return true;
-        }
-
-        case UNBIND_FINISHED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            boolean doRebind = data.readInt() != 0;
-            unbindFinished(token, intent, doRebind);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SERVICE_DONE_EXECUTING_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            int type = data.readInt();
-            int startId = data.readInt();
-            int res = data.readInt();
-            serviceDoneExecuting(token, type, startId, res);
-            reply.writeNoException();
-            return true;
-        }
-
-        case START_INSTRUMENTATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            ComponentName className = ComponentName.readFromParcel(data);
-            String profileFile = data.readString();
-            int fl = data.readInt();
-            Bundle arguments = data.readBundle();
-            IBinder b = data.readStrongBinder();
-            IInstrumentationWatcher w = IInstrumentationWatcher.Stub.asInterface(b);
-            b = data.readStrongBinder();
-            IUiAutomationConnection c = IUiAutomationConnection.Stub.asInterface(b);
-            int userId = data.readInt();
-            String abiOverride = data.readString();
-            boolean res = startInstrumentation(className, profileFile, fl, arguments, w, c, userId,
-                    abiOverride);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-
-        case FINISH_INSTRUMENTATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            int resultCode = data.readInt();
-            Bundle results = data.readBundle();
-            finishInstrumentation(app, resultCode, results);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_CONFIGURATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Configuration config = getConfiguration();
-            reply.writeNoException();
-            config.writeToParcel(reply, 0);
-            return true;
-        }
-
-        case UPDATE_CONFIGURATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Configuration config = Configuration.CREATOR.createFromParcel(data);
-            final boolean updated = updateConfiguration(config);
-            reply.writeNoException();
-            reply.writeInt(updated ? 1 : 0);
-            return true;
-        }
-
-        case UPDATE_DISPLAY_OVERRIDE_CONFIGURATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final Configuration config = Configuration.CREATOR.createFromParcel(data);
-            final int displayId = data.readInt();
-            final boolean updated = updateDisplayOverrideConfiguration(config, displayId);
-            reply.writeNoException();
-            reply.writeInt(updated ? 1 : 0);
-            return true;
-        }
-
-        case SET_REQUESTED_ORIENTATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            int requestedOrientation = data.readInt();
-            setRequestedOrientation(token, requestedOrientation);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_REQUESTED_ORIENTATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            int req = getRequestedOrientation(token);
-            reply.writeNoException();
-            reply.writeInt(req);
-            return true;
-        }
-
-        case GET_ACTIVITY_CLASS_FOR_TOKEN_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            ComponentName cn = getActivityClassForToken(token);
-            reply.writeNoException();
-            ComponentName.writeToParcel(cn, reply);
-            return true;
-        }
-
-        case GET_PACKAGE_FOR_TOKEN_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            reply.writeNoException();
-            reply.writeString(getPackageForToken(token));
-            return true;
-        }
-
-        case GET_INTENT_SENDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int type = data.readInt();
-            String packageName = data.readString();
-            IBinder token = data.readStrongBinder();
-            String resultWho = data.readString();
-            int requestCode = data.readInt();
-            Intent[] requestIntents;
-            String[] requestResolvedTypes;
-            if (data.readInt() != 0) {
-                requestIntents = data.createTypedArray(Intent.CREATOR);
-                requestResolvedTypes = data.createStringArray();
-            } else {
-                requestIntents = null;
-                requestResolvedTypes = null;
-            }
-            int fl = data.readInt();
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int userId = data.readInt();
-            IIntentSender res = getIntentSender(type, packageName, token,
-                    resultWho, requestCode, requestIntents,
-                    requestResolvedTypes, fl, options, userId);
-            reply.writeNoException();
-            reply.writeStrongBinder(res != null ? res.asBinder() : null);
-            return true;
-        }
-
-        case CANCEL_INTENT_SENDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender r = IIntentSender.Stub.asInterface(
-                data.readStrongBinder());
-            cancelIntentSender(r);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_PACKAGE_FOR_INTENT_SENDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender r = IIntentSender.Stub.asInterface(
-                data.readStrongBinder());
-            String res = getPackageForIntentSender(r);
-            reply.writeNoException();
-            reply.writeString(res);
-            return true;
-        }
-
-        case GET_UID_FOR_INTENT_SENDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender r = IIntentSender.Stub.asInterface(
-                data.readStrongBinder());
-            int res = getUidForIntentSender(r);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case HANDLE_INCOMING_USER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int callingPid = data.readInt();
-            int callingUid = data.readInt();
-            int userId = data.readInt();
-            boolean allowAll = data.readInt() != 0 ;
-            boolean requireFull = data.readInt() != 0;
-            String name = data.readString();
-            String callerPackage = data.readString();
-            int res = handleIncomingUser(callingPid, callingUid, userId, allowAll,
-                    requireFull, name, callerPackage);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case SET_PROCESS_LIMIT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int max = data.readInt();
-            setProcessLimit(max);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_PROCESS_LIMIT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int limit = getProcessLimit();
-            reply.writeNoException();
-            reply.writeInt(limit);
-            return true;
-        }
-
-        case SET_PROCESS_FOREGROUND_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            int pid = data.readInt();
-            boolean isForeground = data.readInt() != 0;
-            setProcessForeground(token, pid, isForeground);
-            reply.writeNoException();
-            return true;
-        }
-
-        case CHECK_PERMISSION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String perm = data.readString();
-            int pid = data.readInt();
-            int uid = data.readInt();
-            int res = checkPermission(perm, pid, uid);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case CHECK_PERMISSION_WITH_TOKEN_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String perm = data.readString();
-            int pid = data.readInt();
-            int uid = data.readInt();
-            IBinder token = data.readStrongBinder();
-            int res = checkPermissionWithToken(perm, pid, uid, token);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case CHECK_URI_PERMISSION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Uri uri = Uri.CREATOR.createFromParcel(data);
-            int pid = data.readInt();
-            int uid = data.readInt();
-            int mode = data.readInt();
-            int userId = data.readInt();
-            IBinder callerToken = data.readStrongBinder();
-            int res = checkUriPermission(uri, pid, uid, mode, userId, callerToken);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case CLEAR_APP_DATA_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String packageName = data.readString();
-            IPackageDataObserver observer = IPackageDataObserver.Stub.asInterface(
-                    data.readStrongBinder());
-            int userId = data.readInt();
-            boolean res = clearApplicationUserData(packageName, observer, userId);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case GRANT_URI_PERMISSION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            String targetPkg = data.readString();
-            Uri uri = Uri.CREATOR.createFromParcel(data);
-            int mode = data.readInt();
-            int userId = data.readInt();
-            grantUriPermission(app, targetPkg, uri, mode, userId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case REVOKE_URI_PERMISSION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            Uri uri = Uri.CREATOR.createFromParcel(data);
-            int mode = data.readInt();
-            int userId = data.readInt();
-            revokeUriPermission(app, uri, mode, userId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case TAKE_PERSISTABLE_URI_PERMISSION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Uri uri = Uri.CREATOR.createFromParcel(data);
-            int mode = data.readInt();
-            int userId = data.readInt();
-            takePersistableUriPermission(uri, mode, userId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Uri uri = Uri.CREATOR.createFromParcel(data);
-            int mode = data.readInt();
-            int userId = data.readInt();
-            releasePersistableUriPermission(uri, mode, userId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_PERSISTED_URI_PERMISSIONS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final String packageName = data.readString();
-            final boolean incoming = data.readInt() != 0;
-            final ParceledListSlice<UriPermission> perms = getPersistedUriPermissions(
-                    packageName, incoming);
-            reply.writeNoException();
-            perms.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            return true;
-        }
-
-        case GET_GRANTED_URI_PERMISSIONS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final String packageName = data.readString();
-            final int userId = data.readInt();
-            final ParceledListSlice<UriPermission> perms = getGrantedUriPermissions(packageName,
-                    userId);
-            reply.writeNoException();
-            perms.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            return true;
-        }
-
-        case CLEAR_GRANTED_URI_PERMISSIONS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final String packageName = data.readString();
-            final int userId = data.readInt();
-            clearGrantedUriPermissions(packageName, userId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SHOW_WAITING_FOR_DEBUGGER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            boolean waiting = data.readInt() != 0;
-            showWaitingForDebugger(app, waiting);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_MEMORY_INFO_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
-            getMemoryInfo(mi);
-            reply.writeNoException();
-            mi.writeToParcel(reply, 0);
-            return true;
-        }
-
-        case UNHANDLED_BACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            unhandledBack();
-            reply.writeNoException();
-            return true;
-        }
-
-        case OPEN_CONTENT_URI_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Uri uri = Uri.parse(data.readString());
-            ParcelFileDescriptor pfd = openContentUri(uri);
-            reply.writeNoException();
-            if (pfd != null) {
-                reply.writeInt(1);
-                pfd.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            } else {
-                reply.writeInt(0);
-            }
-            return true;
-        }
-
-        case SET_LOCK_SCREEN_SHOWN_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final boolean showing = data.readInt() != 0;
-            setLockScreenShown(showing);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SET_DEBUG_APP_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String pn = data.readString();
-            boolean wfd = data.readInt() != 0;
-            boolean per = data.readInt() != 0;
-            setDebugApp(pn, wfd, per);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SET_ALWAYS_FINISH_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            boolean enabled = data.readInt() != 0;
-            setAlwaysFinish(enabled);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SET_ACTIVITY_CONTROLLER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IActivityController watcher = IActivityController.Stub.asInterface(
-                    data.readStrongBinder());
-            boolean imAMonkey = data.readInt() != 0;
-            setActivityController(watcher, imAMonkey);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SET_LENIENT_BACKGROUND_CHECK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            boolean enabled = data.readInt() != 0;
-            setLenientBackgroundCheck(enabled);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_MEMORY_TRIM_LEVEL_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int level = getMemoryTrimLevel();
-            reply.writeNoException();
-            reply.writeInt(level);
-            return true;
-        }
-
-        case ENTER_SAFE_MODE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            enterSafeMode();
-            reply.writeNoException();
-            return true;
-        }
-
-        case NOTE_WAKEUP_ALARM_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender is = IIntentSender.Stub.asInterface(
-                    data.readStrongBinder());
-            int sourceUid = data.readInt();
-            String sourcePkg = data.readString();
-            String tag = data.readString();
-            noteWakeupAlarm(is, sourceUid, sourcePkg, tag);
-            reply.writeNoException();
-            return true;
-        }
-
-        case NOTE_ALARM_START_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender is = IIntentSender.Stub.asInterface(
-                    data.readStrongBinder());
-            int sourceUid = data.readInt();
-            String tag = data.readString();
-            noteAlarmStart(is, sourceUid, tag);
-            reply.writeNoException();
-            return true;
-        }
-
-        case NOTE_ALARM_FINISH_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender is = IIntentSender.Stub.asInterface(
-                    data.readStrongBinder());
-            int sourceUid = data.readInt();
-            String tag = data.readString();
-            noteAlarmFinish(is, sourceUid, tag);
-            reply.writeNoException();
-            return true;
-        }
-
-        case KILL_PIDS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int[] pids = data.createIntArray();
-            String reason = data.readString();
-            boolean secure = data.readInt() != 0;
-            boolean res = killPids(pids, reason, secure);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String reason = data.readString();
-            boolean res = killProcessesBelowForeground(reason);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case HANDLE_APPLICATION_CRASH_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder app = data.readStrongBinder();
-            ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(data);
-            handleApplicationCrash(app, ci);
-            reply.writeNoException();
-            return true;
-        }
-
-        case HANDLE_APPLICATION_WTF_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder app = data.readStrongBinder();
-            String tag = data.readString();
-            boolean system = data.readInt() != 0;
-            ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(data);
-            boolean res = handleApplicationWtf(app, tag, system, ci);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case HANDLE_APPLICATION_STRICT_MODE_VIOLATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder app = data.readStrongBinder();
-            int violationMask = data.readInt();
-            StrictMode.ViolationInfo info = new StrictMode.ViolationInfo(data);
-            handleApplicationStrictModeViolation(app, violationMask, info);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SIGNAL_PERSISTENT_PROCESSES_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int sig = data.readInt();
-            signalPersistentProcesses(sig);
-            reply.writeNoException();
-            return true;
-        }
-
-        case KILL_BACKGROUND_PROCESSES_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String packageName = data.readString();
-            int userId = data.readInt();
-            killBackgroundProcesses(packageName, userId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            killAllBackgroundProcesses();
-            reply.writeNoException();
-            return true;
-        }
-
-        case KILL_PACKAGE_DEPENDENTS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String packageName = data.readString();
-            int userId = data.readInt();
-            killPackageDependents(packageName, userId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case FORCE_STOP_PACKAGE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String packageName = data.readString();
-            int userId = data.readInt();
-            forceStopPackage(packageName, userId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_MY_MEMORY_STATE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            ActivityManager.RunningAppProcessInfo info =
-                    new ActivityManager.RunningAppProcessInfo();
-            getMyMemoryState(info);
-            reply.writeNoException();
-            info.writeToParcel(reply, 0);
-            return true;
-        }
-
-        case GET_DEVICE_CONFIGURATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            ConfigurationInfo config = getDeviceConfigurationInfo();
-            reply.writeNoException();
-            config.writeToParcel(reply, 0);
-            return true;
-        }
-
-        case PROFILE_CONTROL_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String process = data.readString();
-            int userId = data.readInt();
-            boolean start = data.readInt() != 0;
-            int profileType = data.readInt();
-            ProfilerInfo profilerInfo = data.readInt() != 0
-                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
-            boolean res = profileControl(process, userId, start, profilerInfo, profileType);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case SHUTDOWN_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            boolean res = shutdown(data.readInt());
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case STOP_APP_SWITCHES_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            stopAppSwitches();
-            reply.writeNoException();
-            return true;
-        }
-
-        case RESUME_APP_SWITCHES_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            resumeAppSwitches();
-            reply.writeNoException();
-            return true;
-        }
-
-        case PEEK_SERVICE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Intent service = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            String callingPackage = data.readString();
-            IBinder binder = peekService(service, resolvedType, callingPackage);
-            reply.writeNoException();
-            reply.writeStrongBinder(binder);
-            return true;
-        }
-
-        case START_BACKUP_AGENT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String packageName = data.readString();
-            int backupRestoreMode = data.readInt();
-            int userId = data.readInt();
-            boolean success = bindBackupAgent(packageName, backupRestoreMode, userId);
-            reply.writeNoException();
-            reply.writeInt(success ? 1 : 0);
-            return true;
-        }
-
-        case BACKUP_AGENT_CREATED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String packageName = data.readString();
-            IBinder agent = data.readStrongBinder();
-            backupAgentCreated(packageName, agent);
-            reply.writeNoException();
-            return true;
-        }
-
-        case UNBIND_BACKUP_AGENT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            ApplicationInfo info = ApplicationInfo.CREATOR.createFromParcel(data);
-            unbindBackupAgent(info);
-            reply.writeNoException();
-            return true;
-        }
-
-        case ADD_PACKAGE_DEPENDENCY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String packageName = data.readString();
-            addPackageDependency(packageName);
-            reply.writeNoException();
-            return true;
-        }
-
-        case KILL_APPLICATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String pkg = data.readString();
-            int appId = data.readInt();
-            int userId = data.readInt();
-            String reason = data.readString();
-            killApplication(pkg, appId, userId, reason);
-            reply.writeNoException();
-            return true;
-        }
-
-        case CLOSE_SYSTEM_DIALOGS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String reason = data.readString();
-            closeSystemDialogs(reason);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_PROCESS_MEMORY_INFO_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int[] pids = data.createIntArray();
-            Debug.MemoryInfo[] res =  getProcessMemoryInfo(pids);
-            reply.writeNoException();
-            reply.writeTypedArray(res, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            return true;
-        }
-
-        case KILL_APPLICATION_PROCESS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String processName = data.readString();
-            int uid = data.readInt();
-            killApplicationProcess(processName, uid);
-            reply.writeNoException();
-            return true;
-        }
-
-        case OVERRIDE_PENDING_TRANSITION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            String packageName = data.readString();
-            int enterAnim = data.readInt();
-            int exitAnim = data.readInt();
-            overridePendingTransition(token, packageName, enterAnim, exitAnim);
-            reply.writeNoException();
-            return true;
-        }
-
-        case IS_USER_A_MONKEY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            boolean areThey = isUserAMonkey();
-            reply.writeNoException();
-            reply.writeInt(areThey ? 1 : 0);
-            return true;
-        }
-
-        case SET_USER_IS_MONKEY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final boolean monkey = (data.readInt() == 1);
-            setUserIsMonkey(monkey);
-            reply.writeNoException();
-            return true;
-        }
-
-        case FINISH_HEAVY_WEIGHT_APP_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            finishHeavyWeightApp();
-            reply.writeNoException();
-            return true;
-        }
-
-        case IS_IMMERSIVE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            boolean isit = isImmersive(token);
-            reply.writeNoException();
-            reply.writeInt(isit ? 1 : 0);
-            return true;
-        }
-
-        case IS_TOP_OF_TASK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            final boolean isTopOfTask = isTopOfTask(token);
-            reply.writeNoException();
-            reply.writeInt(isTopOfTask ? 1 : 0);
-            return true;
-        }
-
-        case CONVERT_FROM_TRANSLUCENT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            boolean converted = convertFromTranslucent(token);
-            reply.writeNoException();
-            reply.writeInt(converted ? 1 : 0);
-            return true;
-        }
-
-        case CONVERT_TO_TRANSLUCENT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            final Bundle bundle;
-            if (data.readInt() == 0) {
-                bundle = null;
-            } else {
-                bundle = data.readBundle();
-            }
-            final ActivityOptions options = ActivityOptions.fromBundle(bundle);
-            boolean converted = convertToTranslucent(token, options);
-            reply.writeNoException();
-            reply.writeInt(converted ? 1 : 0);
-            return true;
-        }
-
-        case GET_ACTIVITY_OPTIONS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            final ActivityOptions options = getActivityOptions(token);
-            reply.writeNoException();
-            reply.writeBundle(options == null ? null : options.toBundle());
-            return true;
-        }
-
-        case SET_IMMERSIVE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            boolean imm = data.readInt() == 1;
-            setImmersive(token, imm);
-            reply.writeNoException();
-            return true;
-        }
-
-        case IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            boolean isit = isTopActivityImmersive();
-            reply.writeNoException();
-            reply.writeInt(isit ? 1 : 0);
-            return true;
-        }
-
-        case CRASH_APPLICATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int uid = data.readInt();
-            int initialPid = data.readInt();
-            String packageName = data.readString();
-            String message = data.readString();
-            crashApplication(uid, initialPid, packageName, message);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_PROVIDER_MIME_TYPE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Uri uri = Uri.CREATOR.createFromParcel(data);
-            int userId = data.readInt();
-            String type = getProviderMimeType(uri, userId);
-            reply.writeNoException();
-            reply.writeString(type);
-            return true;
-        }
-
-        case NEW_URI_PERMISSION_OWNER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String name = data.readString();
-            IBinder perm = newUriPermissionOwner(name);
-            reply.writeNoException();
-            reply.writeStrongBinder(perm);
-            return true;
-        }
-
-        case GET_URI_PERMISSION_OWNER_FOR_ACTIVITY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder activityToken = data.readStrongBinder();
-            IBinder perm = getUriPermissionOwnerForActivity(activityToken);
-            reply.writeNoException();
-            reply.writeStrongBinder(perm);
-            return true;
-        }
-
-        case GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder owner = data.readStrongBinder();
-            int fromUid = data.readInt();
-            String targetPkg = data.readString();
-            Uri uri = Uri.CREATOR.createFromParcel(data);
-            int mode = data.readInt();
-            int sourceUserId = data.readInt();
-            int targetUserId = data.readInt();
-            grantUriPermissionFromOwner(owner, fromUid, targetPkg, uri, mode, sourceUserId,
-                    targetUserId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder owner = data.readStrongBinder();
-            Uri uri = null;
-            if (data.readInt() != 0) {
-                uri = Uri.CREATOR.createFromParcel(data);
-            }
-            int mode = data.readInt();
-            int userId = data.readInt();
-            revokeUriPermissionFromOwner(owner, uri, mode, userId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case CHECK_GRANT_URI_PERMISSION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int callingUid = data.readInt();
-            String targetPkg = data.readString();
-            Uri uri = Uri.CREATOR.createFromParcel(data);
-            int modeFlags = data.readInt();
-            int userId = data.readInt();
-            int res = checkGrantUriPermission(callingUid, targetPkg, uri, modeFlags, userId);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case DUMP_HEAP_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String process = data.readString();
-            int userId = data.readInt();
-            boolean managed = data.readInt() != 0;
-            String path = data.readString();
-            ParcelFileDescriptor fd = data.readInt() != 0
-                    ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
-            boolean res = dumpHeap(process, userId, managed, path, fd);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case START_ACTIVITIES_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder b = data.readStrongBinder();
-            IApplicationThread app = IApplicationThread.Stub.asInterface(b);
-            String callingPackage = data.readString();
-            Intent[] intents = data.createTypedArray(Intent.CREATOR);
-            String[] resolvedTypes = data.createStringArray();
-            IBinder resultTo = data.readStrongBinder();
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int userId = data.readInt();
-            int result = startActivities(app, callingPackage, intents, resolvedTypes, resultTo,
-                    options, userId);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
-        case GET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            int mode = getFrontActivityScreenCompatMode();
-            reply.writeNoException();
-            reply.writeInt(mode);
-            return true;
-        }
-
-        case SET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            int mode = data.readInt();
-            setFrontActivityScreenCompatMode(mode);
-            reply.writeNoException();
-            reply.writeInt(mode);
-            return true;
-        }
-
-        case GET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            String pkg = data.readString();
-            int mode = getPackageScreenCompatMode(pkg);
-            reply.writeNoException();
-            reply.writeInt(mode);
-            return true;
-        }
-
-        case SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            String pkg = data.readString();
-            int mode = data.readInt();
-            setPackageScreenCompatMode(pkg, mode);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SWITCH_USER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int userid = data.readInt();
-            boolean result = switchUser(userid);
-            reply.writeNoException();
-            reply.writeInt(result ? 1 : 0);
-            return true;
-        }
-
-        case START_USER_IN_BACKGROUND_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int userid = data.readInt();
-            boolean result = startUserInBackground(userid);
-            reply.writeNoException();
-            reply.writeInt(result ? 1 : 0);
-            return true;
-        }
-
-        case UNLOCK_USER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int userId = data.readInt();
-            byte[] token = data.createByteArray();
-            byte[] secret = data.createByteArray();
-            IProgressListener listener = IProgressListener.Stub
-                    .asInterface(data.readStrongBinder());
-            boolean result = unlockUser(userId, token, secret, listener);
-            reply.writeNoException();
-            reply.writeInt(result ? 1 : 0);
-            return true;
-        }
-
-        case STOP_USER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int userid = data.readInt();
-            boolean force = data.readInt() != 0;
-            IStopUserCallback callback = IStopUserCallback.Stub.asInterface(
-                    data.readStrongBinder());
-            int result = stopUser(userid, force, callback);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
-        case GET_CURRENT_USER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            UserInfo userInfo = getCurrentUser();
-            reply.writeNoException();
-            userInfo.writeToParcel(reply, 0);
-            return true;
-        }
-
-        case IS_USER_RUNNING_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int userid = data.readInt();
-            int _flags = data.readInt();
-            boolean result = isUserRunning(userid, _flags);
-            reply.writeNoException();
-            reply.writeInt(result ? 1 : 0);
-            return true;
-        }
-
-        case GET_RUNNING_USER_IDS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int[] result = getRunningUserIds();
-            reply.writeNoException();
-            reply.writeIntArray(result);
-            return true;
-        }
-
-        case REMOVE_TASK_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            int taskId = data.readInt();
-            boolean result = removeTask(taskId);
-            reply.writeNoException();
-            reply.writeInt(result ? 1 : 0);
-            return true;
-        }
-
-        case REGISTER_PROCESS_OBSERVER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IProcessObserver observer = IProcessObserver.Stub.asInterface(
-                    data.readStrongBinder());
-            registerProcessObserver(observer);
-            return true;
-        }
-
-        case UNREGISTER_PROCESS_OBSERVER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IProcessObserver observer = IProcessObserver.Stub.asInterface(
-                    data.readStrongBinder());
-            unregisterProcessObserver(observer);
-            return true;
-        }
-
-        case REGISTER_UID_OBSERVER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IUidObserver observer = IUidObserver.Stub.asInterface(
-                    data.readStrongBinder());
-            int which = data.readInt();
-            registerUidObserver(observer, which);
-            return true;
-        }
-
-        case UNREGISTER_UID_OBSERVER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IUidObserver observer = IUidObserver.Stub.asInterface(
-                    data.readStrongBinder());
-            unregisterUidObserver(observer);
-            return true;
-        }
-
-        case GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            String pkg = data.readString();
-            boolean ask = getPackageAskScreenCompat(pkg);
-            reply.writeNoException();
-            reply.writeInt(ask ? 1 : 0);
-            return true;
-        }
-
-        case SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            String pkg = data.readString();
-            boolean ask = data.readInt() != 0;
-            setPackageAskScreenCompat(pkg, ask);
-            reply.writeNoException();
-            return true;
-        }
-
-        case IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender r = IIntentSender.Stub.asInterface(
-                    data.readStrongBinder());
-            boolean res = isIntentSenderTargetedToPackage(r);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case IS_INTENT_SENDER_AN_ACTIVITY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender r = IIntentSender.Stub.asInterface(
-                data.readStrongBinder());
-            boolean res = isIntentSenderAnActivity(r);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case GET_INTENT_FOR_INTENT_SENDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender r = IIntentSender.Stub.asInterface(
-                data.readStrongBinder());
-            Intent intent = getIntentForIntentSender(r);
-            reply.writeNoException();
-            if (intent != null) {
-                reply.writeInt(1);
-                intent.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            } else {
-                reply.writeInt(0);
-            }
-            return true;
-        }
-
-        case GET_TAG_FOR_INTENT_SENDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender r = IIntentSender.Stub.asInterface(
-                data.readStrongBinder());
-            String prefix = data.readString();
-            String tag = getTagForIntentSender(r, prefix);
-            reply.writeNoException();
-            reply.writeString(tag);
-            return true;
-        }
-
-        case UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Configuration config = Configuration.CREATOR.createFromParcel(data);
-            updatePersistentConfiguration(config);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_PROCESS_PSS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int[] pids = data.createIntArray();
-            long[] pss = getProcessPss(pids);
-            reply.writeNoException();
-            reply.writeLongArray(pss);
-            return true;
-        }
-
-        case SHOW_BOOT_MESSAGE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            CharSequence msg = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
-            boolean always = data.readInt() != 0;
-            showBootMessage(msg, always);
-            reply.writeNoException();
-            return true;
-        }
-
-        case KEYGUARD_GOING_AWAY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            keyguardGoingAway(data.readInt());
-            reply.writeNoException();
-            return true;
-        }
-
-        case SHOULD_UP_RECREATE_TASK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            String destAffinity = data.readString();
-            boolean res = shouldUpRecreateTask(token, destAffinity);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case NAVIGATE_UP_TO_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Intent target = Intent.CREATOR.createFromParcel(data);
-            int resultCode = data.readInt();
-            Intent resultData = null;
-            if (data.readInt() != 0) {
-                resultData = Intent.CREATOR.createFromParcel(data);
-            }
-            boolean res = navigateUpTo(token, target, resultCode, resultData);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case GET_LAUNCHED_FROM_UID_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            int res = getLaunchedFromUid(token);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case GET_LAUNCHED_FROM_PACKAGE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            String res = getLaunchedFromPackage(token);
-            reply.writeNoException();
-            reply.writeString(res);
-            return true;
-        }
-
-        case REGISTER_USER_SWITCH_OBSERVER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface(
-                    data.readStrongBinder());
-            String name = data.readString();
-            registerUserSwitchObserver(observer, name);
-            reply.writeNoException();
-            return true;
-        }
-
-        case UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface(
-                    data.readStrongBinder());
-            unregisterUserSwitchObserver(observer);
-            reply.writeNoException();
-            return true;
-        }
-
-        case REQUEST_BUG_REPORT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int bugreportType = data.readInt();
-            requestBugReport(bugreportType);
-            reply.writeNoException();
-            return true;
-        }
-
-        case INPUT_DISPATCHING_TIMED_OUT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int pid = data.readInt();
-            boolean aboveSystem = data.readInt() != 0;
-            String reason = data.readString();
-            long res = inputDispatchingTimedOut(pid, aboveSystem, reason);
-            reply.writeNoException();
-            reply.writeLong(res);
-            return true;
-        }
-
-        case GET_ASSIST_CONTEXT_EXTRAS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int requestType = data.readInt();
-            Bundle res = getAssistContextExtras(requestType);
-            reply.writeNoException();
-            reply.writeBundle(res);
-            return true;
-        }
-
-        case REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int requestType = data.readInt();
-            IResultReceiver receiver = IResultReceiver.Stub.asInterface(data.readStrongBinder());
-            Bundle receiverExtras = data.readBundle();
-            IBinder activityToken = data.readStrongBinder();
-            boolean focused = data.readInt() == 1;
-            boolean newSessionId = data.readInt() == 1;
-            boolean res = requestAssistContextExtras(requestType, receiver, receiverExtras,
-                    activityToken, focused, newSessionId);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case REPORT_ASSIST_CONTEXT_EXTRAS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Bundle extras = data.readBundle();
-            AssistStructure structure = AssistStructure.CREATOR.createFromParcel(data);
-            AssistContent content = AssistContent.CREATOR.createFromParcel(data);
-            Uri referrer = data.readInt() != 0 ? Uri.CREATOR.createFromParcel(data) : null;
-            reportAssistContextExtras(token, extras, structure, content, referrer);
-            reply.writeNoException();
-            return true;
-        }
-
-        case LAUNCH_ASSIST_INTENT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            int requestType = data.readInt();
-            String hint = data.readString();
-            int userHandle = data.readInt();
-            Bundle args = data.readBundle();
-            boolean res = launchAssistIntent(intent, requestType, hint, userHandle, args);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            boolean res = isAssistDataAllowedOnCurrentActivity();
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Bundle args = data.readBundle();
-            boolean res = showAssistFromActivity(token, args);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case KILL_UID_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int appId = data.readInt();
-            int userId = data.readInt();
-            String reason = data.readString();
-            killUid(appId, userId, reason);
-            reply.writeNoException();
-            return true;
-        }
-
-        case HANG_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder who = data.readStrongBinder();
-            boolean allowRestart = data.readInt() != 0;
-            hang(who, allowRestart);
-            reply.writeNoException();
-            return true;
-        }
-
-        case REPORT_ACTIVITY_FULLY_DRAWN_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            reportActivityFullyDrawn(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case NOTIFY_ACTIVITY_DRAWN_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            notifyActivityDrawn(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case RESTART_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            restart();
-            reply.writeNoException();
-            return true;
-        }
-
-        case PERFORM_IDLE_MAINTENANCE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            performIdleMaintenance();
-            reply.writeNoException();
-            return true;
-        }
-
-        case CREATE_VIRTUAL_ACTIVITY_CONTAINER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder parentActivityToken = data.readStrongBinder();
-            IActivityContainerCallback callback =
-                    IActivityContainerCallback.Stub.asInterface(data.readStrongBinder());
-            IActivityContainer activityContainer =
-                    createVirtualActivityContainer(parentActivityToken, callback);
-            reply.writeNoException();
-            if (activityContainer != null) {
-                reply.writeInt(1);
-                reply.writeStrongBinder(activityContainer.asBinder());
-            } else {
-                reply.writeInt(0);
-            }
-            return true;
-        }
-
-        case CREATE_STACK_ON_DISPLAY: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int displayId = data.readInt();
-            IActivityContainer activityContainer = createStackOnDisplay(displayId);
-            reply.writeNoException();
-            if (activityContainer != null) {
-                reply.writeInt(1);
-                reply.writeStrongBinder(activityContainer.asBinder());
-            } else {
-                reply.writeInt(0);
-            }
-            return true;
-        }
-
-        case GET_ACTIVITY_DISPLAY_ID_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder activityToken = data.readStrongBinder();
-            int displayId = getActivityDisplayId(activityToken);
-            reply.writeNoException();
-            reply.writeInt(displayId);
-            return true;
-        }
-
-        case START_LOCK_TASK_BY_TASK_ID_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int taskId = data.readInt();
-            startLockTaskMode(taskId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case START_LOCK_TASK_BY_TOKEN_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            startLockTaskMode(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case START_SYSTEM_LOCK_TASK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int taskId = data.readInt();
-            startSystemLockTaskMode(taskId);
-            reply.writeNoException();
-            return true;
-        }
-
-        case STOP_LOCK_TASK_MODE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            stopLockTaskMode();
-            reply.writeNoException();
-            return true;
-        }
-
-        case STOP_SYSTEM_LOCK_TASK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            stopSystemLockTaskMode();
-            reply.writeNoException();
-            return true;
-        }
-
-        case IS_IN_LOCK_TASK_MODE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final boolean isInLockTaskMode = isInLockTaskMode();
-            reply.writeNoException();
-            reply.writeInt(isInLockTaskMode ? 1 : 0);
-            return true;
-        }
-
-        case GET_LOCK_TASK_MODE_STATE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int lockTaskModeState = getLockTaskModeState();
-            reply.writeNoException();
-            reply.writeInt(lockTaskModeState);
-            return true;
-        }
-
-        case SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final IBinder token = data.readStrongBinder();
-            showLockTaskEscapeMessage(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SET_TASK_DESCRIPTION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            ActivityManager.TaskDescription values =
-                    ActivityManager.TaskDescription.CREATOR.createFromParcel(data);
-            setTaskDescription(token, values);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SET_TASK_RESIZEABLE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int taskId = data.readInt();
-            final int resizeableMode = data.readInt();
-            setTaskResizeable(taskId, resizeableMode);
-            reply.writeNoException();
-            return true;
-        }
-
-        case RESIZE_TASK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int taskId = data.readInt();
-            int resizeMode = data.readInt();
-            Rect r = Rect.CREATOR.createFromParcel(data);
-            resizeTask(taskId, r, resizeMode);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_TASK_BOUNDS_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int taskId = data.readInt();
-            Rect r = getTaskBounds(taskId);
-            reply.writeNoException();
-            r.writeToParcel(reply, 0);
-            return true;
-        }
-
-        case GET_TASK_DESCRIPTION_ICON_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String filename = data.readString();
-            int userId = data.readInt();
-            Bitmap icon = getTaskDescriptionIcon(filename, userId);
-            reply.writeNoException();
-            if (icon == null) {
-                reply.writeInt(0);
-            } else {
-                reply.writeInt(1);
-                icon.writeToParcel(reply, 0);
-            }
-            return true;
-        }
-
-        case START_IN_PLACE_ANIMATION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final Bundle bundle;
-            if (data.readInt() == 0) {
-                bundle = null;
-            } else {
-                bundle = data.readBundle();
-            }
-            final ActivityOptions options = ActivityOptions.fromBundle(bundle);
-            startInPlaceAnimationOnFrontMostApplication(options);
-            reply.writeNoException();
-            return true;
-        }
-
-        case REQUEST_VISIBLE_BEHIND_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            boolean enable = data.readInt() > 0;
-            boolean success = requestVisibleBehind(token, enable);
-            reply.writeNoException();
-            reply.writeInt(success ? 1 : 0);
-            return true;
-        }
-
-        case IS_BACKGROUND_VISIBLE_BEHIND_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            final boolean enabled = isBackgroundVisibleBehind(token);
-            reply.writeNoException();
-            reply.writeInt(enabled ? 1 : 0);
-            return true;
-        }
-
-        case BACKGROUND_RESOURCES_RELEASED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            backgroundResourcesReleased(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            notifyLaunchTaskBehindComplete(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            notifyEnterAnimationComplete(token);
-            reply.writeNoException();
-            return true;
-        }
-
-        case BOOT_ANIMATION_COMPLETE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            bootAnimationComplete();
-            reply.writeNoException();
-            return true;
-        }
-
-        case NOTIFY_CLEARTEXT_NETWORK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int uid = data.readInt();
-            final byte[] firstPacket = data.createByteArray();
-            notifyCleartextNetwork(uid, firstPacket);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SET_DUMP_HEAP_DEBUG_LIMIT_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String procName = data.readString();
-            int uid = data.readInt();
-            long maxMemSize = data.readLong();
-            String reportPackage = data.readString();
-            setDumpHeapDebugLimit(procName, uid, maxMemSize, reportPackage);
-            reply.writeNoException();
-            return true;
-        }
-
-        case DUMP_HEAP_FINISHED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String path = data.readString();
-            dumpHeapFinished(path);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SET_VOICE_KEEP_AWAKE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IVoiceInteractionSession session = IVoiceInteractionSession.Stub.asInterface(
-                    data.readStrongBinder());
-            boolean keepAwake = data.readInt() != 0;
-            setVoiceKeepAwake(session, keepAwake);
-            reply.writeNoException();
-            return true;
-        }
-
-        case UPDATE_LOCK_TASK_PACKAGES_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            int userId = data.readInt();
-            String[] packages = data.readStringArray();
-            updateLockTaskPackages(userId, packages);
-            reply.writeNoException();
-            return true;
-        }
-
-        case UPDATE_DEVICE_OWNER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String packageName = data.readString();
-            updateDeviceOwner(packageName);
-            reply.writeNoException();
-            return true;
-        }
-
-        case GET_PACKAGE_PROCESS_STATE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String pkg = data.readString();
-            String callingPackage = data.readString();
-            int res = getPackageProcessState(pkg, callingPackage);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-
-        case SET_PROCESS_MEMORY_TRIM_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            String process = data.readString();
-            int userId = data.readInt();
-            int level = data.readInt();
-            boolean res = setProcessMemoryTrimLevel(process, userId, level);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case IS_ROOT_VOICE_INTERACTION_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            boolean res = isRootVoiceInteraction(token);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case START_BINDER_TRACKING_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            boolean res = startBinderTracking();
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-
-        case STOP_BINDER_TRACKING_AND_DUMP_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            ParcelFileDescriptor fd = data.readInt() != 0
-                    ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
-            boolean res = stopBinderTrackingAndDump(fd);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-        case GET_ACTIVITY_STACK_ID_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            int stackId = getActivityStackId(token);
-            reply.writeNoException();
-            reply.writeInt(stackId);
-            return true;
-        }
-        case EXIT_FREEFORM_MODE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            exitFreeformMode(token);
-            reply.writeNoException();
-            return true;
-        }
-        case REPORT_SIZE_CONFIGURATIONS: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            int[] horizontal = readIntArray(data);
-            int[] vertical = readIntArray(data);
-            int[] smallest = readIntArray(data);
-            reportSizeConfigurations(token, horizontal, vertical, smallest);
-            return true;
-        }
-        case SUPPRESS_RESIZE_CONFIG_CHANGES_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final boolean suppress = data.readInt() == 1;
-            suppressResizeConfigChanges(suppress);
-            reply.writeNoException();
-            return true;
-        }
-        case MOVE_TASKS_TO_FULLSCREEN_STACK_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int stackId = data.readInt();
-            final boolean onTop = data.readInt() == 1;
-            moveTasksToFullscreenStack(stackId, onTop);
-            reply.writeNoException();
-            return true;
-        }
-        case GET_APP_START_MODE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int uid = data.readInt();
-            final String pkg = data.readString();
-            int res = getAppStartMode(uid, pkg);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-        case IN_MULTI_WINDOW_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final IBinder token = data.readStrongBinder();
-            final boolean inMultiWindow = isInMultiWindowMode(token);
-            reply.writeNoException();
-            reply.writeInt(inMultiWindow ? 1 : 0);
-            return true;
-        }
-        case IN_PICTURE_IN_PICTURE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final IBinder token = data.readStrongBinder();
-            final boolean inPip = isInPictureInPictureMode(token);
-            reply.writeNoException();
-            reply.writeInt(inPip ? 1 : 0);
-            return true;
-        }
-        case ENTER_PICTURE_IN_PICTURE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final IBinder token = data.readStrongBinder();
-            enterPictureInPictureMode(token);
-            reply.writeNoException();
-            return true;
-        }
-        case SET_VR_MODE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final IBinder token = data.readStrongBinder();
-            final boolean enable = data.readInt() == 1;
-            final ComponentName packageName = ComponentName.CREATOR.createFromParcel(data);
-            int res = setVrMode(token, enable, packageName);
-            reply.writeNoException();
-            reply.writeInt(res);
-            return true;
-        }
-        case IS_VR_PACKAGE_ENABLED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final ComponentName packageName = ComponentName.CREATOR.createFromParcel(data);
-            boolean res = isVrModePackageEnabled(packageName);
-            reply.writeNoException();
-            reply.writeInt(res ? 1 : 0);
-            return true;
-        }
-        case IS_APP_FOREGROUND_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int userHandle = data.readInt();
-            final boolean isForeground = isAppForeground(userHandle);
-            reply.writeNoException();
-            reply.writeInt(isForeground ? 1 : 0);
-            return true;
-        }
-        case NOTIFY_PINNED_STACK_ANIMATION_ENDED_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            reply.writeNoException();
-            return true;
-        }
-        case REMOVE_STACK: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int stackId = data.readInt();
-            removeStack(stackId);
-            reply.writeNoException();
-            return true;
-        }
-        case NOTIFY_LOCKED_PROFILE: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int userId = data.readInt();
-            notifyLockedProfile(userId);
-            reply.writeNoException();
-            return true;
-        }
-        case START_CONFIRM_DEVICE_CREDENTIAL_INTENT: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final Intent intent = Intent.CREATOR.createFromParcel(data);
-            startConfirmDeviceCredentialIntent(intent);
-            reply.writeNoException();
-            return true;
-        }
-        case SEND_IDLE_JOB_TRIGGER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            sendIdleJobTrigger();
-            reply.writeNoException();
-            return true;
-        }
-        case SEND_INTENT_SENDER_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IIntentSender sender = IIntentSender.Stub.asInterface(data.readStrongBinder());
-            int scode = data.readInt();
-            Intent intent = data.readInt() != 0 ? Intent.CREATOR.createFromParcel(data) : null;
-            String resolvedType = data.readString();
-            IIntentReceiver finishedReceiver = IIntentReceiver.Stub.asInterface(
-                    data.readStrongBinder());
-            String requiredPermission = data.readString();
-            Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null;
-            int result = sendIntentSender(sender, scode, intent, resolvedType, finishedReceiver,
-                    requiredPermission, options);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-        case SET_VR_THREAD_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int tid = data.readInt();
-            setVrThread(tid);
-            reply.writeNoException();
-            return true;
-        }
-        case SET_RENDER_THREAD_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final int tid = data.readInt();
-            setRenderThread(tid);
-            reply.writeNoException();
-            return true;
-        }
-        case SET_HAS_TOP_UI: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final boolean hasTopUi = data.readInt() != 0;
-            setHasTopUi(hasTopUi);
-            reply.writeNoException();
-            return true;
-        }
-        case CAN_BYPASS_WORK_CHALLENGE: {
-            data.enforceInterface(IActivityManager.descriptor);
-            final PendingIntent intent = PendingIntent.CREATOR.createFromParcel(data);
-            final boolean result = canBypassWorkChallenge(intent);
-            reply.writeNoException();
-            reply.writeInt(result ? 1 : 0);
-            return true;
-        }
-        }
-
-        return super.onTransact(code, data, reply, flags);
-    }
-
-    private int[] readIntArray(Parcel data) {
-        int[] smallest = null;
-        int smallestSize = data.readInt();
-        if (smallestSize > 0) {
-            smallest = new int[smallestSize];
-            data.readIntArray(smallest);
-        }
-        return smallest;
-    }
-
-    public IBinder asBinder() {
-        return this;
-    }
-
-    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
-        protected IActivityManager create() {
-            IBinder b = ServiceManager.getService("activity");
-            if (false) {
-                Log.v("ActivityManager", "default service binder = " + b);
-            }
-            IActivityManager am = asInterface(b);
-            if (false) {
-                Log.v("ActivityManager", "default service = " + am);
-            }
-            return am;
-        }
-    };
-}
-
-class ActivityManagerProxy implements IActivityManager
-{
-    public ActivityManagerProxy(IBinder remote)
-    {
-        mRemote = remote;
-    }
-
-    public IBinder asBinder()
-    {
-        return mRemote;
-    }
-
-    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
-            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
-            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        data.writeString(callingPackage);
-        intent.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeStrongBinder(resultTo);
-        data.writeString(resultWho);
-        data.writeInt(requestCode);
-        data.writeInt(startFlags);
-        if (profilerInfo != null) {
-            data.writeInt(1);
-            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        } else {
-            data.writeInt(0);
-        }
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
-    public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent,
-            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
-            int startFlags, ProfilerInfo profilerInfo, Bundle options,
-            int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        data.writeString(callingPackage);
-        intent.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeStrongBinder(resultTo);
-        data.writeString(resultWho);
-        data.writeInt(requestCode);
-        data.writeInt(startFlags);
-        if (profilerInfo != null) {
-            data.writeInt(1);
-            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        } else {
-            data.writeInt(0);
-        }
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(userId);
-        mRemote.transact(START_ACTIVITY_AS_USER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-    public int startActivityAsCaller(IApplicationThread caller, String callingPackage,
-            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
-            int startFlags, ProfilerInfo profilerInfo, Bundle options, boolean ignoreTargetSecurity,
-            int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        data.writeString(callingPackage);
-        intent.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeStrongBinder(resultTo);
-        data.writeString(resultWho);
-        data.writeInt(requestCode);
-        data.writeInt(startFlags);
-        if (profilerInfo != null) {
-            data.writeInt(1);
-            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        } else {
-            data.writeInt(0);
-        }
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(ignoreTargetSecurity ? 1 : 0);
-        data.writeInt(userId);
-        mRemote.transact(START_ACTIVITY_AS_CALLER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-    public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
-            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
-            int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options,
-            int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        data.writeString(callingPackage);
-        intent.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeStrongBinder(resultTo);
-        data.writeString(resultWho);
-        data.writeInt(requestCode);
-        data.writeInt(startFlags);
-        if (profilerInfo != null) {
-            data.writeInt(1);
-            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        } else {
-            data.writeInt(0);
-        }
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(userId);
-        mRemote.transact(START_ACTIVITY_AND_WAIT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        WaitResult result = WaitResult.CREATOR.createFromParcel(reply);
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-    public int startActivityWithConfig(IApplicationThread caller, String callingPackage,
-            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
-            int requestCode, int startFlags, Configuration config,
-            Bundle options, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        data.writeString(callingPackage);
-        intent.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeStrongBinder(resultTo);
-        data.writeString(resultWho);
-        data.writeInt(requestCode);
-        data.writeInt(startFlags);
-        config.writeToParcel(data, 0);
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(userId);
-        mRemote.transact(START_ACTIVITY_WITH_CONFIG_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-    public int startActivityIntentSender(IApplicationThread caller,
-            IntentSender intent, Intent fillInIntent, String resolvedType,
-            IBinder resultTo, String resultWho, int requestCode,
-            int flagsMask, int flagsValues, Bundle options) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        intent.writeToParcel(data, 0);
-        if (fillInIntent != null) {
-            data.writeInt(1);
-            fillInIntent.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeString(resolvedType);
-        data.writeStrongBinder(resultTo);
-        data.writeString(resultWho);
-        data.writeInt(requestCode);
-        data.writeInt(flagsMask);
-        data.writeInt(flagsValues);
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(START_ACTIVITY_INTENT_SENDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-    public int startVoiceActivity(String callingPackage, int callingPid, int callingUid,
-            Intent intent, String resolvedType, IVoiceInteractionSession session,
-            IVoiceInteractor interactor, int startFlags, ProfilerInfo profilerInfo,
-            Bundle options, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(callingPackage);
-        data.writeInt(callingPid);
-        data.writeInt(callingUid);
-        intent.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeStrongBinder(session.asBinder());
-        data.writeStrongBinder(interactor.asBinder());
-        data.writeInt(startFlags);
-        if (profilerInfo != null) {
-            data.writeInt(1);
-            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        } else {
-            data.writeInt(0);
-        }
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(userId);
-        mRemote.transact(START_VOICE_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
-    public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(callingActivity);
-        data.writeBundle(options);
-        mRemote.transact(START_LOCAL_VOICE_INTERACTION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        reply.recycle();
-        data.recycle();
-    }
-
-    public void stopLocalVoiceInteraction(IBinder callingActivity) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(callingActivity);
-        mRemote.transact(STOP_LOCAL_VOICE_INTERACTION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        reply.recycle();
-        data.recycle();
-    }
-
-    public boolean supportsLocalVoiceInteraction() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(SUPPORTS_LOCAL_VOICE_INTERACTION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result != 0;
-    }
-
-    public boolean startNextMatchingActivity(IBinder callingActivity,
-            Intent intent, Bundle options) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(callingActivity);
-        intent.writeToParcel(data, 0);
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(START_NEXT_MATCHING_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result != 0;
-    }
-    public int startActivityFromRecents(int taskId, Bundle options)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        if (options == null) {
-            data.writeInt(0);
-        } else {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        }
-        mRemote.transact(START_ACTIVITY_FROM_RECENTS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-    public boolean finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeInt(resultCode);
-        if (resultData != null) {
-            data.writeInt(1);
-            resultData.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(finishTask);
-        mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeString(resultWho);
-        data.writeInt(requestCode);
-        mRemote.transact(FINISH_SUB_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public boolean finishActivityAffinity(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(FINISH_ACTIVITY_AFFINITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public void finishVoiceTask(IVoiceInteractionSession session) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(session.asBinder());
-        mRemote.transact(FINISH_VOICE_TASK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void requestActivityRelaunch(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(REQUEST_ACTIVITY_RELAUNCH, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public boolean releaseActivityInstance(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(RELEASE_ACTIVITY_INSTANCE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public void releaseSomeActivities(IApplicationThread app) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(app.asBinder());
-        mRemote.transact(RELEASE_SOME_ACTIVITIES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public boolean willActivityBeVisible(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(WILL_ACTIVITY_BE_VISIBLE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public Intent registerReceiver(IApplicationThread caller, String packageName,
-            IIntentReceiver receiver,
-            IntentFilter filter, String perm, int userId) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        data.writeString(packageName);
-        data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
-        filter.writeToParcel(data, 0);
-        data.writeString(perm);
-        data.writeInt(userId);
-        mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        Intent intent = null;
-        int haveIntent = reply.readInt();
-        if (haveIntent != 0) {
-            intent = Intent.CREATOR.createFromParcel(reply);
-        }
-        reply.recycle();
-        data.recycle();
-        return intent;
-    }
-    public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(receiver.asBinder());
-        mRemote.transact(UNREGISTER_RECEIVER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public int broadcastIntent(IApplicationThread caller,
-            Intent intent, String resolvedType, IIntentReceiver resultTo,
-            int resultCode, String resultData, Bundle map,
-            String[] requiredPermissions, int appOp, Bundle options, boolean serialized,
-            boolean sticky, int userId) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        intent.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
-        data.writeInt(resultCode);
-        data.writeString(resultData);
-        data.writeBundle(map);
-        data.writeStringArray(requiredPermissions);
-        data.writeInt(appOp);
-        data.writeBundle(options);
-        data.writeInt(serialized ? 1 : 0);
-        data.writeInt(sticky ? 1 : 0);
-        data.writeInt(userId);
-        mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-    public void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId)
-            throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        intent.writeToParcel(data, 0);
-        data.writeInt(userId);
-        mRemote.transact(UNBROADCAST_INTENT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map,
-            boolean abortBroadcast, int flags) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(who);
-        data.writeInt(resultCode);
-        data.writeString(resultData);
-        data.writeBundle(map);
-        data.writeInt(abortBroadcast ? 1 : 0);
-        data.writeInt(flags);
-        mRemote.transact(FINISH_RECEIVER_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void attachApplication(IApplicationThread app) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(app.asBinder());
-        mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void activityIdle(IBinder token, Configuration config, boolean stopProfiling)
-            throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        if (config != null) {
-            data.writeInt(1);
-            config.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(stopProfiling ? 1 : 0);
-        mRemote.transact(ACTIVITY_IDLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void activityResumed(IBinder token) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(ACTIVITY_RESUMED_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void activityPaused(IBinder token) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void activityStopped(IBinder token, Bundle state,
-            PersistableBundle persistentState, CharSequence description) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeBundle(state);
-        data.writePersistableBundle(persistentState);
-        TextUtils.writeToParcel(description, data, 0);
-        mRemote.transact(ACTIVITY_STOPPED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void activitySlept(IBinder token) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(ACTIVITY_SLEPT_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void activityDestroyed(IBinder token) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(ACTIVITY_DESTROYED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void activityRelaunched(IBinder token) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(ACTIVITY_RELAUNCHED_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public String getCallingPackage(IBinder token) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(GET_CALLING_PACKAGE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        String res = reply.readString();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public ComponentName getCallingActivity(IBinder token)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(GET_CALLING_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ComponentName res = ComponentName.readFromParcel(reply);
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(callingPackage);
-        mRemote.transact(GET_APP_TASKS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ArrayList<IAppTask> list = null;
-        int N = reply.readInt();
-        if (N >= 0) {
-            list = new ArrayList<>();
-            while (N > 0) {
-                IAppTask task = IAppTask.Stub.asInterface(reply.readStrongBinder());
-                list.add(task);
-                N--;
-            }
-        }
-        data.recycle();
-        reply.recycle();
-        return list;
-    }
-    public int addAppTask(IBinder activityToken, Intent intent,
-            ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(activityToken);
-        intent.writeToParcel(data, 0);
-        description.writeToParcel(data, 0);
-        thumbnail.writeToParcel(data, 0);
-        mRemote.transact(ADD_APP_TASK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public Point getAppTaskThumbnailSize() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        Point size = Point.CREATOR.createFromParcel(reply);
-        data.recycle();
-        reply.recycle();
-        return size;
-    }
-    public List<ActivityManager.RunningTaskInfo> getTasks(int maxNum, int flags)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(maxNum);
-        data.writeInt(flags);
-        mRemote.transact(GET_TASKS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ArrayList<ActivityManager.RunningTaskInfo> list = null;
-        int N = reply.readInt();
-        if (N >= 0) {
-            list = new ArrayList<>();
-            while (N > 0) {
-                ActivityManager.RunningTaskInfo info =
-                        ActivityManager.RunningTaskInfo.CREATOR
-                                .createFromParcel(reply);
-                list.add(info);
-                N--;
-            }
-        }
-        data.recycle();
-        reply.recycle();
-        return list;
-    }
-    public ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
-            int flags, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(maxNum);
-        data.writeInt(flags);
-        data.writeInt(userId);
-        mRemote.transact(GET_RECENT_TASKS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        final ParceledListSlice<ActivityManager.RecentTaskInfo> list = ParceledListSlice.CREATOR
-                .createFromParcel(reply);
-        data.recycle();
-        reply.recycle();
-        return list;
-    }
-    public ActivityManager.TaskThumbnail getTaskThumbnail(int id) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(id);
-        mRemote.transact(GET_TASK_THUMBNAIL_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ActivityManager.TaskThumbnail taskThumbnail = null;
-        if (reply.readInt() != 0) {
-            taskThumbnail = ActivityManager.TaskThumbnail.CREATOR.createFromParcel(reply);
-        }
-        data.recycle();
-        reply.recycle();
-        return taskThumbnail;
-    }
-    public List<ActivityManager.RunningServiceInfo> getServices(int maxNum, int flags)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(maxNum);
-        data.writeInt(flags);
-        mRemote.transact(GET_SERVICES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ArrayList<ActivityManager.RunningServiceInfo> list = null;
-        int N = reply.readInt();
-        if (N >= 0) {
-            list = new ArrayList<>();
-            while (N > 0) {
-                ActivityManager.RunningServiceInfo info =
-                        ActivityManager.RunningServiceInfo.CREATOR
-                        .createFromParcel(reply);
-                list.add(info);
-                N--;
-            }
-        }
-        data.recycle();
-        reply.recycle();
-        return list;
-    }
-    public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState()
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_PROCESSES_IN_ERROR_STATE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ArrayList<ActivityManager.ProcessErrorStateInfo> list
-            = reply.createTypedArrayList(ActivityManager.ProcessErrorStateInfo.CREATOR);
-        data.recycle();
-        reply.recycle();
-        return list;
-    }
-    public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses()
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_RUNNING_APP_PROCESSES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ArrayList<ActivityManager.RunningAppProcessInfo> list
-        = reply.createTypedArrayList(ActivityManager.RunningAppProcessInfo.CREATOR);
-        data.recycle();
-        reply.recycle();
-        return list;
-    }
-    public List<ApplicationInfo> getRunningExternalApplications()
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_RUNNING_EXTERNAL_APPLICATIONS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ArrayList<ApplicationInfo> list
-        = reply.createTypedArrayList(ApplicationInfo.CREATOR);
-        data.recycle();
-        reply.recycle();
-        return list;
-    }
-    public void moveTaskToFront(int task, int flags, Bundle options) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(task);
-        data.writeInt(flags);
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(MOVE_TASK_TO_FRONT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeInt(nonRoot ? 1 : 0);
-        mRemote.transact(MOVE_ACTIVITY_TASK_TO_BACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public void moveTaskBackwards(int task) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(task);
-        mRemote.transact(MOVE_TASK_BACKWARDS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    @Override
-    public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        data.writeInt(stackId);
-        data.writeInt(toTop ? 1 : 0);
-        mRemote.transact(MOVE_TASK_TO_STACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    @Override
-    public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
-            Rect initialBounds, boolean moveHomeStackFront) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        data.writeInt(createMode);
-        data.writeInt(toTop ? 1 : 0);
-        data.writeInt(animate ? 1 : 0);
-        if (initialBounds != null) {
-            data.writeInt(1);
-            initialBounds.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(moveHomeStackFront ? 1 : 0);
-        mRemote.transact(MOVE_TASK_TO_DOCKED_STACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() > 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    @Override
-    public boolean moveTopActivityToPinnedStack(int stackId, Rect r)
-        throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(stackId);
-        r.writeToParcel(data, 0);
-        mRemote.transact(MOVE_TOP_ACTIVITY_TO_PINNED_STACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        final boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    @Override
-    public void resizeStack(int stackId, Rect r, boolean allowResizeInDockedMode,
-            boolean preserveWindows, boolean animate, int animationDuration)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(stackId);
-        if (r != null) {
-            data.writeInt(1);
-            r.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(allowResizeInDockedMode ? 1 : 0);
-        data.writeInt(preserveWindows ? 1 : 0);
-        data.writeInt(animate ? 1 : 0);
-        data.writeInt(animationDuration);
-        mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    @Override
-    public void swapDockedAndFullscreenStack() throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(SWAP_DOCKED_AND_FULLSCREEN_STACK, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    @Override
-    public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
-            Rect tempDockedTaskInsetBounds,
-            Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds)
-            throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        if (dockedBounds != null) {
-            data.writeInt(1);
-            dockedBounds.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        if (tempDockedTaskBounds != null) {
-            data.writeInt(1);
-            tempDockedTaskBounds.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        if (tempDockedTaskInsetBounds != null) {
-            data.writeInt(1);
-            tempDockedTaskInsetBounds.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        if (tempOtherTaskBounds != null) {
-            data.writeInt(1);
-            tempOtherTaskBounds.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        if (tempOtherTaskInsetBounds != null) {
-            data.writeInt(1);
-            tempOtherTaskInsetBounds.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(RESIZE_DOCKED_STACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        if (pinnedBounds != null) {
-            data.writeInt(1);
-            pinnedBounds.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        if (tempPinnedTaskBounds != null) {
-            data.writeInt(1);
-            tempPinnedTaskBounds.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(RESIZE_PINNED_STACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        data.writeInt(stackId);
-        data.writeInt(position);
-        mRemote.transact(POSITION_TASK_IN_STACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    @Override
-    public List<StackInfo> getAllStackInfos() throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_ALL_STACK_INFOS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ArrayList<StackInfo> list = reply.createTypedArrayList(StackInfo.CREATOR);
-        data.recycle();
-        reply.recycle();
-        return list;
-    }
-    @Override
-    public StackInfo getStackInfo(int stackId) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(stackId);
-        mRemote.transact(GET_STACK_INFO_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        StackInfo info = null;
-        if (res != 0) {
-            info = StackInfo.CREATOR.createFromParcel(reply);
-        }
-        data.recycle();
-        reply.recycle();
-        return info;
-    }
-    @Override
-    public boolean isInHomeStack(int taskId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        mRemote.transact(IS_IN_HOME_STACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean isInHomeStack = reply.readInt() > 0;
-        data.recycle();
-        reply.recycle();
-        return isInHomeStack;
-    }
-    @Override
-    public void setFocusedStack(int stackId) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(stackId);
-        mRemote.transact(SET_FOCUSED_STACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    @Override
-    public int getFocusedStackId() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_FOCUSED_STACK_ID_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int focusedStackId = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return focusedStackId;
-    }
-    @Override
-    public void setFocusedTask(int taskId) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        mRemote.transact(SET_FOCUSED_TASK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    @Override
-    public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(listener.asBinder());
-        mRemote.transact(REGISTER_TASK_STACK_LISTENER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        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();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeInt(onlyRoot ? 1 : 0);
-        mRemote.transact(GET_TASK_FOR_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public ContentProviderHolder getContentProvider(IApplicationThread caller,
-            String name, int userId, boolean stable) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        data.writeString(name);
-        data.writeInt(userId);
-        data.writeInt(stable ? 1 : 0);
-        mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        ContentProviderHolder cph = null;
-        if (res != 0) {
-            cph = ContentProviderHolder.CREATOR.createFromParcel(reply);
-        }
-        data.recycle();
-        reply.recycle();
-        return cph;
-    }
-    public ContentProviderHolder getContentProviderExternal(String name, int userId, IBinder token)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(name);
-        data.writeInt(userId);
-        data.writeStrongBinder(token);
-        mRemote.transact(GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        ContentProviderHolder cph = null;
-        if (res != 0) {
-            cph = ContentProviderHolder.CREATOR.createFromParcel(reply);
-        }
-        data.recycle();
-        reply.recycle();
-        return cph;
-    }
-    public void publishContentProviders(IApplicationThread caller,
-            List<ContentProviderHolder> providers) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        data.writeTypedList(providers);
-        mRemote.transact(PUBLISH_CONTENT_PROVIDERS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public boolean refContentProvider(IBinder connection, int stable, int unstable)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(connection);
-        data.writeInt(stable);
-        data.writeInt(unstable);
-        mRemote.transact(REF_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public void unstableProviderDied(IBinder connection) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(connection);
-        mRemote.transact(UNSTABLE_PROVIDER_DIED_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void appNotRespondingViaProvider(IBinder connection) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(connection);
-        mRemote.transact(APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void removeContentProvider(IBinder connection, boolean stable) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(connection);
-        data.writeInt(stable ? 1 : 0);
-        mRemote.transact(REMOVE_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void removeContentProviderExternal(String name, IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(name);
-        data.writeStrongBinder(token);
-        mRemote.transact(REMOVE_CONTENT_PROVIDER_EXTERNAL_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public PendingIntent getRunningServiceControlPanel(ComponentName service)
-            throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        service.writeToParcel(data, 0);
-        mRemote.transact(GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION, data, reply, 0);
-        reply.readException();
-        PendingIntent res = PendingIntent.readPendingIntentOrNullFromParcel(reply);
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public ComponentName startService(IApplicationThread caller, Intent service,
-            String resolvedType, String callingPackage, int userId) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        service.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeString(callingPackage);
-        data.writeInt(userId);
-        mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ComponentName res = ComponentName.readFromParcel(reply);
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public int stopService(IApplicationThread caller, Intent service,
-            String resolvedType, int userId) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        service.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeInt(userId);
-        mRemote.transact(STOP_SERVICE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-    public boolean stopServiceToken(ComponentName className, IBinder token,
-            int startId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        ComponentName.writeToParcel(className, data);
-        data.writeStrongBinder(token);
-        data.writeInt(startId);
-        mRemote.transact(STOP_SERVICE_TOKEN_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public void setServiceForeground(ComponentName className, IBinder token,
-            int id, Notification notification, int flags) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        ComponentName.writeToParcel(className, data);
-        data.writeStrongBinder(token);
-        data.writeInt(id);
-        if (notification != null) {
-            data.writeInt(1);
-            notification.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(flags);
-        mRemote.transact(SET_SERVICE_FOREGROUND_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public int bindService(IApplicationThread caller, IBinder token,
-            Intent service, String resolvedType, IServiceConnection connection,
-            int flags,  String callingPackage, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        data.writeStrongBinder(token);
-        service.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeStrongBinder(connection.asBinder());
-        data.writeInt(flags);
-        data.writeString(callingPackage);
-        data.writeInt(userId);
-        mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public boolean unbindService(IServiceConnection connection) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(connection.asBinder());
-        mRemote.transact(UNBIND_SERVICE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public void publishService(IBinder token,
-            Intent intent, IBinder service) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        intent.writeToParcel(data, 0);
-        data.writeStrongBinder(service);
-        mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void unbindFinished(IBinder token, Intent intent, boolean doRebind)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        intent.writeToParcel(data, 0);
-        data.writeInt(doRebind ? 1 : 0);
-        mRemote.transact(UNBIND_FINISHED_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void serviceDoneExecuting(IBinder token, int type, int startId,
-            int res) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeInt(type);
-        data.writeInt(startId);
-        data.writeInt(res);
-        mRemote.transact(SERVICE_DONE_EXECUTING_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public IBinder peekService(Intent service, String resolvedType, String callingPackage)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        service.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeString(callingPackage);
-        mRemote.transact(PEEK_SERVICE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        IBinder binder = reply.readStrongBinder();
-        reply.recycle();
-        data.recycle();
-        return binder;
-    }
-
-    public boolean bindBackupAgent(String packageName, int backupRestoreMode, int userId)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeInt(backupRestoreMode);
-        data.writeInt(userId);
-        mRemote.transact(START_BACKUP_AGENT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean success = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return success;
-    }
-
-    public void clearPendingBackup() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(CLEAR_PENDING_BACKUP_TRANSACTION, data, reply, 0);
-        reply.recycle();
-        data.recycle();
-    }
-
-    public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeStrongBinder(agent);
-        mRemote.transact(BACKUP_AGENT_CREATED_TRANSACTION, data, reply, 0);
-        reply.recycle();
-        data.recycle();
-    }
-
-    public void unbindBackupAgent(ApplicationInfo app) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        app.writeToParcel(data, 0);
-        mRemote.transact(UNBIND_BACKUP_AGENT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        reply.recycle();
-        data.recycle();
-    }
-
-    public boolean startInstrumentation(ComponentName className, String profileFile,
-            int flags, Bundle arguments, IInstrumentationWatcher watcher,
-            IUiAutomationConnection connection, int userId, String instructionSet)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        ComponentName.writeToParcel(className, data);
-        data.writeString(profileFile);
-        data.writeInt(flags);
-        data.writeBundle(arguments);
-        data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
-        data.writeStrongBinder(connection != null ? connection.asBinder() : null);
-        data.writeInt(userId);
-        data.writeString(instructionSet);
-        mRemote.transact(START_INSTRUMENTATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-
-    public void finishInstrumentation(IApplicationThread target,
-            int resultCode, Bundle results) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(target != null ? target.asBinder() : null);
-        data.writeInt(resultCode);
-        data.writeBundle(results);
-        mRemote.transact(FINISH_INSTRUMENTATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public Configuration getConfiguration() throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_CONFIGURATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        Configuration res = Configuration.CREATOR.createFromParcel(reply);
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-    public boolean updateConfiguration(Configuration values) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        values.writeToParcel(data, 0);
-        mRemote.transact(UPDATE_CONFIGURATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean updated = reply.readInt() == 1;
-        data.recycle();
-        reply.recycle();
-        return updated;
-    }
-    public boolean updateDisplayOverrideConfiguration(Configuration values, int displayId)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        values.writeToParcel(data, 0);
-        data.writeInt(displayId);
-        mRemote.transact(UPDATE_DISPLAY_OVERRIDE_CONFIGURATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean updated = reply.readInt() == 1;
-        data.recycle();
-        reply.recycle();
-        return updated;
-    }
-    public void setRequestedOrientation(IBinder token, int requestedOrientation)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeInt(requestedOrientation);
-        mRemote.transact(SET_REQUESTED_ORIENTATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public int getRequestedOrientation(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(GET_REQUESTED_ORIENTATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public ComponentName getActivityClassForToken(IBinder token)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(GET_ACTIVITY_CLASS_FOR_TOKEN_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ComponentName res = ComponentName.readFromParcel(reply);
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public String getPackageForToken(IBinder token) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(GET_PACKAGE_FOR_TOKEN_TRANSACTION, data, reply, 0);
-        reply.readException();
-        String res = reply.readString();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public IIntentSender getIntentSender(int type,
-            String packageName, IBinder token, String resultWho,
-            int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
-            Bundle options, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(type);
-        data.writeString(packageName);
-        data.writeStrongBinder(token);
-        data.writeString(resultWho);
-        data.writeInt(requestCode);
-        if (intents != null) {
-            data.writeInt(1);
-            data.writeTypedArray(intents, 0);
-            data.writeStringArray(resolvedTypes);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(flags);
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(userId);
-        mRemote.transact(GET_INTENT_SENDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        IIntentSender res = IIntentSender.Stub.asInterface(
-                reply.readStrongBinder());
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public void cancelIntentSender(IIntentSender sender) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(sender.asBinder());
-        mRemote.transact(CANCEL_INTENT_SENDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public String getPackageForIntentSender(IIntentSender sender) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(sender.asBinder());
-        mRemote.transact(GET_PACKAGE_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        String res = reply.readString();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public int getUidForIntentSender(IIntentSender sender) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(sender.asBinder());
-        mRemote.transact(GET_UID_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
-            boolean requireFull, String name, String callerPackage) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(callingPid);
-        data.writeInt(callingUid);
-        data.writeInt(userId);
-        data.writeInt(allowAll ? 1 : 0);
-        data.writeInt(requireFull ? 1 : 0);
-        data.writeString(name);
-        data.writeString(callerPackage);
-        mRemote.transact(HANDLE_INCOMING_USER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public void setProcessLimit(int max) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(max);
-        mRemote.transact(SET_PROCESS_LIMIT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public int getProcessLimit() throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_PROCESS_LIMIT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public void setProcessForeground(IBinder token, int pid,
-            boolean isForeground) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeInt(pid);
-        data.writeInt(isForeground ? 1 : 0);
-        mRemote.transact(SET_PROCESS_FOREGROUND_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public int checkPermission(String permission, int pid, int uid)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(permission);
-        data.writeInt(pid);
-        data.writeInt(uid);
-        mRemote.transact(CHECK_PERMISSION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public int checkPermissionWithToken(String permission, int pid, int uid, IBinder callerToken)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(permission);
-        data.writeInt(pid);
-        data.writeInt(uid);
-        data.writeStrongBinder(callerToken);
-        mRemote.transact(CHECK_PERMISSION_WITH_TOKEN_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public boolean clearApplicationUserData(final String packageName,
-            final IPackageDataObserver observer, final int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeStrongBinder((observer != null) ? observer.asBinder() : null);
-        data.writeInt(userId);
-        mRemote.transact(CLEAR_APP_DATA_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId,
-            IBinder callerToken) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        uri.writeToParcel(data, 0);
-        data.writeInt(pid);
-        data.writeInt(uid);
-        data.writeInt(mode);
-        data.writeInt(userId);
-        data.writeStrongBinder(callerToken);
-        mRemote.transact(CHECK_URI_PERMISSION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public void grantUriPermission(IApplicationThread caller, String targetPkg,
-            Uri uri, int mode, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller.asBinder());
-        data.writeString(targetPkg);
-        uri.writeToParcel(data, 0);
-        data.writeInt(mode);
-        data.writeInt(userId);
-        mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void revokeUriPermission(IApplicationThread caller, Uri uri,
-            int mode, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller.asBinder());
-        uri.writeToParcel(data, 0);
-        data.writeInt(mode);
-        data.writeInt(userId);
-        mRemote.transact(REVOKE_URI_PERMISSION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void takePersistableUriPermission(Uri uri, int mode, int userId)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        uri.writeToParcel(data, 0);
-        data.writeInt(mode);
-        data.writeInt(userId);
-        mRemote.transact(TAKE_PERSISTABLE_URI_PERMISSION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void releasePersistableUriPermission(Uri uri, int mode, int userId)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        uri.writeToParcel(data, 0);
-        data.writeInt(mode);
-        data.writeInt(userId);
-        mRemote.transact(RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public ParceledListSlice<UriPermission> getPersistedUriPermissions(
-            String packageName, boolean incoming) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeInt(incoming ? 1 : 0);
-        mRemote.transact(GET_PERSISTED_URI_PERMISSIONS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        @SuppressWarnings("unchecked")
-        final ParceledListSlice<UriPermission> perms = ParceledListSlice.CREATOR.createFromParcel(
-                reply);
-        data.recycle();
-        reply.recycle();
-        return perms;
-    }
-
-    @Override
-    public ParceledListSlice<UriPermission> getGrantedUriPermissions(String packageName, int userId)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeInt(userId);
-        mRemote.transact(GET_GRANTED_URI_PERMISSIONS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        @SuppressWarnings("unchecked")
-        final ParceledListSlice<UriPermission> perms = ParceledListSlice.CREATOR.createFromParcel(
-                reply);
-        data.recycle();
-        reply.recycle();
-        return perms;
-    }
-
-    @Override
-    public void clearGrantedUriPermissions(String packageName, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeInt(userId);
-        mRemote.transact(CLEAR_GRANTED_URI_PERMISSIONS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void showWaitingForDebugger(IApplicationThread who, boolean waiting)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(who.asBinder());
-        data.writeInt(waiting ? 1 : 0);
-        mRemote.transact(SHOW_WAITING_FOR_DEBUGGER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_MEMORY_INFO_TRANSACTION, data, reply, 0);
-        reply.readException();
-        outInfo.readFromParcel(reply);
-        data.recycle();
-        reply.recycle();
-    }
-    public void unhandledBack() throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(UNHANDLED_BACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(OPEN_CONTENT_URI_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ParcelFileDescriptor pfd = null;
-        if (reply.readInt() != 0) {
-            pfd = ParcelFileDescriptor.CREATOR.createFromParcel(reply);
-        }
-        data.recycle();
-        reply.recycle();
-        return pfd;
-    }
-    public void setLockScreenShown(boolean showing) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(showing ? 1 : 0);
-        mRemote.transact(SET_LOCK_SCREEN_SHOWN_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void setDebugApp(
-        String packageName, boolean waitForDebugger, boolean persistent)
-        throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeInt(waitForDebugger ? 1 : 0);
-        data.writeInt(persistent ? 1 : 0);
-        mRemote.transact(SET_DEBUG_APP_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void setAlwaysFinish(boolean enabled) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(enabled ? 1 : 0);
-        mRemote.transact(SET_ALWAYS_FINISH_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void setActivityController(IActivityController watcher, boolean imAMonkey)
-            throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
-        data.writeInt(imAMonkey ? 1 : 0);
-        mRemote.transact(SET_ACTIVITY_CONTROLLER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void setLenientBackgroundCheck(boolean enabled) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(enabled ? 1 : 0);
-        mRemote.transact(SET_LENIENT_BACKGROUND_CHECK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public int getMemoryTrimLevel() throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_MEMORY_TRIM_LEVEL_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int level = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return level;
-    }
-    public void enterSafeMode() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(ENTER_SAFE_MODE_TRANSACTION, data, null, 0);
-        data.recycle();
-    }
-    public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg, String tag)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(sender.asBinder());
-        data.writeInt(sourceUid);
-        data.writeString(sourcePkg);
-        data.writeString(tag);
-        mRemote.transact(NOTE_WAKEUP_ALARM_TRANSACTION, data, null, 0);
-        data.recycle();
-    }
-    public void noteAlarmStart(IIntentSender sender, int sourceUid, String tag)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(sender.asBinder());
-        data.writeInt(sourceUid);
-        data.writeString(tag);
-        mRemote.transact(NOTE_ALARM_START_TRANSACTION, data, null, 0);
-        data.recycle();
-    }
-    public void noteAlarmFinish(IIntentSender sender, int sourceUid, String tag)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(sender.asBinder());
-        data.writeInt(sourceUid);
-        data.writeString(tag);
-        mRemote.transact(NOTE_ALARM_FINISH_TRANSACTION, data, null, 0);
-        data.recycle();
-    }
-    public boolean killPids(int[] pids, String reason, boolean secure) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeIntArray(pids);
-        data.writeString(reason);
-        data.writeInt(secure ? 1 : 0);
-        mRemote.transact(KILL_PIDS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    @Override
-    public boolean killProcessesBelowForeground(String reason) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(reason);
-        mRemote.transact(KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION, data, reply, 0);
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-    public boolean testIsSystemReady()
-    {
-        /* this base class version is never called */
-        return true;
-    }
-    public void handleApplicationCrash(IBinder app,
-            ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(app);
-        crashInfo.writeToParcel(data, 0);
-        mRemote.transact(HANDLE_APPLICATION_CRASH_TRANSACTION, data, reply, 0);
-        reply.readException();
-        reply.recycle();
-        data.recycle();
-    }
-
-    public boolean handleApplicationWtf(IBinder app, String tag, boolean system,
-            ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(app);
-        data.writeString(tag);
-        data.writeInt(system ? 1 : 0);
-        crashInfo.writeToParcel(data, 0);
-        mRemote.transact(HANDLE_APPLICATION_WTF_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-
-    public void handleApplicationStrictModeViolation(IBinder app,
-            int violationMask,
-            StrictMode.ViolationInfo info) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(app);
-        data.writeInt(violationMask);
-        info.writeToParcel(data, 0);
-        mRemote.transact(HANDLE_APPLICATION_STRICT_MODE_VIOLATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        reply.recycle();
-        data.recycle();
-    }
-
-    public void signalPersistentProcesses(int sig) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(sig);
-        mRemote.transact(SIGNAL_PERSISTENT_PROCESSES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void killBackgroundProcesses(String packageName, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeInt(userId);
-        mRemote.transact(KILL_BACKGROUND_PROCESSES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void killAllBackgroundProcesses() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void killPackageDependents(String packageName, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeInt(userId);
-        mRemote.transact(KILL_PACKAGE_DEPENDENTS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void forceStopPackage(String packageName, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeInt(userId);
-        mRemote.transact(FORCE_STOP_PACKAGE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo)
-            throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_MY_MEMORY_STATE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        outInfo.readFromParcel(reply);
-        reply.recycle();
-        data.recycle();
-    }
-
-    public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_DEVICE_CONFIGURATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ConfigurationInfo res = ConfigurationInfo.CREATOR.createFromParcel(reply);
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-
-    public boolean profileControl(String process, int userId, boolean start,
-            ProfilerInfo profilerInfo, int profileType) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(process);
-        data.writeInt(userId);
-        data.writeInt(start ? 1 : 0);
-        data.writeInt(profileType);
-        if (profilerInfo != null) {
-            data.writeInt(1);
-            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(PROFILE_CONTROL_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-
-    public boolean shutdown(int timeout) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(timeout);
-        mRemote.transact(SHUTDOWN_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-
-    public void stopAppSwitches() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(STOP_APP_SWITCHES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        reply.recycle();
-        data.recycle();
-    }
-
-    public void resumeAppSwitches() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(RESUME_APP_SWITCHES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        reply.recycle();
-        data.recycle();
-    }
-
-    public void addPackageDependency(String packageName) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        mRemote.transact(ADD_PACKAGE_DEPENDENCY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void killApplication(String pkg, int appId, int userId, String reason)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(pkg);
-        data.writeInt(appId);
-        data.writeInt(userId);
-        data.writeString(reason);
-        mRemote.transact(KILL_APPLICATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void closeSystemDialogs(String reason) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(reason);
-        mRemote.transact(CLOSE_SYSTEM_DIALOGS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeIntArray(pids);
-        mRemote.transact(GET_PROCESS_MEMORY_INFO_TRANSACTION, data, reply, 0);
-        reply.readException();
-        Debug.MemoryInfo[] res = reply.createTypedArray(Debug.MemoryInfo.CREATOR);
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public void killApplicationProcess(String processName, int uid) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(processName);
-        data.writeInt(uid);
-        mRemote.transact(KILL_APPLICATION_PROCESS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void overridePendingTransition(IBinder token, String packageName,
-            int enterAnim, int exitAnim) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeString(packageName);
-        data.writeInt(enterAnim);
-        data.writeInt(exitAnim);
-        mRemote.transact(OVERRIDE_PENDING_TRANSITION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public boolean isUserAMonkey() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(IS_USER_A_MONKEY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public void setUserIsMonkey(boolean monkey) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(monkey ? 1 : 0);
-        mRemote.transact(SET_USER_IS_MONKEY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void finishHeavyWeightApp() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(FINISH_HEAVY_WEIGHT_APP_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public boolean convertFromTranslucent(IBinder token)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(CONVERT_FROM_TRANSLUCENT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public boolean convertToTranslucent(IBinder token, ActivityOptions options)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        if (options == null) {
-            data.writeInt(0);
-        } else {
-            data.writeInt(1);
-            data.writeBundle(options.toBundle());
-        }
-        mRemote.transact(CONVERT_TO_TRANSLUCENT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public ActivityOptions getActivityOptions(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(GET_ACTIVITY_OPTIONS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        ActivityOptions options = ActivityOptions.fromBundle(reply.readBundle());
-        data.recycle();
-        reply.recycle();
-        return options;
-    }
-
-    public void setImmersive(IBinder token, boolean immersive)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeInt(immersive ? 1 : 0);
-        mRemote.transact(SET_IMMERSIVE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public boolean isImmersive(IBinder token)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(IS_IMMERSIVE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() == 1;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public boolean isTopOfTask(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(IS_TOP_OF_TASK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() == 1;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public boolean isTopActivityImmersive()
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() == 1;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public void crashApplication(int uid, int initialPid, String packageName,
-            String message) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(uid);
-        data.writeInt(initialPid);
-        data.writeString(packageName);
-        data.writeString(message);
-        mRemote.transact(CRASH_APPLICATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public String getProviderMimeType(Uri uri, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        uri.writeToParcel(data, 0);
-        data.writeInt(userId);
-        mRemote.transact(GET_PROVIDER_MIME_TYPE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        String res = reply.readString();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public IBinder newUriPermissionOwner(String name)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(name);
-        mRemote.transact(NEW_URI_PERMISSION_OWNER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        IBinder res = reply.readStrongBinder();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public IBinder getUriPermissionOwnerForActivity(IBinder activityToken) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(activityToken);
-        mRemote.transact(GET_URI_PERMISSION_OWNER_FOR_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        IBinder res = reply.readStrongBinder();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
-            Uri uri, int mode, int sourceUserId, int targetUserId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(owner);
-        data.writeInt(fromUid);
-        data.writeString(targetPkg);
-        uri.writeToParcel(data, 0);
-        data.writeInt(mode);
-        data.writeInt(sourceUserId);
-        data.writeInt(targetUserId);
-        mRemote.transact(GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void revokeUriPermissionFromOwner(IBinder owner, Uri uri,
-            int mode, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(owner);
-        if (uri != null) {
-            data.writeInt(1);
-            uri.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(mode);
-        data.writeInt(userId);
-        mRemote.transact(REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public int checkGrantUriPermission(int callingUid, String targetPkg,
-            Uri uri, int modeFlags, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(callingUid);
-        data.writeString(targetPkg);
-        uri.writeToParcel(data, 0);
-        data.writeInt(modeFlags);
-        data.writeInt(userId);
-        mRemote.transact(CHECK_GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public boolean dumpHeap(String process, int userId, boolean managed,
-            String path, ParcelFileDescriptor fd) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(process);
-        data.writeInt(userId);
-        data.writeInt(managed ? 1 : 0);
-        data.writeString(path);
-        if (fd != null) {
-            data.writeInt(1);
-            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(DUMP_HEAP_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-
-    public int startActivities(IApplicationThread caller, String callingPackage,
-            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
-        data.writeString(callingPackage);
-        data.writeTypedArray(intents, 0);
-        data.writeStringArray(resolvedTypes);
-        data.writeStrongBinder(resultTo);
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        data.writeInt(userId);
-        mRemote.transact(START_ACTIVITIES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
-    public int getFrontActivityScreenCompatMode() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int mode = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return mode;
-    }
-
-    public void setFrontActivityScreenCompatMode(int mode) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(mode);
-        mRemote.transact(SET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        reply.recycle();
-        data.recycle();
-    }
-
-    public int getPackageScreenCompatMode(String packageName) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        mRemote.transact(GET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int mode = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return mode;
-    }
-
-    public void setPackageScreenCompatMode(String packageName, int mode)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeInt(mode);
-        mRemote.transact(SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        reply.recycle();
-        data.recycle();
-    }
-
-    public boolean getPackageAskScreenCompat(String packageName) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        mRemote.transact(GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean ask = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return ask;
-    }
-
-    public void setPackageAskScreenCompat(String packageName, boolean ask)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeInt(ask ? 1 : 0);
-        mRemote.transact(SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        reply.recycle();
-        data.recycle();
-    }
-
-    public boolean switchUser(int userid) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(userid);
-        mRemote.transact(SWITCH_USER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean result = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
-    public boolean startUserInBackground(int userid) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(userid);
-        mRemote.transact(START_USER_IN_BACKGROUND_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean result = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
-    public boolean unlockUser(int userId, byte[] token, byte[] secret, IProgressListener listener)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(userId);
-        data.writeByteArray(token);
-        data.writeByteArray(secret);
-        data.writeStrongInterface(listener);
-        mRemote.transact(IActivityManager.UNLOCK_USER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean result = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
-    public int stopUser(int userid, boolean force, IStopUserCallback callback)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(userid);
-        data.writeInt(force ? 1 : 0);
-        data.writeStrongInterface(callback);
-        mRemote.transact(STOP_USER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
-    public UserInfo getCurrentUser() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_CURRENT_USER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        UserInfo userInfo = UserInfo.CREATOR.createFromParcel(reply);
-        reply.recycle();
-        data.recycle();
-        return userInfo;
-    }
-
-    public boolean isUserRunning(int userid, int flags) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(userid);
-        data.writeInt(flags);
-        mRemote.transact(IS_USER_RUNNING_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean result = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
-    public int[] getRunningUserIds() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_RUNNING_USER_IDS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int[] result = reply.createIntArray();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
-    public boolean removeTask(int taskId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        mRemote.transact(REMOVE_TASK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean result = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
-    public void registerProcessObserver(IProcessObserver observer) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(observer != null ? observer.asBinder() : null);
-        mRemote.transact(REGISTER_PROCESS_OBSERVER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void unregisterProcessObserver(IProcessObserver observer) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(observer != null ? observer.asBinder() : null);
-        mRemote.transact(UNREGISTER_PROCESS_OBSERVER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void registerUidObserver(IUidObserver observer, int which) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(observer != null ? observer.asBinder() : null);
-        data.writeInt(which);
-        mRemote.transact(REGISTER_UID_OBSERVER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void unregisterUidObserver(IUidObserver observer) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(observer != null ? observer.asBinder() : null);
-        mRemote.transact(UNREGISTER_UID_OBSERVER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(sender.asBinder());
-        mRemote.transact(IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public boolean isIntentSenderAnActivity(IIntentSender sender) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(sender.asBinder());
-        mRemote.transact(IS_INTENT_SENDER_AN_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(sender.asBinder());
-        mRemote.transact(GET_INTENT_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        Intent res = reply.readInt() != 0
-                ? Intent.CREATOR.createFromParcel(reply) : null;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public String getTagForIntentSender(IIntentSender sender, String prefix)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(sender.asBinder());
-        data.writeString(prefix);
-        mRemote.transact(GET_TAG_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        String res = reply.readString();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public void updatePersistentConfiguration(Configuration values) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        values.writeToParcel(data, 0);
-        mRemote.transact(UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public long[] getProcessPss(int[] pids) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeIntArray(pids);
-        mRemote.transact(GET_PROCESS_PSS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        long[] res = reply.createLongArray();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public void showBootMessage(CharSequence msg, boolean always) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        TextUtils.writeToParcel(msg, data, 0);
-        data.writeInt(always ? 1 : 0);
-        mRemote.transact(SHOW_BOOT_MESSAGE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void keyguardGoingAway(int flags)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(flags);
-        mRemote.transact(KEYGUARD_GOING_AWAY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public boolean shouldUpRecreateTask(IBinder token, String destAffinity)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeString(destAffinity);
-        mRemote.transact(SHOULD_UP_RECREATE_TASK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean result = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return result;
-    }
-
-    public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        target.writeToParcel(data, 0);
-        data.writeInt(resultCode);
-        if (resultData != null) {
-            data.writeInt(1);
-            resultData.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(NAVIGATE_UP_TO_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean result = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return result;
-    }
-
-    public int getLaunchedFromUid(IBinder activityToken) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(activityToken);
-        mRemote.transact(GET_LAUNCHED_FROM_UID_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return result;
-    }
-
-    public String getLaunchedFromPackage(IBinder activityToken) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(activityToken);
-        mRemote.transact(GET_LAUNCHED_FROM_PACKAGE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        String result = reply.readString();
-        data.recycle();
-        reply.recycle();
-        return result;
-    }
-
-    public void registerUserSwitchObserver(IUserSwitchObserver observer,
-            String name) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(observer != null ? observer.asBinder() : null);
-        data.writeString(name);
-        mRemote.transact(REGISTER_USER_SWITCH_OBSERVER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void unregisterUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(observer != null ? observer.asBinder() : null);
-        mRemote.transact(UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void requestBugReport(@ActivityManager.BugreportMode int bugreportType)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(bugreportType);
-        mRemote.transact(REQUEST_BUG_REPORT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(pid);
-        data.writeInt(aboveSystem ? 1 : 0);
-        data.writeString(reason);
-        mRemote.transact(INPUT_DISPATCHING_TIMED_OUT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        long res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public Bundle getAssistContextExtras(int requestType) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(requestType);
-        mRemote.transact(GET_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        Bundle res = reply.readBundle();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
-            Bundle receiverExtras,
-            IBinder activityToken, boolean focused, boolean newSessionId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(requestType);
-        data.writeStrongBinder(receiver.asBinder());
-        data.writeBundle(receiverExtras);
-        data.writeStrongBinder(activityToken);
-        data.writeInt(focused ? 1 : 0);
-        data.writeInt(newSessionId ? 1 : 0);
-        mRemote.transact(REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public void reportAssistContextExtras(IBinder token, Bundle extras, AssistStructure structure,
-            AssistContent content, Uri referrer) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeBundle(extras);
-        structure.writeToParcel(data, 0);
-        content.writeToParcel(data, 0);
-        if (referrer != null) {
-            data.writeInt(1);
-            referrer.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(REPORT_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
-            Bundle args) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        intent.writeToParcel(data, 0);
-        data.writeInt(requestType);
-        data.writeString(hint);
-        data.writeInt(userHandle);
-        data.writeBundle(args);
-        mRemote.transact(LAUNCH_ASSIST_INTENT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public boolean isAssistDataAllowedOnCurrentActivity() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public boolean showAssistFromActivity(IBinder token, Bundle args) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeBundle(args);
-        mRemote.transact(SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public void killUid(int appId, int userId, String reason) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(appId);
-        data.writeInt(userId);
-        data.writeString(reason);
-        mRemote.transact(KILL_UID_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void hang(IBinder who, boolean allowRestart) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(who);
-        data.writeInt(allowRestart ? 1 : 0);
-        mRemote.transact(HANG_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void reportActivityFullyDrawn(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(REPORT_ACTIVITY_FULLY_DRAWN_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void notifyActivityDrawn(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(NOTIFY_ACTIVITY_DRAWN_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void restart() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(RESTART_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void performIdleMaintenance() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(PERFORM_IDLE_MAINTENANCE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void sendIdleJobTrigger() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(SEND_IDLE_JOB_TRIGGER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public IActivityContainer createVirtualActivityContainer(IBinder parentActivityToken,
-            IActivityContainerCallback callback) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(parentActivityToken);
-        data.writeStrongBinder(callback == null ? null : callback.asBinder());
-        mRemote.transact(CREATE_VIRTUAL_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        final int result = reply.readInt();
-        final IActivityContainer res;
-        if (result == 1) {
-            res = IActivityContainer.Stub.asInterface(reply.readStrongBinder());
-        } else {
-            res = null;
-        }
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public boolean startBinderTracking() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(START_BINDER_TRACKING_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-
-    public boolean stopBinderTrackingAndDump(ParcelFileDescriptor fd) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        if (fd != null) {
-            data.writeInt(1);
-            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(STOP_BINDER_TRACKING_AND_DUMP_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean res = reply.readInt() != 0;
-        reply.recycle();
-        data.recycle();
-        return res;
-    }
-
-    public int setVrMode(IBinder token, boolean enabled, ComponentName packageName)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeInt(enabled ? 1 : 0);
-        packageName.writeToParcel(data, 0);
-        mRemote.transact(SET_VR_MODE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    public boolean isVrModePackageEnabled(ComponentName packageName)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        packageName.writeToParcel(data, 0);
-        mRemote.transact(IS_VR_PACKAGE_ENABLED_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res == 1;
-    }
-
-    @Override
-    public IActivityContainer createStackOnDisplay(int displayId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(displayId);
-        mRemote.transact(CREATE_STACK_ON_DISPLAY, data, reply, 0);
-        reply.readException();
-        final int result = reply.readInt();
-        final IActivityContainer res;
-        if (result == 1) {
-            res = IActivityContainer.Stub.asInterface(reply.readStrongBinder());
-        } else {
-            res = null;
-        }
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    @Override
-    public int getActivityDisplayId(IBinder activityToken)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(activityToken);
-        mRemote.transact(GET_ACTIVITY_DISPLAY_ID_TRANSACTION, data, reply, 0);
-        reply.readException();
-        final int displayId = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return displayId;
-    }
-
-    @Override
-    public void startLockTaskMode(int taskId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        mRemote.transact(START_LOCK_TASK_BY_TASK_ID_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void startLockTaskMode(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(START_LOCK_TASK_BY_TOKEN_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void startSystemLockTaskMode(int taskId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        mRemote.transact(START_SYSTEM_LOCK_TASK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void stopLockTaskMode() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(STOP_LOCK_TASK_MODE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void stopSystemLockTaskMode() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(STOP_SYSTEM_LOCK_TASK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public boolean isInLockTaskMode() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(IS_IN_LOCK_TASK_MODE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean isInLockTaskMode = reply.readInt() == 1;
-        data.recycle();
-        reply.recycle();
-        return isInLockTaskMode;
-    }
-
-    @Override
-    public int getLockTaskModeState() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(GET_LOCK_TASK_MODE_STATE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int lockTaskModeState = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return lockTaskModeState;
-    }
-
-    @Override
-    public void showLockTaskEscapeMessage(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION, data, reply,
-                IBinder.FLAG_ONEWAY);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        values.writeToParcel(data, 0);
-        mRemote.transact(SET_TASK_DESCRIPTION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void setTaskResizeable(int taskId, int resizeableMode) throws  RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        data.writeInt(resizeableMode);
-        mRemote.transact(SET_TASK_RESIZEABLE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void resizeTask(int taskId, Rect r, int resizeMode) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        data.writeInt(resizeMode);
-        r.writeToParcel(data, 0);
-        mRemote.transact(RESIZE_TASK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public Rect getTaskBounds(int taskId) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(taskId);
-        mRemote.transact(GET_TASK_BOUNDS_TRANSACTION, data, reply, 0);
-        reply.readException();
-        Rect rect = Rect.CREATOR.createFromParcel(reply);
-        data.recycle();
-        reply.recycle();
-        return rect;
-    }
-
-    @Override
-    public Bitmap getTaskDescriptionIcon(String filename, int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(filename);
-        data.writeInt(userId);
-        mRemote.transact(GET_TASK_DESCRIPTION_ICON_TRANSACTION, data, reply, 0);
-        reply.readException();
-        final Bitmap icon = reply.readInt() == 0 ? null : Bitmap.CREATOR.createFromParcel(reply);
-        data.recycle();
-        reply.recycle();
-        return icon;
-    }
-
-    @Override
-    public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions options)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        if (options == null) {
-            data.writeInt(0);
-        } else {
-            data.writeInt(1);
-            data.writeBundle(options.toBundle());
-        }
-        mRemote.transact(START_IN_PLACE_ANIMATION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public boolean requestVisibleBehind(IBinder token, boolean visible) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        data.writeInt(visible ? 1 : 0);
-        mRemote.transact(REQUEST_VISIBLE_BEHIND_TRANSACTION, data, reply, 0);
-        reply.readException();
-        boolean success = reply.readInt() > 0;
-        data.recycle();
-        reply.recycle();
-        return success;
-    }
-
-    @Override
-    public boolean isBackgroundVisibleBehind(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(IS_BACKGROUND_VISIBLE_BEHIND_TRANSACTION, data, reply, 0);
-        reply.readException();
-        final boolean visible = reply.readInt() > 0;
-        data.recycle();
-        reply.recycle();
-        return visible;
-    }
-
-    @Override
-    public void backgroundResourcesReleased(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(BACKGROUND_RESOURCES_RELEASED_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void notifyEnterAnimationComplete(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void bootAnimationComplete() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(BOOT_ANIMATION_COMPLETE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(uid);
-        data.writeByteArray(firstPacket);
-        mRemote.transact(NOTIFY_CLEARTEXT_NETWORK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize,
-            String reportPackage) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(processName);
-        data.writeInt(uid);
-        data.writeLong(maxMemSize);
-        data.writeString(reportPackage);
-        mRemote.transact(SET_DUMP_HEAP_DEBUG_LIMIT_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void dumpHeapFinished(String path) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(path);
-        mRemote.transact(DUMP_HEAP_FINISHED_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(session.asBinder());
-        data.writeInt(keepAwake ? 1 : 0);
-        mRemote.transact(SET_VOICE_KEEP_AWAKE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(userId);
-        data.writeStringArray(packages);
-        mRemote.transact(UPDATE_LOCK_TASK_PACKAGES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void updateDeviceOwner(String packageName) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        mRemote.transact(UPDATE_DEVICE_OWNER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public int getPackageProcessState(String packageName, String callingPackage)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(packageName);
-        data.writeString(callingPackage);
-        mRemote.transact(GET_PACKAGE_PROCESS_STATE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    @Override
-    public boolean setProcessMemoryTrimLevel(String process, int userId, int level)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeString(process);
-        data.writeInt(userId);
-        data.writeInt(level);
-        mRemote.transact(SET_PROCESS_MEMORY_TRIM_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res != 0;
-    }
-
-    @Override
-    public boolean isRootVoiceInteraction(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(IS_ROOT_VOICE_INTERACTION_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res != 0;
-    }
-
-    @Override
-    public void exitFreeformMode(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(EXIT_FREEFORM_MODE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public int getActivityStackId(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(GET_ACTIVITY_STACK_ID_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int stackId = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return stackId;
-    }
-
-    @Override
-    public void reportSizeConfigurations(IBinder token, int[] horizontalSizeConfiguration,
-            int[] verticalSizeConfigurations, int[] smallestSizeConfigurations)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        writeIntArray(horizontalSizeConfiguration, data);
-        writeIntArray(verticalSizeConfigurations, data);
-        writeIntArray(smallestSizeConfigurations, data);
-        mRemote.transact(REPORT_SIZE_CONFIGURATIONS, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    private static void writeIntArray(int[] array, Parcel data) {
-        if (array == null) {
-            data.writeInt(0);
-        } else {
-            data.writeInt(array.length);
-            data.writeIntArray(array);
-        }
-    }
-
-    @Override
-    public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(suppress ? 1 : 0);
-        mRemote.transact(SUPPRESS_RESIZE_CONFIG_CHANGES_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(fromStackId);
-        data.writeInt(onTop ? 1 : 0);
-        mRemote.transact(MOVE_TASKS_TO_FULLSCREEN_STACK_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public int getAppStartMode(int uid, String packageName) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(uid);
-        data.writeString(packageName);
-        mRemote.transact(GET_APP_START_MODE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    @Override
-    public boolean isInMultiWindowMode(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(IN_MULTI_WINDOW_TRANSACTION, data, reply, 0);
-        reply.readException();
-        final boolean multiWindowMode = reply.readInt() == 1 ? true : false;
-        data.recycle();
-        reply.recycle();
-        return multiWindowMode;
-    }
-
-    @Override
-    public boolean isInPictureInPictureMode(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(IN_PICTURE_IN_PICTURE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        final boolean pipMode = reply.readInt() == 1 ? true : false;
-        data.recycle();
-        reply.recycle();
-        return pipMode;
-    }
-
-    @Override
-    public void enterPictureInPictureMode(IBinder token) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        mRemote.transact(ENTER_PICTURE_IN_PICTURE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public boolean isAppForeground(int uid) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(uid);
-        mRemote.transact(IS_APP_FOREGROUND_TRANSACTION, data, reply, 0);
-        final boolean isForeground = reply.readInt() == 1 ? true : false;
-        data.recycle();
-        reply.recycle();
-        return isForeground;
-    };
-
-    @Override
-    public void notifyPinnedStackAnimationEnded() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(NOTIFY_PINNED_STACK_ANIMATION_ENDED_TRANSACTION, data, reply, 0);
-        data.recycle();
-        reply.recycle();
-    };
-
-    @Override
-    public void removeStack(int stackId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(stackId);
-        mRemote.transact(REMOVE_STACK, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void notifyLockedProfile(@UserIdInt int userId) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(userId);
-        mRemote.transact(NOTIFY_LOCKED_PROFILE, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public void startConfirmDeviceCredentialIntent(Intent intent) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        intent.writeToParcel(data, 0);
-        mRemote.transact(START_CONFIRM_DEVICE_CREDENTIAL_INTENT, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
-    public int sendIntentSender(IIntentSender target, int code, Intent intent, String resolvedType,
-            IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(target.asBinder());
-        data.writeInt(code);
-        if ((intent!=null)) {
-            data.writeInt(1);
-            intent.writeToParcel(data, 0);
-        }
-        else {
-            data.writeInt(0);
-        }
-        data.writeString(resolvedType);
-        data.writeStrongBinder((((finishedReceiver!=null))?(finishedReceiver.asBinder()):(null)));
-        data.writeString(requiredPermission);
-        if ((options!=null)) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        }
-        else {
-            data.writeInt(0);
-        }
-        mRemote.transact(SEND_INTENT_SENDER_TRANSACTION, data, reply, 0);
-        reply.readException();
-        final int res = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return res;
-    }
-
-    @Override
-    public void setVrThread(int tid)
-        throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(tid);
-        mRemote.transact(SET_VR_THREAD_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-        return;
-    }
-
-    public void setRenderThread(int tid)
-        throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(tid);
-        mRemote.transact(SET_RENDER_THREAD_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-        return;
-    }
-
-    public void setHasTopUi(boolean hasTopUi)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(hasTopUi ? 1 : 0);
-        mRemote.transact(SET_HAS_TOP_UI, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-        return;
-    }
-    @Override
-    public boolean canBypassWorkChallenge(PendingIntent intent)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        intent.writeToParcel(data, 0);
-        mRemote.transact(CAN_BYPASS_WORK_CHALLENGE, data, reply, 0);
-        reply.readException();
-        final int result = reply.readInt();
-        data.recycle();
-        reply.recycle();
-        return result != 0;
-    }
-
-    private IBinder mRemote;
-}
+}
\ No newline at end of file
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e9a200f..3e8d90b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -421,11 +421,10 @@
         final String[] mNames;
         final IContentProvider mProvider;
         final ContentProvider mLocalProvider;
-        final IActivityManager.ContentProviderHolder mHolder;
+        final ContentProviderHolder mHolder;
 
         ProviderClientRecord(String[] names, IContentProvider provider,
-                ContentProvider localProvider,
-                IActivityManager.ContentProviderHolder holder) {
+                ContentProvider localProvider, ContentProviderHolder holder) {
             mNames = names;
             mProvider = provider;
             mLocalProvider = localProvider;
@@ -3825,7 +3824,7 @@
     }
 
     private static final class ProviderRefCount {
-        public final IActivityManager.ContentProviderHolder holder;
+        public final ContentProviderHolder holder;
         public final ProviderClientRecord client;
         public int stableCount;
         public int unstableCount;
@@ -3837,7 +3836,7 @@
         // here.
         public boolean removePending;
 
-        ProviderRefCount(IActivityManager.ContentProviderHolder inHolder,
+        ProviderRefCount(ContentProviderHolder inHolder,
                 ProviderClientRecord inClient, int sCount, int uCount) {
             holder = inHolder;
             client = inClient;
@@ -5480,8 +5479,7 @@
 
     private void installContentProviders(
             Context context, List<ProviderInfo> providers) {
-        final ArrayList<IActivityManager.ContentProviderHolder> results =
-            new ArrayList<IActivityManager.ContentProviderHolder>();
+        final ArrayList<ContentProviderHolder> results = new ArrayList<>();
 
         for (ProviderInfo cpi : providers) {
             if (DEBUG_PROVIDER) {
@@ -5492,7 +5490,7 @@
                 buf.append(cpi.name);
                 Log.i(TAG, buf.toString());
             }
-            IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
+            ContentProviderHolder cph = installProvider(context, null, cpi,
                     false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
             if (cph != null) {
                 cph.noReleaseNeeded = true;
@@ -5521,7 +5519,7 @@
         // Note that we cannot hold the lock while acquiring and installing the
         // provider since it might take a long time to run and it could also potentially
         // be re-entrant in the case where the provider is in the same process.
-        IActivityManager.ContentProviderHolder holder = null;
+        ContentProviderHolder holder = null;
         try {
             holder = ActivityManagerNative.getDefault().getContentProvider(
                     getApplicationThread(), auth, userId, stable);
@@ -5821,7 +5819,7 @@
     }
 
     private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
-            ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {
+            ContentProvider localProvider, ContentProviderHolder holder) {
         final String auths[] = holder.info.authority.split(";");
         final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
 
@@ -5854,8 +5852,8 @@
      * and returns the existing provider.  This can happen due to concurrent
      * attempts to acquire the same provider.
      */
-    private IActivityManager.ContentProviderHolder installProvider(Context context,
-            IActivityManager.ContentProviderHolder holder, ProviderInfo info,
+    private ContentProviderHolder installProvider(Context context,
+            ContentProviderHolder holder, ProviderInfo info,
             boolean noisy, boolean noReleaseNeeded, boolean stable) {
         ContentProvider localProvider = null;
         IContentProvider provider;
@@ -5915,7 +5913,7 @@
                     + info.name);
         }
 
-        IActivityManager.ContentProviderHolder retHolder;
+        ContentProviderHolder retHolder;
 
         synchronized (mProviderMap) {
             if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
@@ -5931,7 +5929,7 @@
                     }
                     provider = pr.mProvider;
                 } else {
-                    holder = new IActivityManager.ContentProviderHolder(info);
+                    holder = new ContentProviderHolder(info);
                     holder.provider = provider;
                     holder.noReleaseNeeded = true;
                     pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index c075ed6..cada1b8 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -448,13 +448,6 @@
             mGuard.open("release");
         }
 
-        void attachToDisplay(int displayId) {
-            try {
-                mIActivityContainer.attachToDisplay(displayId);
-            } catch (RemoteException e) {
-            }
-        }
-
         void setSurface(Surface surface, int width, int height, int density)
                 throws RemoteException {
             mIActivityContainer.setSurface(surface, width, height, density);
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/core/java/android/app/ApplicationErrorReport.aidl
similarity index 71%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to core/java/android/app/ApplicationErrorReport.aidl
index 5f66d16..5b57457 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/core/java/android/app/ApplicationErrorReport.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * 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
+ *     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,
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.app;
 
-parcelable PublishConfig;
+/** @hide */
+parcelable ApplicationErrorReport.ParcelableCrashInfo;
\ No newline at end of file
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 9fa8a5d..6cfa362 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -451,6 +451,47 @@
     }
 
     /**
+     * Parcelable version of {@link CrashInfo}
+     *
+     * @hide
+     */
+    public static class ParcelableCrashInfo extends CrashInfo implements Parcelable {
+        /**
+         * Create an uninitialized instance of CrashInfo.
+         */
+        public ParcelableCrashInfo() {
+        }
+
+        /**
+         * Create an instance of CrashInfo initialized from an exception.
+         */
+        public ParcelableCrashInfo(Throwable tr) {
+            super(tr);
+        }
+
+        public ParcelableCrashInfo(Parcel in) {
+            super(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public static final Parcelable.Creator<ParcelableCrashInfo> CREATOR =
+                new Parcelable.Creator<ParcelableCrashInfo>() {
+                    @Override
+                    public ParcelableCrashInfo createFromParcel(Parcel in) {
+                        return new ParcelableCrashInfo(in);
+                    }
+
+                    @Override
+                    public ParcelableCrashInfo[] newArray(int size) {
+                        return new ParcelableCrashInfo[size];
+                    }
+                };
+    }
+
+    /**
      * Describes an application not responding error.
      */
     public static class AnrInfo {
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/core/java/android/app/ContentProviderHolder.aidl
similarity index 89%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to core/java/android/app/ContentProviderHolder.aidl
index 5f66d16..bd56775 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/core/java/android/app/ContentProviderHolder.aidl
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.app;
 
-parcelable PublishConfig;
+/** @hide */
+parcelable ContentProviderHolder;
\ No newline at end of file
diff --git a/core/java/android/app/ContentProviderHolder.java b/core/java/android/app/ContentProviderHolder.java
new file mode 100644
index 0000000..f9998f4
--- /dev/null
+++ b/core/java/android/app/ContentProviderHolder.java
@@ -0,0 +1,78 @@
+/*
+ * 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.ContentProviderNative;
+import android.content.IContentProvider;
+import android.content.pm.ProviderInfo;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Information you can retrieve about a particular application.
+ *
+ * @hide
+ */
+public class ContentProviderHolder implements Parcelable {
+    public final ProviderInfo info;
+    public IContentProvider provider;
+    public IBinder connection;
+    public boolean noReleaseNeeded;
+
+    public ContentProviderHolder(ProviderInfo _info) {
+        info = _info;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        info.writeToParcel(dest, 0);
+        if (provider != null) {
+            dest.writeStrongBinder(provider.asBinder());
+        } else {
+            dest.writeStrongBinder(null);
+        }
+        dest.writeStrongBinder(connection);
+        dest.writeInt(noReleaseNeeded ? 1 : 0);
+    }
+
+    public static final Parcelable.Creator<ContentProviderHolder> CREATOR
+            = new Parcelable.Creator<ContentProviderHolder>() {
+        @Override
+        public ContentProviderHolder createFromParcel(Parcel source) {
+            return new ContentProviderHolder(source);
+        }
+
+        @Override
+        public ContentProviderHolder[] newArray(int size) {
+            return new ContentProviderHolder[size];
+        }
+    };
+
+    private ContentProviderHolder(Parcel source) {
+        info = ProviderInfo.CREATOR.createFromParcel(source);
+        provider = ContentProviderNative.asInterface(
+                source.readStrongBinder());
+        connection = source.readStrongBinder();
+        noReleaseNeeded = source.readInt() != 0;
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl
index 170aff3..1ff3c87 100644
--- a/core/java/android/app/IActivityContainer.aidl
+++ b/core/java/android/app/IActivityContainer.aidl
@@ -25,7 +25,7 @@
 
 /** @hide */
 interface IActivityContainer {
-    void attachToDisplay(int displayId);
+    void addToDisplay(int displayId);
     void setSurface(in Surface surface, int width, int height, int density);
     int startActivity(in Intent intent);
     int startActivityIntentSender(in IIntentSender intentSender);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
new file mode 100644
index 0000000..92d67b7
--- /dev/null
+++ b/core/java/android/app/IActivityManager.aidl
@@ -0,0 +1,567 @@
+/*
+ * 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.app.ActivityManager;
+import android.app.ApplicationErrorReport;
+import android.app.ContentProviderHolder;
+import android.app.IApplicationThread;
+import android.app.IActivityContainer;
+import android.app.IActivityContainerCallback;
+import android.app.IActivityController;
+import android.app.IAppTask;
+import android.app.IInstrumentationWatcher;
+import android.app.IProcessObserver;
+import android.app.IServiceConnection;
+import android.app.IStopUserCallback;
+import android.app.ITaskStackListener;
+import android.app.IUiAutomationConnection;
+import android.app.IUidObserver;
+import android.app.IUserSwitchObserver;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.ProfilerInfo;
+import android.app.WaitResult;
+import android.app.assist.AssistContent;
+import android.app.assist.AssistStructure;
+import android.content.ComponentName;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.IPackageDataObserver;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ProviderInfo;
+import android.content.pm.UserInfo;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.IBinder;
+import android.os.IProgressListener;
+import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
+import android.os.StrictMode;
+import android.service.voice.IVoiceInteractionSession;
+import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.os.IResultReceiver;
+
+import java.util.List;
+
+/**
+ * System private API for talking with the activity manager service.  This
+ * provides calls from the application back to the activity manager.
+ *
+ * {@hide}
+ */
+interface IActivityManager {
+    // Please keep these transaction codes the same -- they are also
+    // sent by C++ code. when a new method is added, use the next available transaction id.
+
+    // Special low-level communication with activity manager.
+    void handleApplicationCrash(in IBinder app,
+            in ApplicationErrorReport.ParcelableCrashInfo crashInfo) = 1;
+    int startActivity(in IApplicationThread caller, in String callingPackage, in Intent intent,
+            in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode,
+            int flags, in ProfilerInfo profilerInfo, in Bundle options) = 2;
+    void unhandledBack() = 3;
+    ParcelFileDescriptor openContentUri(in String uriString) = 4;
+
+    boolean finishActivity(in IBinder token, int code, in Intent data, int finishTask) = 10;
+    Intent registerReceiver(in IApplicationThread caller, in String callerPackage,
+            in IIntentReceiver receiver, in IntentFilter filter,
+            in String requiredPermission, int userId) = 11;
+    void unregisterReceiver(in IIntentReceiver receiver) = 12;
+    int broadcastIntent(in IApplicationThread caller, in Intent intent,
+            in String resolvedType, in IIntentReceiver resultTo, int resultCode,
+            in String resultData, in Bundle map, in String[] requiredPermissions,
+            int appOp, in Bundle options, boolean serialized, boolean sticky, int userId) = 13;
+    void unbroadcastIntent(in IApplicationThread caller, in Intent intent, int userId) = 14;
+    oneway void finishReceiver(in IBinder who, int resultCode, in String resultData, in Bundle map,
+            boolean abortBroadcast, int flags) = 15;
+    void attachApplication(in IApplicationThread app) = 16;
+    oneway void activityIdle(in IBinder token, in Configuration config,
+            in boolean stopProfiling) = 17;
+    void activityPaused(in IBinder token) = 18;
+    oneway void activityStopped(in IBinder token, in Bundle state,
+            in PersistableBundle persistentState, in CharSequence description) = 19;
+    String getCallingPackage(in IBinder token) = 20;
+    ComponentName getCallingActivity(in IBinder token) = 21;
+    List<ActivityManager.RunningTaskInfo> getTasks(int maxNum, int flags) = 22;
+    void moveTaskToFront(int task, int flags, in Bundle options) = 23;
+    void moveTaskBackwards(int task) = 25;
+    int getTaskForActivity(in IBinder token, in boolean onlyRoot) = 26;
+    ContentProviderHolder getContentProvider(in IApplicationThread caller,
+            in String name, int userId, boolean stable) = 28;
+    void publishContentProviders(in IApplicationThread caller,
+            in List<ContentProviderHolder> providers) = 29;
+    boolean refContentProvider(in IBinder connection, int stableDelta, int unstableDelta) = 30;
+    void finishSubActivity(in IBinder token, in String resultWho, int requestCode) = 31;
+    PendingIntent getRunningServiceControlPanel(in ComponentName service) = 32;
+    ComponentName startService(in IApplicationThread caller, in Intent service,
+            in String resolvedType, in String callingPackage, int userId) = 33;
+    int stopService(in IApplicationThread caller, in Intent service,
+            in String resolvedType, int userId) = 34;
+    int bindService(in IApplicationThread caller, in IBinder token, in Intent service,
+            in String resolvedType, in IServiceConnection connection, int flags,
+            in String callingPackage, int userId) = 35;
+    boolean unbindService(in IServiceConnection connection) = 36;
+    void publishService(in IBinder token, in Intent intent, in IBinder service) = 37;
+    void activityResumed(in IBinder token) = 38;
+    void setDebugApp(in String packageName, boolean waitForDebugger, boolean persistent) = 41;
+    void setAlwaysFinish(boolean enabled) = 42;
+    boolean startInstrumentation(in ComponentName className, in String profileFile,
+            int flags, in Bundle arguments, in IInstrumentationWatcher watcher,
+            in IUiAutomationConnection connection, int userId,
+            in String abiOverride) = 43;
+    void finishInstrumentation(in IApplicationThread target, int resultCode,
+            in Bundle results) = 44;
+    /**
+     * @return A copy of global {@link Configuration}, contains general settings for the entire
+     *         system. Corresponds to the configuration of the default display.
+     * @throws RemoteException
+     */
+    Configuration getConfiguration() = 45;
+    /**
+     * Updates global configuration and applies changes to the entire system.
+     * @param values Update values for global configuration. If null is passed it will request the
+     *               Window Manager to compute new config for the default display.
+     * @throws RemoteException
+     * @return Returns true if the configuration was updated.
+     */
+    boolean updateConfiguration(in Configuration values) = 46;
+    boolean stopServiceToken(in ComponentName className, in IBinder token, int startId) = 47;
+    ComponentName getActivityClassForToken(in IBinder token) = 48;
+    String getPackageForToken(in IBinder token) = 49;
+    void setProcessLimit(int max) = 50;
+    int getProcessLimit() = 51;
+    int checkPermission(in String permission, int pid, int uid) = 52;
+    int checkUriPermission(in Uri uri, int pid, int uid, int mode, int userId,
+            in IBinder callerToken) = 53;
+    void grantUriPermission(in IApplicationThread caller, in String targetPkg, in Uri uri,
+            int mode, int userId) = 54;
+    void revokeUriPermission(in IApplicationThread caller, in Uri uri, int mode, int userId) = 55;
+    void setActivityController(in IActivityController watcher, boolean imAMonkey) = 56;
+    void showWaitingForDebugger(in IApplicationThread who, boolean waiting) = 57;
+    /*
+     * This will deliver the specified signal to all the persistent processes. Currently only
+     * SIGUSR1 is delivered. All others are ignored.
+     */
+    void signalPersistentProcesses(int signal) = 58;
+    ParceledListSlice getRecentTasks(int maxNum,
+            int flags, int userId) = 59;
+    oneway void serviceDoneExecuting(in IBinder token, int type, int startId, int res) = 60;
+    oneway void activityDestroyed(in IBinder token) = 61;
+    IIntentSender getIntentSender(int type, in String packageName, in IBinder token,
+            in String resultWho, int requestCode, in Intent[] intents, in String[] resolvedTypes,
+            int flags, in Bundle options, int userId) = 62;
+    void cancelIntentSender(in IIntentSender sender) = 63;
+    String getPackageForIntentSender(in IIntentSender sender) = 64;
+    void enterSafeMode() = 65;
+    boolean startNextMatchingActivity(in IBinder callingActivity,
+            in Intent intent, in Bundle options) = 66;
+    void noteWakeupAlarm(in IIntentSender sender, int sourceUid,
+            in String sourcePkg, in String tag) = 67;
+    void removeContentProvider(in IBinder connection, boolean stable) = 68;
+    void setRequestedOrientation(in IBinder token, int requestedOrientation) = 69;
+    int getRequestedOrientation(in IBinder token) = 70;
+    void unbindFinished(in IBinder token, in Intent service, boolean doRebind) = 71;
+    void setProcessForeground(in IBinder token, int pid, boolean isForeground) = 72;
+    void setServiceForeground(in ComponentName className, in IBinder token,
+            int id, in Notification notification, int flags) = 73;
+    boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot) = 74;
+    void getMemoryInfo(out ActivityManager.MemoryInfo outInfo) = 75;
+    List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() = 76;
+    boolean clearApplicationUserData(in String packageName,
+            in IPackageDataObserver observer, int userId) = 77;
+    void forceStopPackage(in String packageName, int userId) = 78;
+    boolean killPids(in int[] pids, in String reason, boolean secure) = 79;
+    List<ActivityManager.RunningServiceInfo> getServices(int maxNum, int flags) = 80;
+    ActivityManager.TaskThumbnail getTaskThumbnail(int taskId) = 81;
+    // Retrieve running application processes in the system
+    List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() = 82;
+    // Get device configuration
+    ConfigurationInfo getDeviceConfigurationInfo() = 83;
+    IBinder peekService(in Intent service, in String resolvedType, in String callingPackage) = 84;
+    // Turn on/off profiling in a particular process.
+    boolean profileControl(in String process, int userId, boolean start,
+            in ProfilerInfo profilerInfo, int profileType) = 85;
+    boolean shutdown(int timeout) = 86;
+    void stopAppSwitches() = 87;
+    void resumeAppSwitches() = 88;
+    boolean bindBackupAgent(in String packageName, int backupRestoreMode, int userId) = 89;
+    void backupAgentCreated(in String packageName, in IBinder agent) = 90;
+    void unbindBackupAgent(in ApplicationInfo appInfo) = 91;
+    int getUidForIntentSender(in IIntentSender sender) = 92;
+    int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
+            boolean requireFull, in String name, in String callerPackage) = 93;
+    void addPackageDependency(in String packageName) = 94;
+    void killApplication(in String pkg, int appId, int userId, in String reason) = 95;
+    void closeSystemDialogs(in String reason) = 96;
+    Debug.MemoryInfo[] getProcessMemoryInfo(in int[] pids) = 97;
+    void killApplicationProcess(in String processName, int uid) = 98;
+    int startActivityIntentSender(in IApplicationThread caller,
+            in IntentSender intent, in Intent fillInIntent, in String resolvedType,
+            in IBinder resultTo, in String resultWho, int requestCode,
+            int flagsMask, int flagsValues, in Bundle options) = 99;
+    void overridePendingTransition(in IBinder token, in String packageName,
+            int enterAnim, int exitAnim) = 100;
+    // Special low-level communication with activity manager.
+    boolean handleApplicationWtf(in IBinder app, in String tag, boolean system,
+            in ApplicationErrorReport.ParcelableCrashInfo crashInfo) = 101;
+    void killBackgroundProcesses(in String packageName, int userId) = 102;
+    boolean isUserAMonkey() = 103;
+    WaitResult startActivityAndWait(in IApplicationThread caller, in String callingPackage,
+            in Intent intent, in String resolvedType, in IBinder resultTo, in String resultWho,
+            int requestCode, int flags, in ProfilerInfo profilerInfo, in Bundle options,
+            int userId) = 104;
+    boolean willActivityBeVisible(in IBinder token) = 105;
+    int startActivityWithConfig(in IApplicationThread caller, in String callingPackage,
+            in Intent intent, in String resolvedType, in IBinder resultTo, in String resultWho,
+            int requestCode, int startFlags, in Configuration newConfig,
+            in Bundle options, int userId) = 106;
+    // Retrieve info of applications installed on external media that are currently
+    // running.
+    List<ApplicationInfo> getRunningExternalApplications() = 107;
+    void finishHeavyWeightApp() = 108;
+    // A StrictMode violation to be handled.  The violationMask is a
+    // subset of the original StrictMode policy bitmask, with only the
+    // bit violated and penalty bits to be executed by the
+    // ActivityManagerService remaining set.
+    void handleApplicationStrictModeViolation(in IBinder app, int violationMask,
+            in StrictMode.ViolationInfo crashInfo) = 109;
+    boolean isImmersive(in IBinder token) = 110;
+    void setImmersive(in IBinder token, boolean immersive) = 111;
+    boolean isTopActivityImmersive() = 112;
+    void crashApplication(int uid, int initialPid, in String packageName, in String message) = 113;
+    String getProviderMimeType(in Uri uri, int userId) = 114;
+    IBinder newUriPermissionOwner(in String name) = 115;
+    void grantUriPermissionFromOwner(in IBinder owner, int fromUid, in String targetPkg,
+            in Uri uri, int mode, int sourceUserId, int targetUserId) = 116;
+    void revokeUriPermissionFromOwner(in IBinder owner, in Uri uri, int mode, int userId) = 117;
+    int checkGrantUriPermission(int callingUid, in String targetPkg, in Uri uri,
+            int modeFlags, int userId) = 118;
+    // Cause the specified process to dump the specified heap.
+    boolean dumpHeap(in String process, int userId, boolean managed, in String path,
+            in ParcelFileDescriptor fd) = 119;
+    int startActivities(in IApplicationThread caller, in String callingPackage,
+            in Intent[] intents, in String[] resolvedTypes, in IBinder resultTo,
+            in Bundle options, int userId) = 120;
+    boolean isUserRunning(int userid, int flags) = 121;
+    oneway void activitySlept(in IBinder token) = 122;
+    int getFrontActivityScreenCompatMode() = 123;
+    void setFrontActivityScreenCompatMode(int mode) = 124;
+    int getPackageScreenCompatMode(in String packageName) = 125;
+    void setPackageScreenCompatMode(in String packageName, int mode) = 126;
+    boolean getPackageAskScreenCompat(in String packageName) = 127;
+    void setPackageAskScreenCompat(in String packageName, boolean ask) = 128;
+    boolean switchUser(int userid) = 129;
+    void setFocusedTask(int taskId) = 130;
+    boolean removeTask(int taskId) = 131;
+    void registerProcessObserver(in IProcessObserver observer) = 132;
+    void unregisterProcessObserver(in IProcessObserver observer) = 133;
+    boolean isIntentSenderTargetedToPackage(in IIntentSender sender) = 134;
+    void updatePersistentConfiguration(in Configuration values) = 135;
+    long[] getProcessPss(in int[] pids) = 136;
+    void showBootMessage(in CharSequence msg, boolean always) = 137;
+    void killAllBackgroundProcesses() = 139;
+    ContentProviderHolder getContentProviderExternal(in String name, int userId,
+            in IBinder token) = 140;
+    void removeContentProviderExternal(in String name, in IBinder token) = 141;
+    // Get memory information about the calling process.
+    void getMyMemoryState(out ActivityManager.RunningAppProcessInfo outInfo) = 142;
+    boolean killProcessesBelowForeground(in String reason) = 143;
+    UserInfo getCurrentUser() = 144;
+    boolean shouldUpRecreateTask(in IBinder token, in String destAffinity) = 145;
+    boolean navigateUpTo(in IBinder token, in Intent target, int resultCode,
+            in Intent resultData) = 146;
+    void setLockScreenShown(boolean showing) = 147;
+    boolean finishActivityAffinity(in IBinder token) = 148;
+    // This is not public because you need to be very careful in how you
+    // manage your activity to make sure it is always the uid you expect.
+    int getLaunchedFromUid(in IBinder activityToken) = 149;
+    void unstableProviderDied(in IBinder connection) = 150;
+    boolean isIntentSenderAnActivity(in IIntentSender sender) = 151;
+    int startActivityAsUser(in IApplicationThread caller, in String callingPackage,
+            in Intent intent, in String resolvedType, in IBinder resultTo, in String resultWho,
+            int requestCode, int flags, in ProfilerInfo profilerInfo,
+            in Bundle options, int userId) = 152;
+    int stopUser(int userid, boolean force, in IStopUserCallback callback) = 153;
+    void registerUserSwitchObserver(in IUserSwitchObserver observer, in String name) = 154;
+    void unregisterUserSwitchObserver(in IUserSwitchObserver observer) = 155;
+    int[] getRunningUserIds() = 156;
+    void requestBugReport(int bugreportType) = 157;
+    long inputDispatchingTimedOut(int pid, boolean aboveSystem, in String reason) = 158;
+    void clearPendingBackup() = 159;
+    Intent getIntentForIntentSender(in IIntentSender sender) = 160;
+    Bundle getAssistContextExtras(int requestType) = 161;
+    void reportAssistContextExtras(in IBinder token, in Bundle extras,
+            in AssistStructure structure, in AssistContent content, in Uri referrer) = 162;
+    // This is not public because you need to be very careful in how you
+    // manage your activity to make sure it is always the uid you expect.
+    String getLaunchedFromPackage(in IBinder activityToken) = 163;
+    void killUid(int appId, int userId, in String reason) = 164;
+    void setUserIsMonkey(boolean monkey) = 165;
+    void hang(in IBinder who, boolean allowRestart) = 166;
+    IActivityContainer createVirtualActivityContainer(in IBinder parentActivityToken,
+            in IActivityContainerCallback callback) = 167;
+    void moveTaskToStack(int taskId, int stackId, boolean toTop) = 168;
+    /**
+     * Resizes the input stack id to the given bounds.
+     *
+     * @param stackId Id of the stack to resize.
+     * @param bounds Bounds to resize the stack to or {@code null} for fullscreen.
+     * @param allowResizeInDockedMode True if the resize should be allowed when the docked stack is
+     *                                active.
+     * @param preserveWindows True if the windows of activities contained in the stack should be
+     *                        preserved.
+     * @param animate True if the stack resize should be animated.
+     * @param animationDuration The duration of the resize animation in milliseconds or -1 if the
+     *                          default animation duration should be used.
+     * @throws RemoteException
+     */
+    void resizeStack(int stackId, in Rect bounds, boolean allowResizeInDockedMode,
+            boolean preserveWindows, boolean animate, int animationDuration) = 169;
+    List<ActivityManager.StackInfo> getAllStackInfos() = 170;
+    void setFocusedStack(int stackId) = 171;
+    ActivityManager.StackInfo getStackInfo(int stackId) = 172;
+    boolean convertFromTranslucent(in IBinder token) = 173;
+    boolean convertToTranslucent(in IBinder token, in Bundle options) = 174;
+    void notifyActivityDrawn(in IBinder token) = 175;
+    void reportActivityFullyDrawn(in IBinder token) = 176;
+    void restart() = 177;
+    void performIdleMaintenance() = 178;
+    void takePersistableUriPermission(in Uri uri, int modeFlags, int userId) = 179;
+    void releasePersistableUriPermission(in Uri uri, int modeFlags, int userId) = 180;
+    ParceledListSlice getPersistedUriPermissions(in String packageName, boolean incoming) = 181;
+    void appNotRespondingViaProvider(in IBinder connection) = 182;
+    Rect getTaskBounds(int taskId) = 183;
+    int getActivityDisplayId(in IBinder activityToken) = 184;
+    boolean setProcessMemoryTrimLevel(in String process, int uid, int level) = 186;
+
+
+    // Start of L transactions
+    String getTagForIntentSender(in IIntentSender sender, in String prefix) = 210;
+    boolean startUserInBackground(int userid) = 211;
+    boolean isInHomeStack(int taskId) = 212;
+    void startLockTaskModeById(int taskId) = 213;
+    void startLockTaskModeByToken(in IBinder token) = 214;
+    void stopLockTaskMode() = 215;
+    boolean isInLockTaskMode() = 216;
+    void setTaskDescription(in IBinder token, in ActivityManager.TaskDescription values) = 217;
+    int startVoiceActivity(in String callingPackage, int callingPid, int callingUid,
+            in Intent intent, in String resolvedType, in IVoiceInteractionSession session,
+            in IVoiceInteractor interactor, int flags, in ProfilerInfo profilerInfo,
+            in Bundle options, int userId) = 218;
+    Bundle getActivityOptions(in IBinder token) = 219;
+    List<IBinder> getAppTasks(in String callingPackage) = 220;
+    void startSystemLockTaskMode(int taskId) = 221;
+    void stopSystemLockTaskMode() = 222;
+    void finishVoiceTask(in IVoiceInteractionSession session) = 223;
+    boolean isTopOfTask(in IBinder token) = 224;
+    boolean requestVisibleBehind(in IBinder token, boolean visible) = 225;
+    boolean isBackgroundVisibleBehind(in IBinder token) = 226;
+    void backgroundResourcesReleased(in IBinder token) = 227;
+    void notifyLaunchTaskBehindComplete(in IBinder token) = 228;
+    int startActivityFromRecents(int taskId, in Bundle options) = 229;
+    void notifyEnterAnimationComplete(in IBinder token) = 230;
+    int startActivityAsCaller(in IApplicationThread caller, in String callingPackage,
+            in Intent intent, in String resolvedType, in IBinder resultTo, in String resultWho,
+            int requestCode, int flags, in ProfilerInfo profilerInfo, in Bundle options,
+            boolean ignoreTargetSecurity, int userId) = 232;
+    int addAppTask(in IBinder activityToken, in Intent intent,
+            in ActivityManager.TaskDescription description, in Bitmap thumbnail) = 233;
+    Point getAppTaskThumbnailSize() = 234;
+    boolean releaseActivityInstance(in IBinder token) = 235;
+    void releaseSomeActivities(in IApplicationThread app) = 236;
+    void bootAnimationComplete() = 237;
+    Bitmap getTaskDescriptionIcon(in String filename, int userId) = 238;
+    boolean launchAssistIntent(in Intent intent, int requestType, in String hint, int userHandle,
+            in Bundle args) = 239;
+    void startInPlaceAnimationOnFrontMostApplication(in Bundle opts) = 240;
+    int checkPermissionWithToken(in String permission, int pid, int uid,
+            in IBinder callerToken) = 241;
+    void registerTaskStackListener(in ITaskStackListener listener) = 242;
+
+
+    // Start of M transactions
+    void notifyCleartextNetwork(int uid, in byte[] firstPacket) = 280;
+    IActivityContainer createStackOnDisplay(int displayId) = 281;
+    int getFocusedStackId() = 282;
+    void setTaskResizeable(int taskId, int resizeableMode) = 283;
+    boolean requestAssistContextExtras(int requestType, in IResultReceiver receiver,
+            in Bundle receiverExtras, in IBinder activityToken,
+            boolean focused, boolean newSessionId) = 284;
+    void resizeTask(int taskId, in Rect bounds, int resizeMode) = 285;
+    int getLockTaskModeState() = 286;
+    void setDumpHeapDebugLimit(in String processName, int uid, long maxMemSize,
+            in String reportPackage) = 287;
+    void dumpHeapFinished(in String path) = 288;
+    void setVoiceKeepAwake(in IVoiceInteractionSession session, boolean keepAwake) = 289;
+    void updateLockTaskPackages(int userId, in String[] packages) = 290;
+    void noteAlarmStart(in IIntentSender sender, int sourceUid, in String tag) = 291;
+    void noteAlarmFinish(in IIntentSender sender, int sourceUid, in String tag) = 292;
+    int getPackageProcessState(in String packageName, in String callingPackage) = 293;
+    oneway void showLockTaskEscapeMessage(in IBinder token) = 294;
+    void updateDeviceOwner(in String packageName) = 295;
+    /**
+     * Notify the system that the keyguard is going away.
+     *
+     * @param flags See {@link android.view.WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
+     *              etc.
+     */
+    void keyguardGoingAway(int flags) = 296;
+    void registerUidObserver(in IUidObserver observer, int which, String callingPackage) = 297;
+    void unregisterUidObserver(in IUidObserver observer) = 298;
+    boolean isAssistDataAllowedOnCurrentActivity() = 299;
+    boolean showAssistFromActivity(in IBinder token, in Bundle args) = 300;
+    boolean isRootVoiceInteraction(in IBinder token) = 301;
+
+
+    // Start of N transactions
+    // Start Binder transaction tracking for all applications.
+    boolean startBinderTracking() = 340;
+    // Stop Binder transaction tracking for all applications and dump trace data to the given file
+    // descriptor.
+    boolean stopBinderTrackingAndDump(in ParcelFileDescriptor fd) = 341;
+    void positionTaskInStack(int taskId, int stackId, int position) = 342;
+    int getActivityStackId(in IBinder token) = 343;
+    void exitFreeformMode(in IBinder token) = 344;
+    void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration,
+            in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations) = 345;
+    boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
+            in Rect initialBounds, boolean moveHomeStackFront) = 346;
+    void suppressResizeConfigChanges(boolean suppress) = 347;
+    void moveTasksToFullscreenStack(int fromStackId, boolean onTop) = 348;
+    boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds) = 349;
+    int getAppStartMode(int uid, in String packageName) = 350;
+    boolean unlockUser(int userid, in byte[] token, in byte[] secret,
+            in IProgressListener listener) = 351;
+    boolean isInMultiWindowMode(in IBinder token) = 352;
+    boolean isInPictureInPictureMode(in IBinder token) = 353;
+    void killPackageDependents(in String packageName, int userId) = 354;
+    void enterPictureInPictureMode(in IBinder token) = 355;
+    void activityRelaunched(in IBinder token) = 356;
+    IBinder getUriPermissionOwnerForActivity(in IBinder activityToken) = 357;
+    /**
+     * Resizes the docked stack, and all other stacks as the result of the dock stack bounds change.
+     *
+     * @param dockedBounds The bounds for the docked stack.
+     * @param tempDockedTaskBounds The temporary bounds for the tasks in the docked stack, which
+     *                             might be different from the stack bounds to allow more
+     *                             flexibility while resizing, or {@code null} if they should be the
+     *                             same as the stack bounds.
+     * @param tempDockedTaskInsetBounds The temporary bounds for the tasks to calculate the insets.
+     *                                  When resizing, we usually "freeze" the layout of a task. To
+     *                                  achieve that, we also need to "freeze" the insets, which
+     *                                  gets achieved by changing task bounds but not bounds used
+     *                                  to calculate the insets in this transient state
+     * @param tempOtherTaskBounds The temporary bounds for the tasks in all other stacks, or
+     *                            {@code null} if they should be the same as the stack bounds.
+     * @param tempOtherTaskInsetBounds Like {@code tempDockedTaskInsetBounds}, but for the other
+     *                                 stacks.
+     * @throws RemoteException
+     */
+    void resizeDockedStack(in Rect dockedBounds, in Rect tempDockedTaskBounds,
+            in Rect tempDockedTaskInsetBounds,
+            in Rect tempOtherTaskBounds, in Rect tempOtherTaskInsetBounds) = 358;
+    int setVrMode(in IBinder token, boolean enabled, in ComponentName packageName) = 359;
+    // Gets the URI permissions granted to an arbitrary package.
+    // NOTE: this is different from getPersistedUriPermissions(), which returns the URIs the package
+    // granted to another packages (instead of those granted to it).
+    ParceledListSlice getGrantedUriPermissions(in String packageName, int userId) = 360;
+    // Clears the URI permissions granted to an arbitrary package.
+    void clearGrantedUriPermissions(in String packageName, int userId) = 361;
+    boolean isAppForeground(int uid) = 362;
+    void startLocalVoiceInteraction(in IBinder token, in Bundle options) = 363;
+    void stopLocalVoiceInteraction(in IBinder token) = 364;
+    boolean supportsLocalVoiceInteraction() = 365;
+    void notifyPinnedStackAnimationEnded() = 366;
+    void removeStack(int stackId) = 367;
+    void setLenientBackgroundCheck(boolean enabled) = 368;
+    int getMemoryTrimLevel() = 369;
+    /**
+     * Resizes the pinned stack.
+     *
+     * @param pinnedBounds The bounds for the pinned stack.
+     * @param tempPinnedTaskBounds The temporary bounds for the tasks in the pinned stack, which
+     *                             might be different from the stack bounds to allow more
+     *                             flexibility while resizing, or {@code null} if they should be the
+     *                             same as the stack bounds.
+     */
+    void resizePinnedStack(in Rect pinnedBounds, in Rect tempPinnedTaskBounds) = 370;
+    boolean isVrModePackageEnabled(in ComponentName packageName) = 371;
+    /**
+     * Moves all tasks from the docked stack in the fullscreen stack and puts the top task of the
+     * fullscreen stack into the docked stack.
+     */
+    void swapDockedAndFullscreenStack() = 372;
+    void notifyLockedProfile(int userId) = 373;
+    void startConfirmDeviceCredentialIntent(in Intent intent) = 374;
+    void sendIdleJobTrigger() = 375;
+    int sendIntentSender(in IIntentSender target, int code, in Intent intent,
+            in String resolvedType, in IIntentReceiver finishedReceiver,
+            in String requiredPermission, in Bundle options) = 376;
+
+
+    // Start of N MR1 transactions
+    void setVrThread(int tid) = 377;
+    void setRenderThread(int tid) = 378;
+    /**
+     * Lets activity manager know whether the calling process is currently showing "top-level" UI
+     * that is not an activity, i.e. windows on the screen the user is currently interacting with.
+     *
+     * <p>This flag can only be set for persistent processes.
+     *
+     * @param hasTopUi Whether the calling process has "top-level" UI.
+     */
+    void setHasTopUi(boolean hasTopUi) = 379;
+    /**
+     * Returns if the target of the PendingIntent can be fired directly, without triggering
+     * a work profile challenge. This can happen if the PendingIntent is to start direct-boot
+     * aware activities, and the target user is in RUNNING_LOCKED state, i.e. we should allow
+     * direct-boot aware activity to bypass work challenge when the user hasn't unlocked yet.
+     * @param intent the {@link  PendingIntent} to be tested.
+     * @return {@code true} if the intent should not trigger a work challenge, {@code false}
+     *     otherwise.
+     * @throws RemoteException
+     */
+    boolean canBypassWorkChallenge(in PendingIntent intent) = 380;
+
+    // Start of O transactions
+    void requestActivityRelaunch(in IBinder token) = 400;
+    /**
+     * Updates override configuration applied to specific display.
+     * @param values Update values for display configuration. If null is passed it will request the
+     *               Window Manager to compute new config for the specified display.
+     * @param displayId Id of the display to apply the config to.
+     * @throws RemoteException
+     * @return Returns true if the configuration was updated.
+     */
+    boolean updateDisplayOverrideConfiguration(in Configuration values, int displayId) = 401;
+    void unregisterTaskStackListener(ITaskStackListener listener) = 402;
+    void moveStackToDisplay(int stackId, int displayId) = 403;
+
+    // Please keep these transaction codes the same -- they are also
+    // sent by C++ code. when a new method is added, use the next available transaction id.
+}
\ No newline at end of file
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
deleted file mode 100644
index 0323651..0000000
--- a/core/java/android/app/IActivityManager.java
+++ /dev/null
@@ -1,1103 +0,0 @@
-/*
- * Copyright (C) 2006 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.annotation.UserIdInt;
-import android.app.ActivityManager.RunningServiceInfo;
-import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackInfo;
-import android.app.assist.AssistContent;
-import android.app.assist.AssistStructure;
-import android.content.ComponentName;
-import android.content.ContentProviderNative;
-import android.content.IContentProvider;
-import android.content.IIntentReceiver;
-import android.content.IIntentSender;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.content.UriPermission;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ParceledListSlice;
-import android.content.pm.ProviderInfo;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Debug;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.IProgressListener;
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-import android.os.StrictMode;
-import android.service.voice.IVoiceInteractionSession;
-import com.android.internal.app.IVoiceInteractor;
-import com.android.internal.os.IResultReceiver;
-
-import java.util.List;
-
-/**
- * System private API for talking with the activity manager service.  This
- * provides calls from the application back to the activity manager.
- *
- * {@hide}
- */
-public interface IActivityManager extends IInterface {
-    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
-            String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
-            ProfilerInfo profilerInfo, Bundle options) throws RemoteException;
-    public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent,
-            String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
-            ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException;
-    public int startActivityAsCaller(IApplicationThread caller, String callingPackage,
-            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
-            int flags, ProfilerInfo profilerInfo, Bundle options, boolean ignoreTargetSecurity,
-            int userId) throws RemoteException;
-    public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
-            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
-            int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options,
-            int userId) throws RemoteException;
-    public int startActivityWithConfig(IApplicationThread caller, String callingPackage,
-            Intent intent, String resolvedType, IBinder resultTo, String resultWho,
-            int requestCode, int startFlags, Configuration newConfig,
-            Bundle options, int userId) throws RemoteException;
-    public int startActivityIntentSender(IApplicationThread caller,
-            IntentSender intent, Intent fillInIntent, String resolvedType,
-            IBinder resultTo, String resultWho, int requestCode,
-            int flagsMask, int flagsValues, Bundle options) throws RemoteException;
-    public int startVoiceActivity(String callingPackage, int callingPid, int callingUid,
-            Intent intent, String resolvedType, IVoiceInteractionSession session,
-            IVoiceInteractor interactor, int flags, ProfilerInfo profilerInfo, Bundle options,
-            int userId) throws RemoteException;
-    public boolean startNextMatchingActivity(IBinder callingActivity,
-            Intent intent, Bundle options) throws RemoteException;
-    public int startActivityFromRecents(int taskId, Bundle options)
-            throws RemoteException;
-    public boolean finishActivity(IBinder token, int code, Intent data, int finishTask)
-            throws RemoteException;
-    public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
-    public boolean finishActivityAffinity(IBinder token) throws RemoteException;
-    public void finishVoiceTask(IVoiceInteractionSession session) throws RemoteException;
-    public void requestActivityRelaunch(IBinder token) throws RemoteException;
-    public boolean releaseActivityInstance(IBinder token) throws RemoteException;
-    public void releaseSomeActivities(IApplicationThread app) throws RemoteException;
-    public boolean willActivityBeVisible(IBinder token) throws RemoteException;
-    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
-            IIntentReceiver receiver, IntentFilter filter,
-            String requiredPermission, int userId) throws RemoteException;
-    public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException;
-    public int broadcastIntent(IApplicationThread caller, Intent intent,
-            String resolvedType, IIntentReceiver resultTo, int resultCode,
-            String resultData, Bundle map, String[] requiredPermissions,
-            int appOp, Bundle options, boolean serialized, boolean sticky, int userId) throws RemoteException;
-    public void unbroadcastIntent(IApplicationThread caller, Intent intent, int userId) throws RemoteException;
-    public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map,
-            boolean abortBroadcast, int flags) throws RemoteException;
-    public void attachApplication(IApplicationThread app) throws RemoteException;
-    public void activityResumed(IBinder token) throws RemoteException;
-    public void activityIdle(IBinder token, Configuration config,
-            boolean stopProfiling) throws RemoteException;
-    public void activityPaused(IBinder token) throws RemoteException;
-    public void activityStopped(IBinder token, Bundle state,
-            PersistableBundle persistentState, CharSequence description) throws RemoteException;
-    public void activitySlept(IBinder token) throws RemoteException;
-    public void activityDestroyed(IBinder token) throws RemoteException;
-    public void activityRelaunched(IBinder token) throws RemoteException;
-    public void reportSizeConfigurations(IBinder token, int[] horizontalSizeConfiguration,
-            int[] verticalSizeConfigurations, int[] smallestWidthConfigurations)
-            throws RemoteException;
-    public String getCallingPackage(IBinder token) throws RemoteException;
-    public ComponentName getCallingActivity(IBinder token) throws RemoteException;
-    public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException;
-    public int addAppTask(IBinder activityToken, Intent intent,
-            ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException;
-    public Point getAppTaskThumbnailSize() throws RemoteException;
-    public List<RunningTaskInfo> getTasks(int maxNum, int flags) throws RemoteException;
-    public ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
-            int flags, int userId) throws RemoteException;
-    public ActivityManager.TaskThumbnail getTaskThumbnail(int taskId) throws RemoteException;
-    public List<RunningServiceInfo> getServices(int maxNum, int flags) throws RemoteException;
-    public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState()
-            throws RemoteException;
-    public void moveTaskToFront(int task, int flags, Bundle options) throws RemoteException;
-    public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
-    public void moveTaskBackwards(int task) throws RemoteException;
-    public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
-    public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
-            Rect initialBounds, boolean moveHomeStackFront) throws RemoteException;
-    public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) throws RemoteException;
-
-    /**
-     * Resizes the input stack id to the given bounds.
-     *
-     * @param stackId Id of the stack to resize.
-     * @param bounds Bounds to resize the stack to or {@code null} for fullscreen.
-     * @param allowResizeInDockedMode True if the resize should be allowed when the docked stack is
-     *                                active.
-     * @param preserveWindows True if the windows of activities contained in the stack should be
-     *                        preserved.
-     * @param animate True if the stack resize should be animated.
-     * @param animationDuration The duration of the resize animation in milliseconds or -1 if the
-     *                          default animation duration should be used.
-     * @throws RemoteException
-     */
-    public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode,
-            boolean preserveWindows, boolean animate, int animationDuration) throws RemoteException;
-
-    /**
-     * Moves all tasks from the docked stack in the fullscreen stack and puts the top task of the
-     * fullscreen stack into the docked stack.
-     */
-    public void swapDockedAndFullscreenStack() throws RemoteException;
-
-    /**
-     * Resizes the docked stack, and all other stacks as the result of the dock stack bounds change.
-     *
-     * @param dockedBounds The bounds for the docked stack.
-     * @param tempDockedTaskBounds The temporary bounds for the tasks in the docked stack, which
-     *                             might be different from the stack bounds to allow more
-     *                             flexibility while resizing, or {@code null} if they should be the
-     *                             same as the stack bounds.
-     * @param tempDockedTaskInsetBounds The temporary bounds for the tasks to calculate the insets.
-     *                                  When resizing, we usually "freeze" the layout of a task. To
-     *                                  achieve that, we also need to "freeze" the insets, which
-     *                                  gets achieved by changing task bounds but not bounds used
-     *                                  to calculate the insets in this transient state
-     * @param tempOtherTaskBounds The temporary bounds for the tasks in all other stacks, or
-     *                            {@code null} if they should be the same as the stack bounds.
-     * @param tempOtherTaskInsetBounds Like {@code tempDockedTaskInsetBounds}, but for the other
-     *                                 stacks.
-     * @throws RemoteException
-     */
-    public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
-            Rect tempDockedTaskInsetBounds,
-            Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) throws RemoteException;
-    /**
-     * Resizes the pinned stack.
-     *
-     * @param pinnedBounds The bounds for the pinned stack.
-     * @param tempPinnedTaskBounds The temporary bounds for the tasks in the pinned stack, which
-     *                             might be different from the stack bounds to allow more
-     *                             flexibility while resizing, or {@code null} if they should be the
-     *                             same as the stack bounds.
-     */
-    public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) throws RemoteException;
-    public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException;
-    public List<StackInfo> getAllStackInfos() throws RemoteException;
-    public StackInfo getStackInfo(int stackId) throws RemoteException;
-    public boolean isInHomeStack(int taskId) throws RemoteException;
-    public void setFocusedStack(int stackId) throws RemoteException;
-    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;
-    public ContentProviderHolder getContentProviderExternal(String name, int userId, IBinder token)
-            throws RemoteException;
-    public void removeContentProvider(IBinder connection, boolean stable) throws RemoteException;
-    public void removeContentProviderExternal(String name, IBinder token) throws RemoteException;
-    public void publishContentProviders(IApplicationThread caller,
-            List<ContentProviderHolder> providers) throws RemoteException;
-    public boolean refContentProvider(IBinder connection, int stableDelta, int unstableDelta)
-            throws RemoteException;
-    public void unstableProviderDied(IBinder connection) throws RemoteException;
-    public void appNotRespondingViaProvider(IBinder connection) throws RemoteException;
-    public PendingIntent getRunningServiceControlPanel(ComponentName service)
-            throws RemoteException;
-    public ComponentName startService(IApplicationThread caller, Intent service,
-            String resolvedType, String callingPackage, int userId) throws RemoteException;
-    public int stopService(IApplicationThread caller, Intent service,
-            String resolvedType, int userId) throws RemoteException;
-    public boolean stopServiceToken(ComponentName className, IBinder token,
-            int startId) throws RemoteException;
-    public void setServiceForeground(ComponentName className, IBinder token,
-            int id, Notification notification, int flags) throws RemoteException;
-    public int bindService(IApplicationThread caller, IBinder token, Intent service,
-            String resolvedType, IServiceConnection connection, int flags,
-            String callingPackage, int userId) throws RemoteException;
-    public boolean unbindService(IServiceConnection connection) throws RemoteException;
-    public void publishService(IBinder token,
-            Intent intent, IBinder service) throws RemoteException;
-    public void unbindFinished(IBinder token, Intent service,
-            boolean doRebind) throws RemoteException;
-    /* oneway */
-    public void serviceDoneExecuting(IBinder token, int type, int startId,
-            int res) throws RemoteException;
-    public IBinder peekService(Intent service, String resolvedType, String callingPackage)
-            throws RemoteException;
-
-    public boolean bindBackupAgent(String packageName, int backupRestoreMode, int userId)
-            throws RemoteException;
-    public void clearPendingBackup() throws RemoteException;
-    public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException;
-    public void unbindBackupAgent(ApplicationInfo appInfo) throws RemoteException;
-    public void killApplicationProcess(String processName, int uid) throws RemoteException;
-
-    public boolean startInstrumentation(ComponentName className, String profileFile,
-            int flags, Bundle arguments, IInstrumentationWatcher watcher,
-            IUiAutomationConnection connection, int userId,
-            String abiOverride) throws RemoteException;
-    public void finishInstrumentation(IApplicationThread target,
-            int resultCode, Bundle results) throws RemoteException;
-
-    /**
-     * @return A copy of global {@link Configuration}, contains general settings for the entire
-     *         system. Corresponds to the configuration of the default display.
-     * @throws RemoteException
-     */
-    public Configuration getConfiguration() throws RemoteException;
-
-    /**
-     * Updates global configuration and applies changes to the entire system.
-     * @param values Update values for global configuration. If null is passed it will request the
-     *               Window Manager to compute new config for the default display.
-     * @throws RemoteException
-     * @return Returns true if the configuration was updated.
-     */
-    public boolean updateConfiguration(Configuration values) throws RemoteException;
-
-    /**
-     * Updates override configuration applied to specific display.
-     * @param values Update values for display configuration. If null is passed it will request the
-     *               Window Manager to compute new config for the specified display.
-     * @param displayId Id of the display to apply the config to.
-     * @throws RemoteException
-     * @return Returns true if the configuration was updated.
-     */
-    public boolean updateDisplayOverrideConfiguration(Configuration values, int displayId)
-            throws RemoteException;
-
-    public void setRequestedOrientation(IBinder token,
-            int requestedOrientation) throws RemoteException;
-    public int getRequestedOrientation(IBinder token) throws RemoteException;
-
-    public ComponentName getActivityClassForToken(IBinder token) throws RemoteException;
-    public String getPackageForToken(IBinder token) throws RemoteException;
-
-    public IIntentSender getIntentSender(int type,
-            String packageName, IBinder token, String resultWho,
-            int requestCode, Intent[] intents, String[] resolvedTypes,
-            int flags, Bundle options, int userId) throws RemoteException;
-    public void cancelIntentSender(IIntentSender sender) throws RemoteException;
-    public boolean clearApplicationUserData(final String packageName,
-            final IPackageDataObserver observer, int userId) throws RemoteException;
-    public String getPackageForIntentSender(IIntentSender sender) throws RemoteException;
-    public int getUidForIntentSender(IIntentSender sender) throws RemoteException;
-
-    public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
-            boolean requireFull, String name, String callerPackage) throws RemoteException;
-
-    public void setProcessLimit(int max) throws RemoteException;
-    public int getProcessLimit() throws RemoteException;
-
-    public void setProcessForeground(IBinder token, int pid,
-            boolean isForeground) throws RemoteException;
-
-    public int checkPermission(String permission, int pid, int uid)
-            throws RemoteException;
-    public int checkPermissionWithToken(String permission, int pid, int uid, IBinder callerToken)
-            throws RemoteException;
-
-    public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId,
-            IBinder callerToken) throws RemoteException;
-    public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri,
-            int mode, int userId) throws RemoteException;
-    public void revokeUriPermission(IApplicationThread caller, Uri uri, int mode, int userId)
-            throws RemoteException;
-    public void takePersistableUriPermission(Uri uri, int modeFlags, int userId)
-            throws RemoteException;
-    public void releasePersistableUriPermission(Uri uri, int modeFlags, int userId)
-            throws RemoteException;
-    public ParceledListSlice<UriPermission> getPersistedUriPermissions(
-            String packageName, boolean incoming) throws RemoteException;
-
-    // Gets the URI permissions granted to an arbitrary package.
-    // NOTE: this is different from getPersistedUriPermissions(), which returns the URIs the package
-    // granted to another packages (instead of those granted to it).
-    public ParceledListSlice<UriPermission> getGrantedUriPermissions(String packageName, int userId)
-            throws RemoteException;
-
-    // Clears the URI permissions granted to an arbitrary package.
-    public void clearGrantedUriPermissions(String packageName, int userId) throws RemoteException;
-
-    public void showWaitingForDebugger(IApplicationThread who, boolean waiting)
-            throws RemoteException;
-
-    public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException;
-
-    public void killBackgroundProcesses(final String packageName, int userId)
-            throws RemoteException;
-    public void killAllBackgroundProcesses() throws RemoteException;
-    public void killPackageDependents(final String packageName, int userId) throws RemoteException;
-    public void forceStopPackage(final String packageName, int userId) throws RemoteException;
-
-    public void setLockScreenShown(boolean showing) throws RemoteException;
-
-    public void unhandledBack() throws RemoteException;
-    public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException;
-    public void setDebugApp(
-        String packageName, boolean waitForDebugger, boolean persistent)
-        throws RemoteException;
-    public void setAlwaysFinish(boolean enabled) throws RemoteException;
-    public void setActivityController(IActivityController watcher, boolean imAMonkey)
-        throws RemoteException;
-    public void setLenientBackgroundCheck(boolean enabled) throws RemoteException;
-    public int getMemoryTrimLevel() throws RemoteException;
-
-    public void enterSafeMode() throws RemoteException;
-
-    public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg, String tag)
-            throws RemoteException;
-    public void noteAlarmStart(IIntentSender sender, int sourceUid, String tag)
-            throws RemoteException;
-    public void noteAlarmFinish(IIntentSender sender, int sourceUid, String tag)
-            throws RemoteException;
-
-    public boolean killPids(int[] pids, String reason, boolean secure) throws RemoteException;
-    public boolean killProcessesBelowForeground(String reason) throws RemoteException;
-
-    // Special low-level communication with activity manager.
-    public void handleApplicationCrash(IBinder app,
-            ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;
-    public boolean handleApplicationWtf(IBinder app, String tag, boolean system,
-            ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;
-
-    // A StrictMode violation to be handled.  The violationMask is a
-    // subset of the original StrictMode policy bitmask, with only the
-    // bit violated and penalty bits to be executed by the
-    // ActivityManagerService remaining set.
-    public void handleApplicationStrictModeViolation(IBinder app, int violationMask,
-            StrictMode.ViolationInfo crashInfo) throws RemoteException;
-
-    /*
-     * This will deliver the specified signal to all the persistent processes. Currently only
-     * SIGUSR1 is delivered. All others are ignored.
-     */
-    public void signalPersistentProcesses(int signal) throws RemoteException;
-    // Retrieve running application processes in the system
-    public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses()
-            throws RemoteException;
-    // Retrieve info of applications installed on external media that are currently
-    // running.
-    public List<ApplicationInfo> getRunningExternalApplications()
-            throws RemoteException;
-    // Get memory information about the calling process.
-    public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo)
-            throws RemoteException;
-    // Get device configuration
-    public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException;
-
-    // Turn on/off profiling in a particular process.
-    public boolean profileControl(String process, int userId, boolean start,
-            ProfilerInfo profilerInfo, int profileType) throws RemoteException;
-
-    public boolean shutdown(int timeout) throws RemoteException;
-
-    public void stopAppSwitches() throws RemoteException;
-    public void resumeAppSwitches() throws RemoteException;
-
-    public void addPackageDependency(String packageName) throws RemoteException;
-
-    public void killApplication(String pkg, int appId, int userId, String reason)
-            throws RemoteException;
-
-    public void closeSystemDialogs(String reason) throws RemoteException;
-
-    public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
-            throws RemoteException;
-
-    public void overridePendingTransition(IBinder token, String packageName,
-            int enterAnim, int exitAnim) throws RemoteException;
-
-    public boolean isUserAMonkey() throws RemoteException;
-
-    public void setUserIsMonkey(boolean monkey) throws RemoteException;
-
-    public void finishHeavyWeightApp() throws RemoteException;
-
-    public boolean convertFromTranslucent(IBinder token) throws RemoteException;
-    public boolean convertToTranslucent(IBinder token, ActivityOptions options) throws RemoteException;
-    public void notifyActivityDrawn(IBinder token) throws RemoteException;
-    public ActivityOptions getActivityOptions(IBinder token) throws RemoteException;
-
-    public void bootAnimationComplete() throws RemoteException;
-
-    public void setImmersive(IBinder token, boolean immersive) throws RemoteException;
-    public boolean isImmersive(IBinder token) throws RemoteException;
-    public boolean isTopActivityImmersive() throws RemoteException;
-    public boolean isTopOfTask(IBinder token) throws RemoteException;
-
-    public void crashApplication(int uid, int initialPid, String packageName,
-            String message) throws RemoteException;
-
-    public String getProviderMimeType(Uri uri, int userId) throws RemoteException;
-
-    public IBinder newUriPermissionOwner(String name) throws RemoteException;
-    public IBinder getUriPermissionOwnerForActivity(IBinder activityToken) throws RemoteException;
-    public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
-            Uri uri, int mode, int sourceUserId, int targetUserId) throws RemoteException;
-    public void revokeUriPermissionFromOwner(IBinder owner, Uri uri,
-            int mode, int userId) throws RemoteException;
-
-    public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri,
-            int modeFlags, int userId) throws RemoteException;
-
-    // Cause the specified process to dump the specified heap.
-    public boolean dumpHeap(String process, int userId, boolean managed, String path,
-        ParcelFileDescriptor fd) throws RemoteException;
-
-    public int startActivities(IApplicationThread caller, String callingPackage,
-            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options, int userId) throws RemoteException;
-
-    public int getFrontActivityScreenCompatMode() throws RemoteException;
-    public void setFrontActivityScreenCompatMode(int mode) throws RemoteException;
-    public int getPackageScreenCompatMode(String packageName) throws RemoteException;
-    public void setPackageScreenCompatMode(String packageName, int mode)
-            throws RemoteException;
-    public boolean getPackageAskScreenCompat(String packageName) throws RemoteException;
-    public void setPackageAskScreenCompat(String packageName, boolean ask)
-            throws RemoteException;
-
-    // Multi-user APIs
-    public boolean switchUser(int userid) throws RemoteException;
-    public boolean startUserInBackground(int userid) throws RemoteException;
-    public boolean unlockUser(int userid, byte[] token, byte[] secret, IProgressListener listener)
-            throws RemoteException;
-    public int stopUser(int userid, boolean force, IStopUserCallback callback) throws RemoteException;
-    public UserInfo getCurrentUser() throws RemoteException;
-    public boolean isUserRunning(int userid, int flags) throws RemoteException;
-    public int[] getRunningUserIds() throws RemoteException;
-
-    public boolean removeTask(int taskId) throws RemoteException;
-
-    public void registerProcessObserver(IProcessObserver observer) throws RemoteException;
-    public void unregisterProcessObserver(IProcessObserver observer) throws RemoteException;
-
-    public void registerUidObserver(IUidObserver observer, int which) throws RemoteException;
-    public void unregisterUidObserver(IUidObserver observer) throws RemoteException;
-
-    public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException;
-
-    public boolean isIntentSenderAnActivity(IIntentSender sender) throws RemoteException;
-
-    public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException;
-
-    public String getTagForIntentSender(IIntentSender sender, String prefix) throws RemoteException;
-
-    public void updatePersistentConfiguration(Configuration values) throws RemoteException;
-
-    public long[] getProcessPss(int[] pids) throws RemoteException;
-
-    public void showBootMessage(CharSequence msg, boolean always) throws RemoteException;
-
-    /**
-     * Notify the system that the keyguard is going away.
-     *
-     * @param flags See {@link android.view.WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
-     *              etc.
-     */
-    public void keyguardGoingAway(int flags) throws RemoteException;
-
-    public boolean shouldUpRecreateTask(IBinder token, String destAffinity)
-            throws RemoteException;
-
-    public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData)
-            throws RemoteException;
-
-    // These are not public because you need to be very careful in how you
-    // manage your activity to make sure it is always the uid you expect.
-    public int getLaunchedFromUid(IBinder activityToken) throws RemoteException;
-    public String getLaunchedFromPackage(IBinder activityToken) throws RemoteException;
-
-    public void registerUserSwitchObserver(IUserSwitchObserver observer,
-            String name) throws RemoteException;
-    public void unregisterUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
-
-    public void requestBugReport(int bugreportType) throws RemoteException;
-
-    public long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason)
-            throws RemoteException;
-
-    public Bundle getAssistContextExtras(int requestType) throws RemoteException;
-
-    public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
-            Bundle receiverExtras,
-            IBinder activityToken, boolean focused, boolean newSessionId) throws RemoteException;
-
-    public void reportAssistContextExtras(IBinder token, Bundle extras,
-            AssistStructure structure, AssistContent content, Uri referrer) throws RemoteException;
-
-    public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
-            Bundle args) throws RemoteException;
-
-    public boolean isAssistDataAllowedOnCurrentActivity() throws RemoteException;
-
-    public boolean showAssistFromActivity(IBinder token, Bundle args) throws RemoteException;
-
-    public void killUid(int appId, int userId, String reason) throws RemoteException;
-
-    public void hang(IBinder who, boolean allowRestart) throws RemoteException;
-
-    public void reportActivityFullyDrawn(IBinder token) throws RemoteException;
-
-    public void restart() throws RemoteException;
-
-    public void performIdleMaintenance() throws RemoteException;
-
-    public void sendIdleJobTrigger() throws RemoteException;
-
-    public IActivityContainer createVirtualActivityContainer(IBinder parentActivityToken,
-            IActivityContainerCallback callback) throws RemoteException;
-
-    public IActivityContainer createStackOnDisplay(int displayId) throws RemoteException;
-
-    public int getActivityDisplayId(IBinder activityToken) throws RemoteException;
-
-    public void startSystemLockTaskMode(int taskId) throws RemoteException;
-
-    public void startLockTaskMode(int taskId) throws RemoteException;
-
-    public void startLockTaskMode(IBinder token) throws RemoteException;
-
-    public void stopLockTaskMode() throws RemoteException;
-
-    public void stopSystemLockTaskMode() throws RemoteException;
-
-    public boolean isInLockTaskMode() throws RemoteException;
-
-    public int getLockTaskModeState() throws RemoteException;
-
-    public void showLockTaskEscapeMessage(IBinder token) throws RemoteException;
-
-    public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
-            throws RemoteException;
-    public void setTaskResizeable(int taskId, int resizeableMode) throws RemoteException;
-    public void resizeTask(int taskId, Rect bounds, int resizeMode) throws RemoteException;
-
-    public Rect getTaskBounds(int taskId) throws RemoteException;
-    public Bitmap getTaskDescriptionIcon(String filename, int userId) throws RemoteException;
-
-    public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts)
-            throws RemoteException;
-
-    public boolean requestVisibleBehind(IBinder token, boolean visible) throws RemoteException;
-    public boolean isBackgroundVisibleBehind(IBinder token) throws RemoteException;
-    public void backgroundResourcesReleased(IBinder token) throws RemoteException;
-
-    public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException;
-    public void notifyEnterAnimationComplete(IBinder token) throws RemoteException;
-
-    public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException;
-
-    public void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize,
-            String reportPackage) throws RemoteException;
-    public void dumpHeapFinished(String path) throws RemoteException;
-
-    public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake)
-            throws RemoteException;
-    public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException;
-    public void updateDeviceOwner(String packageName) throws RemoteException;
-
-    public int getPackageProcessState(String packageName, String callingPackage)
-            throws RemoteException;
-
-    public boolean setProcessMemoryTrimLevel(String process, int uid, int level)
-            throws RemoteException;
-
-    public boolean isRootVoiceInteraction(IBinder token) throws RemoteException;
-
-    // Start Binder transaction tracking for all applications.
-    public boolean startBinderTracking() throws RemoteException;
-
-    // Stop Binder transaction tracking for all applications and dump trace data to the given file
-    // descriptor.
-    public boolean stopBinderTrackingAndDump(ParcelFileDescriptor fd) throws RemoteException;
-
-    public int getActivityStackId(IBinder token) throws RemoteException;
-    public void exitFreeformMode(IBinder token) throws RemoteException;
-
-    public void suppressResizeConfigChanges(boolean suppress) throws RemoteException;
-
-    public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) throws RemoteException;
-
-    public int getAppStartMode(int uid, String packageName) throws RemoteException;
-
-    public boolean isInMultiWindowMode(IBinder token) throws RemoteException;
-
-    public boolean isInPictureInPictureMode(IBinder token) throws RemoteException;
-
-    public void enterPictureInPictureMode(IBinder token) throws RemoteException;
-
-    public int setVrMode(IBinder token, boolean enabled, ComponentName packageName)
-            throws RemoteException;
-
-    public boolean isVrModePackageEnabled(ComponentName packageName) throws RemoteException;
-
-    public boolean isAppForeground(int uid) throws RemoteException;
-
-    public void startLocalVoiceInteraction(IBinder token, Bundle options) throws RemoteException;
-
-    public void stopLocalVoiceInteraction(IBinder token) throws RemoteException;
-
-    public boolean supportsLocalVoiceInteraction() throws RemoteException;
-
-    public void notifyPinnedStackAnimationEnded() throws RemoteException;
-
-    public void removeStack(int stackId) throws RemoteException;
-
-    public void notifyLockedProfile(@UserIdInt int userId) throws RemoteException;
-
-    public void startConfirmDeviceCredentialIntent(Intent intent) throws RemoteException;
-
-    public int sendIntentSender(IIntentSender target, int code, Intent intent, String resolvedType,
-            IIntentReceiver finishedReceiver, String requiredPermission, Bundle options)
-            throws RemoteException;
-
-    public void setVrThread(int tid) throws RemoteException;
-    public void setRenderThread(int tid) throws RemoteException;
-
-    /**
-     * Lets activity manager know whether the calling process is currently showing "top-level" UI
-     * that is not an activity, i.e. windows on the screen the user is currently interacting with.
-     *
-     * <p>This flag can only be set for persistent processes.
-     *
-     * @param hasTopUi Whether the calling process has "top-level" UI.
-     */
-    public void setHasTopUi(boolean hasTopUi) throws RemoteException;
-
-    /**
-     * Returns if the target of the PendingIntent can be fired directly, without triggering
-     * a work profile challenge. This can happen if the PendingIntent is to start direct-boot
-     * aware activities, and the target user is in RUNNING_LOCKED state, i.e. we should allow
-     * direct-boot aware activity to bypass work challenge when the user hasn't unlocked yet.
-     * @param intent the {@link  PendingIntent} to be tested.
-     * @return {@code true} if the intent should not trigger a work challenge, {@code false}
-     *     otherwise.
-     * @throws RemoteException
-     */
-    public boolean canBypassWorkChallenge(PendingIntent intent) throws RemoteException;
-
-    /*
-     * Private non-Binder interfaces
-     */
-    /* package */ boolean testIsSystemReady();
-
-    /** Information you can retrieve about a particular application. */
-    public static class ContentProviderHolder implements Parcelable {
-        public final ProviderInfo info;
-        public IContentProvider provider;
-        public IBinder connection;
-        public boolean noReleaseNeeded;
-
-        public ContentProviderHolder(ProviderInfo _info) {
-            info = _info;
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            info.writeToParcel(dest, 0);
-            if (provider != null) {
-                dest.writeStrongBinder(provider.asBinder());
-            } else {
-                dest.writeStrongBinder(null);
-            }
-            dest.writeStrongBinder(connection);
-            dest.writeInt(noReleaseNeeded ? 1 : 0);
-        }
-
-        public static final Parcelable.Creator<ContentProviderHolder> CREATOR
-                = new Parcelable.Creator<ContentProviderHolder>() {
-            @Override
-            public ContentProviderHolder createFromParcel(Parcel source) {
-                return new ContentProviderHolder(source);
-            }
-
-            @Override
-            public ContentProviderHolder[] newArray(int size) {
-                return new ContentProviderHolder[size];
-            }
-        };
-
-        private ContentProviderHolder(Parcel source) {
-            info = ProviderInfo.CREATOR.createFromParcel(source);
-            provider = ContentProviderNative.asInterface(
-                    source.readStrongBinder());
-            connection = source.readStrongBinder();
-            noReleaseNeeded = source.readInt() != 0;
-        }
-    }
-
-    /** Information returned after waiting for an activity start. */
-    public static class WaitResult implements Parcelable {
-        public int result;
-        public boolean timeout;
-        public ComponentName who;
-        public long thisTime;
-        public long totalTime;
-
-        public WaitResult() {
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeInt(result);
-            dest.writeInt(timeout ? 1 : 0);
-            ComponentName.writeToParcel(who, dest);
-            dest.writeLong(thisTime);
-            dest.writeLong(totalTime);
-        }
-
-        public static final Parcelable.Creator<WaitResult> CREATOR
-                = new Parcelable.Creator<WaitResult>() {
-            @Override
-            public WaitResult createFromParcel(Parcel source) {
-                return new WaitResult(source);
-            }
-
-            @Override
-            public WaitResult[] newArray(int size) {
-                return new WaitResult[size];
-            }
-        };
-
-        private WaitResult(Parcel source) {
-            result = source.readInt();
-            timeout = source.readInt() != 0;
-            who = ComponentName.readFromParcel(source);
-            thisTime = source.readLong();
-            totalTime = source.readLong();
-        }
-    }
-
-    String descriptor = "android.app.IActivityManager";
-
-    // Please keep these transaction codes the same -- they are also
-    // sent by C++ code.
-    int HANDLE_APPLICATION_CRASH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;
-    int START_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;
-    int UNHANDLED_BACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3;
-    int OPEN_CONTENT_URI_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4;
-
-    // Remaining non-native transaction codes.
-    int FINISH_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+10;
-    int REGISTER_RECEIVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+11;
-    int UNREGISTER_RECEIVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+12;
-    int BROADCAST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+13;
-    int UNBROADCAST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+14;
-    int FINISH_RECEIVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+15;
-    int ATTACH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+16;
-    int ACTIVITY_IDLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+17;
-    int ACTIVITY_PAUSED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+18;
-    int ACTIVITY_STOPPED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+19;
-    int GET_CALLING_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+20;
-    int GET_CALLING_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+21;
-    int GET_TASKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+22;
-    int MOVE_TASK_TO_FRONT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+23;
-
-    int MOVE_TASK_BACKWARDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+25;
-    int GET_TASK_FOR_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+26;
-
-    int GET_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28;
-    int PUBLISH_CONTENT_PROVIDERS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
-    int REF_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
-    int FINISH_SUB_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
-    int GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
-    int START_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
-    int STOP_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34;
-    int BIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
-    int UNBIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
-    int PUBLISH_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+37;
-    int ACTIVITY_RESUMED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38;
-    int SET_DEBUG_APP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+41;
-    int SET_ALWAYS_FINISH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+42;
-    int START_INSTRUMENTATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+43;
-    int FINISH_INSTRUMENTATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+44;
-    int GET_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+45;
-    int UPDATE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+46;
-    int STOP_SERVICE_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+47;
-    int GET_ACTIVITY_CLASS_FOR_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+48;
-    int GET_PACKAGE_FOR_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49;
-    int SET_PROCESS_LIMIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50;
-    int GET_PROCESS_LIMIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+51;
-    int CHECK_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+52;
-    int CHECK_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+53;
-    int GRANT_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+54;
-    int REVOKE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+55;
-    int SET_ACTIVITY_CONTROLLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+56;
-    int SHOW_WAITING_FOR_DEBUGGER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+57;
-    int SIGNAL_PERSISTENT_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58;
-    int GET_RECENT_TASKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59;
-    int SERVICE_DONE_EXECUTING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+60;
-    int ACTIVITY_DESTROYED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+61;
-    int GET_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+62;
-    int CANCEL_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+63;
-    int GET_PACKAGE_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+64;
-    int ENTER_SAFE_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+65;
-    int START_NEXT_MATCHING_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+66;
-    int NOTE_WAKEUP_ALARM_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+67;
-    int REMOVE_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+68;
-    int SET_REQUESTED_ORIENTATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+69;
-    int GET_REQUESTED_ORIENTATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+70;
-    int UNBIND_FINISHED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+71;
-    int SET_PROCESS_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+72;
-    int SET_SERVICE_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+73;
-    int MOVE_ACTIVITY_TASK_TO_BACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+74;
-    int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+75;
-    int GET_PROCESSES_IN_ERROR_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+76;
-    int CLEAR_APP_DATA_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+77;
-    int FORCE_STOP_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+78;
-    int KILL_PIDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+79;
-    int GET_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+80;
-    int GET_TASK_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+81;
-    int GET_RUNNING_APP_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+82;
-    int GET_DEVICE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+83;
-    int PEEK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+84;
-    int PROFILE_CONTROL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+85;
-    int SHUTDOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+86;
-    int STOP_APP_SWITCHES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+87;
-    int RESUME_APP_SWITCHES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+88;
-    int START_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+89;
-    int BACKUP_AGENT_CREATED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+90;
-    int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91;
-    int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
-    int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
-    int ADD_PACKAGE_DEPENDENCY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
-    int KILL_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
-    int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
-    int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
-    int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98;
-    int START_ACTIVITY_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+99;
-    int OVERRIDE_PENDING_TRANSITION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+100;
-    int HANDLE_APPLICATION_WTF_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+101;
-    int KILL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+102;
-    int IS_USER_A_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+103;
-    int START_ACTIVITY_AND_WAIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+104;
-    int WILL_ACTIVITY_BE_VISIBLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+105;
-    int START_ACTIVITY_WITH_CONFIG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+106;
-    int GET_RUNNING_EXTERNAL_APPLICATIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+107;
-    int FINISH_HEAVY_WEIGHT_APP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+108;
-    int HANDLE_APPLICATION_STRICT_MODE_VIOLATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+109;
-    int IS_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+110;
-    int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111;
-    int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112;
-    int CRASH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+113;
-    int GET_PROVIDER_MIME_TYPE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+114;
-    int NEW_URI_PERMISSION_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+115;
-    int GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+116;
-    int REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+117;
-    int CHECK_GRANT_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+118;
-    int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+119;
-    int START_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+120;
-    int IS_USER_RUNNING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+121;
-    int ACTIVITY_SLEPT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+122;
-    int GET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+123;
-    int SET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+124;
-    int GET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+125;
-    int SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+126;
-    int GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+127;
-    int SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+128;
-    int SWITCH_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+129;
-    int SET_FOCUSED_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+130;
-    int REMOVE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+131;
-    int REGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+132;
-    int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+133;
-    int IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+134;
-    int UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+135;
-    int GET_PROCESS_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+136;
-    int SHOW_BOOT_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+137;
-    int KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+139;
-    int GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+140;
-    int REMOVE_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+141;
-    int GET_MY_MEMORY_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+142;
-    int KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+143;
-    int GET_CURRENT_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+144;
-    int SHOULD_UP_RECREATE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145;
-    int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146;
-    int SET_LOCK_SCREEN_SHOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+147;
-    int FINISH_ACTIVITY_AFFINITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+148;
-    int GET_LAUNCHED_FROM_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+149;
-    int UNSTABLE_PROVIDER_DIED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+150;
-    int IS_INTENT_SENDER_AN_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+151;
-    int START_ACTIVITY_AS_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+152;
-    int STOP_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+153;
-    int REGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+154;
-    int UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+155;
-    int GET_RUNNING_USER_IDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+156;
-    int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157;
-    int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158;
-    int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159;
-    int GET_INTENT_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+160;
-    int GET_ASSIST_CONTEXT_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+161;
-    int REPORT_ASSIST_CONTEXT_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+162;
-    int GET_LAUNCHED_FROM_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+163;
-    int KILL_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+164;
-    int SET_USER_IS_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+165;
-    int HANG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+166;
-    int CREATE_VIRTUAL_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+167;
-    int MOVE_TASK_TO_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+168;
-    int RESIZE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+169;
-    int GET_ALL_STACK_INFOS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
-    int SET_FOCUSED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+171;
-    int GET_STACK_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172;
-    int CONVERT_FROM_TRANSLUCENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+173;
-    int CONVERT_TO_TRANSLUCENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+174;
-    int NOTIFY_ACTIVITY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+175;
-    int REPORT_ACTIVITY_FULLY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+176;
-    int RESTART_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+177;
-    int PERFORM_IDLE_MAINTENANCE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+178;
-    int TAKE_PERSISTABLE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+179;
-    int RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+180;
-    int GET_PERSISTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+181;
-    int APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+182;
-    int GET_TASK_BOUNDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+183;
-    int GET_ACTIVITY_DISPLAY_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184;
-    int DELETE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+185;
-    int SET_PROCESS_MEMORY_TRIM_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+186;
-
-    // Start of L transactions
-    int GET_TAG_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+210;
-    int START_USER_IN_BACKGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+211;
-    int IS_IN_HOME_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+212;
-    int START_LOCK_TASK_BY_TASK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+213;
-    int START_LOCK_TASK_BY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+214;
-    int STOP_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+215;
-    int IS_IN_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+216;
-    int SET_TASK_DESCRIPTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217;
-    int START_VOICE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+218;
-    int GET_ACTIVITY_OPTIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+219;
-    int GET_APP_TASKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+220;
-    int START_SYSTEM_LOCK_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+221;
-    int STOP_SYSTEM_LOCK_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+222;
-    int FINISH_VOICE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+223;
-    int IS_TOP_OF_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+224;
-    int REQUEST_VISIBLE_BEHIND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+225;
-    int IS_BACKGROUND_VISIBLE_BEHIND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+226;
-    int BACKGROUND_RESOURCES_RELEASED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+227;
-    int NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+228;
-    int START_ACTIVITY_FROM_RECENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 229;
-    int NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+230;
-    int START_ACTIVITY_AS_CALLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+232;
-    int ADD_APP_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+233;
-    int GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+234;
-    int RELEASE_ACTIVITY_INSTANCE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+235;
-    int RELEASE_SOME_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+236;
-    int BOOT_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+237;
-    int GET_TASK_DESCRIPTION_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+238;
-    int LAUNCH_ASSIST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+239;
-    int START_IN_PLACE_ANIMATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+240;
-    int CHECK_PERMISSION_WITH_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+241;
-    int REGISTER_TASK_STACK_LISTENER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+242;
-
-    // Start of M transactions
-    int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+280;
-    int CREATE_STACK_ON_DISPLAY = IBinder.FIRST_CALL_TRANSACTION+281;
-    int GET_FOCUSED_STACK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+282;
-    int SET_TASK_RESIZEABLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+283;
-    int REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+284;
-    int RESIZE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+285;
-    int GET_LOCK_TASK_MODE_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+286;
-    int SET_DUMP_HEAP_DEBUG_LIMIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+287;
-    int DUMP_HEAP_FINISHED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+288;
-    int SET_VOICE_KEEP_AWAKE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+289;
-    int UPDATE_LOCK_TASK_PACKAGES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+290;
-    int NOTE_ALARM_START_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+291;
-    int NOTE_ALARM_FINISH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+292;
-    int GET_PACKAGE_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+293;
-    int SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+294;
-    int UPDATE_DEVICE_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+295;
-    int KEYGUARD_GOING_AWAY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+296;
-    int REGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+297;
-    int UNREGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+298;
-    int IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION
-            = IBinder.FIRST_CALL_TRANSACTION+299;
-    int SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+300;
-    int IS_ROOT_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+301;
-
-    // Start of N transactions
-    int START_BINDER_TRACKING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 340;
-    int STOP_BINDER_TRACKING_AND_DUMP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 341;
-    int POSITION_TASK_IN_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 342;
-    int GET_ACTIVITY_STACK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 343;
-    int EXIT_FREEFORM_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 344;
-    int REPORT_SIZE_CONFIGURATIONS = IBinder.FIRST_CALL_TRANSACTION + 345;
-    int MOVE_TASK_TO_DOCKED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 346;
-    int SUPPRESS_RESIZE_CONFIG_CHANGES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 347;
-    int MOVE_TASKS_TO_FULLSCREEN_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 348;
-    int MOVE_TOP_ACTIVITY_TO_PINNED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 349;
-    int GET_APP_START_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 350;
-    int UNLOCK_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 351;
-    int IN_MULTI_WINDOW_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 352;
-    int IN_PICTURE_IN_PICTURE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 353;
-    int KILL_PACKAGE_DEPENDENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 354;
-    int ENTER_PICTURE_IN_PICTURE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 355;
-    int ACTIVITY_RELAUNCHED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 356;
-    int GET_URI_PERMISSION_OWNER_FOR_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 357;
-    int RESIZE_DOCKED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 358;
-    int SET_VR_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 359;
-    int GET_GRANTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 360;
-    int CLEAR_GRANTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 361;
-    int IS_APP_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 362;
-    int START_LOCAL_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 363;
-    int STOP_LOCAL_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 364;
-    int SUPPORTS_LOCAL_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 365;
-    int NOTIFY_PINNED_STACK_ANIMATION_ENDED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 366;
-    int REMOVE_STACK = IBinder.FIRST_CALL_TRANSACTION + 367;
-    int SET_LENIENT_BACKGROUND_CHECK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+368;
-    int GET_MEMORY_TRIM_LEVEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+369;
-    int RESIZE_PINNED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 370;
-    int IS_VR_PACKAGE_ENABLED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 371;
-    int SWAP_DOCKED_AND_FULLSCREEN_STACK = IBinder.FIRST_CALL_TRANSACTION + 372;
-    int NOTIFY_LOCKED_PROFILE = IBinder.FIRST_CALL_TRANSACTION + 373;
-    int START_CONFIRM_DEVICE_CREDENTIAL_INTENT = IBinder.FIRST_CALL_TRANSACTION + 374;
-    int SEND_IDLE_JOB_TRIGGER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 375;
-    int SEND_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 376;
-
-    // Start of N MR1 transactions
-    int SET_VR_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 377;
-    int SET_RENDER_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 378;
-    int SET_HAS_TOP_UI = IBinder.FIRST_CALL_TRANSACTION + 379;
-    int CAN_BYPASS_WORK_CHALLENGE = IBinder.FIRST_CALL_TRANSACTION + 380;
-
-    // Start of O transactions
-    int REQUEST_ACTIVITY_RELAUNCH = IBinder.FIRST_CALL_TRANSACTION+400;
-    int UPDATE_DISPLAY_OVERRIDE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 401;
-    int UNREGISTER_TASK_STACK_LISTENER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+402;
-}
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index e2f6fb5..c2b5b93 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -56,30 +56,30 @@
      * When adding a new method, assign the next available transaction id.
      */
     void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
-            int configChanges, boolean dontReport) = 1;
+            int configChanges, boolean dontReport) = 0;
     void scheduleStopActivity(IBinder token, boolean showWindow,
-            int configChanges) = 3;
-    void scheduleWindowVisibility(IBinder token, boolean showWindow) = 4;
+            int configChanges) = 2;
+    void scheduleWindowVisibility(IBinder token, boolean showWindow) = 3;
     void scheduleResumeActivity(IBinder token, int procState, boolean isForward,
-            in Bundle resumeArgs) = 5;
-    void scheduleSendResult(IBinder token, in List<ResultInfo> results) = 6;
+            in Bundle resumeArgs) = 4;
+    void scheduleSendResult(IBinder token, in List<ResultInfo> results) = 5;
     void scheduleLaunchActivity(in Intent intent, IBinder token, int ident,
             in ActivityInfo info, in Configuration curConfig, in Configuration overrideConfig,
             in CompatibilityInfo compatInfo, in String referrer, IVoiceInteractor voiceInteractor,
             int procState, in Bundle state, in PersistableBundle persistentState,
             in List<ResultInfo> pendingResults, in List<ReferrerIntent> pendingNewIntents,
-            boolean notResumed, boolean isForward, in ProfilerInfo profilerInfo) = 7;
+            boolean notResumed, boolean isForward, in ProfilerInfo profilerInfo) = 6;
     void scheduleNewIntent(
-            in List<ReferrerIntent> intent, IBinder token, boolean andPause) = 8;
+            in List<ReferrerIntent> intent, IBinder token, boolean andPause) = 7;
     void scheduleDestroyActivity(IBinder token, boolean finished,
-            int configChanges) = 9;
+            int configChanges) = 8;
     void scheduleReceiver(in Intent intent, in ActivityInfo info,
             in CompatibilityInfo compatInfo,
             int resultCode, in String data, in Bundle extras, boolean sync,
-            int sendingUser, int processState) = 10;
+            int sendingUser, int processState) = 9;
     void scheduleCreateService(IBinder token, in ServiceInfo info,
-            in CompatibilityInfo compatInfo, int processState) = 11;
-    void scheduleStopService(IBinder token) = 12;
+            in CompatibilityInfo compatInfo, int processState) = 10;
+    void scheduleStopService(IBinder token) = 11;
     void bindApplication(in String packageName, in ApplicationInfo info,
             in List<ProviderInfo> providers, in ComponentName testName,
             in ProfilerInfo profilerInfo, in Bundle testArguments,
@@ -87,75 +87,75 @@
             int debugMode, boolean enableBinderTracking, boolean trackAllocation,
             boolean restrictedBackupMode, boolean persistent, in Configuration config,
             in CompatibilityInfo compatInfo, in Map services,
-            in Bundle coreSettings, in String buildSerial) = 13;
-    void scheduleExit() = 14;
-    void scheduleConfigurationChanged(in Configuration config) = 16;
+            in Bundle coreSettings, in String buildSerial) = 12;
+    void scheduleExit() = 13;
+    void scheduleConfigurationChanged(in Configuration config) = 15;
     void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
-            int flags, in Intent args) = 17;
-    void updateTimeZone() = 18;
-    void processInBackground() = 19;
+            int flags, in Intent args) = 16;
+    void updateTimeZone() = 17;
+    void processInBackground() = 18;
     void scheduleBindService(IBinder token,
-            in Intent intent, boolean rebind, int processState) = 20;
+            in Intent intent, boolean rebind, int processState) = 19;
     void scheduleUnbindService(IBinder token,
-            in Intent intent) = 21;
+            in Intent intent) = 20;
     void dumpService(in ParcelFileDescriptor fd, IBinder servicetoken,
-            in String[] args) = 22;
+            in String[] args) = 21;
     void scheduleRegisteredReceiver(IIntentReceiver receiver, in Intent intent,
             int resultCode, in String data, in Bundle extras, boolean ordered,
-            boolean sticky, int sendingUser, int processState) = 23;
-    void scheduleLowMemory() = 24;
+            boolean sticky, int sendingUser, int processState) = 22;
+    void scheduleLowMemory() = 23;
     void scheduleActivityConfigurationChanged(IBinder token, in Configuration overrideConfig,
-            boolean reportToActivity) = 25;
+            boolean reportToActivity) = 24;
     void scheduleRelaunchActivity(IBinder token, in List<ResultInfo> pendingResults,
             in List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed,
-            in Configuration config, in Configuration overrideConfig, boolean preserveWindow) = 26;
-    void scheduleSleeping(IBinder token, boolean sleeping) = 27;
-    void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType) = 28;
-    void setSchedulingGroup(int group) = 29;
+            in Configuration config, in Configuration overrideConfig, boolean preserveWindow) = 25;
+    void scheduleSleeping(IBinder token, boolean sleeping) = 26;
+    void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType) = 27;
+    void setSchedulingGroup(int group) = 28;
     void scheduleCreateBackupAgent(in ApplicationInfo app, in CompatibilityInfo compatInfo,
-            int backupMode) = 30;
+            int backupMode) = 29;
     void scheduleDestroyBackupAgent(in ApplicationInfo app,
-            in CompatibilityInfo compatInfo) = 31;
-    void scheduleOnNewActivityOptions(IBinder token, in Bundle options) = 32;
-    void scheduleSuicide() = 33;
-    void dispatchPackageBroadcast(int cmd, in String[] packages) = 34;
-    void scheduleCrash(in String msg) = 35;
-    void dumpHeap(boolean managed, in String path, in ParcelFileDescriptor fd) = 36;
+            in CompatibilityInfo compatInfo) = 30;
+    void scheduleOnNewActivityOptions(IBinder token, in Bundle options) = 31;
+    void scheduleSuicide() = 32;
+    void dispatchPackageBroadcast(int cmd, in String[] packages) = 33;
+    void scheduleCrash(in String msg) = 34;
+    void dumpHeap(boolean managed, in String path, in ParcelFileDescriptor fd) = 35;
     void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix,
-            in String[] args) = 37;
-    void clearDnsCache() = 38;
+            in String[] args) = 36;
+    void clearDnsCache() = 37;
     void setHttpProxy(in String proxy, in String port, in String exclList,
-            in Uri pacFileUrl) = 39;
-    void setCoreSettings(in Bundle coreSettings) = 40;
-    void updatePackageCompatibilityInfo(in String pkg, in CompatibilityInfo info) = 41;
-    void scheduleTrimMemory(int level) = 42;
+            in Uri pacFileUrl) = 38;
+    void setCoreSettings(in Bundle coreSettings) = 39;
+    void updatePackageCompatibilityInfo(in String pkg, in CompatibilityInfo info) = 40;
+    void scheduleTrimMemory(int level) = 41;
     void dumpMemInfo(in ParcelFileDescriptor fd, in Debug.MemoryInfo mem, boolean checkin,
             boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
-            in String[] args) = 43;
-    void dumpGfxInfo(in ParcelFileDescriptor fd, in String[] args) = 44;
+            in String[] args) = 42;
+    void dumpGfxInfo(in ParcelFileDescriptor fd, in String[] args) = 43;
     void dumpProvider(in ParcelFileDescriptor fd, IBinder servicetoken,
-            in String[] args) = 45;
-    void dumpDbInfo(in ParcelFileDescriptor fd, in String[] args) = 46;
-    void unstableProviderDied(IBinder provider) = 47;
+            in String[] args) = 44;
+    void dumpDbInfo(in ParcelFileDescriptor fd, in String[] args) = 45;
+    void unstableProviderDied(IBinder provider) = 46;
     void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
-            int requestType, int sessionId) = 48;
-    void scheduleTranslucentConversionComplete(IBinder token, boolean timeout) = 49;
-    void setProcessState(int state) = 50;
-    void scheduleInstallProvider(in ProviderInfo provider) = 51;
-    void updateTimePrefs(boolean is24Hour) = 52;
-    void scheduleCancelVisibleBehind(IBinder token) = 53;
-    void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean enabled) = 54;
-    void scheduleEnterAnimationComplete(IBinder token) = 55;
-    void notifyCleartextNetwork(in byte[] firstPacket) = 56;
-    void startBinderTracking() = 57;
-    void stopBinderTrackingAndDump(in ParcelFileDescriptor fd) = 58;
-    void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode) = 59;
+            int requestType, int sessionId) = 47;
+    void scheduleTranslucentConversionComplete(IBinder token, boolean timeout) = 48;
+    void setProcessState(int state) = 49;
+    void scheduleInstallProvider(in ProviderInfo provider) = 50;
+    void updateTimePrefs(boolean is24Hour) = 51;
+    void scheduleCancelVisibleBehind(IBinder token) = 52;
+    void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean enabled) = 53;
+    void scheduleEnterAnimationComplete(IBinder token) = 54;
+    void notifyCleartextNetwork(in byte[] firstPacket) = 55;
+    void startBinderTracking() = 56;
+    void stopBinderTrackingAndDump(in ParcelFileDescriptor fd) = 57;
+    void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode) = 58;
     void schedulePictureInPictureModeChanged(IBinder token,
-            boolean isInPictureInPictureMode) = 60;
+            boolean isInPictureInPictureMode) = 59;
     void scheduleLocalVoiceInteractionStarted(IBinder token,
-            IVoiceInteractor voiceInteractor) = 61;
-    void handleTrustStorageUpdate() = 62;
-    void attachAgent(String path) = 63;
+            IVoiceInteractor voiceInteractor) = 60;
+    void handleTrustStorageUpdate() = 61;
+    void attachAgent(String path) = 62;
     /**
      * Don't change the existing transaction Ids as they could be used in the native code.
      * When adding a new method, assign the next available transaction id.
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
index 70007f5..af55788 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -16,13 +16,21 @@
 
 package android.app;
 
+import static android.content.Context.DISPLAY_SERVICE;
+import static android.content.Context.WINDOW_SERVICE;
+import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
+import android.os.Binder;
+import android.os.IBinder;
 import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.Gravity;
+import android.view.Window;
+import android.view.WindowManager;
 import android.view.WindowManagerImpl;
 import android.os.Handler;
 import android.os.Message;
@@ -145,6 +153,7 @@
 
     private final Display mDisplay;
     private final DisplayManager mDisplayManager;
+    private final IBinder mToken = new Binder();
 
     /**
      * Creates a new presentation that is attached to the specified display
@@ -177,9 +186,14 @@
         super(createPresentationContext(outerContext, display, theme), theme, false);
 
         mDisplay = display;
-        mDisplayManager = (DisplayManager)getContext().getSystemService(Context.DISPLAY_SERVICE);
+        mDisplayManager = (DisplayManager)getContext().getSystemService(DISPLAY_SERVICE);
 
-        getWindow().setGravity(Gravity.FILL);
+        final Window w = getWindow();
+        final WindowManager.LayoutParams attr = w.getAttributes();
+        attr.token = mToken;
+        w.setAttributes(attr);
+        w.setGravity(Gravity.FILL);
+        w.setType(TYPE_PRESENTATION);
         setCanceledOnTouchOutside(false);
     }
 
@@ -308,13 +322,13 @@
         // such as the parent window, which is important if the presentation uses
         // an application window type.
         final WindowManagerImpl outerWindowManager =
-                (WindowManagerImpl)outerContext.getSystemService(Context.WINDOW_SERVICE);
+                (WindowManagerImpl)outerContext.getSystemService(WINDOW_SERVICE);
         final WindowManagerImpl displayWindowManager =
                 outerWindowManager.createPresentationWindowManager(displayContext);
         return new ContextThemeWrapper(displayContext, theme) {
             @Override
             public Object getSystemService(String name) {
-                if (Context.WINDOW_SERVICE.equals(name)) {
+                if (WINDOW_SERVICE.equals(name)) {
                     return displayWindowManager;
                 }
                 return super.getSystemService(name);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 2d46495..f38c0d8 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -81,8 +81,8 @@
 import android.net.wifi.RttManager;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiScanner;
-import android.net.wifi.nan.IWifiNanManager;
-import android.net.wifi.nan.WifiNanManager;
+import android.net.wifi.aware.IWifiAwareManager;
+import android.net.wifi.aware.WifiAwareManager;
 import android.net.wifi.p2p.IWifiP2pManager;
 import android.net.wifi.p2p.WifiP2pManager;
 import android.nfc.NfcManager;
@@ -510,16 +510,16 @@
                 return new WifiP2pManager(service);
             }});
 
-        registerService(Context.WIFI_NAN_SERVICE, WifiNanManager.class,
-                new CachedServiceFetcher<WifiNanManager>() {
+        registerService(Context.WIFI_AWARE_SERVICE, WifiAwareManager.class,
+                new CachedServiceFetcher<WifiAwareManager>() {
             @Override
-            public WifiNanManager createService(ContextImpl ctx) throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getService(Context.WIFI_NAN_SERVICE);
-                IWifiNanManager service = IWifiNanManager.Stub.asInterface(b);
+            public WifiAwareManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getService(Context.WIFI_AWARE_SERVICE);
+                IWifiAwareManager service = IWifiAwareManager.Stub.asInterface(b);
                 if (service == null) {
                     return null;
                 }
-                return new WifiNanManager(ctx.getOuterContext(), service);
+                return new WifiAwareManager(ctx.getOuterContext(), service);
             }});
 
         registerService(Context.WIFI_SCANNING_SERVICE, WifiScanner.class,
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/core/java/android/app/WaitResult.aidl
similarity index 90%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to core/java/android/app/WaitResult.aidl
index 5f66d16..22a6558 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/core/java/android/app/WaitResult.aidl
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.app;
 
-parcelable PublishConfig;
+/** @hide */
+parcelable WaitResult;
\ No newline at end of file
diff --git a/core/java/android/app/WaitResult.java b/core/java/android/app/WaitResult.java
new file mode 100644
index 0000000..af196cf
--- /dev/null
+++ b/core/java/android/app/WaitResult.java
@@ -0,0 +1,72 @@
+/*
+ * 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.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Information returned after waiting for an activity start.
+ *
+ * @hide
+ */
+public class WaitResult implements Parcelable {
+    public int result;
+    public boolean timeout;
+    public ComponentName who;
+    public long thisTime;
+    public long totalTime;
+
+    public WaitResult() {
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(result);
+        dest.writeInt(timeout ? 1 : 0);
+        ComponentName.writeToParcel(who, dest);
+        dest.writeLong(thisTime);
+        dest.writeLong(totalTime);
+    }
+
+    public static final Parcelable.Creator<WaitResult> CREATOR
+            = new Parcelable.Creator<WaitResult>() {
+        @Override
+        public WaitResult createFromParcel(Parcel source) {
+            return new WaitResult(source);
+        }
+
+        @Override
+        public WaitResult[] newArray(int size) {
+            return new WaitResult[size];
+        }
+    };
+
+    private WaitResult(Parcel source) {
+        result = source.readInt();
+        timeout = source.readInt() != 0;
+        who = ComponentName.readFromParcel(source);
+        thisTime = source.readLong();
+        totalTime = source.readLong();
+    }
+}
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/core/java/android/app/admin/ConnectEvent.aidl
similarity index 89%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to core/java/android/app/admin/ConnectEvent.aidl
index 5f66d16..bab40f5 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/core/java/android/app/admin/ConnectEvent.aidl
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.app.admin;
 
-parcelable PublishConfig;
+/** {@hide} */
+parcelable ConnectEvent;
+
diff --git a/core/java/android/app/admin/ConnectEvent.java b/core/java/android/app/admin/ConnectEvent.java
new file mode 100644
index 0000000..e05feaf
--- /dev/null
+++ b/core/java/android/app/admin/ConnectEvent.java
@@ -0,0 +1,87 @@
+/*
+ * 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.admin;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class that represents a connect library call event.
+ * @hide
+ */
+public final class ConnectEvent extends NetworkEvent implements Parcelable {
+
+    /** The destination IP address. */
+    private final String ipAddress;
+
+    /** The destination port number. */
+    private final int port;
+
+    public ConnectEvent(String ipAddress, int port, String packageName, long timestamp) {
+        super(packageName, timestamp);
+        this.ipAddress = ipAddress;
+        this.port = port;
+    }
+
+    private ConnectEvent(Parcel in) {
+        this.ipAddress = in.readString();
+        this.port = in.readInt();
+        this.packageName = in.readString();
+        this.timestamp = in.readLong();
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("ConnectEvent(%s, %d, %d, %s)", ipAddress, port, timestamp,
+                packageName);
+    }
+
+    public static final Parcelable.Creator<ConnectEvent> CREATOR
+            = new Parcelable.Creator<ConnectEvent>() {
+        @Override
+        public ConnectEvent createFromParcel(Parcel in) {
+            if (in.readInt() != PARCEL_TOKEN_CONNECT_EVENT) {
+                return null;
+            }
+            return new ConnectEvent(in);
+        }
+
+        @Override
+        public ConnectEvent[] newArray(int size) {
+            return new ConnectEvent[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        // write parcel token first
+        out.writeInt(PARCEL_TOKEN_CONNECT_EVENT);
+        out.writeString(ipAddress);
+        out.writeInt(port);
+        out.writeString(packageName);
+        out.writeLong(timestamp);
+    }
+}
+
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index dd70b5d..360087c 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -276,6 +276,15 @@
             = "android.app.action.SECURITY_LOGS_AVAILABLE";
 
     /**
+     * Broadcast action: notify that a new batch of network logs is ready to be collected.
+     * @see DeviceAdminReceiver#onNetworkLogsAvailable
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_NETWORK_LOGS_AVAILABLE
+            = "android.app.action.NETWORK_LOGS_AVAILABLE";
+
+    /**
      * A string containing the SHA-256 hash of the bugreport file.
      *
      * @see #ACTION_BUGREPORT_SHARE
@@ -635,6 +644,22 @@
     }
 
     /**
+     * Called when a new batch of network logs can be retrieved. This callback method will only ever
+     * be called when network logging is enabled. The logs can only be retrieved while network
+     * logging is enabled.
+     *
+     * <p>This callback is only applicable to device owners.
+     *
+     * @param context The running context as per {@link #onReceive}.
+     * @param intent The received intent as per {@link #onReceive}.
+     * @see DevicePolicyManager#retrieveNetworkLogs(ComponentName)
+     *
+     * @hide
+     */
+    public void onNetworkLogsAvailable(Context context, Intent intent) {
+    }
+
+    /**
      * Intercept standard device administrator broadcasts.  Implementations
      * should not override this method; it is better to implement the
      * convenience callbacks for each action.
@@ -688,6 +713,8 @@
             onBugreportFailed(context, intent, failureCode);
         } else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
             onSecurityLogsAvailable(context, intent);
+        } else if (ACTION_NETWORK_LOGS_AVAILABLE.equals(action)) {
+            onNetworkLogsAvailable(context, intent);
         }
     }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 105a064..538e52b 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -26,6 +26,7 @@
 import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
 import android.app.Activity;
+import android.app.admin.NetworkEvent;
 import android.app.admin.PasswordMetrics;
 import android.app.admin.SecurityLog.SecurityEvent;
 import android.content.ComponentName;
@@ -6650,6 +6651,7 @@
      * @throws {@link SecurityException} if {@code admin} is not a device owner.
      * @throws {@link RemoteException} if network logging could not be enabled or disabled due to
      *         the logging service not being available
+     * @see #retrieveNetworkLogs
      *
      * @hide
      */
@@ -6679,4 +6681,31 @@
             throw re.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Called by device owner to retrieve a new batch of network logging events.
+     *
+     * <p> {@link NetworkEvent} can be one of {@link DnsEvent} or {@link ConnectEvent}.
+     *
+     * <p> The list of network events is sorted chronologically, and contains at most 1200 events.
+     *
+     * <p> Access to the logs is rate limited and this method will only return a new batch of logs
+     * after the device device owner has been notified via
+     * {@link DeviceAdminReceiver#onNetworkLogsAvailable}.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @return A new batch of network logs which is a list of {@link NetworkEvent}. Returns
+     * {@code null} if there's no batch currently awaiting for retrieval or if logging is disabled.
+     * @throws {@link SecurityException} if {@code admin} is not a device owner.
+     *
+     * @hide
+     */
+    public List<NetworkEvent> retrieveNetworkLogs(@NonNull ComponentName admin) {
+        throwIfParentInstance("retrieveNetworkLogs");
+        try {
+            return mService.retrieveNetworkLogs(admin);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/core/java/android/app/admin/DnsEvent.aidl
similarity index 89%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to core/java/android/app/admin/DnsEvent.aidl
index 5f66d16..6da962a 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/core/java/android/app/admin/DnsEvent.aidl
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.app.admin;
 
-parcelable PublishConfig;
+/** {@hide} */
+parcelable DnsEvent;
+
diff --git a/core/java/android/app/admin/DnsEvent.java b/core/java/android/app/admin/DnsEvent.java
new file mode 100644
index 0000000..0ec134a
--- /dev/null
+++ b/core/java/android/app/admin/DnsEvent.java
@@ -0,0 +1,108 @@
+/*
+ * 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.admin;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class that represents a DNS lookup event.
+ * @hide
+ */
+public final class DnsEvent extends NetworkEvent implements Parcelable {
+
+    /** The hostname that was looked up. */
+    private final String hostname;
+
+    /** Contains (possibly a subset of) the IP addresses returned. */
+    private final String[] ipAddresses;
+
+    /**
+     * The number of IP addresses returned from the DNS lookup event. May be different from the
+     * length of ipAddresses if there were too many addresses to log.
+     */
+    private final int ipAddressesCount;
+
+    public DnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount,
+            String packageName, long timestamp) {
+        super(packageName, timestamp);
+        this.hostname = hostname;
+        this.ipAddresses = ipAddresses;
+        this.ipAddressesCount = ipAddressesCount;
+    }
+
+    private DnsEvent(Parcel in) {
+        this.hostname = in.readString();
+        this.ipAddresses = in.createStringArray();
+        this.ipAddressesCount = in.readInt();
+        this.packageName = in.readString();
+        this.timestamp = in.readLong();
+    }
+
+    /** Returns the hostname that was looked up. */
+    public String getHostname() {
+        return hostname;
+    }
+
+    /** Returns (possibly a subset of) the IP addresses returned. */
+    public String[] getIpAddresses() {
+        return ipAddresses;
+    }
+
+    /**
+     * Returns the number of IP addresses returned from the DNS lookup event. May be different from
+     * the length of ipAddresses if there were too many addresses to log.
+     */
+    public int getIpAddressesCount() {
+        return ipAddressesCount;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("DnsEvent(%s, %s, %d, %d, %s)", hostname,
+                (ipAddresses == null) ? "NONE" : String.join(" ", ipAddresses),
+                ipAddressesCount, timestamp, packageName);
+    }
+
+    public static final Parcelable.Creator<DnsEvent> CREATOR
+            = new Parcelable.Creator<DnsEvent>() {
+        @Override
+        public DnsEvent createFromParcel(Parcel in) {
+            if (in.readInt() != PARCEL_TOKEN_DNS_EVENT) {
+                return null;
+            }
+            return new DnsEvent(in);
+        }
+
+        @Override
+        public DnsEvent[] newArray(int size) {
+            return new DnsEvent[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        // write parcel token first
+        out.writeInt(PARCEL_TOKEN_DNS_EVENT);
+        out.writeString(hostname);
+        out.writeStringArray(ipAddresses);
+        out.writeInt(ipAddressesCount);
+        out.writeString(packageName);
+        out.writeLong(timestamp);
+    }
+}
+
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 3cfa1e8..b0aec8c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -17,6 +17,7 @@
 
 package android.app.admin;
 
+import android.app.admin.NetworkEvent;
 import android.app.admin.SystemUpdatePolicy;
 import android.app.admin.PasswordMetrics;
 import android.content.ComponentName;
@@ -317,4 +318,5 @@
 
     void setNetworkLoggingEnabled(in ComponentName admin, boolean enabled);
     boolean isNetworkLoggingEnabled(in ComponentName admin);
+    List<NetworkEvent> retrieveNetworkLogs(in ComponentName admin);
 }
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/core/java/android/app/admin/NetworkEvent.aidl
similarity index 89%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to core/java/android/app/admin/NetworkEvent.aidl
index 5f66d16..5fa5dbf 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/core/java/android/app/admin/NetworkEvent.aidl
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.app.admin;
 
-parcelable PublishConfig;
+/** {@hide} */
+parcelable NetworkEvent;
+
diff --git a/core/java/android/app/admin/NetworkEvent.java b/core/java/android/app/admin/NetworkEvent.java
new file mode 100644
index 0000000..ec7ed00
--- /dev/null
+++ b/core/java/android/app/admin/NetworkEvent.java
@@ -0,0 +1,85 @@
+/*
+ * 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.admin;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelFormatException;
+
+/**
+ * An abstract class that represents a network event.
+ * @hide
+ */
+public abstract class NetworkEvent implements Parcelable {
+
+    protected static final int PARCEL_TOKEN_DNS_EVENT = 1;
+    protected static final int PARCEL_TOKEN_CONNECT_EVENT = 2;
+
+    /** The package name of the UID that performed the query. */
+    protected String packageName;
+
+    /** The timestamp of the event being reported in milliseconds. */
+    protected long timestamp;
+
+    protected NetworkEvent() {
+        //empty constructor
+    }
+
+    protected NetworkEvent(String packageName, long timestamp) {
+        this.packageName = packageName;
+        this.timestamp = timestamp;
+    }
+
+    /** Returns the package name of the UID that performed the query. */
+    public String getPackageName() {
+        return packageName;
+    }
+
+    /** Returns the timestamp of the event being reported in milliseconds. */
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Parcelable.Creator<NetworkEvent> CREATOR
+            = new Parcelable.Creator<NetworkEvent>() {
+        public NetworkEvent createFromParcel(Parcel in) {
+            final int initialPosition = in.dataPosition();
+            final int parcelToken = in.readInt();
+            // we need to move back to the position from before we read parcelToken
+            in.setDataPosition(initialPosition);
+            switch (parcelToken) {
+                case PARCEL_TOKEN_DNS_EVENT:
+                    return DnsEvent.CREATOR.createFromParcel(in);
+                case PARCEL_TOKEN_CONNECT_EVENT:
+                    return ConnectEvent.CREATOR.createFromParcel(in);
+                default:
+                    throw new ParcelFormatException("Unexpected NetworkEvent token in parcel: "
+                            + parcelToken);
+            }
+        }
+
+        public NetworkEvent[] newArray(int size) {
+            return new NetworkEvent[size];
+        }
+    };
+}
+
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index f64bec7..3670b91 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -256,6 +256,15 @@
             return tag;
         }
 
+        private static @Metered int convertMetered(int metered) {
+            switch (metered) {
+                case android.net.NetworkStats.METERED_ALL : return METERED_ALL;
+                case android.net.NetworkStats.METERED_NO: return METERED_NO;
+                case android.net.NetworkStats.METERED_YES: return METERED_YES;
+            }
+            return 0;
+        }
+
         private static @Roaming int convertRoaming(int roaming) {
             switch (roaming) {
                 case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL;
@@ -530,8 +539,7 @@
         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.mMetered = Bucket.convertMetered(mRecycledSummaryEntry.metered);
         bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming);
         bucketOut.mBeginTimeStamp = mStartTimeStamp;
         bucketOut.mEndTimeStamp = mEndTimeStamp;
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index e805fab..6cd4e92 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -52,16 +52,17 @@
  * {@link #querySummaryForUser} <p />
  * {@link #querySummary} <p />
  * These queries aggregate network usage across the whole interval. Therefore there will be only one
- * bucket for a particular key and state and roaming combination. In case of the user-wide and
- * device-wide summaries a single bucket containing the totalised network usage is returned.
+ * bucket for a particular key, state, metered and roaming combination. In case of the user-wide
+ * and device-wide summaries a single bucket containing the totalised network usage is returned.
  * <h3>
  * History queries
  * </h3>
  * {@link #queryDetailsForUid} <p />
  * {@link #queryDetails} <p />
- * These queries do not aggregate over time but do aggregate over state and roaming. Therefore there
- * can be multiple buckets for a particular key but all Bucket's state is going to be
- * {@link NetworkStats.Bucket#STATE_ALL} and all Bucket's roaming is going to be
+ * These queries do not aggregate over time but do aggregate over state, metered and roaming.
+ * Therefore there can be multiple buckets for a particular key but all Bucket's state is going to
+ * be {@link NetworkStats.Bucket#STATE_ALL}, all Bucket's metered is going to be
+ * {@link NetworkStats.Bucket#METERED_ALL}, and all Bucket's roaming is going to be
  * {@link NetworkStats.Bucket#ROAMING_ALL}.
  * <p />
  * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
@@ -104,10 +105,11 @@
 
     /**
      * Query network usage statistics summaries. Result is summarised data usage for the whole
-     * device. Result is a single Bucket aggregated over time, state, uid, tag and roaming. This
-     * means the bucket's start and end timestamp are going to be the same as the 'startTime' and
-     * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
-     * {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE}
+     * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
+     * roaming. This means the bucket's start and end timestamp are going to be the same as the
+     * 'startTime' and 'endTime' parameters. State is going to be
+     * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
+     * tag {@link NetworkStats.Bucket#TAG_NONE}, metered {@link NetworkStats.Bucket#METERED_ALL},
      * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
      *
      * @param networkType As defined in {@link ConnectivityManager}, e.g.
@@ -143,8 +145,10 @@
      * Query network usage statistics summaries. Result is summarised data usage for all uids
      * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
      * This means the bucket's start and end timestamp are going to be the same as the 'startTime'
-     * and 'endTime' parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid
-     * {@link NetworkStats.Bucket#UID_ALL}.
+     * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
+     * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
+     * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
+     * {@link NetworkStats.Bucket#ROAMING_ALL}.
      *
      * @param networkType As defined in {@link ConnectivityManager}, e.g.
      *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
@@ -178,9 +182,10 @@
     /**
      * Query network usage statistics summaries. Result filtered to include only uids belonging to
      * calling user. Result is aggregated over time, hence all buckets will have the same start and
-     * end timestamps. Not aggregated over state or uid. This means buckets' start and end
-     * timestamps are going to be the same as the 'startTime' and 'endTime' parameters.
-     * State and uid are going to vary, and tag is going to be the same.
+     * end timestamps. Not aggregated over state, uid, metered, or roaming. This means buckets'
+     * start and end timestamps are going to be the same as the 'startTime' and 'endTime'
+     * parameters. State, uid, metered, and roaming are going to vary, and tag is going to be the
+     * same.
      *
      * @param networkType As defined in {@link ConnectivityManager}, e.g.
      *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
@@ -226,7 +231,9 @@
      * belonging to calling user. Result is aggregated over state but not aggregated over time.
      * This means buckets' start and end timestamps are going to be between 'startTime' and
      * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the
-     * same as the 'uid' parameter and tag the same as 'tag' parameter.
+     * same as the 'uid' parameter and tag the same as 'tag' parameter. metered is going to be
+     * {@link NetworkStats.Bucket#METERED_ALL}, and roaming is going to be
+     * {@link NetworkStats.Bucket#ROAMING_ALL}.
      * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
      * interpolate across partial buckets. Since bucket length is in the order of hours, this
      * method cannot be used to measure data usage on a fine grained time scale.
@@ -263,10 +270,12 @@
 
     /**
      * Query network usage statistics details. Result filtered to include only uids belonging to
-     * calling user. Result is aggregated over state but not aggregated over time or uid. This means
-     * buckets' start and end timestamps are going to be between 'startTime' and 'endTime'
-     * parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
-     * tag {@link NetworkStats.Bucket#TAG_NONE} and roaming is going to be
+     * calling user. Result is aggregated over state but not aggregated over time, uid, tag,
+     * metered, nor roaming. This means buckets' start and end timestamps are going to be between
+     * 'startTime' and 'endTime' parameters. State is going to be
+     * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
+     * tag {@link NetworkStats.Bucket#TAG_NONE}, metered is going to be
+     * {@link NetworkStats.Bucket#METERED_ALL}, and roaming is going to be
      * {@link NetworkStats.Bucket#ROAMING_ALL}.
      * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
      * interpolate across partial buckets. Since bucket length is in the order of hours, this
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2f2ffc9..322cc7b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2688,7 +2688,7 @@
             NETWORK_STATS_SERVICE,
             //@hide: NETWORK_POLICY_SERVICE,
             WIFI_SERVICE,
-            WIFI_NAN_SERVICE,
+            WIFI_AWARE_SERVICE,
             WIFI_P2P_SERVICE,
             WIFI_SCANNING_SERVICE,
             //@hide: WIFI_RTT_SERVICE,
@@ -3161,14 +3161,14 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
-     * {@link android.net.wifi.nan.WifiNanManager} for handling management of
-     * Wi-Fi NAN.
+     * {@link android.net.wifi.aware.WifiAwareManager} for handling management of
+     * Wi-Fi Aware.
      *
      * @see #getSystemService
-     * @see android.net.wifi.nan.WifiNanManager
-     * @hide PROPOSED_NAN_API
+     * @see android.net.wifi.aware.WifiAwareManager
+     * @hide PROPOSED_AWARE_API
      */
-    public static final String WIFI_NAN_SERVICE = "wifinan";
+    public static final String WIFI_AWARE_SERVICE = "wifiaware";
 
     /**
      * Use with {@link #getSystemService} to retrieve a {@link
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e031275..4eecd48 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3120,6 +3120,11 @@
      * URIs that can be opened with
      * {@link ContentResolver#openFileDescriptor(Uri, String)}.
      * <p>
+     * Callers can set a document URI through {@link #setData(Uri)} to indicate
+     * the initial location of documents navigator. System will do its best to
+     * launch the navigator in the specified document if it's a folder, or the
+     * folder that contains the specified document if not.
+     * <p>
      * Output: The URI of the item that was picked, returned in
      * {@link #getData()}. This must be a {@code content://} URI so that any
      * receiver can access it. If multiple documents were selected, they are
@@ -3156,6 +3161,11 @@
      * URIs that can be opened with
      * {@link ContentResolver#openFileDescriptor(Uri, String)}.
      * <p>
+     * Callers can set a document URI through {@link #setData(Uri)} to indicate
+     * the initial location of documents navigator. System will do its best to
+     * launch the navigator in the specified document if it's a folder, or the
+     * folder that contains the specified document if not.
+     * <p>
      * Output: The URI of the item that was created. This must be a
      * {@code content://} URI so that any receiver can access it.
      *
@@ -3178,6 +3188,11 @@
      * {@link DocumentsContract#buildChildDocumentsUriUsingTree(Uri, String)}
      * with the returned URI.
      * <p>
+     * Callers can set a document URI through {@link #setData(Uri)} to indicate
+     * the initial location of documents navigator. System will do its best to
+     * initiate the navigator in the specified document if it's a folder, or
+     * the folder that contains the specified document if not.
+     * <p>
      * Output: The URI representing the selected directory tree.
      *
      * @see DocumentsContract
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index ecfc00f..74ec8e4 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -489,14 +489,6 @@
     public static final int PRIVATE_FLAG_DIRECT_BOOT_AWARE = 1 << 6;
 
     /**
-     * Value for {@link #privateFlags}: set to {@code true} if the application
-     * is AutoPlay.
-     *
-     * {@hide}
-     */
-    public static final int PRIVATE_FLAG_AUTOPLAY = 1 << 7;
-
-    /**
      * When set, at least one component inside this application is direct boot
      * aware.
      *
@@ -1197,13 +1189,6 @@
     /**
      * @hide
      */
-    public boolean isAutoPlayApp() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_AUTOPLAY) != 0;
-    }
-
-    /**
-     * @hide
-     */
     public boolean isEphemeralApp() {
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_EPHEMERAL) != 0;
     }
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/core/java/android/content/pm/ConfigurationInfo.aidl
similarity index 74%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to core/java/android/content/pm/ConfigurationInfo.aidl
index 5f66d16..0fa1003 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/core/java/android/content/pm/ConfigurationInfo.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * 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
+ *     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,
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.content.pm;
 
-parcelable PublishConfig;
+parcelable ConfigurationInfo;
\ No newline at end of file
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 26e0346..052fa61 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2040,12 +2040,12 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
-     * {@link #hasSystemFeature}: The device supports Wi-Fi NAN.
+     * {@link #hasSystemFeature}: The device supports Wi-Fi Aware.
      *
-     * @hide PROPOSED_NAN_API
+     * @hide PROPOSED_AWARE_API
      */
     @SdkConstant(SdkConstantType.FEATURE)
-    public static final String FEATURE_WIFI_NAN = "android.hardware.wifi.nan";
+    public static final String FEATURE_WIFI_AWARE = "android.hardware.wifi.aware";
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index da4eb2d..1f013ae 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -189,4 +189,17 @@
     public abstract void revokeRuntimePermission(String packageName, String name, int userId,
             boolean overridePolicy);
 
+    /**
+     * Retrieve the official name associated with a user id.  This name is
+     * guaranteed to never change, though it is possible for the underlying
+     * user id to be changed.  That is, if you are storing information about
+     * user ids in persistent storage, you should use the string returned
+     * by this function instead of the raw user-id.
+     *
+     * @param uid The user id for which you would like to retrieve a name.
+     * @return Returns a unique name for the given user id, or null if the
+     * user id is not currently assigned.
+     */
+    public abstract String getNameForUid(int uid);
+
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 13c8ab1..bb9c18a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -23,6 +23,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -697,23 +698,23 @@
     public static PackageLite parsePackageLite(File packageFile, int flags)
             throws PackageParserException {
         if (packageFile.isDirectory()) {
-            return parseClusterPackageLite(packageFile, flags);
+            return parseClusterPackageLite(packageFile, flags, null);
         } else {
-            return parseMonolithicPackageLite(packageFile, flags);
+            return parseMonolithicPackageLite(packageFile, flags, null);
         }
     }
 
-    private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
-            throws PackageParserException {
+    private static PackageLite parseMonolithicPackageLite(File packageFile, int flags,
+            AssetManager cachedAssetManager) throws PackageParserException {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
-        final ApkLite baseApk = parseApkLite(packageFile, flags);
+        final ApkLite baseApk = parseApkLite(packageFile, flags, cachedAssetManager);
         final String packagePath = packageFile.getAbsolutePath();
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         return new PackageLite(packagePath, baseApk, null, null, null);
     }
 
-    private static PackageLite parseClusterPackageLite(File packageDir, int flags)
-            throws PackageParserException {
+    private static PackageLite parseClusterPackageLite(File packageDir, int flags,
+            AssetManager cachedAssetManager) throws PackageParserException {
         final File[] files = packageDir.listFiles();
         if (ArrayUtils.isEmpty(files)) {
             throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
@@ -727,7 +728,7 @@
         final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
         for (File file : files) {
             if (isApkFile(file)) {
-                final ApkLite lite = parseApkLite(file, flags);
+                final ApkLite lite = parseApkLite(file, flags, cachedAssetManager);
 
                 // Assert that all package names and version codes are
                 // consistent with the first one we encounter.
@@ -820,16 +821,16 @@
      * must be done separately in {@link #collectCertificates(Package, int)}.
      */
     private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
-        final PackageLite lite = parseClusterPackageLite(packageDir, 0);
+        final AssetManager assets = newConfiguredAssetManager();
+        final PackageLite lite = parseClusterPackageLite(packageDir, 0, assets);
 
         if (mOnlyCoreApps && !lite.coreApp) {
             throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                     "Not a coreApp: " + packageDir);
         }
 
-        final AssetManager assets = new AssetManager();
         try {
-            // Load the base and all splits into the AssetManager
+            // Load all splits into the AssetManager (base has already been loaded earlier)
             // so that resources can be overriden when parsing the manifests.
             loadApkIntoAssetManager(assets, lite.baseCodePath, flags);
 
@@ -879,7 +880,8 @@
      */
     @Deprecated
     public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
-        final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
+        final AssetManager assets = newConfiguredAssetManager();
+        final PackageLite lite = parseMonolithicPackageLite(apkFile, flags, assets);
         if (mOnlyCoreApps) {
             if (!lite.coreApp) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
@@ -887,7 +889,6 @@
             }
         }
 
-        final AssetManager assets = new AssetManager();
         try {
             final Package pkg = parseBaseApk(apkFile, assets, flags);
             pkg.setCodePath(apkFile.getAbsolutePath());
@@ -937,8 +938,6 @@
         XmlResourceParser parser = null;
         try {
             res = new Resources(assets, mMetrics, null);
-            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    Build.VERSION.RESOURCES_SDK_INT);
             parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
 
             final String[] outError = new String[1];
@@ -1304,6 +1303,13 @@
         return res;
     }
 
+    private static AssetManager newConfiguredAssetManager() {
+        AssetManager assetManager = new AssetManager();
+        assetManager.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                Build.VERSION.RESOURCES_SDK_INT);
+        return assetManager;
+    }
+
     /**
      * Utility method that retrieves lightweight details about a single APK
      * file, including package name, split name, and install location.
@@ -1314,15 +1320,17 @@
      */
     public static ApkLite parseApkLite(File apkFile, int flags)
             throws PackageParserException {
+        return parseApkLite(apkFile, flags, null);
+    }
+
+    private static ApkLite parseApkLite(File apkFile, int flags,
+            @Nullable AssetManager cachedAssetManager) throws PackageParserException {
         final String apkPath = apkFile.getAbsolutePath();
 
         AssetManager assets = null;
         XmlResourceParser parser = null;
         try {
-            assets = new AssetManager();
-            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    Build.VERSION.RESOURCES_SDK_INT);
-
+            assets = cachedAssetManager == null ? newConfiguredAssetManager() : cachedAssetManager;
             int cookie = assets.addAssetPath(apkPath);
             if (cookie == 0) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
@@ -1361,7 +1369,9 @@
                     "Failed to parse " + apkPath, e);
         } finally {
             IoUtils.closeQuietly(parser);
-            IoUtils.closeQuietly(assets);
+            if (cachedAssetManager == null) {
+                IoUtils.closeQuietly(assets);
+            }
         }
     }
 
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 8233ad2..c46fe29 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -553,6 +553,7 @@
             if (!mPreloading && useCache) {
                 final Drawable cachedDrawable = caches.getInstance(key, wrapper, theme);
                 if (cachedDrawable != null) {
+                    cachedDrawable.setChangingConfigurations(value.changingConfigurations);
                     return cachedDrawable;
                 }
             }
@@ -588,9 +589,11 @@
             // If we were able to obtain a drawable, store it in the appropriate
             // cache: preload, not themed, null theme, or theme-specific. Don't
             // pollute the cache with drawables loaded from a foreign density.
-            if (dr != null && useCache) {
+            if (dr != null) {
                 dr.setChangingConfigurations(value.changingConfigurations);
-                cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
+                if (useCache) {
+                    cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
+                }
             }
 
             return dr;
diff --git a/core/java/android/hardware/radio/RadioMetadata.java b/core/java/android/hardware/radio/RadioMetadata.java
index b7715da..d07b407 100644
--- a/core/java/android/hardware/radio/RadioMetadata.java
+++ b/core/java/android/hardware/radio/RadioMetadata.java
@@ -530,14 +530,13 @@
         Bitmap bmp = null;
         try {
             bmp = BitmapFactory.decodeByteArray(value, 0, value.length);
-        } catch (Exception e) {
-        } finally {
-            if (bmp == null) {
-                return -1;
+            if (bmp != null) {
+                mBundle.putParcelable(key, bmp);
+                return 0;
             }
-            mBundle.putParcelable(key, bmp);
-            return 0;
+        } catch (Exception e) {
         }
+        return -1;
     }
 
     int putClockFromNative(int nativeKey, long utcEpochSeconds, int timezoneOffsetInMinutes) {
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 6196400..dacea55 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -419,14 +419,14 @@
     public static final int TRANSPORT_VPN = 4;
 
     /**
-     * Indicates this network uses a Wi-Fi NAN transport.
+     * Indicates this network uses a Wi-Fi Aware transport.
      *
-     * @hide PROPOSED_NAN_API
+     * @hide PROPOSED_AWARE_API
      */
-    public static final int TRANSPORT_WIFI_NAN = 5;
+    public static final int TRANSPORT_WIFI_AWARE = 5;
 
     private static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
-    private static final int MAX_TRANSPORT = TRANSPORT_WIFI_NAN;
+    private static final int MAX_TRANSPORT = TRANSPORT_WIFI_AWARE;
 
     /**
      * Adds the given transport type to this {@code NetworkCapability} instance.
@@ -896,7 +896,7 @@
                 case TRANSPORT_BLUETOOTH:   transports += "BLUETOOTH"; break;
                 case TRANSPORT_ETHERNET:    transports += "ETHERNET"; break;
                 case TRANSPORT_VPN:         transports += "VPN"; break;
-                case TRANSPORT_WIFI_NAN:    transports += "WIFI_NAN"; break;
+                case TRANSPORT_WIFI_AWARE:  transports += "WIFI_AWARE"; break;
             }
             if (++i < types.length) transports += "|";
         }
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index d570e66..c704ef0 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -171,7 +171,8 @@
         String subscriberId = null;
         String networkId = null;
         boolean roaming = false;
-        boolean metered = false;
+        boolean metered = !state.networkCapabilities.hasCapability(
+                NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
 
         if (isNetworkTypeMobile(type)) {
             if (state.subscriberId == null) {
@@ -185,9 +186,6 @@
             subscriberId = state.subscriberId;
             roaming = state.networkInfo.isRoaming();
 
-            metered = !state.networkCapabilities.hasCapability(
-                    NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
-
         } else if (type == TYPE_WIFI) {
             if (state.networkId != null) {
                 networkId = state.networkId;
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index f65a50f..77ce65b 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -68,11 +68,18 @@
     // TODO: Rename TAG_NONE to TAG_ALL.
     public static final int TAG_NONE = 0;
 
-    /** {@link #set} value for all roaming values. */
+    /** {@link #metered} value to account for all metered states. */
+    public static final int METERED_ALL = -1;
+    /** {@link #metered} value where native, unmetered data is accounted. */
+    public static final int METERED_NO = 0;
+    /** {@link #metered} value where metered data is accounted. */
+    public static final int METERED_YES = 1;
+
+    /** {@link #roaming} value to account for all roaming states. */
     public static final int ROAMING_ALL = -1;
-    /** {@link #set} value where native, non-roaming data is accounted. */
+    /** {@link #roaming} value where native, non-roaming data is accounted. */
     public static final int ROAMING_NO = 0;
-    /** {@link #set} value where roaming data is accounted. */
+    /** {@link #roaming} value where roaming data is accounted. */
     public static final int ROAMING_YES = 1;
 
     // TODO: move fields to "mVariable" notation
@@ -88,6 +95,7 @@
     private int[] uid;
     private int[] set;
     private int[] tag;
+    private int[] metered;
     private int[] roaming;
     private long[] rxBytes;
     private long[] rxPackets;
@@ -105,6 +113,12 @@
          * to disk. We merge in the correct value when reporting this value to clients of
          * getSummary().
          */
+        public int metered;
+        /**
+         * Note that this is only populated w/ the default value when read from /proc or written
+         * to disk. We merge in the correct value when reporting this value to clients of
+         * getSummary().
+         */
         public int roaming;
         public long rxBytes;
         public long rxPackets;
@@ -123,16 +137,17 @@
 
         public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
                 long txBytes, long txPackets, long operations) {
-            this(iface, uid, set, tag, ROAMING_NO, rxBytes, rxPackets, txBytes, txPackets,
-                    operations);
+            this(iface, uid, set, tag, METERED_NO, ROAMING_NO, rxBytes, rxPackets, txBytes,
+                    txPackets, operations);
         }
 
-        public Entry(String iface, int uid, int set, int tag, int roaming, long rxBytes,
-                long rxPackets, long txBytes, long txPackets, long operations) {
+        public Entry(String iface, int uid, int set, int tag, int metered, int roaming,
+                 long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
             this.iface = iface;
             this.uid = uid;
             this.set = set;
             this.tag = tag;
+            this.metered = metered;
             this.roaming = roaming;
             this.rxBytes = rxBytes;
             this.rxPackets = rxPackets;
@@ -165,6 +180,7 @@
             builder.append(" uid=").append(uid);
             builder.append(" set=").append(setToString(set));
             builder.append(" tag=").append(tagToString(tag));
+            builder.append(" metered=").append(meteredToString(metered));
             builder.append(" roaming=").append(roamingToString(roaming));
             builder.append(" rxBytes=").append(rxBytes);
             builder.append(" rxPackets=").append(rxPackets);
@@ -178,13 +194,18 @@
         public boolean equals(Object o) {
             if (o instanceof Entry) {
                 final Entry e = (Entry) o;
-                return uid == e.uid && set == e.set && tag == e.tag && roaming == e.roaming
-                        && rxBytes == e.rxBytes && rxPackets == e.rxPackets && txBytes == e.txBytes
-                        && txPackets == e.txPackets && operations == e.operations
-                        && iface.equals(e.iface);
+                return uid == e.uid && set == e.set && tag == e.tag && metered == e.metered
+                        && roaming == e.roaming && rxBytes == e.rxBytes && rxPackets == e.rxPackets
+                        && txBytes == e.txBytes && txPackets == e.txPackets
+                        && operations == e.operations && iface.equals(e.iface);
             }
             return false;
         }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(uid, set, tag, metered, roaming, iface);
+        }
     }
 
     public NetworkStats(long elapsedRealtime, int initialSize) {
@@ -196,6 +217,7 @@
             this.uid = new int[initialSize];
             this.set = new int[initialSize];
             this.tag = new int[initialSize];
+            this.metered = new int[initialSize];
             this.roaming = new int[initialSize];
             this.rxBytes = new long[initialSize];
             this.rxPackets = new long[initialSize];
@@ -209,6 +231,7 @@
             this.uid = EmptyArray.INT;
             this.set = EmptyArray.INT;
             this.tag = EmptyArray.INT;
+            this.metered = EmptyArray.INT;
             this.roaming = EmptyArray.INT;
             this.rxBytes = EmptyArray.LONG;
             this.rxPackets = EmptyArray.LONG;
@@ -226,6 +249,7 @@
         uid = parcel.createIntArray();
         set = parcel.createIntArray();
         tag = parcel.createIntArray();
+        metered = parcel.createIntArray();
         roaming = parcel.createIntArray();
         rxBytes = parcel.createLongArray();
         rxPackets = parcel.createLongArray();
@@ -243,6 +267,7 @@
         dest.writeIntArray(uid);
         dest.writeIntArray(set);
         dest.writeIntArray(tag);
+        dest.writeIntArray(metered);
         dest.writeIntArray(roaming);
         dest.writeLongArray(rxBytes);
         dest.writeLongArray(rxPackets);
@@ -277,10 +302,11 @@
     }
 
     @VisibleForTesting
-    public NetworkStats addValues(String iface, int uid, int set, int tag, int roaming,
+    public NetworkStats addValues(String iface, int uid, int set, int tag, int metered, int roaming,
             long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
         return addValues(new Entry(
-                iface, uid, set, tag, roaming, rxBytes, rxPackets, txBytes, txPackets, operations));
+                iface, uid, set, tag, metered, roaming, rxBytes, rxPackets, txBytes, txPackets,
+                operations));
     }
 
     /**
@@ -294,6 +320,7 @@
             uid = Arrays.copyOf(uid, newLength);
             set = Arrays.copyOf(set, newLength);
             tag = Arrays.copyOf(tag, newLength);
+            metered = Arrays.copyOf(metered, newLength);
             roaming = Arrays.copyOf(roaming, newLength);
             rxBytes = Arrays.copyOf(rxBytes, newLength);
             rxPackets = Arrays.copyOf(rxPackets, newLength);
@@ -307,6 +334,7 @@
         uid[size] = entry.uid;
         set[size] = entry.set;
         tag[size] = entry.tag;
+        metered[size] = entry.metered;
         roaming[size] = entry.roaming;
         rxBytes[size] = entry.rxBytes;
         rxPackets[size] = entry.rxPackets;
@@ -327,6 +355,7 @@
         entry.uid = uid[i];
         entry.set = set[i];
         entry.tag = tag[i];
+        entry.metered = metered[i];
         entry.roaming = roaming[i];
         entry.rxBytes = rxBytes[i];
         entry.rxPackets = rxPackets[i];
@@ -381,7 +410,8 @@
      * also be used to subtract values from existing rows.
      */
     public NetworkStats combineValues(Entry entry) {
-        final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.roaming);
+        final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered,
+                entry.roaming);
         if (i == -1) {
             // only create new entry when positive contribution
             addValues(entry);
@@ -409,10 +439,11 @@
     /**
      * Find first stats index that matches the requested parameters.
      */
-    public int findIndex(String iface, int uid, int set, int tag, int roaming) {
+    public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming) {
         for (int i = 0; i < size; i++) {
             if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
-                    && roaming == this.roaming[i] && Objects.equals(iface, this.iface[i])) {
+                    && metered == this.metered[i] && roaming == this.roaming[i]
+                    && Objects.equals(iface, this.iface[i])) {
                 return i;
             }
         }
@@ -424,7 +455,7 @@
      * search around the hinted index as an optimization.
      */
     @VisibleForTesting
-    public int findIndexHinted(String iface, int uid, int set, int tag, int roaming,
+    public int findIndexHinted(String iface, int uid, int set, int tag, int metered, int roaming,
             int hintIndex) {
         for (int offset = 0; offset < size; offset++) {
             final int halfOffset = offset / 2;
@@ -438,7 +469,8 @@
             }
 
             if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
-                    && roaming == this.roaming[i] && Objects.equals(iface, this.iface[i])) {
+                    && metered == this.metered[i] && roaming == this.roaming[i]
+                    && Objects.equals(iface, this.iface[i])) {
                 return i;
             }
         }
@@ -452,7 +484,7 @@
      */
     public void spliceOperationsFrom(NetworkStats stats) {
         for (int i = 0; i < size; i++) {
-            final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], roaming[i]);
+            final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], metered[i], roaming[i]);
             if (j == -1) {
                 operations[i] = 0;
             } else {
@@ -542,6 +574,7 @@
         entry.uid = limitUid;
         entry.set = SET_ALL;
         entry.tag = TAG_NONE;
+        entry.metered = METERED_ALL;
         entry.roaming = ROAMING_ALL;
         entry.rxBytes = 0;
         entry.rxPackets = 0;
@@ -637,11 +670,12 @@
             entry.uid = left.uid[i];
             entry.set = left.set[i];
             entry.tag = left.tag[i];
+            entry.metered = left.metered[i];
             entry.roaming = left.roaming[i];
 
             // find remote row that matches, and subtract
             final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag,
-                    entry.roaming, i);
+                    entry.metered, entry.roaming, i);
             if (j == -1) {
                 // newly appearing row, return entire value
                 entry.rxBytes = left.rxBytes[i];
@@ -687,6 +721,7 @@
         entry.uid = UID_ALL;
         entry.set = SET_ALL;
         entry.tag = TAG_NONE;
+        entry.metered = METERED_ALL;
         entry.roaming = ROAMING_ALL;
         entry.operations = 0L;
 
@@ -716,6 +751,7 @@
         entry.iface = IFACE_ALL;
         entry.set = SET_ALL;
         entry.tag = TAG_NONE;
+        entry.metered = METERED_ALL;
         entry.roaming = ROAMING_ALL;
 
         for (int i = 0; i < size; i++) {
@@ -762,6 +798,7 @@
             pw.print(" uid="); pw.print(uid[i]);
             pw.print(" set="); pw.print(setToString(set[i]));
             pw.print(" tag="); pw.print(tagToString(tag[i]));
+            pw.print(" metered="); pw.print(meteredToString(metered[i]));
             pw.print(" roaming="); pw.print(roamingToString(roaming[i]));
             pw.print(" rxBytes="); pw.print(rxBytes[i]);
             pw.print(" rxPackets="); pw.print(rxPackets[i]);
@@ -830,6 +867,22 @@
     }
 
     /**
+     * Return text description of {@link #metered} value.
+     */
+    public static String meteredToString(int metered) {
+        switch (metered) {
+            case METERED_ALL:
+                return "ALL";
+            case METERED_NO:
+                return "NO";
+            case METERED_YES:
+                return "YES";
+            default:
+                return "UNKNOWN";
+        }
+    }
+
+    /**
      * Return text description of {@link #roaming} value.
      */
     public static String roamingToString(int roaming) {
@@ -998,6 +1051,7 @@
                 tmpEntry.uid = uid[i];
                 tmpEntry.tag = tag[i];
                 tmpEntry.set = set[i];
+                tmpEntry.metered = metered[i];
                 tmpEntry.roaming = roaming[i];
                 combineValues(tmpEntry);
                 if (tag[i] == TAG_NONE) {
@@ -1017,24 +1071,25 @@
         moved.set = SET_DBG_VPN_OUT;
         moved.tag = TAG_NONE;
         moved.iface = underlyingIface;
+        moved.metered = METERED_ALL;
         moved.roaming = ROAMING_ALL;
         combineValues(moved);
 
         // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
         // the TAG_NONE traffic.
         //
-        // Relies on the fact that the underlying traffic only has state ROAMING_NO, which
-        // should be the case as it comes directly from the /proc file. We only blend in the
+        // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO,
+        // which should be the case as it comes directly from the /proc file. We only blend in the
         // roaming data after applying these adjustments, by checking the NetworkIdentity of the
         // underlying iface.
         int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE,
-                ROAMING_NO);
+                METERED_NO, ROAMING_NO);
         if (idxVpnBackground != -1) {
             tunSubtract(idxVpnBackground, this, moved);
         }
 
         int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE,
-                ROAMING_NO);
+                METERED_NO, ROAMING_NO);
         if (idxVpnForeground != -1) {
             tunSubtract(idxVpnForeground, this, moved);
         }
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index cf77567..7b7533b 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -563,7 +563,11 @@
         boolean res;
         // Log any exceptions as warnings, don't silently suppress them.
         // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
+        final boolean tracingEnabled = Binder.isTracingEnabled();
         try {
+            if (tracingEnabled) {
+                Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);
+            }
             res = onTransact(code, data, reply, flags);
         } catch (RemoteException|RuntimeException e) {
             if (LOG_RUNTIME_EXCEPTION) {
@@ -587,6 +591,10 @@
             reply.setDataPosition(0);
             reply.writeException(re);
             res = true;
+        } finally {
+            if (tracingEnabled) {
+                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
+            }
         }
         checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
         reply.recycle();
@@ -613,8 +621,21 @@
 
     public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
         Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
-        if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); }
-        return transactNative(code, data, reply, flags);
+        final boolean tracingEnabled = Binder.isTracingEnabled();
+        if (tracingEnabled) {
+            final Throwable tr = new Throwable();
+            Binder.getTransactionTracker().addTrace(tr);
+            StackTraceElement stackTraceElement = tr.getStackTrace()[1];
+            Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
+                    stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
+        }
+        try {
+            return transactNative(code, data, reply, flags);
+        } finally {
+            if (tracingEnabled) {
+                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
+            }
+        }
     }
 
     public native String getInterfaceDescriptor() throws RemoteException;
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 312a098..e5832c8 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -755,6 +755,11 @@
          * N MR1: Nougat++.
          */
         public static final int N_MR1 = 25;
+
+        /**
+         * O.
+         */
+        public static final int O = CUR_DEVELOPMENT; // STOPSHIP Replace with the real version.
     }
 
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/HardwarePropertiesManager.java b/core/java/android/os/HardwarePropertiesManager.java
index 6dec0dc..2b00ecb 100644
--- a/core/java/android/os/HardwarePropertiesManager.java
+++ b/core/java/android/os/HardwarePropertiesManager.java
@@ -55,9 +55,7 @@
     public @interface TemperatureSource {}
 
     /**
-     * Device temperature types. These must match the values in
-     * frameworks/native/include/hardwareproperties/HardwarePropertiesManager.h
-     * TODO(b/32022261) Remove this comment.
+     * Device temperature types.
      */
     /** Temperature of CPUs in Celsius. */
     public static final int DEVICE_TEMPERATURE_CPU = Constants.TemperatureType.CPU;
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/core/java/android/os/StrictMode.aidl
similarity index 73%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to core/java/android/os/StrictMode.aidl
index 5f66d16..d045db4 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/core/java/android/os/StrictMode.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * 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
+ *     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,
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.os;
 
-parcelable PublishConfig;
+/** @hide */
+parcelable StrictMode.ViolationInfo;
\ No newline at end of file
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index ff69cf6..e9a3936 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -16,6 +16,7 @@
 package android.os;
 
 import android.animation.ValueAnimator;
+import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.ActivityThread;
 import android.app.ApplicationErrorReport;
@@ -1554,7 +1555,7 @@
                     // We restore the current policy below, in the finally block.
                     setThreadPolicyMask(0);
 
-                    ActivityManagerNative.getDefault().handleApplicationStrictModeViolation(
+                    ActivityManager.getService().handleApplicationStrictModeViolation(
                         RuntimeInit.getApplicationObject(),
                         violationMaskSubset,
                         info);
@@ -2373,7 +2374,7 @@
      *
      * @hide
      */
-    public static class ViolationInfo {
+    public static class ViolationInfo implements Parcelable {
         public String message;
 
         /**
@@ -2528,6 +2529,7 @@
         /**
          * Save a ViolationInfo instance to a parcel.
          */
+        @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeString(message);
             crashInfo.writeToParcel(dest, flags);
@@ -2584,6 +2586,23 @@
             }
         }
 
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        public static final Parcelable.Creator<ViolationInfo> CREATOR =
+                new Parcelable.Creator<ViolationInfo>() {
+                    @Override
+                    public ViolationInfo createFromParcel(Parcel in) {
+                        return new ViolationInfo(in);
+                    }
+
+                    @Override
+                    public ViolationInfo[] newArray(int size) {
+                        return new ViolationInfo[size];
+                    }
+                };
     }
 
     // Dummy throwable, for now, since we don't know when or where the
diff --git a/core/java/android/os/TransactionTracker.java b/core/java/android/os/TransactionTracker.java
index 77f3e02..ebb4699 100644
--- a/core/java/android/os/TransactionTracker.java
+++ b/core/java/android/os/TransactionTracker.java
@@ -43,8 +43,8 @@
         resetTraces();
     }
 
-    public void addTrace() {
-        String trace = Log.getStackTraceString(new Throwable());
+    public void addTrace(Throwable tr) {
+        String trace = Log.getStackTraceString(tr);
         synchronized (this) {
             if (mTraces.containsKey(trace)) {
                 mTraces.put(trace, mTraces.get(trace) + 1);
diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl
index af0d7b7..390df99 100644
--- a/core/java/android/os/storage/IMountService.aidl
+++ b/core/java/android/os/storage/IMountService.aidl
@@ -38,29 +38,29 @@
     /**
      * Registers an IMountServiceListener for receiving async notifications.
      */
-    void registerListener(IMountServiceListener listener) = 1;
+    void registerListener(IMountServiceListener listener) = 0;
     /**
      * Unregisters an IMountServiceListener
      */
-    void unregisterListener(IMountServiceListener listener) = 2;
+    void unregisterListener(IMountServiceListener listener) = 1;
     /**
      * Returns true if a USB mass storage host is connected
      */
-    boolean isUsbMassStorageConnected() = 3;
+    boolean isUsbMassStorageConnected() = 2;
     /**
      * Enables / disables USB mass storage. The caller should check actual
      * status of enabling/disabling USB mass storage via StorageEventListener.
      */
-    void setUsbMassStorageEnabled(boolean enable) = 4;
+    void setUsbMassStorageEnabled(boolean enable) = 3;
     /**
      * Returns true if a USB mass storage host is enabled (media is shared)
      */
-    boolean isUsbMassStorageEnabled() = 5;
+    boolean isUsbMassStorageEnabled() = 4;
     /**
      * Mount external storage at given mount point. Returns an int consistent
      * with MountServiceResultCode
      */
-    int mountVolume(in String mountPoint) = 6;
+    int mountVolume(in String mountPoint) = 5;
     /**
      * Safely unmount external storage at given mount point. The unmount is an
      * asynchronous operation. Applications should register StorageEventListener
@@ -71,75 +71,75 @@
      * @param removeEncryption whether or not encryption mapping should be removed from the volume.
      *     This value implies {@code force}.
      */
-    void unmountVolume(in String mountPoint, boolean force, boolean removeEncryption) = 7;
+    void unmountVolume(in String mountPoint, boolean force, boolean removeEncryption) = 6;
     /**
      * Format external storage given a mount point. Returns an int consistent
      * with MountServiceResultCode
      */
-    int formatVolume(in String mountPoint) = 8;
+    int formatVolume(in String mountPoint) = 7;
     /**
      * Returns an array of pids with open files on the specified path.
      */
-    int[] getStorageUsers(in String path) = 9;
+    int[] getStorageUsers(in String path) = 8;
     /**
      * Gets the state of a volume via its mountpoint.
      */
-    String getVolumeState(in String mountPoint) = 10;
+    String getVolumeState(in String mountPoint) = 9;
     /*
      * Creates a secure container with the specified parameters. Returns an int
      * consistent with MountServiceResultCode
      */
     int createSecureContainer(in String id, int sizeMb, in String fstype, in String key,
-            int ownerUid, boolean external) = 11;
+            int ownerUid, boolean external) = 10;
     /*
      * Finalize a container which has just been created and populated. After
      * finalization, the container is immutable. Returns an int consistent with
      * MountServiceResultCode
      */
-    int finalizeSecureContainer(in String id) = 12;
+    int finalizeSecureContainer(in String id) = 11;
     /*
      * Destroy a secure container, and free up all resources associated with it.
      * NOTE: Ensure all references are released prior to deleting. Returns an
      * int consistent with MountServiceResultCode
      */
-    int destroySecureContainer(in String id, boolean force) = 13;
+    int destroySecureContainer(in String id, boolean force) = 12;
     /*
      * Mount a secure container with the specified key and owner UID. Returns an
      * int consistent with MountServiceResultCode
      */
-    int mountSecureContainer(in String id, in String key, int ownerUid, boolean readOnly) = 14;
+    int mountSecureContainer(in String id, in String key, int ownerUid, boolean readOnly) = 13;
     /*
      * Unount a secure container. Returns an int consistent with
      * MountServiceResultCode
      */
-    int unmountSecureContainer(in String id, boolean force) = 15;
+    int unmountSecureContainer(in String id, boolean force) = 14;
     /*
      * Returns true if the specified container is mounted
      */
-    boolean isSecureContainerMounted(in String id) = 16;
+    boolean isSecureContainerMounted(in String id) = 15;
     /*
      * Rename an unmounted secure container. Returns an int consistent with
      * MountServiceResultCode
      */
-    int renameSecureContainer(in String oldId, in String newId) = 17;
+    int renameSecureContainer(in String oldId, in String newId) = 16;
     /*
      * Returns the filesystem path of a mounted secure container.
      */
-    String getSecureContainerPath(in String id) = 18;
+    String getSecureContainerPath(in String id) = 17;
     /**
      * Gets an Array of currently known secure container IDs
      */
-    String[] getSecureContainerList() = 19;
+    String[] getSecureContainerList() = 18;
     /**
      * Shuts down the MountService and gracefully unmounts all external media.
      * Invokes call back once the shutdown is complete.
      */
-    void shutdown(IMountShutdownObserver observer) = 20;
+    void shutdown(IMountShutdownObserver observer) = 19;
     /**
      * Call into MountService by PackageManager to notify that its done
      * processing the media status update request.
      */
-    void finishMediaUpdate() = 21;
+    void finishMediaUpdate() = 20;
     /**
      * Mounts an Opaque Binary Blob (OBB) with the specified decryption key and
      * only allows the calling process's UID access to the contents.
@@ -147,43 +147,43 @@
      * it of the terminal state of the call.
      */
     void mountObb(in String rawPath, in String canonicalPath, in String key,
-            IObbActionListener token, int nonce) = 22;
+            IObbActionListener token, int nonce) = 21;
     /**
      * Unmounts an Opaque Binary Blob (OBB). When the force flag is specified,
      * any program using it will be forcibly killed to unmount the image.
      * MountService will call back to the supplied IObbActionListener to inform
      * it of the terminal state of the call.
      */
-    void unmountObb(in String rawPath, boolean force, IObbActionListener token, int nonce) = 23;
+    void unmountObb(in String rawPath, boolean force, IObbActionListener token, int nonce) = 22;
     /**
      * Checks whether the specified Opaque Binary Blob (OBB) is mounted
      * somewhere.
      */
-    boolean isObbMounted(in String rawPath) = 24;
+    boolean isObbMounted(in String rawPath) = 23;
     /**
      * Gets the path to the mounted Opaque Binary Blob (OBB).
      */
-    String getMountedObbPath(in String rawPath) = 25;
+    String getMountedObbPath(in String rawPath) = 24;
     /**
      * Returns whether or not the external storage is emulated.
      */
-    boolean isExternalStorageEmulated() = 26;
+    boolean isExternalStorageEmulated() = 25;
     /**
      * Decrypts any encrypted volumes.
      */
-    int decryptStorage(in String password) = 27;
+    int decryptStorage(in String password) = 26;
     /**
      * Encrypts storage.
      */
-    int encryptStorage(int type, in String password) = 28;
+    int encryptStorage(int type, in String password) = 27;
     /**
      * Changes the encryption password.
      */
-    int changeEncryptionPassword(int type, in String password) = 29;
+    int changeEncryptionPassword(int type, in String password) = 28;
     /**
      * Returns list of all mountable volumes.
      */
-    StorageVolume[] getVolumeList(int uid, in String packageName, int flags) = 30;
+    StorageVolume[] getVolumeList(int uid, in String packageName, int flags) = 29;
     /**
      * Gets the path on the filesystem for the ASEC container itself.
      *
@@ -191,7 +191,7 @@
      * @return path to filesystem or {@code null} if it's not found
      * @throws RemoteException
      */
-    String getSecureContainerFilesystemPath(in String cid) = 31;
+    String getSecureContainerFilesystemPath(in String cid) = 30;
     /**
      * Determines the encryption state of the volume.
      * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible
@@ -201,17 +201,17 @@
      * This is still useful to get the error state when encryption has failed
      * and CryptKeeper needs to throw up a screen advising the user what to do
      */
-    int getEncryptionState() = 32;
+    int getEncryptionState() = 31;
     /**
      * Verify the encryption password against the stored volume.  This method
      * may only be called by the system process.
      */
-    int verifyEncryptionPassword(in String password) = 33;
+    int verifyEncryptionPassword(in String password) = 32;
     /*
      * Fix permissions in a container which has just been created and populated.
      * Returns an int consistent with MountServiceResultCode
      */
-    int fixPermissionsSecureContainer(in String id, int gid, in String filename) = 34;
+    int fixPermissionsSecureContainer(in String id, int gid, in String filename) = 33;
     /**
      * Ensure that all directories along given path exist, creating parent
      * directories as needed. Validates that given path is absolute and that it
@@ -219,73 +219,73 @@
      * path belongs to a volume managed by vold, and that path is either
      * external storage data or OBB directory belonging to calling app.
      */
-    int mkdirs(in String callingPkg, in String path) = 35;
+    int mkdirs(in String callingPkg, in String path) = 34;
     /**
      * Determines the type of the encryption password
      * @return PasswordType
      */
-    int getPasswordType() = 36;
+    int getPasswordType() = 35;
     /**
      * Get password from vold
      * @return password or empty string
      */
-    String getPassword() = 37;
+    String getPassword() = 36;
     /**
      * Securely clear password from vold
      */
-    oneway void clearPassword() = 38;
+    oneway void clearPassword() = 37;
     /**
      * Set a field in the crypto header.
      * @param field field to set
      * @param contents contents to set in field
      */
-    oneway void setField(in String field, in String contents) = 39;
+    oneway void setField(in String field, in String contents) = 38;
     /**
      * Gets a field from the crypto header.
      * @param field field to get
      * @return contents of field
      */
-    String getField(in String field) = 40;
-    int resizeSecureContainer(in String id, int sizeMb, in String key) = 41;
+    String getField(in String field) = 39;
+    int resizeSecureContainer(in String id, int sizeMb, in String key) = 40;
     /**
      * Report the time of the last maintenance operation such as fstrim.
      * @return Timestamp of the last maintenance operation, in the
      *     System.currentTimeMillis() time base
      * @throws RemoteException
      */
-    long lastMaintenance() = 42;
+    long lastMaintenance() = 41;
     /**
      * Kick off an immediate maintenance operation
      * @throws RemoteException
      */
-    void runMaintenance() = 43;
-    void waitForAsecScan() = 44;
-    DiskInfo[] getDisks() = 45;
-    VolumeInfo[] getVolumes(int flags) = 46;
-    VolumeRecord[] getVolumeRecords(int flags) = 47;
-    void mount(in String volId) = 48;
-    void unmount(in String volId) = 49;
-    void format(in String volId) = 50;
-    void partitionPublic(in String diskId) = 51;
-    void partitionPrivate(in String diskId) = 52;
-    void partitionMixed(in String diskId, int ratio) = 53;
-    void setVolumeNickname(in String fsUuid, in String nickname) = 54;
-    void setVolumeUserFlags(in String fsUuid, int flags, int mask) = 55;
-    void forgetVolume(in String fsUuid) = 56;
-    void forgetAllVolumes() = 57;
-    String getPrimaryStorageUuid() = 58;
-    void setPrimaryStorageUuid(in String volumeUuid, IPackageMoveObserver callback) = 59;
-    long benchmark(in String volId) = 60;
-    void setDebugFlags(int flags, int mask) = 61;
-    void createUserKey(int userId, int serialNumber, boolean ephemeral) = 62;
-    void destroyUserKey(int userId) = 63;
-    void unlockUserKey(int userId, int serialNumber, in byte[] token, in byte[] secret) = 64;
-    void lockUserKey(int userId) = 65;
-    boolean isUserKeyUnlocked(int userId) = 66;
-    void prepareUserStorage(in String volumeUuid, int userId, int serialNumber, int flags) = 67;
-    void destroyUserStorage(in String volumeUuid, int userId, int flags) = 68;
-    boolean isConvertibleToFBE() = 69;
-    ParcelFileDescriptor mountAppFuse(in String name) = 70;
-    void addUserKeyAuth(int userId, int serialNumber, in byte[] token, in byte[] secret) = 71;
-    void fixateNewestUserKeyAuth(int userId) = 72;
+    void runMaintenance() = 42;
+    void waitForAsecScan() = 43;
+    DiskInfo[] getDisks() = 44;
+    VolumeInfo[] getVolumes(int flags) = 45;
+    VolumeRecord[] getVolumeRecords(int flags) = 46;
+    void mount(in String volId) = 47;
+    void unmount(in String volId) = 48;
+    void format(in String volId) = 49;
+    void partitionPublic(in String diskId) = 50;
+    void partitionPrivate(in String diskId) = 51;
+    void partitionMixed(in String diskId, int ratio) = 52;
+    void setVolumeNickname(in String fsUuid, in String nickname) = 53;
+    void setVolumeUserFlags(in String fsUuid, int flags, int mask) = 54;
+    void forgetVolume(in String fsUuid) = 55;
+    void forgetAllVolumes() = 56;
+    String getPrimaryStorageUuid() = 57;
+    void setPrimaryStorageUuid(in String volumeUuid, IPackageMoveObserver callback) = 58;
+    long benchmark(in String volId) = 59;
+    void setDebugFlags(int flags, int mask) = 60;
+    void createUserKey(int userId, int serialNumber, boolean ephemeral) = 61;
+    void destroyUserKey(int userId) = 62;
+    void unlockUserKey(int userId, int serialNumber, in byte[] token, in byte[] secret) = 63;
+    void lockUserKey(int userId) = 64;
+    boolean isUserKeyUnlocked(int userId) = 65;
+    void prepareUserStorage(in String volumeUuid, int userId, int serialNumber, int flags) = 66;
+    void destroyUserStorage(in String volumeUuid, int userId, int flags) = 67;
+    boolean isConvertibleToFBE() = 68;
+    ParcelFileDescriptor mountAppFuse(in String name) = 69;
+    void addUserKeyAuth(int userId, int serialNumber, in byte[] token, in byte[] secret) = 70;
+    void fixateNewestUserKeyAuth(int userId) = 71;
 }
\ No newline at end of file
diff --git a/core/java/android/os/storage/IMountServiceListener.aidl b/core/java/android/os/storage/IMountServiceListener.aidl
index e149978..0e20cd3 100644
--- a/core/java/android/os/storage/IMountServiceListener.aidl
+++ b/core/java/android/os/storage/IMountServiceListener.aidl
@@ -35,7 +35,7 @@
      *
      * @param available true if a UMS host is connected.
      */
-    void onUsbMassStorageConnectionChanged(boolean connected) = 1;
+    void onUsbMassStorageConnectionChanged(boolean connected) = 0;
 
     /**
      * Storage state has changed.
@@ -45,17 +45,17 @@
      * @param newState The new state of the volume. Note: State is one of the
      *            values returned by Environment.getExternalStorageState()
      */
-    void onStorageStateChanged(in String path, in String oldState, in String newState) = 2;
+    void onStorageStateChanged(in String path, in String oldState, in String newState) = 1;
 
-    void onVolumeStateChanged(in VolumeInfo vol, int oldState, int newState) = 3;
+    void onVolumeStateChanged(in VolumeInfo vol, int oldState, int newState) = 2;
 
-    void onVolumeRecordChanged(in VolumeRecord rec) = 4;
+    void onVolumeRecordChanged(in VolumeRecord rec) = 3;
 
-    void onVolumeForgotten(in String fsUuid) = 5;
+    void onVolumeForgotten(in String fsUuid) = 4;
 
-    void onDiskScanned(in DiskInfo disk, int volumeCount) = 6;
+    void onDiskScanned(in DiskInfo disk, int volumeCount) = 5;
 
-    void onDiskDestroyed(in DiskInfo disk) = 7;
+    void onDiskDestroyed(in DiskInfo disk) = 6;
 
     /**
      * Don't change the existing transaction Ids as they could be used in the native code.
diff --git a/core/java/android/os/storage/IMountShutdownObserver.aidl b/core/java/android/os/storage/IMountShutdownObserver.aidl
index 3353bc5..f3e1654 100644
--- a/core/java/android/os/storage/IMountShutdownObserver.aidl
+++ b/core/java/android/os/storage/IMountShutdownObserver.aidl
@@ -30,7 +30,7 @@
      *
      * @param statusCode indicates success or failure of the shutdown.
      */
-    void onShutDownComplete(int statusCode) = 1;
+    void onShutDownComplete(int statusCode) = 0;
 
     /**
      * Don't change the existing transaction Ids as they could be used in the native code.
diff --git a/core/java/android/os/storage/IObbActionListener.aidl b/core/java/android/os/storage/IObbActionListener.aidl
index 71e6aaf..61ba4d5 100644
--- a/core/java/android/os/storage/IObbActionListener.aidl
+++ b/core/java/android/os/storage/IObbActionListener.aidl
@@ -33,7 +33,7 @@
      * @param nonce identifier that is meaningful to the receiver
      * @param status status code as defined in {@link OnObbStateChangeListener}
      */
-    void onObbResult(in String filename, int nonce, int status) = 1;
+    void onObbResult(in String filename, int nonce, int status) = 0;
 
     /**
      * Don't change the existing transaction Ids as they could be used in the native code.
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 20c7073..2dcf220 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -636,7 +636,7 @@
     /** {@hide} */
     public static final String METHOD_EJECT_ROOT = "android:ejectRoot";
     /** {@hide} */
-    public static final String METHOD_FIND_PATH = "android:findPath";
+    public static final String METHOD_FIND_DOCUMENT_PATH = "android:findDocumentPath";
 
     /** {@hide} */
     public static final String EXTRA_PARENT_URI = "parentUri";
@@ -1304,22 +1304,20 @@
      * from the top of the tree or the root document to the requested document,
      * both inclusive.
      *
-     * Document id should be unique across roots.
+     * Document ID should be unique across roots.
      *
      * @param treeUri treeUri of the document which path is requested.
      * @return a list of documents ID starting from the top of the tree to the
      *      requested document, or {@code null} if failed.
-     * @see DocumentsProvider#findPath(String, String)
-     *
-     * {@hide}
+     * @see DocumentsProvider#findDocumentPath(String, String)
      */
-    public static List<String> findPath(ContentResolver resolver, Uri treeUri) {
+    public static List<String> findDocumentPath(ContentResolver resolver, Uri treeUri) {
         checkArgument(isTreeUri(treeUri), treeUri + " is not a tree uri.");
 
         final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
                 treeUri.getAuthority());
         try {
-            return findPath(client, treeUri).getPath();
+            return findDocumentPath(client, treeUri).getPath();
         } catch (Exception e) {
             Log.w(TAG, "Failed to find path", e);
             return null;
@@ -1339,15 +1337,17 @@
      * @param uri uri of the document which path is requested. It can be either a
      *          plain document uri or a tree uri.
      * @return the path of the document.
-     * @see DocumentsProvider#findPath(String, String)
+     * @see DocumentsProvider#findDocumentPath(String, String)
      *
      * {@hide}
      */
-    public static Path findPath(ContentProviderClient client, Uri uri) throws RemoteException {
+    public static Path findDocumentPath(ContentProviderClient client, Uri uri)
+            throws RemoteException {
+
         final Bundle in = new Bundle();
         in.putParcelable(DocumentsContract.EXTRA_URI, uri);
 
-        final Bundle out = client.call(METHOD_FIND_PATH, null, in);
+        final Bundle out = client.call(METHOD_FIND_DOCUMENT_PATH, null, in);
 
         return out.getParcelable(DocumentsContract.EXTRA_RESULT);
     }
@@ -1393,9 +1393,8 @@
     }
 
     /**
-     * Holds a path from a root to a particular document under it.
-     *
-     * @hide
+     * Holds a path from a document to a particular document under it. It
+     * may also contains the root ID where the path resides.
      */
     public static final class Path implements Parcelable {
 
@@ -1406,7 +1405,7 @@
          * Creates a Path.
          *
          * @param rootId the ID of the root. May be null.
-         * @param path the list of document ids from the parent document at
+         * @param path the list of document ID from the parent document at
          *          position 0 to the child document.
          */
         public Path(@Nullable String rootId, List<String> path) {
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 4256484..96c2556 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -20,7 +20,7 @@
 import static android.provider.DocumentsContract.METHOD_CREATE_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_DELETE_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_EJECT_ROOT;
-import static android.provider.DocumentsContract.METHOD_FIND_PATH;
+import static android.provider.DocumentsContract.METHOD_FIND_DOCUMENT_PATH;
 import static android.provider.DocumentsContract.METHOD_IS_CHILD_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_MOVE_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_REMOVE_DOCUMENT;
@@ -350,17 +350,15 @@
      * document.
      *
      * @param childDocumentId the document which path is requested.
-     * @param parentDocumentId the document with which path starts if not null, or
-     *     null to indicate path to root is requested.
+     * @param parentDocumentId the document from which the path starts if not null,
+     *     or null to indicate a path from the root is requested.
      * @return the path of the requested document. If parentDocumentId is null
      *     returned root ID must not be null. If parentDocumentId is not null
      *     returned root ID must be null.
-     *
-     * @hide
      */
-    public Path findPath(String childDocumentId, @Nullable String parentDocumentId)
+    public Path findDocumentPath(String childDocumentId, @Nullable String parentDocumentId)
             throws FileNotFoundException {
-        throw new UnsupportedOperationException("findPath not supported.");
+        throw new UnsupportedOperationException("findDocumentPath not supported.");
     }
 
     /**
@@ -468,9 +466,6 @@
      * least {@link Document#COLUMN_DISPLAY_NAME} be matched in a
      * case-insensitive fashion.
      * <p>
-     * Only documents may be returned; directories are not supported in search
-     * results.
-     * <p>
      * If your provider is cloud-based, and you have some data cached or pinned
      * locally, you may return the local data immediately, setting
      * {@link DocumentsContract#EXTRA_LOADING} on the Cursor to indicate that
@@ -914,7 +909,7 @@
 
             // It's responsibility of the provider to revoke any grants, as the document may be
             // still attached to another parents.
-        } else if (METHOD_FIND_PATH.equals(method)) {
+        } else if (METHOD_FIND_DOCUMENT_PATH.equals(method)) {
             final boolean isTreeUri = isTreeUri(documentUri);
 
             if (isTreeUri) {
@@ -927,7 +922,7 @@
                     ? DocumentsContract.getTreeDocumentId(documentUri)
                     : null;
 
-            Path path = findPath(documentId, parentDocumentId);
+            Path path = findDocumentPath(documentId, parentDocumentId);
 
             // Ensure provider doesn't leak information to unprivileged callers.
             if (isTreeUri) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 89c6eb2..1b905a0 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5161,18 +5161,10 @@
                 "accessibility_display_magnification_scale";
 
         /**
-         * Setting that specifies whether the display magnification should be
-         * automatically updated. If this fearture is enabled the system will
-         * exit magnification mode or pan the viewport when a context change
-         * occurs. For example, on staring a new activity or rotating the screen,
-         * the system may zoom out so the user can see the new context he is in.
-         * Another example is on showing a window that is not visible in the
-         * magnified viewport the system may pan the viewport to make the window
-         * the has popped up so the user knows that the context has changed.
-         * Whether a screen magnification is performed is controlled by
-         * {@link #ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED}
+         * Unused mangnification setting
          *
          * @hide
+         * @deprecated
          */
         public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE =
                 "accessibility_display_magnification_auto_update";
@@ -6491,7 +6483,6 @@
             ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
             ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
             ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
-            ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
             ACCESSIBILITY_SCRIPT_INJECTION,
             ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
             ENABLED_ACCESSIBILITY_SERVICES,
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index f9afcc7..fd6fc7d 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -634,6 +634,17 @@
     }
 
     /**
+     * Return the total height of this layout.
+     *
+     * @param cap if true and max lines is set, returns the height of the layout at the max lines.
+     *
+     * @hide
+     */
+    public int getHeight(boolean cap) {
+        return getHeight();
+    }
+
+    /**
      * Return the base alignment of this layout.
      */
     public final Alignment getAlignment() {
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index bdbe8b0..081be3a 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -836,7 +836,7 @@
                     here = endPos;
                     breakIndex++;
 
-                    if (mLineCount >= mMaximumVisibleLineCount) {
+                    if (mLineCount >= mMaximumVisibleLineCount && mEllipsized) {
                         return;
                     }
                 }
@@ -920,7 +920,25 @@
 
         boolean firstLine = (j == 0);
         boolean currentLineIsTheLastVisibleOne = (j + 1 == mMaximumVisibleLineCount);
-        boolean lastLine = currentLineIsTheLastVisibleOne || (end == bufEnd);
+
+        if (ellipsize != null) {
+            // If there is only one line, then do any type of ellipsis except when it is MARQUEE
+            // if there are multiple lines, just allow END ellipsis on the last line
+            boolean forceEllipsis = moreChars && (mLineCount + 1 == mMaximumVisibleLineCount);
+
+            boolean doEllipsis =
+                    (((mMaximumVisibleLineCount == 1 && moreChars) || (firstLine && !moreChars)) &&
+                            ellipsize != TextUtils.TruncateAt.MARQUEE) ||
+                    (!firstLine && (currentLineIsTheLastVisibleOne || !moreChars) &&
+                            ellipsize == TextUtils.TruncateAt.END);
+            if (doEllipsis) {
+                calculateEllipsis(start, end, widths, widthStart,
+                        ellipsisWidth, ellipsize, j,
+                        textWidth, paint, forceEllipsis);
+            }
+        }
+
+        boolean lastLine = mEllipsized || (end == bufEnd);
 
         if (firstLine) {
             if (trackPad) {
@@ -944,7 +962,6 @@
             }
         }
 
-
         if (needMultiply && !lastLine) {
             double ex = (below - above) * (spacingmult - 1) + spacingadd;
             if (ex >= 0) {
@@ -960,6 +977,15 @@
         lines[off + TOP] = v;
         lines[off + DESCENT] = below + extra;
 
+        // special case for non-ellipsized last visible line when maxLines is set
+        // store the height as if it was ellipsized
+        if (!mEllipsized && currentLineIsTheLastVisibleOne) {
+            // below calculation as if it was the last line
+            int maxLineBelow = includePad ? bottom : below;
+            // similar to the calculation of v below, without the extra.
+            mMaxLineHeight = v + (maxLineBelow - above);
+        }
+
         v += (below - above) + extra;
         lines[off + mColumns + START] = end;
         lines[off + mColumns + TOP] = v;
@@ -981,23 +1007,6 @@
                     start - widthStart, end - start);
         }
 
-        if (ellipsize != null) {
-            // If there is only one line, then do any type of ellipsis except when it is MARQUEE
-            // if there are multiple lines, just allow END ellipsis on the last line
-            boolean forceEllipsis = moreChars && (mLineCount + 1 == mMaximumVisibleLineCount);
-
-            boolean doEllipsis =
-                        (((mMaximumVisibleLineCount == 1 && moreChars) || (firstLine && !moreChars)) &&
-                                ellipsize != TextUtils.TruncateAt.MARQUEE) ||
-                        (!firstLine && (currentLineIsTheLastVisibleOne || !moreChars) &&
-                                ellipsize == TextUtils.TruncateAt.END);
-            if (doEllipsis) {
-                calculateEllipsis(start, end, widths, widthStart,
-                        ellipsisWidth, ellipsize, j,
-                        textWidth, paint, forceEllipsis);
-            }
-        }
-
         mLineCount++;
         return v;
     }
@@ -1105,7 +1114,7 @@
                 }
             }
         }
-
+        mEllipsized = true;
         mLines[mColumns * line + ELLIPSIS_START] = ellipsisStart;
         mLines[mColumns * line + ELLIPSIS_COUNT] = ellipsisCount;
     }
@@ -1243,6 +1252,25 @@
         return mEllipsizedWidth;
     }
 
+    /**
+     * Return the total height of this layout.
+     *
+     * @param cap if true and max lines is set, returns the height of the layout at the max lines.
+     *
+     * @hide
+     */
+    public int getHeight(boolean cap) {
+        if (cap && mLineCount >= mMaximumVisibleLineCount && mMaxLineHeight == -1 &&
+                Log.isLoggable(TAG, Log.WARN)) {
+            Log.w(TAG, "maxLineHeight should not be -1. "
+                    + " maxLines:" + mMaximumVisibleLineCount
+                    + " lineCount:" + mLineCount);
+        }
+
+        return cap && mLineCount >= mMaximumVisibleLineCount && mMaxLineHeight != -1 ?
+                mMaxLineHeight : super.getHeight();
+    }
+
     private static native long nNewBuilder();
     private static native void nFreeBuilder(long nativePtr);
     private static native void nFinishBuilder(long nativePtr);
@@ -1281,6 +1309,21 @@
     private int mColumns;
     private int mEllipsizedWidth;
 
+    /**
+     * Keeps track if ellipsize is applied to the text.
+     */
+    private boolean mEllipsized;
+
+    /**
+     * If maxLines is set, ellipsize is not set, and the actual line count of text is greater than
+     * or equal to maxLine, this variable holds the ideal visual height of the maxLine'th line
+     * starting from the top of the layout. If maxLines is not set its value will be -1.
+     *
+     * The value is the same as getLineTop(maxLines) for ellipsized version where structurally no
+     * more than maxLines is contained.
+     */
+    private int mMaxLineHeight = -1;
+
     private static final int COLUMNS_NORMAL = 4;
     private static final int COLUMNS_ELLIPSIZE = 6;
     private static final int START = 0;
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 03a2d62..c411860 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -850,6 +850,11 @@
             int limit, boolean runIsRtl, Canvas c, float x, int top, int y,
             int bottom, FontMetricsInt fmi, boolean needWidth) {
 
+        if (measureLimit < start || measureLimit > limit) {
+            throw new IndexOutOfBoundsException("measureLimit (" + measureLimit + ") is out of "
+                    + "start (" + start + ") and limit (" + limit + ") bounds");
+        }
+
         // Case of an empty line, make sure we update fmi according to mPaint
         if (start == measureLimit) {
             TextPaint wp = mWorkPaint;
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl
index 830591d..a81eef8 100644
--- a/core/java/android/view/IPinnedStackController.aidl
+++ b/core/java/android/view/IPinnedStackController.aidl
@@ -30,4 +30,9 @@
      * Notifies the controller that the user is currently interacting with the PIP.
      */
     oneway void setInInteractiveMode(boolean inInteractiveMode);
+
+    /**
+     * Notifies the controller that the desired snap mode is to the closest edge.
+     */
+    oneway void setSnapToEdge(boolean snapToEdge);
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 39d7883..bccb822 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -85,8 +85,8 @@
     void pauseKeyDispatching(IBinder token);
     void resumeKeyDispatching(IBinder token);
     void setEventDispatching(boolean enabled);
-    void addWindowToken(IBinder token, int type);
-    void removeWindowToken(IBinder token);
+    void addWindowToken(IBinder token, int type, int displayId);
+    void removeWindowToken(IBinder token, int displayId);
     /**
      * Adds an application token to the specified task Id.
      * @param addPos The position to add the token to in the task.
@@ -183,7 +183,7 @@
     void notifyAppStopped(IBinder token);
     void startAppFreezingScreen(IBinder token, int configChanges);
     void stopAppFreezingScreen(IBinder token, boolean force);
-    void removeAppToken(IBinder token);
+    void removeAppToken(IBinder token, int displayId);
 
     /** Used by system ui to report that recents has shown itself. */
     void endProlongedAnimations();
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 51d818b..7a3c95e 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -26,8 +26,6 @@
 
 import dalvik.annotation.optimization.FastNative;
 
-import libcore.util.NativeAllocationRegistry;
-
 /**
  * <p>A display list records a series of graphics related operations and can replay
  * them later. Display lists are usually built by recording operations on a
@@ -132,36 +130,46 @@
  */
 public class RenderNode {
 
- // Use a Holder to allow static initialization in the boot image.
-    private static class NoImagePreloadHolder {
-        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-            RenderNode.class.getClassLoader(), nGetNativeFinalizer(), 1024);
-    }
-
     private boolean mValid;
     // Do not access directly unless you are ThreadedRenderer
-    final long mNativeRenderNode;
+    long mNativeRenderNode;
     private final View mOwningView;
 
     private RenderNode(String name, View owningView) {
         mNativeRenderNode = nCreate(name);
-        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
         mOwningView = owningView;
-        if (mOwningView instanceof SurfaceView) {
-            nRequestPositionUpdates(mNativeRenderNode, (SurfaceView) mOwningView);
-        }
     }
 
     /**
      * @see RenderNode#adopt(long)
      */
     private RenderNode(long nativePtr) {
-        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, nativePtr);
         mNativeRenderNode = nativePtr;
         mOwningView = null;
     }
 
     /**
+     * Immediately destroys the RenderNode
+     * Only suitable for testing/benchmarking where waiting for the GC/finalizer
+     * is not feasible.
+     */
+    public void destroy() {
+        if (mNativeRenderNode != 0) {
+            nFinalize(mNativeRenderNode);
+            mNativeRenderNode = 0;
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            destroy();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
      * Creates a new RenderNode that can be used to record batches of
      * drawing operations, and store / apply render properties when drawn.
      *
@@ -183,6 +191,13 @@
         return new RenderNode(nativePtr);
     }
 
+    /**
+     * Enable callbacks for position changes.
+     */
+    public void requestPositionUpdates(SurfaceView view) {
+        nRequestPositionUpdates(mNativeRenderNode, view);
+    }
+
 
     /**
      * Starts recording a display list for the render node. All
@@ -784,9 +799,6 @@
      */
     void onRenderNodeDetached() {
         discardDisplayList();
-        if (mOwningView != null) {
-            mOwningView.onRenderNodeDetached(this);
-        }
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -823,6 +835,7 @@
 
     // Intentionally not static because it acquires a reference to 'this'
     private native long nCreate(String name);
+    private native void nFinalize(long renderNode);
 
     private static native long nGetNativeFinalizer();
     private static native void nSetDisplayList(long renderNode, long newData);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 5c56ebc..d46910c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -207,6 +207,7 @@
 
     public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        mRenderNode.requestPositionUpdates(this);
 
         setWillNotDraw(true);
     }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ba26926..441f330 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16185,13 +16185,6 @@
     }
 
     /**
-     * Called when the passed RenderNode is removed from the draw tree
-     * @hide
-     */
-    public void onRenderNodeDetached(RenderNode renderNode) {
-    }
-
-    /**
      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
      *
      * @return A non-scaled bitmap representing this view or null if cache is disabled.
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 106b211..2971280 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -249,48 +249,92 @@
          * @see #TYPE_INPUT_METHOD_DIALOG
          */
         @ViewDebug.ExportedProperty(mapping = {
-            @ViewDebug.IntToString(from = TYPE_BASE_APPLICATION, to = "TYPE_BASE_APPLICATION"),
-            @ViewDebug.IntToString(from = TYPE_APPLICATION, to = "TYPE_APPLICATION"),
-            @ViewDebug.IntToString(from = TYPE_APPLICATION_STARTING, to = "TYPE_APPLICATION_STARTING"),
-            @ViewDebug.IntToString(from = TYPE_DRAWN_APPLICATION, to = "TYPE_DRAWN_APPLICATION"),
-            @ViewDebug.IntToString(from = TYPE_APPLICATION_PANEL, to = "TYPE_APPLICATION_PANEL"),
-            @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA, to = "TYPE_APPLICATION_MEDIA"),
-            @ViewDebug.IntToString(from = TYPE_APPLICATION_SUB_PANEL, to = "TYPE_APPLICATION_SUB_PANEL"),
-            @ViewDebug.IntToString(from = TYPE_APPLICATION_ABOVE_SUB_PANEL, to = "TYPE_APPLICATION_ABOVE_SUB_PANEL"),
-            @ViewDebug.IntToString(from = TYPE_APPLICATION_ATTACHED_DIALOG, to = "TYPE_APPLICATION_ATTACHED_DIALOG"),
-            @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA_OVERLAY, to = "TYPE_APPLICATION_MEDIA_OVERLAY"),
-            @ViewDebug.IntToString(from = TYPE_STATUS_BAR, to = "TYPE_STATUS_BAR"),
-            @ViewDebug.IntToString(from = TYPE_SEARCH_BAR, to = "TYPE_SEARCH_BAR"),
-            @ViewDebug.IntToString(from = TYPE_PHONE, to = "TYPE_PHONE"),
-            @ViewDebug.IntToString(from = TYPE_SYSTEM_ALERT, to = "TYPE_SYSTEM_ALERT"),
-            @ViewDebug.IntToString(from = TYPE_TOAST, to = "TYPE_TOAST"),
-            @ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY, to = "TYPE_SYSTEM_OVERLAY"),
-            @ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE, to = "TYPE_PRIORITY_PHONE"),
-            @ViewDebug.IntToString(from = TYPE_SYSTEM_DIALOG, to = "TYPE_SYSTEM_DIALOG"),
-            @ViewDebug.IntToString(from = TYPE_KEYGUARD_DIALOG, to = "TYPE_KEYGUARD_DIALOG"),
-            @ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR, to = "TYPE_SYSTEM_ERROR"),
-            @ViewDebug.IntToString(from = TYPE_INPUT_METHOD, to = "TYPE_INPUT_METHOD"),
-            @ViewDebug.IntToString(from = TYPE_INPUT_METHOD_DIALOG, to = "TYPE_INPUT_METHOD_DIALOG"),
-            @ViewDebug.IntToString(from = TYPE_WALLPAPER, to = "TYPE_WALLPAPER"),
-            @ViewDebug.IntToString(from = TYPE_STATUS_BAR_PANEL, to = "TYPE_STATUS_BAR_PANEL"),
-            @ViewDebug.IntToString(from = TYPE_SECURE_SYSTEM_OVERLAY, to = "TYPE_SECURE_SYSTEM_OVERLAY"),
-            @ViewDebug.IntToString(from = TYPE_DRAG, to = "TYPE_DRAG"),
-            @ViewDebug.IntToString(from = TYPE_STATUS_BAR_SUB_PANEL, to = "TYPE_STATUS_BAR_SUB_PANEL"),
-            @ViewDebug.IntToString(from = TYPE_POINTER, to = "TYPE_POINTER"),
-            @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR, to = "TYPE_NAVIGATION_BAR"),
-            @ViewDebug.IntToString(from = TYPE_VOLUME_OVERLAY, to = "TYPE_VOLUME_OVERLAY"),
-            @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS"),
-            @ViewDebug.IntToString(from = TYPE_INPUT_CONSUMER, to = "TYPE_INPUT_CONSUMER"),
-            @ViewDebug.IntToString(from = TYPE_DREAM, to = "TYPE_DREAM"),
-            @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL, to = "TYPE_NAVIGATION_BAR_PANEL"),
-            @ViewDebug.IntToString(from = TYPE_DISPLAY_OVERLAY, to = "TYPE_DISPLAY_OVERLAY"),
-            @ViewDebug.IntToString(from = TYPE_MAGNIFICATION_OVERLAY, to = "TYPE_MAGNIFICATION_OVERLAY"),
-            @ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION"),
-            @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION, to = "TYPE_VOICE_INTERACTION"),
-            @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, to = "TYPE_VOICE_INTERACTION_STARTING"),
-            @ViewDebug.IntToString(from = TYPE_DOCK_DIVIDER, to = "TYPE_DOCK_DIVIDER"),
-            @ViewDebug.IntToString(from = TYPE_QS_DIALOG, to = "TYPE_QS_DIALOG"),
-            @ViewDebug.IntToString(from = TYPE_SCREENSHOT, to = "TYPE_SCREENSHOT")
+                @ViewDebug.IntToString(from = TYPE_BASE_APPLICATION,
+                        to = "TYPE_BASE_APPLICATION"),
+                @ViewDebug.IntToString(from = TYPE_APPLICATION,
+                        to = "TYPE_APPLICATION"),
+                @ViewDebug.IntToString(from = TYPE_APPLICATION_STARTING,
+                        to = "TYPE_APPLICATION_STARTING"),
+                @ViewDebug.IntToString(from = TYPE_DRAWN_APPLICATION,
+                        to = "TYPE_DRAWN_APPLICATION"),
+                @ViewDebug.IntToString(from = TYPE_APPLICATION_PANEL,
+                        to = "TYPE_APPLICATION_PANEL"),
+                @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA,
+                        to = "TYPE_APPLICATION_MEDIA"),
+                @ViewDebug.IntToString(from = TYPE_APPLICATION_SUB_PANEL,
+                        to = "TYPE_APPLICATION_SUB_PANEL"),
+                @ViewDebug.IntToString(from = TYPE_APPLICATION_ABOVE_SUB_PANEL,
+                        to = "TYPE_APPLICATION_ABOVE_SUB_PANEL"),
+                @ViewDebug.IntToString(from = TYPE_APPLICATION_ATTACHED_DIALOG,
+                        to = "TYPE_APPLICATION_ATTACHED_DIALOG"),
+                @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA_OVERLAY,
+                        to = "TYPE_APPLICATION_MEDIA_OVERLAY"),
+                @ViewDebug.IntToString(from = TYPE_STATUS_BAR,
+                        to = "TYPE_STATUS_BAR"),
+                @ViewDebug.IntToString(from = TYPE_SEARCH_BAR,
+                        to = "TYPE_SEARCH_BAR"),
+                @ViewDebug.IntToString(from = TYPE_PHONE,
+                        to = "TYPE_PHONE"),
+                @ViewDebug.IntToString(from = TYPE_SYSTEM_ALERT,
+                        to = "TYPE_SYSTEM_ALERT"),
+                @ViewDebug.IntToString(from = TYPE_TOAST,
+                        to = "TYPE_TOAST"),
+                @ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY,
+                        to = "TYPE_SYSTEM_OVERLAY"),
+                @ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE,
+                        to = "TYPE_PRIORITY_PHONE"),
+                @ViewDebug.IntToString(from = TYPE_SYSTEM_DIALOG,
+                        to = "TYPE_SYSTEM_DIALOG"),
+                @ViewDebug.IntToString(from = TYPE_KEYGUARD_DIALOG,
+                        to = "TYPE_KEYGUARD_DIALOG"),
+                @ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR,
+                        to = "TYPE_SYSTEM_ERROR"),
+                @ViewDebug.IntToString(from = TYPE_INPUT_METHOD,
+                        to = "TYPE_INPUT_METHOD"),
+                @ViewDebug.IntToString(from = TYPE_INPUT_METHOD_DIALOG,
+                        to = "TYPE_INPUT_METHOD_DIALOG"),
+                @ViewDebug.IntToString(from = TYPE_WALLPAPER,
+                        to = "TYPE_WALLPAPER"),
+                @ViewDebug.IntToString(from = TYPE_STATUS_BAR_PANEL,
+                        to = "TYPE_STATUS_BAR_PANEL"),
+                @ViewDebug.IntToString(from = TYPE_SECURE_SYSTEM_OVERLAY,
+                        to = "TYPE_SECURE_SYSTEM_OVERLAY"),
+                @ViewDebug.IntToString(from = TYPE_DRAG,
+                        to = "TYPE_DRAG"),
+                @ViewDebug.IntToString(from = TYPE_STATUS_BAR_SUB_PANEL,
+                        to = "TYPE_STATUS_BAR_SUB_PANEL"),
+                @ViewDebug.IntToString(from = TYPE_POINTER,
+                        to = "TYPE_POINTER"),
+                @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR,
+                        to = "TYPE_NAVIGATION_BAR"),
+                @ViewDebug.IntToString(from = TYPE_VOLUME_OVERLAY,
+                        to = "TYPE_VOLUME_OVERLAY"),
+                @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS,
+                        to = "TYPE_BOOT_PROGRESS"),
+                @ViewDebug.IntToString(from = TYPE_INPUT_CONSUMER,
+                        to = "TYPE_INPUT_CONSUMER"),
+                @ViewDebug.IntToString(from = TYPE_DREAM,
+                        to = "TYPE_DREAM"),
+                @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL,
+                        to = "TYPE_NAVIGATION_BAR_PANEL"),
+                @ViewDebug.IntToString(from = TYPE_DISPLAY_OVERLAY,
+                        to = "TYPE_DISPLAY_OVERLAY"),
+                @ViewDebug.IntToString(from = TYPE_MAGNIFICATION_OVERLAY,
+                        to = "TYPE_MAGNIFICATION_OVERLAY"),
+                @ViewDebug.IntToString(from = TYPE_PRESENTATION,
+                        to = "TYPE_PRESENTATION"),
+                @ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION,
+                        to = "TYPE_PRIVATE_PRESENTATION"),
+                @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION,
+                        to = "TYPE_VOICE_INTERACTION"),
+                @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING,
+                        to = "TYPE_VOICE_INTERACTION_STARTING"),
+                @ViewDebug.IntToString(from = TYPE_DOCK_DIVIDER,
+                        to = "TYPE_DOCK_DIVIDER"),
+                @ViewDebug.IntToString(from = TYPE_QS_DIALOG,
+                        to = "TYPE_QS_DIALOG"),
+                @ViewDebug.IntToString(from = TYPE_SCREENSHOT,
+                        to = "TYPE_SCREENSHOT")
         })
         public int type;
 
@@ -651,6 +695,13 @@
         public static final int TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36;
 
         /**
+         * Window type: Window for Presentation on an external display.
+         * @see android.app.Presentation
+         * @hide
+         */
+        public static final int TYPE_PRESENTATION = FIRST_SYSTEM_WINDOW + 37;
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index f61a637..6e2a92c 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -241,16 +241,19 @@
      *
      * @param token The token to add.
      * @param type The window type.
+     * @param displayId The display to add the token to.
      */
-    public abstract void addWindowToken(android.os.IBinder token, int type);
+    public abstract void addWindowToken(android.os.IBinder token, int type, int displayId);
 
     /**
      * Removes a window token.
      *
      * @param token The toke to remove.
      * @param removeWindows Whether to also remove the windows associated with the token.
+     * @param displayId The display to remove the token from.
      */
-    public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows);
+    public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows,
+            int displayId);
 
     /**
      * Registers a listener to be notified about app transition events.
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index a8d70c4..8a9bb33 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -339,13 +339,6 @@
         boolean isVisibleLw();
 
         /**
-         * Like {@link #isVisibleLw}, but also counts a window that is currently
-         * "hidden" behind the keyguard as visible.  This allows us to apply
-         * things like window flags that impact the keyguard.
-         */
-        boolean isVisibleOrBehindKeyguardLw();
-
-        /**
          * Is this window currently visible to the user on-screen?  It is
          * displayed either if it is visible or it is currently running an
          * animation before no longer being visible.  Must be called with the
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 71e77c4..2829744 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -35,16 +35,16 @@
  */
 interface IAccessibilityManager {
 
-    int addClient(IAccessibilityManagerClient client, int userId);
+    oneway void interrupt(int userId);
 
-    void sendAccessibilityEvent(in AccessibilityEvent uiEvent, int userId);
+    oneway void sendAccessibilityEvent(in AccessibilityEvent uiEvent, int userId);
+
+    int addClient(IAccessibilityManagerClient client, int userId);
 
     List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId);
 
     List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId);
 
-    void interrupt(int userId);
-
     int addAccessibilityInteractionConnection(IWindow windowToken,
         in IAccessibilityInteractionConnection connection, int userId);
 
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 8cedb17..d5a933c 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2168,6 +2168,7 @@
         }
 
         layoutChildren();
+        mInLayout = false;
 
         mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
 
@@ -2175,7 +2176,6 @@
         if (mFastScroll != null) {
             mFastScroll.onItemCountChanged(getChildCount(), mItemCount);
         }
-        mInLayout = false;
     }
 
     /**
@@ -2705,9 +2705,6 @@
      * fail to relayout them properly to accommodate for new bounds.
      */
     void handleBoundsChange() {
-        if (mInLayout) {
-            return;
-        }
         final int childCount = getChildCount();
         if (childCount > 0) {
             mDataChanged = true;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 316dab5..b2a77d0 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -324,6 +324,14 @@
             return false;
         }
 
+        /**
+         * Overridden by subclasses which have (or inherit) an ApplicationInfo instance
+         * as member variable
+         */
+        public boolean hasSameAppInfo(ApplicationInfo parentInfo) {
+            return true;
+        }
+
         int viewId;
     }
 
@@ -1521,11 +1529,11 @@
             }
         }
 
-        public ViewGroupAction(Parcel parcel, BitmapCache bitmapCache) {
+        ViewGroupAction(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info) {
             viewId = parcel.readInt();
             boolean nestedViewsNull = parcel.readInt() == 0;
             if (!nestedViewsNull) {
-                nestedViews = new RemoteViews(parcel, bitmapCache);
+                nestedViews = new RemoteViews(parcel, bitmapCache, info);
             } else {
                 nestedViews = null;
             }
@@ -1544,6 +1552,13 @@
         }
 
         @Override
+        public boolean hasSameAppInfo(ApplicationInfo parentInfo) {
+            return nestedViews != null
+                    && nestedViews.mApplication.packageName.equals(parentInfo.packageName)
+                    && nestedViews.mApplication.uid == parentInfo.uid;
+        }
+
+        @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
             final Context context = root.getContext();
             final ViewGroup target = (ViewGroup) root.findViewById(viewId);
@@ -2195,10 +2210,10 @@
      * @param parcel
      */
     public RemoteViews(Parcel parcel) {
-        this(parcel, null);
+        this(parcel, null, null);
     }
 
-    private RemoteViews(Parcel parcel, BitmapCache bitmapCache) {
+    private RemoteViews(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info) {
         int mode = parcel.readInt();
 
         // We only store a bitmap cache in the root of the RemoteViews.
@@ -2210,7 +2225,8 @@
         }
 
         if (mode == MODE_NORMAL) {
-            mApplication = parcel.readParcelable(null);
+            mApplication = parcel.readInt() == 0 ? info :
+                    ApplicationInfo.CREATOR.createFromParcel(parcel);
             mLayoutId = parcel.readInt();
             mIsWidgetCollectionChild = parcel.readInt() == 1;
 
@@ -2230,7 +2246,7 @@
                             mActions.add(new ReflectionAction(parcel));
                             break;
                         case ViewGroupAction.TAG:
-                            mActions.add(new ViewGroupAction(parcel, mBitmapCache));
+                            mActions.add(new ViewGroupAction(parcel, mBitmapCache, mApplication));
                             break;
                         case ReflectionActionWithoutParams.TAG:
                             mActions.add(new ReflectionActionWithoutParams(parcel));
@@ -2278,8 +2294,8 @@
             }
         } else {
             // MODE_HAS_LANDSCAPE_AND_PORTRAIT
-            mLandscape = new RemoteViews(parcel, mBitmapCache);
-            mPortrait = new RemoteViews(parcel, mBitmapCache);
+            mLandscape = new RemoteViews(parcel, mBitmapCache, info);
+            mPortrait = new RemoteViews(parcel, mBitmapCache, mLandscape.mApplication);
             mApplication = mPortrait.mApplication;
             mLayoutId = mPortrait.getLayoutId();
         }
@@ -2299,11 +2315,11 @@
         // Do not parcel the Bitmap cache - doing so creates an expensive copy of all bitmaps.
         // Instead pretend we're not owning the cache while parceling.
         mIsRoot = false;
-        writeToParcel(p, 0);
+        writeToParcel(p, PARCELABLE_ELIDE_DUPLICATES);
         p.setDataPosition(0);
         mIsRoot = true;
 
-        RemoteViews rv = new RemoteViews(p, mBitmapCache.clone());
+        RemoteViews rv = new RemoteViews(p, mBitmapCache.clone(), mApplication);
         rv.mIsRoot = true;
 
         p.recycle();
@@ -3536,7 +3552,12 @@
             if (mIsRoot) {
                 mBitmapCache.writeBitmapsToParcel(dest, flags);
             }
-            dest.writeParcelable(mApplication, flags);
+            if (!mIsRoot && (flags & PARCELABLE_ELIDE_DUPLICATES) != 0) {
+                dest.writeInt(0);
+            } else {
+                dest.writeInt(1);
+                mApplication.writeToParcel(dest, flags);
+            }
             dest.writeInt(mLayoutId);
             dest.writeInt(mIsWidgetCollectionChild ? 1 : 0);
             int count;
@@ -3548,7 +3569,8 @@
             dest.writeInt(count);
             for (int i=0; i<count; i++) {
                 Action a = mActions.get(i);
-                a.writeToParcel(dest, 0);
+                a.writeToParcel(dest, a.hasSameAppInfo(mApplication)
+                        ? PARCELABLE_ELIDE_DUPLICATES : 0);
             }
         } else {
             dest.writeInt(MODE_HAS_LANDSCAPE_AND_PORTRAIT);
@@ -3558,7 +3580,8 @@
                 mBitmapCache.writeBitmapsToParcel(dest, flags);
             }
             mLandscape.writeToParcel(dest, flags);
-            mPortrait.writeToParcel(dest, flags);
+            // Both RemoteViews already share the same package and user
+            mPortrait.writeToParcel(dest, flags | PARCELABLE_ELIDE_DUPLICATES);
         }
     }
 
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 0e99c02..1b9055c 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -1051,6 +1051,11 @@
 
                 float d = (float) Math.hypot(viewLp.horizontalOffset, viewLp.verticalOffset);
                 float maxd = (float) Math.hypot(mSlideAmount, 0.4f * mSlideAmount);
+                if (d > maxd) {
+                    // Because mSlideAmount is updated in onLayout(), it is possible that d > maxd
+                    // if we get onLayout() right before this method is called.
+                    d = maxd;
+                }
 
                 if (velocity == 0) {
                     return (invert ? (1 - d / maxd) : d / maxd) * DEFAULT_ANIMATION_DURATION;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2f9c97b..73af755 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -672,6 +672,11 @@
     public static void preloadFontCache() {
         Paint p = new Paint();
         p.setAntiAlias(true);
+        // Ensure that the Typeface is loaded here.
+        // Typically, Typeface is preloaded by zygote but not on all devices, e.g. Android Auto.
+        // So, sets Typeface.DEFAULT explicitly here for ensuring that the Typeface is loaded here
+        // since Paint.measureText can not be called without Typeface static initializer.
+        p.setTypeface(Typeface.DEFAULT);
         // We don't care about the result, just the side-effect of measuring.
         p.measureText("H");
     }
@@ -5152,7 +5157,7 @@
      * call {@link InputMethodManager#restartInput(View)}.</p>
      * @param hintLocales List of the languages that the user is supposed to switch to no matter
      * what input method subtype is currently used. Set {@code null} to clear the current "hint".
-     * @see #getImeHIntLocales()
+     * @see #getImeHintLocales()
      * @see android.view.inputmethod.EditorInfo#hintLocales
      */
     public void setImeHintLocales(@Nullable LocaleList hintLocales) {
@@ -6995,11 +7000,11 @@
                         .setLineSpacing(mSpacingAdd, mSpacingMult)
                         .setIncludePad(mIncludePad)
                         .setBreakStrategy(mBreakStrategy)
-                        .setHyphenationFrequency(mHyphenationFrequency);
+                        .setHyphenationFrequency(mHyphenationFrequency)
+                        .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
                 if (shouldEllipsize) {
                     builder.setEllipsize(mEllipsize)
-                            .setEllipsizedWidth(ellipsisWidth)
-                            .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+                            .setEllipsizedWidth(ellipsisWidth);
                 }
                 mHintLayout = builder.build();
             }
@@ -7086,11 +7091,11 @@
                     .setLineSpacing(mSpacingAdd, mSpacingMult)
                     .setIncludePad(mIncludePad)
                     .setBreakStrategy(mBreakStrategy)
-                    .setHyphenationFrequency(mHyphenationFrequency);
+                    .setHyphenationFrequency(mHyphenationFrequency)
+                    .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
             if (shouldEllipsize) {
                 builder.setEllipsize(effectiveEllipsize)
-                        .setEllipsizedWidth(ellipsisWidth)
-                        .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+                        .setEllipsizedWidth(ellipsisWidth);
             }
             // TODO: explore always setting maxLines
             result = builder.build();
@@ -7362,9 +7367,11 @@
             return 0;
         }
 
-        int linecount = layout.getLineCount();
-        int pad = getCompoundPaddingTop() + getCompoundPaddingBottom();
-        int desired = layout.getLineTop(linecount);
+        /*
+        * Don't cap the hint to a certain number of lines.
+        * (Do cap it, though, if we have a maximum pixel height.)
+        */
+        int desired = layout.getHeight(cap);
 
         final Drawables dr = mDrawables;
         if (dr != null) {
@@ -7372,31 +7379,14 @@
             desired = Math.max(desired, dr.mDrawableHeightRight);
         }
 
-        desired += pad;
+        desired += getCompoundPaddingTop() + getCompoundPaddingBottom();
 
-        if (mMaxMode == LINES) {
-            /*
-             * Don't cap the hint to a certain number of lines.
-             * (Do cap it, though, if we have a maximum pixel height.)
-             */
-            if (cap) {
-                if (linecount > mMaximum) {
-                    desired = layout.getLineTop(mMaximum);
-
-                    if (dr != null) {
-                        desired = Math.max(desired, dr.mDrawableHeightLeft);
-                        desired = Math.max(desired, dr.mDrawableHeightRight);
-                    }
-
-                    desired += pad;
-                    linecount = mMaximum;
-                }
-            }
-        } else {
+        if (mMaxMode != LINES) {
             desired = Math.min(desired, mMaximum);
         }
 
         if (mMinMode == LINES) {
+            int linecount = layout.getLineCount();
             if (linecount < mMinimum) {
                 desired += getLineHeight() * (mMinimum - linecount);
             }
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index c851e4e..e57a224 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -114,7 +114,7 @@
 
                 // Bring up crash dialog, wait for it to be dismissed
                 ActivityManagerNative.getDefault().handleApplicationCrash(
-                        mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
+                        mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
             } catch (Throwable t2) {
                 if (t2 instanceof DeadObjectException) {
                     // System process is dead; ignore
@@ -380,7 +380,8 @@
     public static void wtf(String tag, Throwable t, boolean system) {
         try {
             if (ActivityManagerNative.getDefault().handleApplicationWtf(
-                    mApplicationObject, tag, system, new ApplicationErrorReport.CrashInfo(t))) {
+                    mApplicationObject, tag, system,
+                    new ApplicationErrorReport.ParcelableCrashInfo(t))) {
                 // The Activity Manager has already written us off -- now exit.
                 Process.killProcess(Process.myPid());
                 System.exit(10);
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
index 51804b0..cbacf26 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
@@ -46,18 +46,33 @@
     private final Context mContext;
 
     private final ArrayList<Integer> mSnapGravities = new ArrayList<>();
-    private final int mSnapMode = SNAP_MODE_CORNERS_ONLY;
+    private final int mDefaultSnapMode = SNAP_MODE_CORNERS_ONLY;
+    private int mSnapMode = mDefaultSnapMode;
 
     private Scroller mScroller;
     private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
 
     public PipSnapAlgorithm(Context context) {
         mContext = context;
-        mOrientation = context.getResources().getConfiguration().orientation;
+        onConfigurationChanged();
+    }
+
+    /**
+     * Updates the snap algorithm when the configuration changes.
+     */
+    public void onConfigurationChanged() {
+        mOrientation = mContext.getResources().getConfiguration().orientation;
         calculateSnapTargets();
     }
 
     /**
+     * Enables snapping to the closest edge.
+     */
+    public void setSnapToEdge(boolean snapToEdge) {
+        mSnapMode = snapToEdge ? SNAP_MODE_EDGE : mDefaultSnapMode;
+    }
+
+    /**
      * @return the closest absolute snap stack bounds for the given {@param stackBounds} moving at
      * the given {@param velocityX} and {@param velocityY}.  The {@param movementBounds} should be
      * those for the given {@param stackBounds}.
@@ -90,19 +105,7 @@
         final Rect newBounds = new Rect(stackBounds);
         if (mSnapMode == SNAP_MODE_EDGE) {
             // Find the closest edge to the given stack bounds and snap to it
-            final int fromLeft = stackBounds.left - movementBounds.left;
-            final int fromTop = stackBounds.top - movementBounds.top;
-            final int fromRight = movementBounds.right - stackBounds.left;
-            final int fromBottom = movementBounds.bottom - stackBounds.top;
-            if (fromLeft <= fromTop && fromLeft <= fromRight && fromLeft <= fromBottom) {
-                newBounds.offset(-fromLeft, 0);
-            } else if (fromTop <= fromLeft && fromTop <= fromRight && fromTop <= fromBottom) {
-                newBounds.offset(0, -fromTop);
-            } else if (fromRight < fromLeft && fromRight < fromTop && fromRight < fromBottom) {
-                newBounds.offset(fromRight, 0);
-            } else {
-                newBounds.offset(0, fromBottom);
-            }
+            snapRectToClosestEdge(stackBounds, movementBounds, newBounds);
         } else {
             // Find the closest snap point
             final Rect tmpBounds = new Rect();
@@ -119,6 +122,68 @@
     }
 
     /**
+     * @return returns a fraction that describes where along the {@param movementBounds} the
+     *         {@param stackBounds} are. If the {@param stackBounds} are not currently on the
+     *         {@param movementBounds} exactly, then they will be snapped to the movement bounds.
+     *
+     *         The fraction is defined in a clockwise fashion against the {@param movementBounds}:
+     *
+     *            0   1
+     *          4 +---+ 1
+     *            |   |
+     *          3 +---+ 2
+     *            3   2
+     */
+    public float getSnapFraction(Rect stackBounds, Rect movementBounds) {
+        final Rect tmpBounds = new Rect();
+        snapRectToClosestEdge(stackBounds, movementBounds, tmpBounds);
+        final float widthFraction = (float) (tmpBounds.left - movementBounds.left) /
+                movementBounds.width();
+        final float heightFraction = (float) (tmpBounds.top - movementBounds.top) /
+                movementBounds.height();
+        if (tmpBounds.top == movementBounds.top) {
+            return widthFraction;
+        } else if (tmpBounds.left == movementBounds.right) {
+            return 1f + heightFraction;
+        } else if (tmpBounds.top == movementBounds.bottom) {
+            return 2f + (1f - widthFraction);
+        } else {
+            return 3f + (1f - heightFraction);
+        }
+    }
+
+    /**
+     * Moves the {@param stackBounds} along the {@param movementBounds} to the given snap fraction.
+     * See {@link #getSnapFraction(Rect, Rect)}.
+     *
+     * The fraction is define in a clockwise fashion against the {@param movementBounds}:
+     *
+     *    0   1
+     *  4 +---+ 1
+     *    |   |
+     *  3 +---+ 2
+     *    3   2
+     */
+    public void applySnapFraction(Rect stackBounds, Rect movementBounds, float snapFraction) {
+        if (snapFraction < 1f) {
+            int offset = movementBounds.left + (int) (snapFraction * movementBounds.width());
+            stackBounds.offsetTo(offset, movementBounds.top);
+        } else if (snapFraction < 2f) {
+            snapFraction -= 1f;
+            int offset = movementBounds.top + (int) (snapFraction * movementBounds.height());
+            stackBounds.offsetTo(movementBounds.right, offset);
+        } else if (snapFraction < 3f) {
+            snapFraction -= 2f;
+            int offset = movementBounds.left + (int) ((1f - snapFraction) * movementBounds.width());
+            stackBounds.offsetTo(offset, movementBounds.bottom);
+        } else {
+            snapFraction -= 3f;
+            int offset = movementBounds.top + (int) ((1f - snapFraction) * movementBounds.height());
+            stackBounds.offsetTo(movementBounds.left, offset);
+        }
+    }
+
+    /**
      * @return the closest point in {@param points} to the given {@param x} and {@param y}.
      */
     private Point findClosestPoint(int x, int y, Point[] points) {
@@ -135,6 +200,27 @@
     }
 
     /**
+     * Snaps the {@param stackBounds} to the closest edge of the {@param movementBounds} and writes
+     * the new bounds out to {@param boundsOut}.
+     */
+    private void snapRectToClosestEdge(Rect stackBounds, Rect movementBounds, Rect boundsOut) {
+        final int fromLeft = Math.abs(stackBounds.left - movementBounds.left);
+        final int fromTop = Math.abs(stackBounds.top - movementBounds.top);
+        final int fromRight = Math.abs(movementBounds.right - stackBounds.left);
+        final int fromBottom = Math.abs(movementBounds.bottom - stackBounds.top);
+        boundsOut.set(stackBounds);
+        if (fromLeft <= fromTop && fromLeft <= fromRight && fromLeft <= fromBottom) {
+            boundsOut.offsetTo(movementBounds.left, stackBounds.top);
+        } else if (fromTop <= fromLeft && fromTop <= fromRight && fromTop <= fromBottom) {
+            boundsOut.offsetTo(stackBounds.left, movementBounds.top);
+        } else if (fromRight < fromLeft && fromRight < fromTop && fromRight < fromBottom) {
+            boundsOut.offsetTo(movementBounds.right, stackBounds.top);
+        } else {
+            boundsOut.offsetTo(stackBounds.left, movementBounds.bottom);
+        }
+    }
+
+    /**
      * @return the distance between point {@param p} and the given {@param x} and {@param y}.
      */
     private float distanceToPoint(Point p, int x, int y) {
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 83d5ce3..3d8c85e 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -1594,6 +1594,9 @@
 
     public static int readIntAttribute(XmlPullParser in, String name, int defaultValue) {
         final String value = in.getAttributeValue(null, name);
+        if (TextUtils.isEmpty(value)) {
+            return defaultValue;
+        }
         try {
             return Integer.parseInt(value);
         } catch (NumberFormatException e) {
@@ -1617,6 +1620,9 @@
 
     public static long readLongAttribute(XmlPullParser in, String name, long defaultValue) {
         final String value = in.getAttributeValue(null, name);
+        if (TextUtils.isEmpty(value)) {
+            return defaultValue;
+        }
         try {
             return Long.parseLong(value);
         } catch (NumberFormatException e) {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 506a284..91e8310 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -259,6 +259,7 @@
     libicuuc \
     libicui18n \
     libmedia \
+    libaudioclient \
     libjpeg \
     libusbhost \
     libharfbuzz_ng \
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index a47062e..d9aa8f1 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -655,7 +655,7 @@
         alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
     }
     bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
-            sk_sp<SkColorSpace>(bitmap->info().colorSpace())));
+            sk_ref_sp(bitmap->info().colorSpace())));
 }
 
 // These must match the int values in Bitmap.java
@@ -806,7 +806,7 @@
     std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
 
     if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType,
-            isSRGB ? SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named) : nullptr), rowBytes)) {
+            isSRGB ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : nullptr), rowBytes)) {
         return NULL;
     }
 
@@ -921,7 +921,7 @@
     auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
     bitmapWrapper->getSkBitmap(&bitmap);
 
-    sk_sp<SkColorSpace> sRGB = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+    sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
     bool isSRGB = bitmap.colorSpace() == sRGB.get();
 
     p->writeInt32(isMutable);
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index bc2da91..1ded2c5 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -365,7 +365,7 @@
     SkColorType decodeColorType = codec->computeOutputColorType(prefColorType);
 
     // Construct a color table for the decode if necessary
-    SkAutoTUnref<SkColorTable> colorTable(nullptr);
+    sk_sp<SkColorTable> colorTable(nullptr);
     SkPMColor* colorPtr = nullptr;
     int* colorCount = nullptr;
     int maxColors = 256;
@@ -399,7 +399,7 @@
     }
     SkBitmap decodingBitmap;
     if (!decodingBitmap.setInfo(bitmapInfo) ||
-            !decodingBitmap.tryAllocPixels(decodeAllocator, colorTable)) {
+            !decodingBitmap.tryAllocPixels(decodeAllocator, colorTable.get())) {
         // SkAndroidCodec should recommend a valid SkImageInfo, so setInfo()
         // should only only fail if the calculated value for rowBytes is too
         // large.
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 45bf702..115ee72 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -39,18 +39,20 @@
 #include <jni.h>
 #include <sys/stat.h>
 
+#include <memory>
+
 using namespace android;
 
 static jobject createBitmapRegionDecoder(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream) {
-    SkAutoTDelete<SkBitmapRegionDecoder> brd(
+  std::unique_ptr<SkBitmapRegionDecoder> brd(
             SkBitmapRegionDecoder::Create(stream.release(),
                                           SkBitmapRegionDecoder::kAndroidCodec_Strategy));
-    if (NULL == brd) {
+    if (!brd) {
         doThrowIOE(env, "Image format not supported");
         return nullObjectReturn("CreateBitmapRegionDecoder returned null");
     }
 
-    return GraphicsJNI::createBitmapRegionDecoder(env, brd.detach());
+    return GraphicsJNI::createBitmapRegionDecoder(env, brd.release());
 }
 
 static jobject nativeNewInstanceFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 2088421..15e7165 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -106,7 +106,7 @@
     SkFontMgr::FontParameters params;
     params.setCollectionIndex(ttcIndex);
 
-    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+    sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
     sk_sp<SkTypeface> face(fm->createFromStream(fontData.release(), params));
     if (face == NULL) {
         ALOGE("addFont failed to create font");
@@ -172,7 +172,7 @@
     params.setCollectionIndex(ttcIndex);
     params.setAxes(skiaAxes.get(), skiaAxesLength);
 
-    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+    sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
     sk_sp<SkTypeface> face(fm->createFromStream(fontData.release(), params));
     if (face == NULL) {
         ALOGE("addFont failed to create font, invalid request");
@@ -216,7 +216,7 @@
     sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset, asset));
     std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(std::move(data)));
 
-    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+    sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
     sk_sp<SkTypeface> face(fm->createFromStream(fontData.release(), SkFontMgr::FontParameters()));
     if (face == NULL) {
         ALOGE("addFontFromAsset failed to create font %s", str.c_str());
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index dffb63c..322eed5 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -437,7 +437,7 @@
 
 sk_sp<SkColorSpace> GraphicsJNI::defaultColorSpace() {
 #ifdef ANDROID_ENABLE_LINEAR_BLENDING
-    return SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+    return SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
 #else
     return nullptr;
 #endif
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 38452bb..e10fdbd 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -32,7 +32,7 @@
 #include "SkPathEffect.h"
 #include "SkRasterizer.h"
 #include "SkShader.h"
-#include "SkXfermode.h"
+#include "SkBlendMode.h"
 #include "unicode/uloc.h"
 #include "unicode/ushape.h"
 #include "utils/Blur.h"
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index a2416df..657b1ef 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -2,7 +2,7 @@
 #include "SkGradientShader.h"
 #include "SkImagePriv.h"
 #include "SkShader.h"
-#include "SkXfermode.h"
+#include "SkBlendMode.h"
 #include "core_jni_helpers.h"
 
 #include <Caches.h>
@@ -59,7 +59,7 @@
     // The current shader will no longer need a direct reference owned by Shader.java
     // as all the data needed is contained within the newly created LocalMatrixShader.
     SkASSERT(shaderHandle);
-    SkAutoTUnref<SkShader> currentShader(reinterpret_cast<SkShader*>(shaderHandle));
+    sk_sp<SkShader> currentShader(reinterpret_cast<SkShader*>(shaderHandle));
 
     // Attempt to peel off an existing proxy shader and get the proxy's matrix. If
     // the proxy existed and it's matrix equals the desired matrix then just return
@@ -74,10 +74,10 @@
     //          API enforces that all local matrices are set using this call and
     //          not passed to the constructor of the Shader.
     SkMatrix proxyMatrix;
-    SkAutoTUnref<SkShader> baseShader(currentShader->refAsALocalMatrixShader(&proxyMatrix));
+    sk_sp<SkShader> baseShader = currentShader->makeAsALocalMatrixShader(&proxyMatrix);
     if (baseShader.get()) {
         if (proxyMatrix == *matrix) {
-            return reinterpret_cast<jlong>(currentShader.detach());
+            return reinterpret_cast<jlong>(currentShader.release());
         }
         return reinterpret_cast<jlong>(baseShader->makeWithLocalMatrix(*matrix).release());
     }
@@ -237,7 +237,7 @@
     SkBlendMode mode = static_cast<SkBlendMode>(xfermodeHandle);
     SkShader* shader = SkShader::MakeComposeShader(sk_ref_sp(shaderA),
                                                    sk_ref_sp(shaderB),
-                                                   (SkXfermode::Mode)mode).release();
+                                                   mode).release();
     return reinterpret_cast<jlong>(shader);
 }
 
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
index 899c2da..8934c1e 100644
--- a/core/jni/android/graphics/Utils.cpp
+++ b/core/jni/android/graphics/Utils.cpp
@@ -72,9 +72,6 @@
         amount = newOffset - oldOffset;
     } else {
         amount = fAsset->read(buffer, size);
-        if (amount <= 0) {
-            SkDebugf("---- fAsset->read(%d) returned %d\n", size, amount);
-        }
     }
 
     if (amount < 0) {
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 816d5df..1a33d91 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -24,8 +24,9 @@
 #include "android_os_HwRemoteBinder.h"
 
 #include <JNIHelp.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
 #include <android_runtime/AndroidRuntime.h>
-#include <hidl/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
 #include <hidl/Status.h>
 #include <hwbinder/ProcessState.h>
 #include <nativehelper/ScopedLocalRef.h>
@@ -220,27 +221,31 @@
         return;  // XXX exception already pending?
     }
 
-    const hardware::hidl_version kVersion =
-        hardware::make_hidl_version(versionMajor, versionMinor);
+    using android::hidl::manager::V1_0::IServiceManager;
+
+    const IServiceManager::Version kVersion {
+        .major = static_cast<uint16_t>(versionMajor),
+        .minor = static_cast<uint16_t>(versionMinor),
+    };
 
     sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
 
-    status_t err = hardware::defaultServiceManager()->addService(
-                String16(
-                    reinterpret_cast<const char16_t *>(serviceName),
-                    env->GetStringLength(serviceNameObj)),
+    bool ok = hardware::defaultServiceManager()->add(
+                String8(String16(
+                          reinterpret_cast<const char16_t *>(serviceName),
+                          env->GetStringLength(serviceNameObj))).string(),
                 binder,
                 kVersion);
 
     env->ReleaseStringCritical(serviceNameObj, serviceName);
     serviceName = NULL;
 
-    if (err == OK) {
+    if (ok) {
         LOG(INFO) << "Starting thread pool.";
         ::android::hardware::ProcessState::self()->startThreadPool();
     }
 
-    signalExceptionForError(env, err);
+    signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR));
 }
 
 static jobject JHwBinder_native_getService(
@@ -268,8 +273,12 @@
         return NULL;  // XXX exception already pending?
     }
 
-    const hardware::hidl_version kVersion =
-        hardware::make_hidl_version(versionMajor, versionMinor);
+    using android::hidl::manager::V1_0::IServiceManager;
+
+    const IServiceManager::Version kVersion {
+        .major = static_cast<uint16_t>(versionMajor),
+        .minor = static_cast<uint16_t>(versionMinor),
+    };
 
     LOG(INFO) << "looking for service '"
               << String8(String16(
@@ -277,12 +286,15 @@
                           env->GetStringLength(serviceNameObj))).string()
               << "'";
 
-    sp<hardware::IBinder> service =
-        hardware::defaultServiceManager()->getService(
-                String16(
-                    reinterpret_cast<const char16_t *>(serviceName),
-                    env->GetStringLength(serviceNameObj)),
-                kVersion);
+    sp<hardware::IBinder> service;
+    hardware::defaultServiceManager()->get(
+            String8(String16(
+                      reinterpret_cast<const char16_t *>(serviceName),
+                      env->GetStringLength(serviceNameObj))).string(),
+            kVersion,
+            [&service](sp<hardware::IBinder> out) {
+                service = out;
+            });
 
     env->ReleaseStringCritical(serviceNameObj, serviceName);
     serviceName = NULL;
diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index 3023ba8..1d5d6d5 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -24,7 +24,6 @@
 
 #include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
-#include <hidl/IServiceManager.h>
 #include <hidl/Status.h>
 #include <nativehelper/ScopedLocalRef.h>
 
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 4e0b924..65c1590 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -29,7 +29,7 @@
 #include <SkBitmap.h>
 #include <SkCanvas.h>
 #include <SkMatrix.h>
-#include <SkXfermode.h>
+#include <SkBlendMode.h>
 
 #include <DeferredLayerUpdater.h>
 #include <SkiaShader.h>
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index dd2a7a9..f88de51 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -124,6 +124,10 @@
     renderNode->decStrong(0);
 }
 
+static void android_view_RenderNode_finalize(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
+    releaseRenderNode(reinterpret_cast<RenderNode*>(renderNodePtr));
+}
+
 static jlong android_view_RenderNode_getNativeFinalizer(JNIEnv* env,
         jobject clazz) {
     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&releaseRenderNode));
@@ -650,6 +654,7 @@
 // Regular JNI
 // ----------------------------------------------------------------------------
     { "nCreate",               "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create },
+    { "nFinalize",             "(J)V",   (void*) android_view_RenderNode_finalize },
     { "nGetNativeFinalizer",   "()J",    (void*) android_view_RenderNode_getNativeFinalizer },
     { "nSetDisplayList",       "(JJ)V",   (void*) android_view_RenderNode_setDisplayList },
     { "nOutput",               "(J)V",    (void*) android_view_RenderNode_output },
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index 9fa90ac..4a2b881 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -43,6 +43,7 @@
     jfieldID uid;
     jfieldID set;
     jfieldID tag;
+    jfieldID metered;
     jfieldID roaming;
     jfieldID rxBytes;
     jfieldID rxPackets;
@@ -239,6 +240,9 @@
     ScopedIntArrayRW tag(env, get_int_array(env, stats,
             gNetworkStatsClassInfo.tag, size, grow));
     if (tag.get() == NULL) return -1;
+    ScopedIntArrayRW metered(env, get_int_array(env, stats,
+            gNetworkStatsClassInfo.metered, size, grow));
+    if (metered.get() == NULL) return -1;
     ScopedIntArrayRW roaming(env, get_int_array(env, stats,
             gNetworkStatsClassInfo.roaming, size, grow));
     if (roaming.get() == NULL) return -1;
@@ -265,7 +269,7 @@
         uid[i] = lines[i].uid;
         set[i] = lines[i].set;
         tag[i] = lines[i].tag;
-        // Roaming is populated in Java-land by inspecting the iface properties.
+        // Metered and Roaming are populated in Java-land by inspecting the iface properties.
         rxBytes[i] = lines[i].rxBytes;
         rxPackets[i] = lines[i].rxPackets;
         txBytes[i] = lines[i].txBytes;
@@ -279,6 +283,7 @@
         env->SetObjectField(stats, gNetworkStatsClassInfo.uid, uid.getJavaArray());
         env->SetObjectField(stats, gNetworkStatsClassInfo.set, set.getJavaArray());
         env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray());
+        env->SetObjectField(stats, gNetworkStatsClassInfo.metered, metered.getJavaArray());
         env->SetObjectField(stats, gNetworkStatsClassInfo.roaming, roaming.getJavaArray());
         env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray());
         env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray());
@@ -311,6 +316,7 @@
     gNetworkStatsClassInfo.uid = GetFieldIDOrDie(env, clazz, "uid", "[I");
     gNetworkStatsClassInfo.set = GetFieldIDOrDie(env, clazz, "set", "[I");
     gNetworkStatsClassInfo.tag = GetFieldIDOrDie(env, clazz, "tag", "[I");
+    gNetworkStatsClassInfo.metered = GetFieldIDOrDie(env, clazz, "metered", "[I");
     gNetworkStatsClassInfo.roaming = GetFieldIDOrDie(env, clazz, "roaming", "[I");
     gNetworkStatsClassInfo.rxBytes = GetFieldIDOrDie(env, clazz, "rxBytes", "[J");
     gNetworkStatsClassInfo.rxPackets = GetFieldIDOrDie(env, clazz, "rxPackets", "[J");
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index af117d1..bba3d76 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -449,6 +449,20 @@
                                      jstring instructionSet, jstring dataDir) {
   SetSigChldHandler();
 
+  sigset_t sigchld;
+  sigemptyset(&sigchld);
+  sigaddset(&sigchld, SIGCHLD);
+
+  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
+  // log, which would result in the logging FDs we close being reopened.
+  // This would cause failures because the FDs are not whitelisted.
+  //
+  // Note that the zygote process is single threaded at this point.
+  if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) {
+    ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
+    RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_BLOCK, { SIGCHLD }) failed.");
+  }
+
   // Close any logging related FDs before we start evaluating the list of
   // file descriptors.
   __android_log_close();
@@ -482,6 +496,11 @@
       RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors.");
     }
 
+    if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
+      ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
+      RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
+    }
+
     // Keep capabilities across UID change, unless we're staying root.
     if (uid != 0) {
       EnableKeepCapabilities(env);
diff --git a/core/jni/fd_utils-inl.h b/core/jni/fd_utils-inl.h
index af27069..b78b8ff 100644
--- a/core/jni/fd_utils-inl.h
+++ b/core/jni/fd_utils-inl.h
@@ -51,6 +51,7 @@
   "/dev/null",
   "/dev/socket/zygote",
   "/dev/socket/zygote_secondary",
+  "/dev/socket/webview_zygote",
   "/sys/kernel/debug/tracing/trace_marker",
   "/system/framework/framework-res.apk",
   "/dev/urandom",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b38bb1e..4eebea6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -292,7 +292,7 @@
     <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_SCAN_AVAILABLE" />
-    <protected-broadcast android:name="android.net.wifi.nan.action.WIFI_NAN_STATE_CHANGED" />
+    <protected-broadcast android:name="android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.SCAN_RESULTS" />
     <protected-broadcast android:name="android.net.wifi.RSSI_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.STATE_CHANGE" />
@@ -300,7 +300,6 @@
     <protected-broadcast android:name="android.net.wifi.CONFIGURED_NETWORKS_CHANGE" />
     <protected-broadcast android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
     <protected-broadcast android:name="android.net.wifi.supplicant.STATE_CHANGE" />
-    <protected-broadcast android:name="android.net.wifi.nan.STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.p2p.STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.p2p.DISCOVERY_STATE_CHANGE" />
     <protected-broadcast android:name="android.net.wifi.p2p.THIS_DEVICE_CHANGED" />
@@ -454,6 +453,7 @@
     <protected-broadcast android:name="com.android.server.Wifi.action.TOGGLE_PNO" />
     <protected-broadcast android:name="intent.action.ACTION_RF_BAND_INFO" />
     <protected-broadcast android:name="android.intent.action.MEDIA_RESOURCE_GRANTED" />
+    <protected-broadcast android:name="android.app.action.NETWORK_LOGS_AVAILABLE" />
     <protected-broadcast android:name="android.app.action.SECURITY_LOGS_AVAILABLE" />
 
     <protected-broadcast android:name="android.app.action.INTERRUPTION_FILTER_CHANGED" />
@@ -1774,12 +1774,12 @@
         android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to set the system time zone.
-         <p>Protection level: normal
+         <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.SET_TIME_ZONE"
         android:label="@string/permlab_setTimeZone"
         android:description="@string/permdesc_setTimeZone"
-        android:protectionLevel="normal" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ==================================================== -->
     <!-- Permissions related to changing status bar   -->
diff --git a/core/res/res/layout-notround-watch/alert_dialog_title_material.xml b/core/res/res/layout-notround-watch/alert_dialog_title_material.xml
index 0ab56f9..08eecef 100644
--- a/core/res/res/layout-notround-watch/alert_dialog_title_material.xml
+++ b/core/res/res/layout-notround-watch/alert_dialog_title_material.xml
@@ -18,14 +18,14 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:paddingTop="?attr/dialogPreferredPadding"
+        android:paddingBottom="8dp"
         android:orientation="vertical"
-        android:gravity="top|center_horizontal"
-        android:minHeight="@dimen/alert_dialog_title_height">
+        android:gravity="center_horizontal|top">
     <ImageView android:id="@+id/icon"
             android:adjustViewBounds="true"
             android:maxHeight="24dp"
             android:maxWidth="24dp"
-            android:layout_marginTop="8dp"
             android:layout_marginStart="8dp"
             android:layout_marginBottom="8dp"
             android:layout_width="wrap_content"
@@ -33,7 +33,6 @@
             android:src="@null" />
     <TextView android:id="@+id/alertTitle"
             style="?android:attr/windowTitleStyle"
-            android:layout_marginBottom="8dp"
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
 </LinearLayout>
diff --git a/core/res/res/layout-round-watch/alert_dialog_title_material.xml b/core/res/res/layout-round-watch/alert_dialog_title_material.xml
index aefe28f..dac1e32 100644
--- a/core/res/res/layout-round-watch/alert_dialog_title_material.xml
+++ b/core/res/res/layout-round-watch/alert_dialog_title_material.xml
@@ -18,6 +18,7 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:paddingBottom="8dp"
         android:orientation="vertical"
         android:gravity="top|center_horizontal">
     <FrameLayout
@@ -30,7 +31,6 @@
                 android:maxHeight="24dp"
                 android:maxWidth="24dp"
                 android:layout_marginTop="@dimen/screen_percentage_10"
-                android:layout_marginBottom="8dp"
                 android:layout_gravity="center_horizontal"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
@@ -38,7 +38,6 @@
     </FrameLayout>
     <TextView android:id="@+id/alertTitle"
             style="?android:attr/windowTitleStyle"
-            android:layout_marginBottom="8dp"
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
 </LinearLayout>
diff --git a/core/res/res/layout-watch/alert_dialog_material.xml b/core/res/res/layout-watch/alert_dialog_material.xml
index 2fe13de..960b927 100644
--- a/core/res/res/layout-watch/alert_dialog_material.xml
+++ b/core/res/res/layout-watch/alert_dialog_material.xml
@@ -50,7 +50,7 @@
                 <TextView android:id="@+id/message"
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
-                        android:gravity="@integer/config_dialogTextGravity"
+                        android:gravity="center_horizontal|top"
                         android:textAppearance="@style/TextAppearance.Material.Subhead"
                         android:paddingStart="?dialogPreferredPadding"
                         android:paddingEnd="?dialogPreferredPadding"
@@ -80,7 +80,6 @@
                         android:layout_height="wrap_content"
                         android:layout_gravity="bottom"
                         android:orientation="vertical"
-                        android:minHeight="@dimen/alert_dialog_button_bar_height"
                         android:paddingBottom="?dialogPreferredPadding"
                         style="?android:attr/buttonBarStyle"
                         android:measureWithLargestChild="true">
diff --git a/core/res/res/layout-watch/preference_list_fragment_material.xml b/core/res/res/layout-watch/preference_list_fragment_material.xml
index ae8f203..22e66d5 100644
--- a/core/res/res/layout-watch/preference_list_fragment_material.xml
+++ b/core/res/res/layout-watch/preference_list_fragment_material.xml
@@ -44,7 +44,7 @@
                 android:paddingEnd="@dimen/dialog_padding_material"
                 android:paddingBottom="8dp"
                 android:textAppearance="@style/TextAppearance.Material.Title"
-                android:gravity="center" />
+                android:gravity="center_horizontal|top" />
         </com.android.internal.widget.WatchHeaderListView>
     </FrameLayout>
 
diff --git a/core/res/res/layout/select_dialog_multichoice_material.xml b/core/res/res/layout/select_dialog_multichoice_material.xml
index 36e8e57..731fe16 100644
--- a/core/res/res/layout/select_dialog_multichoice_material.xml
+++ b/core/res/res/layout/select_dialog_multichoice_material.xml
@@ -26,5 +26,5 @@
     android:paddingStart="@dimen/select_dialog_padding_start_material"
     android:paddingEnd="?attr/dialogPreferredPadding"
     android:drawableStart="?attr/listChoiceIndicatorMultiple"
-    android:drawablePadding="20dp"
+    android:drawablePadding="@dimen/select_dialog_drawable_padding_start_material"
     android:ellipsize="marquee" />
diff --git a/core/res/res/layout/select_dialog_singlechoice_material.xml b/core/res/res/layout/select_dialog_singlechoice_material.xml
index 995272a..77b6930 100644
--- a/core/res/res/layout/select_dialog_singlechoice_material.xml
+++ b/core/res/res/layout/select_dialog_singlechoice_material.xml
@@ -26,5 +26,5 @@
     android:paddingStart="@dimen/select_dialog_padding_start_material"
     android:paddingEnd="?attr/dialogPreferredPadding"
     android:drawableStart="?attr/listChoiceIndicatorSingle"
-    android:drawablePadding="20dp"
+    android:drawablePadding="@dimen/select_dialog_drawable_padding_start_material"
     android:ellipsize="marquee" />
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index f873b1c..993d49b 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1432,7 +1432,7 @@
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"সরান"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"প্রস্তাবিত স্তরের চেয়ে বেশি উঁচুতে ভলিউম বাড়াবেন?\n\nউঁচু ভলিউমে বেশি সময় ধরে কিছু শুনলে আপনার শ্রবনশক্তির ক্ষতি হতে পারে।"</string>
-    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"অ্যাক্সেসযোগ্যতা সক্রিয় করতে দুইটি আঙ্গুলকে চেপে নীচে ধরে রাখুন৷"</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"অ্যাক্সেসযোগ্যতা সক্রিয় করতে দুইটি আঙ্গুলকে চেপে নিচে ধরে রাখুন৷"</string>
     <string name="accessibility_enabled" msgid="1381972048564547685">"অ্যাক্সেসযোগ্যতা সক্ষম করা হয়েছে৷"</string>
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"অ্যাক্সেসযোগ্যতা বাতিল করা হয়েছে৷"</string>
     <string name="user_switched" msgid="3768006783166984410">"বর্তমান ব্যবহারকারী <xliff:g id="NAME">%1$s</xliff:g>৷"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 07f6aa8..c63ec41 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1246,7 +1246,7 @@
     <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"La VPN sempre activada està desconnectada"</string>
     <string name="vpn_lockdown_error" msgid="6009249814034708175">"Error de la VPN sempre activada"</string>
     <string name="vpn_lockdown_config" msgid="5099330695245008680">"Toca per configurar"</string>
-    <string name="upload_file" msgid="2897957172366730416">"Trieu un fitxer"</string>
+    <string name="upload_file" msgid="2897957172366730416">"Tria un fitxer"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"No s\'ha escollit cap fitxer"</string>
     <string name="reset" msgid="2448168080964209908">"Restableix"</string>
     <string name="submit" msgid="1602335572089911941">"Envia"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 05155ca..9d8c98b 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1226,7 +1226,7 @@
     <string name="deny" msgid="2081879885755434506">"Ablehnen"</string>
     <string name="permission_request_notification_title" msgid="6486759795926237907">"Berechtigung angefordert"</string>
     <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"Berechtigung angefordert\nfür Konto <xliff:g id="ACCOUNT">%s</xliff:g>"</string>
-    <string name="forward_intent_to_owner" msgid="1207197447013960896">"Sie verwenden diese App außerhalb Ihres Arbeitsprofils"</string>
+    <string name="forward_intent_to_owner" msgid="1207197447013960896">"Du verwendest diese App außerhalb deines Arbeitsprofils"</string>
     <string name="forward_intent_to_work" msgid="621480743856004612">"Du verwendest diese App in deinem Arbeitsprofil."</string>
     <string name="input_method_binding_label" msgid="1283557179944992649">"Eingabemethode"</string>
     <string name="sync_binding_label" msgid="3687969138375092423">"Synchronisieren"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f0cfd0b..6e1012a 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -254,7 +254,7 @@
     <string name="permgrouplab_storage" msgid="1971118770546336966">"저장"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"기기 사진, 미디어, 파일 액세스"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"마이크"</string>
-    <string name="permgroupdesc_microphone" msgid="4988812113943554584">"오디오를 녹음할 수 있도록"</string>
+    <string name="permgroupdesc_microphone" msgid="4988812113943554584">"오디오 녹음"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"카메라"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"사진 및 동영상 촬영"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"전화"</string>
diff --git a/core/res/res/values-notround-watch/config_material.xml b/core/res/res/values-notround-watch/config_material.xml
deleted file mode 100644
index a99674f..0000000
--- a/core/res/res/values-notround-watch/config_material.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<!-- These resources are around just to allow their values to be customized
-     for different hardware and product builds, only for Material theme.  Do not translate.
-
-     NOTE: The naming convention is "config_camelCaseValue".  -->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Gravity that should be used for dialog text styles. Equivalent to: Gravity.START | Gravity.TOP -->
-    <integer name="config_dialogTextGravity">0x00800033</integer>
-</resources>
diff --git a/core/res/res/values-notround-watch/dimens_material.xml b/core/res/res/values-notround-watch/dimens_material.xml
index 9cacb11..9fdf55b 100644
--- a/core/res/res/values-notround-watch/dimens_material.xml
+++ b/core/res/res/values-notround-watch/dimens_material.xml
@@ -15,12 +15,16 @@
 -->
 <resources>
     <dimen name="dialog_padding_material">8dp</dimen>
-    <dimen name="preference_fragment_padding_vertical_material">0dp</dimen>
+    <dimen name="preference_fragment_padding_vertical_material">8dp</dimen>
 
-    <dimen name="list_item_padding_horizontal_material">16dp</dimen>
-    <dimen name="list_item_padding_start_material">16dp</dimen>
-    <dimen name="list_item_padding_end_material">16dp</dimen>
+    <dimen name="list_item_padding_horizontal_material">8dp</dimen>
+    <dimen name="list_item_padding_start_material">8dp</dimen>
+    <dimen name="list_item_padding_end_material">8dp</dimen>
 
-    <dimen name="dialog_list_padding_top_no_title">8dp</dimen>
-    <dimen name="dialog_list_padding_bottom_no_buttons">8dp</dimen>
+    <dimen name="dialog_list_padding_top_no_title">0dp</dimen>
+    <dimen name="dialog_list_padding_bottom_no_buttons">0dp</dimen>
+
+    <!-- Dialog padding minus control padding, used to fix alignment. -->
+    <dimen name="select_dialog_padding_start_material">8dp</dimen>
+    <dimen name="select_dialog_drawable_padding_start_material">8dp</dimen>
 </resources>
diff --git a/core/res/res/values-round-watch/config_material.xml b/core/res/res/values-round-watch/config_material.xml
index 1179870..ae4a6ee 100644
--- a/core/res/res/values-round-watch/config_material.xml
+++ b/core/res/res/values-round-watch/config_material.xml
@@ -20,9 +20,6 @@
     <!-- Don't clip on round screens so the list can scroll past the rounded edges. -->
     <bool name="config_preferenceFragmentClipToPadding">false</bool>
 
-    <!-- Gravity that should be used for dialog text styles. Equivalent to: Gravity.CENTER_HORIZONTAL | Gravity.TOP -->
-    <integer name="config_dialogTextGravity">0x00000031</integer>
-
     <!-- The amount to offset when scrolling to a selection in an AlertDialog -->
     <dimen name="config_alertDialogSelectionScrollOffset">@dimen/screen_percentage_15</dimen>
 </resources>
diff --git a/core/res/res/values-round-watch/dimens_material.xml b/core/res/res/values-round-watch/dimens_material.xml
index f2de4e0..c8f27b1 100644
--- a/core/res/res/values-round-watch/dimens_material.xml
+++ b/core/res/res/values-round-watch/dimens_material.xml
@@ -23,4 +23,8 @@
 
     <dimen name="dialog_list_padding_top_no_title">@dimen/screen_percentage_15</dimen>
     <dimen name="dialog_list_padding_bottom_no_buttons">@dimen/screen_percentage_15</dimen>
+
+    <!-- Dialog padding minus control padding, used to fix alignment. -->
+    <dimen name="select_dialog_padding_start_material">@dimen/screen_percentage_15</dimen>
+    <dimen name="select_dialog_drawable_padding_start_material">8dp</dimen>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 9983142..12a5b7c 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -773,7 +773,7 @@
     <string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"Bu sayfada kal"</string>
     <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nBu sayfadan ayrılmak istediğinizden emin misiniz?"</string>
     <string name="save_password_label" msgid="6860261758665825069">"Onayla"</string>
-    <string name="double_tap_toast" msgid="4595046515400268881">"İpucu: Yakınlaştırmak ve uzaklaştırmak için iki kez hafifçe dokunun."</string>
+    <string name="double_tap_toast" msgid="4595046515400268881">"İpucu: Yakınlaştırmak ve uzaklaştırmak için iki kez dokunun."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Otomatik Doldur"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Otomatik doldurma ayarla"</string>
     <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
@@ -1133,7 +1133,7 @@
     <string name="carrier_app_dialog_button" msgid="7900235513678617329">"UYGULAMAYI AL"</string>
     <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"ŞİMDİ DEĞİL"</string>
     <string name="carrier_app_notification_title" msgid="8921767385872554621">"Yeni SIM kart takıldı"</string>
-    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Kurmak için hafifçe dokunun"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Kurmak için dokunun"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Saati ayarlayın"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tarihi ayarlayın"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ayarla"</string>
@@ -1531,7 +1531,7 @@
     <string name="reason_unknown" msgid="6048913880184628119">"bilinmiyor"</string>
     <string name="reason_service_unavailable" msgid="7824008732243903268">"Yazdırma hizmeti etkin değil"</string>
     <string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> hizmeti yüklendi"</string>
-    <string name="print_service_installed_message" msgid="5897362931070459152">"Etkinleştirmek için hafifçe dokunun"</string>
+    <string name="print_service_installed_message" msgid="5897362931070459152">"Etkinleştirmek için dokunun"</string>
     <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"Yönetici PIN\'ini girin"</string>
     <string name="restr_pin_enter_pin" msgid="3395953421368476103">"PIN\'i girin"</string>
     <string name="restr_pin_incorrect" msgid="8571512003955077924">"Yanlış"</string>
@@ -1660,9 +1660,9 @@
     <string name="user_encrypted_message" msgid="4923292604515744267">"Kilidi açmak için dokunun"</string>
     <string name="user_encrypted_detail" msgid="5708447464349420392">"Kullanıcı verileri kilitlendi"</string>
     <string name="profile_encrypted_detail" msgid="3700965619978314974">"İş profili kilitlendi"</string>
-    <string name="profile_encrypted_message" msgid="6964994232310195874">"İş profilinin kilidini açmak için hafifçe dokunun"</string>
+    <string name="profile_encrypted_message" msgid="6964994232310195874">"İş profilinin kilidini açmak için dokunun"</string>
     <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> cihazına bağlandı"</string>
-    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Dosyaları görüntülemek için hafifçe dokunun"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Dosyaları görüntülemek için dokunun"</string>
     <string name="pin_target" msgid="3052256031352291362">"Sabitle"</string>
     <string name="unpin_target" msgid="3556545602439143442">"Sabitlemeyi kaldır"</string>
     <string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index 7c05b7a..d13d154 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -62,4 +62,7 @@
          ListView/GridView are notably absent since this is their default anyway.
          Set to true for watch devices. -->
     <bool name="config_focusScrollContainersInTouchMode">true</bool>
+
+    <!-- The small screens of watch devices makes multi-window support undesireable. -->
+    <bool name="config_supportsMultiWindow">false</bool>
 </resources>
diff --git a/core/res/res/values-watch/dimens.xml b/core/res/res/values-watch/dimens.xml
new file mode 100644
index 0000000..4c8b39c
--- /dev/null
+++ b/core/res/res/values-watch/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <!-- Dialog title height, not used in watch due to dynamically sized button bar -->
+    <dimen name="alert_dialog_title_height">0dp</dimen>
+    <!-- Dialog button bar height, not used in watch due to dynamically sized button bar -->
+    <dimen name="alert_dialog_button_bar_height">0dp</dimen>
+</resources>
diff --git a/core/res/res/values-watch/styles_material.xml b/core/res/res/values-watch/styles_material.xml
index af4207e..0053c12 100644
--- a/core/res/res/values-watch/styles_material.xml
+++ b/core/res/res/values-watch/styles_material.xml
@@ -98,7 +98,7 @@
         <item name="maxLines">@empty</item>
         <item name="scrollHorizontally">false</item>
         <item name="textAppearance">@style/TextAppearance.Material.DialogWindowTitle</item>
-        <item name="gravity">@integer/config_dialogTextGravity</item>
+        <item name="gravity">center_horizontal|top</item>
         <item name="ellipsize">end</item>
     </style>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0678dfd..ff1d383 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1059,6 +1059,12 @@
     <integer name="config_autoBrightnessBrighteningLightDebounce">4000</integer>
     <integer name="config_autoBrightnessDarkeningLightDebounce">8000</integer>
 
+    <!-- Initial light sensor event rate in milliseconds for automatic brightness control. This is
+         used for obtaining the first light sample when the device stops dozing.
+
+         Set this to -1 to disable this feature. -->
+    <integer name="config_autoBrightnessInitialLightSensorRate">-1</integer>
+
     <!-- Light sensor event rate in milliseconds for automatic brightness control. -->
     <integer name="config_autoBrightnessLightSensorRate">250</integer>
 
@@ -2175,9 +2181,9 @@
     -->
     <string-array translatable="false" name="config_telephonyHardware">
         <!-- modem -->
-        <item>"0,modem,0,0,0,1,1,1"</item>
+        <item>0,modem,0,0,0,1,1,1</item>
         <!-- sim -->
-        <item>"1,sim,0,modem"</item>
+        <item>1,sim,0,modem</item>
     </string-array>
 
     <!-- This string array can be overriden to add an additional DRM support for WebView EME. -->
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 30e7b31..ebe577c 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -129,6 +129,7 @@
 
     <!-- Dialog padding minus control padding, used to fix alignment. -->
     <dimen name="select_dialog_padding_start_material">20dp</dimen>
+    <dimen name="select_dialog_drawable_padding_start_material">20dp</dimen>
 
     <dimen name="seekbar_track_background_height_material">2dp</dimen>
     <dimen name="seekbar_track_progress_height_material">2dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0073f53..92fff65 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1736,6 +1736,7 @@
   <java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
   <java-symbol type="integer" name="config_autoBrightnessBrighteningLightDebounce"/>
   <java-symbol type="integer" name="config_autoBrightnessDarkeningLightDebounce"/>
+  <java-symbol type="integer" name="config_autoBrightnessInitialLightSensorRate"/>
   <java-symbol type="integer" name="config_autoBrightnessLightSensorRate"/>
   <java-symbol type="integer" name="config_carDockKeepsScreenOn" />
   <java-symbol type="integer" name="config_criticalBatteryWarningLevel" />
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index d48a67a..eb85eb4 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -16,6 +16,9 @@
 
 package android.net;
 
+import static android.net.NetworkStats.METERED_ALL;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.METERED_YES;
 import static android.net.NetworkStats.ROAMING_ALL;
 import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.ROAMING_YES;
@@ -45,103 +48,124 @@
     private static final long TEST_START = 1194220800000L;
 
     public void testFindIndex() throws Exception {
-        final NetworkStats stats = new NetworkStats(TEST_START, 4)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 0L,
-                        0L, 10)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 1024L,
-                        8L, 11)
-                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
-                        1024L, 8L, 12)
-                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES, 1024L, 8L,
-                        1024L, 8L, 12);
+        final NetworkStats stats = new NetworkStats(TEST_START, 5)
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
+                        8L, 0L, 0L, 10)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L,
+                        1024L, 8L, 11)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 0L, 0L,
+                        1024L, 8L, 11)
+                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
+                        8L, 1024L, 8L, 12)
+                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 1024L,
+                        8L, 1024L, 8L, 12);
 
-        assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES));
-        assertEquals(2, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO));
-        assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO));
-        assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO));
-        assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, ROAMING_NO));
+        assertEquals(4, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES,
+                ROAMING_YES));
+        assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO));
+        assertEquals(2, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES,
+                ROAMING_NO));
+        assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO));
+        assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO));
+        assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO));
     }
 
     public void testFindIndexHinted() {
         final NetworkStats stats = new NetworkStats(TEST_START, 3)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 0L,
-                        0L, 10)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 1024L,
-                        8L, 11)
-                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
-                        1024L, 8L, 12)
-                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 1024L, 8L,
-                        0L, 0L, 10)
-                .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 0L, 0L, 1024L,
-                        8L, 11)
-                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
-                        1024L, 8L, 12)
-                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES, 1024L, 8L,
-                        1024L, 8L, 12);
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
+                        8L, 0L, 0L, 10)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L,
+                        1024L, 8L, 11)
+                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
+                        8L, 1024L, 8L, 12)
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                        1024L, 8L, 0L, 0L, 10)
+                .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 0L, 0L,
+                        1024L, 8L, 11)
+                .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, 0L, 0L,
+                        1024L, 8L, 11)
+                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
+                        8L, 1024L, 8L, 12)
+                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 1024L,
+                        8L, 1024L, 8L, 12);
 
         // verify that we correctly find across regardless of hinting
         for (int hint = 0; hint < stats.size(); hint++) {
             assertEquals(0, stats.findIndexHinted(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE,
-                    ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, hint));
             assertEquals(1, stats.findIndexHinted(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE,
-                    ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, hint));
             assertEquals(2, stats.findIndexHinted(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE,
-                    ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, hint));
             assertEquals(3, stats.findIndexHinted(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE,
-                    ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, hint));
             assertEquals(4, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D,
-                    ROAMING_NO, hint));
-            assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE,
-                    ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, hint));
+            assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D,
+                    METERED_YES, ROAMING_NO, hint));
             assertEquals(6, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE,
-                    ROAMING_YES, hint));
+                    METERED_NO, ROAMING_NO, hint));
+            assertEquals(7, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE,
+                    METERED_YES, ROAMING_YES, hint));
             assertEquals(-1, stats.findIndexHinted(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE,
-                    ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, hint));
         }
     }
 
     public void testAddEntryGrow() throws Exception {
-        final NetworkStats stats = new NetworkStats(TEST_START, 3);
+        final NetworkStats stats = new NetworkStats(TEST_START, 4);
 
         assertEquals(0, stats.size());
-        assertEquals(3, stats.internalSize());
+        assertEquals(4, stats.internalSize());
 
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L, 2L,
-                2L, 3);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2L, 2L, 2L,
-                2L, 4);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 3L, 3L, 2L,
-                2L, 5);
-
-        assertEquals(3, stats.size());
-        assertEquals(3, stats.internalSize());
-
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4L, 40L, 4L,
-                40L, 7);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 5L, 50L, 4L,
-                40L, 8);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 6L, 60L, 5L,
-                50L, 10);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 7L, 70L, 5L,
-                50L, 11);
-
-        assertEquals(7, stats.size());
-        assertTrue(stats.internalSize() >= 7);
-
-        assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1L, 1L,
                 2L, 2L, 3);
-        assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2L, 2L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 2L, 2L,
                 2L, 2L, 4);
-        assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 3L, 3L,
-                2L, 2L, 5);
-        assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 3L,
+                3L, 2L, 2L, 5);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 3L,
+                3L, 2L, 2L, 5);
+
+        assertEquals(4, stats.size());
+        assertEquals(4, stats.internalSize());
+
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 4L,
                 40L, 4L, 40L, 7);
-        assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 5L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 5L,
                 50L, 4L, 40L, 8);
-        assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 6L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 6L,
                 60L, 5L, 50L, 10);
-        assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 7L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 7L,
                 70L, 5L, 50L, 11);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 7L,
+                70L, 5L, 50L, 11);
+
+        assertEquals(9, stats.size());
+        assertTrue(stats.internalSize() >= 9);
+
+        assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                1L, 1L, 2L, 2L, 3);
+        assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                2L, 2L, 2L, 2L, 4);
+        assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+                3L, 3L, 2L, 2L, 5);
+        assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES,
+                ROAMING_YES, 3L, 3L, 2L, 2L, 5);
+        assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                4L, 40L, 4L, 40L, 7);
+        assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                5L, 50L, 4L, 40L, 8);
+        assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                6L, 60L, 5L, 50L, 10);
+        assertValues(stats, 7, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+                7L, 70L, 5L, 50L, 11);
+        assertValues(stats, 8, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES,
+                ROAMING_YES, 7L, 70L, 5L, 50L, 11);
     }
 
     public void testCombineExisting() throws Exception {
@@ -152,20 +176,18 @@
         stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L,
                 -128L, -1L, -1);
 
-        assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, ROAMING_NO, 384L, 3L,
-                128L, 1L, 9);
-        assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, ROAMING_NO, 128L, 1L, 128L,
-                1L, 2);
+        assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                384L, 3L, 128L, 1L, 9);
+        assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, METERED_NO, ROAMING_NO, 128L,
+                1L, 128L, 1L, 2);
 
         // now try combining that should create row
-        stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L,
-                128L, 1L, 3);
-        assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 1L,
-                128L, 1L, 3);
-        stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L,
-                128L, 1L, 3);
-        assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_NO, 256L, 2L,
-                256L, 2L, 6);
+        stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3);
+        assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                128L, 1L, 128L, 1L, 3);
+        stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3);
+        assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                256L, 2L, 256L, 2L, 6);
     }
 
     public void testSubtractIdenticalData() throws Exception {
@@ -180,10 +202,10 @@
         final NetworkStats result = after.subtract(before);
 
         // identical data should result in zero delta
-        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L,
-                0L, 0);
-        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L,
-                0L, 0);
+        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L,
+                0L, 0L, 0L, 0);
+        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L,
+                0L, 0L, 0L, 0);
     }
 
     public void testSubtractIdenticalRows() throws Exception {
@@ -198,10 +220,10 @@
         final NetworkStats result = after.subtract(before);
 
         // expect delta between measurements
-        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L, 2L,
-                1L, 4);
-        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 3L, 1L, 4L,
-                1L, 8);
+        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1L,
+                1L, 2L, 1L, 4);
+        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 3L,
+                1L, 4L, 1L, 8);
     }
 
     public void testSubtractNewRows() throws Exception {
@@ -217,12 +239,12 @@
         final NetworkStats result = after.subtract(before);
 
         // its okay to have new rows
-        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L,
-                0L, 0);
-        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L,
-                0L, 0);
-        assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
-                1024L, 8L, 20);
+        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L,
+                0L, 0L, 0L, 0);
+        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L,
+                0L, 0L, 0L, 0);
+        assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                1024L, 8L, 1024L, 8L, 20);
     }
 
     public void testSubtractMissingRows() throws Exception {
@@ -237,8 +259,8 @@
 
         // should silently drop omitted rows
         assertEquals(1, result.size());
-        assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L,
-                2L, 3L, 4L, 0);
+        assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO, 1L, 2L, 3L, 4L, 0);
         assertEquals(4L, result.getTotalBytes());
     }
 
@@ -263,13 +285,22 @@
                 .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L);
         assertEquals(64L, uidTag.getTotalBytes());
 
+        final NetworkStats uidMetered = new NetworkStats(TEST_START, 3)
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 32L, 0L,
+                        0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
+                        0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
+                        0L, 0L, 0L);
+        assertEquals(96L, uidMetered.getTotalBytes());
+
         final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L,
-                        0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L,
-                        0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_YES, 32L, 0L, 0L, 0L,
-                        0L);
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 32L, 0L,
+                        0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
+                        0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 32L, 0L,
+                        0L, 0L, 0L);
         assertEquals(96L, uidRoaming.getTotalBytes());
     }
 
@@ -283,95 +314,95 @@
 
     public void testGroupedByIfaceAll() throws Exception {
         final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
-                .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 2L,
-                        20L)
-                .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 128L, 8L, 0L,
+                .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L, 0L,
                         2L, 20L)
-                .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, ROAMING_YES, 128L, 8L, 0L, 2L,
-                        20L);
+                .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO, 128L,
+                        8L, 0L, 2L, 20L)
+                .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES, 128L, 8L, 0L,
+                        2L, 20L);
         final NetworkStats grouped = uidStats.groupedByIface();
 
         assertEquals(3, uidStats.size());
         assertEquals(1, grouped.size());
 
-        assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, ROAMING_ALL, 384L, 24L, 0L,
-                6L, 0L);
+        assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+                384L, 24L, 0L, 6L, 0L);
     }
 
     public void testGroupedByIface() throws Exception {
         final NetworkStats uidStats = new NetworkStats(TEST_START, 7)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L,
-                        2L, 20L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 512L, 32L, 0L,
-                        0L, 0L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 4L, 0L, 0L,
-                        0L)
-                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 512L, 32L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L,
+                        0L, 2L, 20L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 512L,
+                        32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L, 4L,
                         0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L,
-                        0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, 0L,
-                        0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 8L, 0L,
-                        0L, 0L);
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 512L,
+                        32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L,
+                        0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, 128L, 8L,
+                        0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 128L,
+                        8L, 0L, 0L, 0L);
 
         final NetworkStats grouped = uidStats.groupedByIface();
 
         assertEquals(7, uidStats.size());
 
         assertEquals(2, grouped.size());
-        assertValues(grouped, 0, TEST_IFACE, UID_ALL, SET_ALL, TAG_NONE, ROAMING_ALL, 384L, 24L, 0L,
-                2L, 0L);
-        assertValues(grouped, 1, TEST_IFACE2, UID_ALL, SET_ALL, TAG_NONE, ROAMING_ALL, 1024L, 64L,
-                0L, 0L, 0L);
+        assertValues(grouped, 0, TEST_IFACE, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+                384L, 24L, 0L, 2L, 0L);
+        assertValues(grouped, 1, TEST_IFACE2, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+                1024L, 64L, 0L, 0L, 0L);
     }
 
     public void testAddAllValues() {
         final NetworkStats first = new NetworkStats(TEST_START, 5)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L,
-                        0L)
-                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 0L, 0L,
-                        0L, 0L)
-                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 32L, 0L, 0L,
-                        0L, 0L);
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
+                        0L, 0L, 0L)
+                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 32L,
+                        0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, 32L,
+                        0L, 0L, 0L, 0L);
 
         final NetworkStats second = new NetworkStats(TEST_START, 2)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L,
-                        0L)
-                .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
                         0L, 0L, 0L)
-                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 32L, 0L, 0L,
-                        0L, 0L);
+                .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 32L,
+                        0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, 32L,
+                        0L, 0L, 0L, 0L);
 
         first.combineAllValues(second);
 
         assertEquals(4, first.size());
-        assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 64L, 0L, 0L,
-                0L, 0L);
-        assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 0L,
-                0L, 0L, 0L);
-        assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 64L, 0L,
-                0L, 0L, 0L);
-        assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L,
+        assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 64L,
                 0L, 0L, 0L, 0L);
+        assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                32L, 0L, 0L, 0L, 0L);
+        assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
+                64L, 0L, 0L, 0L, 0L);
+        assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                32L, 0L, 0L, 0L, 0L);
     }
 
     public void testGetTotal() {
         final NetworkStats stats = new NetworkStats(TEST_START, 7)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L,
-                        2L, 20L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 512L, 32L, 0L,
-                        0L, 0L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 4L, 0L, 0L,
-                        0L)
-                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 512L, 32L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L,
+                        0L, 2L, 20L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 512L,
+                        32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L, 4L,
                         0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L,
-                        0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, 0L,
-                        0L)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 8L, 0L,
-                        0L, 0L);
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 512L,
+                        32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 128L,
+                        8L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 128L, 8L,
+                        0L, 0L, 0L)
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 128L,
+                        8L, 0L, 0L, 0L);
 
         assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L);
         assertValues(stats.getTotal(null, 100), 1280L, 80L, 0L, 2L, 20L);
@@ -396,10 +427,10 @@
         final NetworkStats after = before.withoutUids(new int[] { 100 });
         assertEquals(6, before.size());
         assertEquals(2, after.size());
-        assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L,
-                0L, 0L, 0L);
-        assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L,
-                0L, 0L);
+        assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                128L, 8L, 0L, 0L, 0L);
+        assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 128L,
+                8L, 0L, 0L, 0L);
     }
 
     public void testClone() throws Exception {
@@ -434,77 +465,90 @@
         final String underlyingIface = "wlan0";
         final int testTag1 = 8888;
         NetworkStats delta = new NetworkStats(TEST_START, 17)
-            .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, 39605L, 46L, 12259L, 55L, 0L)
-            .addValues(tunIface, 10100, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L)
-            .addValues(tunIface, 10120, SET_DEFAULT, TAG_NONE, 72667L, 197L, 43909L, 241L, 0L)
-            .addValues(tunIface, 10120, SET_FOREGROUND, TAG_NONE, 9297L, 17L, 4128L, 21L, 0L)
+            .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 39605L, 46L,
+                    12259L, 55L, 0L)
+            .addValues(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L,
+                    0L, 0L, 0L)
+            .addValues(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 72667L, 197L,
+                    43909L, 241L, 0L)
+            .addValues(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 9297L,
+                    17L, 4128L, 21L, 0L)
             // VPN package also uses some traffic through unprotected network.
-            .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, 4983L, 10L, 1801L, 12L, 0L)
-            .addValues(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L)
+            .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 4983L, 10L,
+                    1801L, 12L, 0L)
+            .addValues(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L,
+                    0L, 0L, 0L)
             // Tag entries
-            .addValues(tunIface, 10120, SET_DEFAULT, testTag1, 21691L, 41L, 13820L, 51L, 0L)
-            .addValues(tunIface, 10120, SET_FOREGROUND, testTag1, 1281L, 2L, 665L, 2L, 0L)
+            .addValues(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO, 21691L, 41L,
+                    13820L, 51L, 0L)
+            .addValues(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO, 1281L, 2L,
+                    665L, 2L, 0L)
             // Irrelevant entries
-            .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, 1685L, 5L, 2070L, 6L, 0L)
+            .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1685L, 5L,
+                    2070L, 6L, 0L)
             // Underlying Iface entries
-            .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, 5178L, 8L, 2139L, 11L, 0L)
-            .addValues(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L)
-            .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, 149873L, 287L,
-                    59217L /* smaller than sum(tun0) */, 299L /* smaller than sum(tun0) */, 0L)
-            .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
+            .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 5178L,
+                    8L, 2139L, 11L, 0L)
+            .addValues(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 0L,
+                    0L, 0L, 0L, 0L)
+            .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                    149873L, 287L, 59217L /* smaller than sum(tun0) */,
+                    299L /* smaller than sum(tun0) */, 0L)
+            .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                    0L, 0L, 0L, 0L, 0L);
 
         assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface));
         assertEquals(20, delta.size());
 
         // tunIface and TEST_IFACE entries are not changed.
-        assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+        assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                 39605L, 46L, 12259L, 55L, 0L);
-        assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 0L, 0L,
-                0L, 0L, 0L);
-        assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+        assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                0L, 0L, 0L, 0L, 0L);
+        assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                 72667L, 197L, 43909L, 241L, 0L);
-        assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO,
+        assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
                 9297L, 17L, 4128L, 21L, 0L);
-        assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+        assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                 4983L, 10L, 1801L, 12L, 0L);
-        assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 0L, 0L,
-                0L, 0L, 0L);
-        assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, ROAMING_NO,
+        assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                0L, 0L, 0L, 0L, 0L);
+        assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO,
                 21691L, 41L, 13820L, 51L, 0L);
-        assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, ROAMING_NO, 1281L,
-                2L, 665L, 2L, 0L);
-        assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1685L, 5L,
-                2070L, 6L, 0L);
+        assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO,
+                1281L, 2L, 665L, 2L, 0L);
+        assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                1685L, 5L, 2070L, 6L, 0L);
 
         // Existing underlying Iface entries are updated
-        assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO,
-                44783L, 54L, 14178L, 62L, 0L);
-        assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_NO,
-                0L, 0L, 0L, 0L, 0L);
+        assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO, 44783L, 54L, 14178L, 62L, 0L);
+        assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO,
+                ROAMING_NO, 0L, 0L, 0L, 0L, 0L);
 
         // VPN underlying Iface entries are updated
-        assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO,
-                28304L, 27L, 1L, 2L, 0L);
-        assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_NO,
-                0L, 0L, 0L, 0L, 0L);
+        assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO, 28304L, 27L, 1L, 2L, 0L);
+        assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO,
+                ROAMING_NO, 0L, 0L, 0L, 0L, 0L);
 
         // New entries are added for new application's underlying Iface traffic
-        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_NO,
-                72667L, 197L, 43123L, 227L, 0L);
-        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO,
-                9297L, 17L, 4054, 19L, 0L);
-        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, ROAMING_NO,
-                21691L, 41L, 13572L, 48L, 0L);
-        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, ROAMING_NO,
-                1281L, 2L, 653L, 1L, 0L);
+        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO, 72667L, 197L, 43123L, 227L, 0L);
+        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO,
+                ROAMING_NO, 9297L, 17L, 4054, 19L, 0L);
+        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, METERED_NO,
+                ROAMING_NO, 21691L, 41L, 13572L, 48L, 0L);
+        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, METERED_NO,
+                ROAMING_NO, 1281L, 2L, 653L, 1L, 0L);
 
         // New entries are added for debug purpose
-        assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO,
-                39605L, 46L, 12039, 51, 0);
-        assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO,
-                81964, 214, 47177, 246, 0);
-        assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, ROAMING_ALL,
-                121569, 260, 59216, 297, 0);
+        assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
+                ROAMING_NO, 39605L, 46L, 12039, 51, 0);
+        assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
+                ROAMING_NO, 81964, 214, 47177, 246, 0);
+        assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, METERED_ALL,
+                ROAMING_ALL, 121569, 260, 59216, 297, 0);
 
     }
 
@@ -518,72 +562,78 @@
         final String underlyingIface = "wlan0";
         NetworkStats delta = new NetworkStats(TEST_START, 9)
             // 2 different apps sent/receive data via tun0.
-            .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, 50000L, 25L, 100000L, 50L, 0L)
-            .addValues(tunIface, 20100, SET_DEFAULT, TAG_NONE, 500L, 2L, 200L, 5L, 0L)
+            .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 50000L, 25L,
+                    100000L, 50L, 0L)
+            .addValues(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 500L, 2L,
+                    200L, 5L, 0L)
             // VPN package resends data through the tunnel (with exaggerated overhead)
-            .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, 240000, 100L, 120000L, 60L, 0L)
+            .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 240000,
+                    100L, 120000L, 60L, 0L)
             // 1 app already has some traffic on the underlying interface, the other doesn't yet
-            .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, 1000L, 10L, 2000L, 20L, 0L)
+            .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1000L,
+                    10L, 2000L, 20L, 0L)
             // Traffic through the underlying interface via the vpn app.
             // This test should redistribute this data correctly.
-            .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE,
+            .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                     75500L, 37L, 130000L, 70L, 0L);
 
         assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface));
         assertEquals(9, delta.size());
 
         // tunIface entries should not be changed.
-        assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+        assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                 50000L, 25L, 100000L, 50L, 0L);
-        assertValues(delta, 1, tunIface, 20100, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+        assertValues(delta, 1, tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                 500L, 2L, 200L, 5L, 0L);
-        assertValues(delta, 2, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+        assertValues(delta, 2, tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                 240000L, 100L, 120000L, 60L, 0L);
 
         // Existing underlying Iface entries are updated
-        assertValues(delta, 3, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO,
-                51000L, 35L, 102000L, 70L, 0L);
+        assertValues(delta, 3, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO, 51000L, 35L, 102000L, 70L, 0L);
 
         // VPN underlying Iface entries are updated
-        assertValues(delta, 4, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO,
-                25000L, 10L, 29800L, 15L, 0L);
+        assertValues(delta, 4, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO, 25000L, 10L, 29800L, 15L, 0L);
 
         // New entries are added for new application's underlying Iface traffic
-        assertContains(delta, underlyingIface, 20100, SET_DEFAULT, TAG_NONE, ROAMING_NO,
-                500L, 2L, 200L, 5L, 0L);
+        assertContains(delta, underlyingIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO, 500L, 2L, 200L, 5L, 0L);
 
         // New entries are added for debug purpose
-        assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO,
-                50000L, 25L, 100000L, 50L, 0L);
-        assertContains(delta, underlyingIface, 20100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO,
-                500, 2L, 200L, 5L, 0L);
-        assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, ROAMING_ALL,
-                50500L, 27L, 100200L, 55, 0);
+        assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
+                ROAMING_NO, 50000L, 25L, 100000L, 50L, 0L);
+        assertContains(delta, underlyingIface, 20100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
+                ROAMING_NO, 500, 2L, 200L, 5L, 0L);
+        assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, METERED_ALL,
+                ROAMING_ALL, 50500L, 27L, 100200L, 55, 0);
     }
 
     private static void assertContains(NetworkStats stats,  String iface, int uid, int set,
-            int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets,
-            long operations) {
-        int index = stats.findIndex(iface, uid, set, tag, roaming);
+            int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes,
+            long txPackets, long operations) {
+        int index = stats.findIndex(iface, uid, set, tag, metered, roaming);
         assertTrue(index != -1);
-        assertValues(stats, index, iface, uid, set, tag, roaming,
+        assertValues(stats, index, iface, uid, set, tag, metered, roaming,
                 rxBytes, rxPackets, txBytes, txPackets, operations);
     }
 
     private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set,
-            int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets,
-            long operations) {
+            int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes,
+            long txPackets, long operations) {
         final NetworkStats.Entry entry = stats.getValues(index, null);
-        assertValues(entry, iface, uid, set, tag, roaming);
+        assertValues(entry, iface, uid, set, tag, metered, roaming);
         assertValues(entry, rxBytes, rxPackets, txBytes, txPackets, operations);
     }
 
     private static void assertValues(
-            NetworkStats.Entry entry, String iface, int uid, int set, int tag, int roaming) {
+            NetworkStats.Entry entry, String iface, int uid, int set, int tag, int metered,
+            int roaming) {
         assertEquals(iface, entry.iface);
         assertEquals(uid, entry.uid);
         assertEquals(set, entry.set);
         assertEquals(tag, entry.tag);
+        assertEquals(metered, entry.metered);
         assertEquals(roaming, entry.roaming);
     }
 
diff --git a/core/tests/coretests/src/android/provider/DocumentsProviderTest.java b/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
index 71546e4..d1c68a9 100644
--- a/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
@@ -60,7 +60,7 @@
                 DocumentsContract.buildDocumentUri(TestDocumentsProvider.AUTHORITY, DOCUMENT_ID);
         try (ContentProviderClient client =
                      mResolver.acquireUnstableContentProviderClient(docUri)) {
-            final Path actual = DocumentsContract.findPath(client, docUri);
+            final Path actual = DocumentsContract.findDocumentPath(client, docUri);
             assertEquals(expected, actual);
         }
     }
@@ -73,7 +73,7 @@
 
         final Uri docUri = buildTreeDocumentUri(
                 TestDocumentsProvider.AUTHORITY, PARENT_DOCUMENT_ID, DOCUMENT_ID);
-        final List<String> actual = DocumentsContract.findPath(mResolver, docUri);
+        final List<String> actual = DocumentsContract.findDocumentPath(mResolver, docUri);
 
         assertEquals(expected.getPath(), actual);
     }
@@ -83,7 +83,7 @@
 
         final Uri docUri = buildTreeDocumentUri(
                 TestDocumentsProvider.AUTHORITY, PARENT_DOCUMENT_ID, DOCUMENT_ID);
-        assertNull(DocumentsContract.findPath(mResolver, docUri));
+        assertNull(DocumentsContract.findDocumentPath(mResolver, docUri));
     }
 
     public void testFindPath_treeUri_erasesNonNullRootId() throws Exception {
@@ -95,7 +95,7 @@
                 TestDocumentsProvider.AUTHORITY, PARENT_DOCUMENT_ID, DOCUMENT_ID);
         try (ContentProviderClient client =
                      mResolver.acquireUnstableContentProviderClient(docUri)) {
-            Path path = DocumentsContract.findPath(client, docUri);
+            Path path = DocumentsContract.findDocumentPath(client, docUri);
             assertNull(path.getRootId());
         }
     }
diff --git a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
index 8dcf566..d61049d 100644
--- a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
+++ b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
@@ -85,7 +85,7 @@
     }
 
     @Override
-    public Path findPath(String documentId, @Nullable String parentDocumentId) {
+    public Path findDocumentPath(String documentId, @Nullable String parentDocumentId) {
         lastDocumentId = documentId;
         lastParentDocumentId = parentDocumentId;
 
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 4e3bf46..7ba46be 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -20,6 +20,7 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.Parcel;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -35,6 +36,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests for RemoteViews.
@@ -43,6 +45,9 @@
 @SmallTest
 public class RemoteViewsTest {
 
+    // This can point to any other package which exists on the device.
+    private static final String OTHER_PACKAGE = "com.android.systemui";
+
     @Rule
     public final ExpectedException exception = ExpectedException.none();
 
@@ -121,4 +126,44 @@
         clone.apply(mContext, mContainer);
     }
 
+    @Test
+    public void parcelSize_nestedViews() {
+        RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
+        // We don't care about the actual layout id.
+        RemoteViews child = new RemoteViews(mPackage, 33);
+        int expectedSize = getParcelSize(original) + getParcelSize(child);
+        original.addView(R.id.layout, child);
+
+        // The application info will get written only once.
+        assertTrue(getParcelSize(original) < expectedSize);
+        assertEquals(getParcelSize(original), getParcelSize(original.clone()));
+
+        original = new RemoteViews(mPackage, R.layout.remote_views_test);
+        child = new RemoteViews(OTHER_PACKAGE, 33);
+        expectedSize = getParcelSize(original) + getParcelSize(child);
+        original.addView(R.id.layout, child);
+
+        // Both the views will get written completely along with an additional view operation
+        assertTrue(getParcelSize(original) > expectedSize);
+        assertEquals(getParcelSize(original), getParcelSize(original.clone()));
+    }
+
+    @Test
+    public void parcelSize_differentOrientation() {
+        RemoteViews landscape = new RemoteViews(mPackage, R.layout.remote_views_test);
+        RemoteViews portrait = new RemoteViews(mPackage, 33);
+
+        // The application info will get written only once.
+        RemoteViews views = new RemoteViews(landscape, portrait);
+        assertTrue(getParcelSize(views) < (getParcelSize(landscape) + getParcelSize(portrait)));
+        assertEquals(getParcelSize(views), getParcelSize(views.clone()));
+    }
+
+    private int getParcelSize(RemoteViews view) {
+        Parcel parcel = Parcel.obtain();
+        view.writeToParcel(parcel, 0);
+        int size = parcel.dataSize();
+        parcel.recycle();
+        return size;
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
index 327f3fd..7f13abc 100644
--- a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.net;
 
+import static android.net.NetworkStats.METERED_NO;
 import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
@@ -101,12 +102,14 @@
 
         final NetworkStats stats = mFactory.readNetworkStatsDetail();
         assertEquals(70, stats.size());
-        assertStatsEntry(stats, "rmnet1", 10021, SET_DEFAULT, 0x30100000, 219110L, 578L, 227423L, 676L);
+        assertStatsEntry(stats, "rmnet1", 10021, SET_DEFAULT, 0x30100000, 219110L, 578L, 227423L,
+                676L);
         assertStatsEntry(stats, "rmnet1", 10021, SET_FOREGROUND, 0x30100000, 742L, 3L, 1265L, 3L);
     }
 
     public void testNetworkStatsSingle() throws Exception {
-        stageFile(R.raw.xt_qtaguid_iface_typical, new File(mTestProc, "net/xt_qtaguid/iface_stat_all"));
+        stageFile(R.raw.xt_qtaguid_iface_typical,
+                new File(mTestProc, "net/xt_qtaguid/iface_stat_all"));
 
         final NetworkStats stats = mFactory.readNetworkStatsSummaryDev();
         assertEquals(6, stats.size());
@@ -122,7 +125,8 @@
         final NetworkStats stats = mFactory.readNetworkStatsSummaryXt();
         assertEquals(3, stats.size());
         assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 6824L, 16L, 5692L, 10L);
-        assertStatsEntry(stats, "rmnet1", UID_ALL, SET_ALL, TAG_NONE, 11153922L, 8051L, 190226L, 2468L);
+        assertStatsEntry(stats, "rmnet1", UID_ALL, SET_ALL, TAG_NONE, 11153922L, 8051L, 190226L,
+                2468L);
         assertStatsEntry(stats, "rmnet2", UID_ALL, SET_ALL, TAG_NONE, 4968L, 35L, 3081L, 39L);
     }
 
@@ -157,7 +161,7 @@
 
     private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set,
             int tag, long rxBytes, long txBytes) {
-        final int i = stats.findIndex(iface, uid, set, tag, ROAMING_NO);
+        final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO);
         final NetworkStats.Entry entry = stats.getValues(i, null);
         assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
         assertEquals("unexpected txBytes", txBytes, entry.txBytes);
@@ -165,7 +169,7 @@
 
     private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set,
             int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) {
-        final int i = stats.findIndex(iface, uid, set, tag, ROAMING_NO);
+        final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO);
         final NetworkStats.Entry entry = stats.getValues(i, null);
         assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
         assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index 80a989a..99aeb43 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -905,20 +905,25 @@
 
 <h4>Drawable</h4>
 
-<p>To create an alias to an existing drawable, use the {@code <bitmap>} element.
-For example:</p>
+<p>
+  To create an alias to an existing drawable, use the {@code <drawable>}
+  element. For example:
+</p>
 
 <pre>
 &lt;?xml version="1.0" encoding="utf-8"?>
-&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/icon_ca" />
+&lt;resources&gt;
+    &lt;drawable name="icon"&gt;&#64;drawable/icon_ca&lt;/drawable&gt;
+&lt;/resources&gt;
 </pre>
 
-<p>If you save this file as {@code icon.xml} (in an alternative resource directory, such as
-{@code res/drawable-en-rCA/}), it is compiled into a resource that you
-can reference as {@code R.drawable.icon}, but is actually an alias for the {@code
-R.drawable.icon_ca} resource (which is saved in {@code res/drawable/}).</p>
-
+<p>
+  If you save this file as {@code drawables.xml} (in an alternative resource
+  directory, such as {@code res/values-en-rCA/}), it is compiled into a
+  resource that you can reference as {@code R.drawable.icon}, but is actually
+  an alias for the {@code R.drawable.icon_ca} resource (which is saved in
+  {@code res/drawable/}).
+</p>
 
 <h4>Layout</h4>
 
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk
index 7d7d42c7..ad1ead8 100644
--- a/libs/androidfw/Android.mk
+++ b/libs/androidfw/Android.mk
@@ -50,6 +50,8 @@
 LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
 LOCAL_SRC_FILES:= $(hostSources)
 LOCAL_C_INCLUDES := external/zlib
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 
 include $(BUILD_HOST_STATIC_LIBRARY)
 
@@ -72,6 +74,8 @@
     libutils \
     libz
 
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
 LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 46fc9d4..ae789d6 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -684,6 +684,7 @@
             sharedRes->add(oass, oidmap, offset + 1, false);
             const_cast<AssetManager*>(this)->mAssetPaths.add(oap);
             const_cast<AssetManager*>(this)->mZipSet.addOverlay(targetPackagePath, oap);
+            delete oidmap;
         }
     }
 
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index b16279c..7d1e328 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -3577,7 +3577,7 @@
             }
             if (pi != NULL) {
                 if (kDebugTableTheme) {
-                    ALOGI("Desired type index is %zd in avail %zu", t, Res_MAXTYPE + 1);
+                    ALOGI("Desired type index is %u in avail %zu", t, Res_MAXTYPE + 1);
                 }
                 if (t <= Res_MAXTYPE) {
                     const type_info& ti = pi->types[t];
diff --git a/include/androidfw/Asset.h b/libs/androidfw/include/androidfw/Asset.h
similarity index 98%
rename from include/androidfw/Asset.h
rename to libs/androidfw/include/androidfw/Asset.h
index 11709ce..461e773 100644
--- a/include/androidfw/Asset.h
+++ b/libs/androidfw/include/androidfw/Asset.h
@@ -49,7 +49,7 @@
 
     static int32_t getGlobalCount();
     static String8 getAssetAllocations();
-    
+
     /* used when opening an asset */
     typedef enum AccessMode {
         ACCESS_UNKNOWN = 0,
@@ -211,7 +211,7 @@
 
     AccessMode  mAccessMode;        // how the asset was opened
     String8    mAssetSource;       // debug string
-    
+
     Asset*		mNext;				// linked list.
     Asset*		mPrev;
 };
@@ -274,7 +274,7 @@
 
     FileMap*    mMap;           // for memory map
     unsigned char* mBuf;        // for read
-    
+
     const void* ensureAlignment(FileMap* map);
 };
 
@@ -311,7 +311,7 @@
     virtual const void* getBuffer(bool wordAligned);
     virtual off64_t getLength(void) const { return mUncompressedLen; }
     virtual off64_t getRemainingLength(void) const { return mUncompressedLen-mOffset; }
-    virtual int openFileDescriptor(off64_t* outStart, off64_t* outLength) const { return -1; }
+    virtual int openFileDescriptor(off64_t* /* outStart */, off64_t* /* outLength */) const { return -1; }
     virtual bool isAllocated(void) const { return mBuf != NULL; }
 
 private:
diff --git a/include/androidfw/AssetDir.h b/libs/androidfw/include/androidfw/AssetDir.h
similarity index 100%
rename from include/androidfw/AssetDir.h
rename to libs/androidfw/include/androidfw/AssetDir.h
diff --git a/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
similarity index 97%
rename from include/androidfw/AssetManager.h
rename to libs/androidfw/include/androidfw/AssetManager.h
index 4377213..0441b9d 100644
--- a/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -33,17 +33,8 @@
 /*
  * Native-app access is via the opaque typedef struct AAssetManager in the C namespace.
  */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 struct AAssetManager { };
 
-#ifdef __cplusplus
-};
-#endif
-
-
 /*
  * Now the proper C++ android-namespace definitions
  */
@@ -83,8 +74,8 @@
     virtual ~AssetManager(void);
 
     static int32_t getGlobalCount();
-    
-    /*                                                                       
+
+    /*
      * Add a new source for assets.  This can be called multiple times to
      * look in multiple places for assets.  It can be either a directory (for
      * finding assets as raw files on the disk) or a ZIP file.  This newly
@@ -178,7 +169,7 @@
      */
     FileType getFileType(const char* fileName);
 
-    /*                                                                       
+    /*
      * Return the complete resource table to find things in the package.
      */
     const ResTable& getResources(bool required = true) const;
@@ -255,12 +246,12 @@
 
         ResTable* getResourceTable();
         ResTable* setResourceTable(ResTable* res);
-        
+
         bool isUpToDate();
 
         void addOverlay(const asset_path& ap);
         bool getOverlay(size_t idx, asset_path* out) const;
-        
+
     protected:
         ~SharedZip();
 
@@ -312,7 +303,7 @@
 
         void addOverlay(const String8& path, const asset_path& overlay);
         bool getOverlay(const String8& path, size_t idx, asset_path* out) const;
-        
+
     private:
         void closeZip(int idx);
 
diff --git a/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h
similarity index 100%
rename from include/androidfw/AttributeResolution.h
rename to libs/androidfw/include/androidfw/AttributeResolution.h
diff --git a/include/androidfw/BackupHelpers.h b/libs/androidfw/include/androidfw/BackupHelpers.h
similarity index 100%
rename from include/androidfw/BackupHelpers.h
rename to libs/androidfw/include/androidfw/BackupHelpers.h
diff --git a/include/androidfw/ByteBucketArray.h b/libs/androidfw/include/androidfw/ByteBucketArray.h
similarity index 100%
rename from include/androidfw/ByteBucketArray.h
rename to libs/androidfw/include/androidfw/ByteBucketArray.h
diff --git a/include/androidfw/CursorWindow.h b/libs/androidfw/include/androidfw/CursorWindow.h
similarity index 100%
rename from include/androidfw/CursorWindow.h
rename to libs/androidfw/include/androidfw/CursorWindow.h
diff --git a/include/androidfw/DisplayEventDispatcher.h b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
similarity index 100%
rename from include/androidfw/DisplayEventDispatcher.h
rename to libs/androidfw/include/androidfw/DisplayEventDispatcher.h
diff --git a/include/androidfw/LocaleData.h b/libs/androidfw/include/androidfw/LocaleData.h
similarity index 100%
rename from include/androidfw/LocaleData.h
rename to libs/androidfw/include/androidfw/LocaleData.h
diff --git a/include/androidfw/ObbFile.h b/libs/androidfw/include/androidfw/ObbFile.h
similarity index 96%
rename from include/androidfw/ObbFile.h
rename to libs/androidfw/include/androidfw/ObbFile.h
index 47559cd..3dbf997 100644
--- a/include/androidfw/ObbFile.h
+++ b/libs/androidfw/include/androidfw/ObbFile.h
@@ -124,20 +124,13 @@
     /* Flags for this OBB type. */
     int32_t mFlags;
 
-    /* Whether the file is salted. */
-    bool mSalted;
-
     /* The encryption salt. */
     unsigned char mSalt[8];
 
     const char* mFileName;
 
-    size_t mFileSize;
-
     size_t mFooterStart;
 
-    unsigned char* mReadBuf;
-
     bool parseObbFile(int fd);
 };
 
diff --git a/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
similarity index 100%
rename from include/androidfw/ResourceTypes.h
rename to libs/androidfw/include/androidfw/ResourceTypes.h
diff --git a/include/androidfw/StreamingZipInflater.h b/libs/androidfw/include/androidfw/StreamingZipInflater.h
similarity index 100%
rename from include/androidfw/StreamingZipInflater.h
rename to libs/androidfw/include/androidfw/StreamingZipInflater.h
diff --git a/include/androidfw/TypeWrappers.h b/libs/androidfw/include/androidfw/TypeWrappers.h
similarity index 98%
rename from include/androidfw/TypeWrappers.h
rename to libs/androidfw/include/androidfw/TypeWrappers.h
index 4233b6b..f1daf33 100644
--- a/include/androidfw/TypeWrappers.h
+++ b/libs/androidfw/include/androidfw/TypeWrappers.h
@@ -31,6 +31,7 @@
         iterator& operator=(const iterator& rhs) {
             mTypeVariant = rhs.mTypeVariant;
             mIndex = rhs.mIndex;
+            return *this;
         }
 
         bool operator==(const iterator& rhs) const {
diff --git a/include/androidfw/ZipFileRO.h b/libs/androidfw/include/androidfw/ZipFileRO.h
similarity index 100%
rename from include/androidfw/ZipFileRO.h
rename to libs/androidfw/include/androidfw/ZipFileRO.h
diff --git a/include/androidfw/ZipUtils.h b/libs/androidfw/include/androidfw/ZipUtils.h
similarity index 100%
rename from include/androidfw/ZipUtils.h
rename to libs/androidfw/include/androidfw/ZipUtils.h
diff --git a/include/androidfw/misc.h b/libs/androidfw/include/androidfw/misc.h
similarity index 100%
rename from include/androidfw/misc.h
rename to libs/androidfw/include/androidfw/misc.h
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 06eb829..8dc502a 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -23,7 +23,11 @@
     pipeline/skia/RenderNodeDrawable.cpp \
     pipeline/skia/ReorderBarrierDrawables.cpp \
     pipeline/skia/SkiaDisplayList.cpp \
+    pipeline/skia/SkiaOpenGLPipeline.cpp \
+    pipeline/skia/SkiaPipeline.cpp \
+    pipeline/skia/SkiaProfileRenderer.cpp \
     pipeline/skia/SkiaRecordingCanvas.cpp \
+    pipeline/skia/SkiaVulkanPipeline.cpp \
     renderstate/Blend.cpp \
     renderstate/MeshState.cpp \
     renderstate/OffscreenBufferPool.cpp \
@@ -296,6 +300,7 @@
     tests/unit/RenderPropertiesTests.cpp \
     tests/unit/SkiaBehaviorTests.cpp \
     tests/unit/SkiaDisplayListTests.cpp \
+    tests/unit/SkiaPipelineTests.cpp \
     tests/unit/SkiaCanvasTests.cpp \
     tests/unit/SnapshotTests.cpp \
     tests/unit/StringUtilsTests.cpp \
@@ -356,6 +361,7 @@
     tests/microbench/FrameBuilderBench.cpp \
     tests/microbench/LinearAllocatorBench.cpp \
     tests/microbench/PathParserBench.cpp \
+    tests/microbench/RenderNodeBench.cpp \
     tests/microbench/ShadowBench.cpp \
     tests/microbench/TaskManagerBench.cpp
 
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index 4cfbb2a..700642e 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -41,6 +41,13 @@
     });
 }
 
+void DeviceInfo::initialize(int maxTextureSize) {
+    std::call_once(sInitializedFlag, [maxTextureSize]() {
+        sDeviceInfo = new DeviceInfo();
+        sDeviceInfo->mMaxTextureSize = maxTextureSize;
+    });
+}
+
 void DeviceInfo::load() {
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
 }
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index e551eb9..aff84b0 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -32,6 +32,7 @@
     // only call this after GL has been initialized, or at any point if compiled
     // with HWUI_NULL_GPU
     static void initialize();
+    static void initialize(int maxTextureSize);
 
     int maxTextureSize() const { return mMaxTextureSize; }
 
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 5213d48..5e4a7f7 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -25,6 +25,7 @@
 #include "RecordedOp.h"
 #include "RenderNode.h"
 #include "VectorDrawable.h"
+#include "renderthread/CanvasContext.h"
 
 namespace android {
 namespace uirenderer {
@@ -105,11 +106,8 @@
 
 bool DisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
         std::function<void(RenderNode*, TreeInfo&, bool)> childFn) {
-    TextureCache& cache = Caches::getInstance().textureCache;
-    for (auto& bitmapResource : bitmapResources) {
-        void* ownerToken = &info.canvasContext;
-        info.prepareTextures = cache.prefetchAndMarkInUse(ownerToken, bitmapResource.get());
-    }
+    info.prepareTextures = info.canvasContext.pinImages(bitmapResources);
+
     for (auto&& op : children) {
         RenderNode* childNode = op->renderNode;
         info.damageAccumulator->pushTransform(&op->localMatrix);
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index b396e22..34c7934 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -25,7 +25,6 @@
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
-#include <SkXfermode.h>
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 3b5fc71..34e6d39 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -257,7 +257,7 @@
             // If the blend mode cannot be implemented using shaders, fall
             // back to the default SrcOver blend mode instead
             if (CC_UNLIKELY(mCaches.extensions().hasFramebufferFetch())) {
-                mDescription.framebufferMode = (SkXfermode::Mode)mode;
+                mDescription.framebufferMode = mode;
                 mDescription.swapSrcDst = (modeUsage == Blend::ModeOrderSwap::Swap);
                 // blending in shader, don't enable
             } else {
@@ -271,11 +271,11 @@
 
     if (colorFilter) {
         SkColor color;
-        SkXfermode::Mode xmode;
+        SkBlendMode bmode;
         SkScalar srcColorMatrix[20];
-        if (colorFilter->asColorMode(&color, &xmode)) {
+        if (colorFilter->asColorMode(&color, &bmode)) {
             mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Blend;
-            mDescription.colorMode = xmode;
+            mDescription.colorMode = bmode;
             mOutGlop->fill.filter.color.set(color);
         } else if (colorFilter->asColorMatrix(srcColorMatrix)) {
             mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Matrix;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index f5beb62..e410d71 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -22,7 +22,7 @@
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
-#include <SkXfermode.h>
+#include <SkBlendMode.h>
 
 #include "Debug.h"
 #include "FloatColor.h"
@@ -142,7 +142,7 @@
     Gradient gradientType;
     bool isSimpleGradient;
 
-    SkXfermode::Mode shadersMode;
+    SkBlendMode shadersMode;
 
     bool isBitmapFirst;
     GLenum bitmapWrapS;
@@ -150,11 +150,11 @@
 
     // Color operations
     ColorFilterMode colorOp;
-    SkXfermode::Mode colorMode;
+    SkBlendMode colorMode;
 
     // Framebuffer blending (requires Extensions.hasFramebufferFetch())
-    // Ignored for all values < SkXfermode::kPlus_Mode
-    SkXfermode::Mode framebufferMode;
+    // Ignored for all values < SkBlendMode::kPlus
+    SkBlendMode framebufferMode;
     bool swapSrcDst;
 
     bool hasDebugHighlight;
@@ -186,16 +186,16 @@
         gradientType = kGradientLinear;
         isSimpleGradient = false;
 
-        shadersMode = SkXfermode::kClear_Mode;
+        shadersMode = SkBlendMode::kClear;
 
         isBitmapFirst = false;
         bitmapWrapS = GL_CLAMP_TO_EDGE;
         bitmapWrapT = GL_CLAMP_TO_EDGE;
 
         colorOp = ColorFilterMode::None;
-        colorMode = SkXfermode::kClear_Mode;
+        colorMode = SkBlendMode::kClear;
 
-        framebufferMode = SkXfermode::kClear_Mode;
+        framebufferMode = SkBlendMode::kClear;
         swapSrcDst = false;
 
         hasDebugHighlight = false;
@@ -244,7 +244,7 @@
         key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
         if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
         if (hasBitmap && hasGradient) {
-            key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
+            key |= ((int)shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
         }
         switch (colorOp) {
             case ColorFilterMode::Matrix:
@@ -252,12 +252,12 @@
                 break;
             case ColorFilterMode::Blend:
                 key |= PROGRAM_KEY_COLOR_BLEND;
-                key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
+                key |= ((int)colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
                 break;
             case ColorFilterMode::None:
                 break;
         }
-        key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
+        key |= ((int)framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
         if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
         if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
         if (hasVertexAlpha) key |= programid(0x1) << PROGRAM_HAS_VERTEX_ALPHA_SHIFT;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 4ef6b85..1afc978 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -572,7 +572,7 @@
 String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) {
     String8 shader(gFS_Header_Start);
 
-    const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode;
+    const bool blendFramebuffer = description.framebufferMode >= SkBlendMode::kPlus;
     if (blendFramebuffer) {
         shader.append(gFS_Header_Extension_FramebufferFetch);
     }
@@ -809,12 +809,12 @@
     return shader;
 }
 
-void ProgramCache::generateBlend(String8& shader, const char* name, SkXfermode::Mode mode) {
+void ProgramCache::generateBlend(String8& shader, const char* name, SkBlendMode mode) {
     shader.append("\nvec4 ");
     shader.append(name);
     shader.append("(vec4 src, vec4 dst) {\n");
     shader.append("    ");
-    shader.append(gBlendOps[mode]);
+    shader.append(gBlendOps[(int)mode]);
     shader.append("}\n");
 }
 
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 292ecdf..c2f715d 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -51,7 +51,7 @@
     Program* generateProgram(const ProgramDescription& description, programid key);
     String8 generateVertexShader(const ProgramDescription& description);
     String8 generateFragmentShader(const ProgramDescription& description);
-    void generateBlend(String8& shader, const char* name, SkXfermode::Mode mode);
+    void generateBlend(String8& shader, const char* name, SkBlendMode mode);
     void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT);
 
     void printLongString(const String8& shader) const;
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index b6031c4..f93e8b8 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -315,7 +315,7 @@
     const ClipBase* mDeferredBarrierClip = nullptr;
     DisplayList* mDisplayList = nullptr;
     bool mHighContrastText = false;
-    SkAutoTUnref<SkDrawFilter> mDrawFilter;
+    sk_sp<SkDrawFilter> mDrawFilter;
 }; // class RecordingCanvas
 
 }; // namespace uirenderer
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 3819c5e..b8964f0 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -33,6 +33,7 @@
 #include "Matrix.h"
 #include "RenderProperties.h"
 #include "pipeline/skia/SkiaDisplayList.h"
+#include "pipeline/skia/SkiaLayer.h"
 
 #include <vector>
 
@@ -60,10 +61,6 @@
 class RenderNode;
 }
 
-namespace skiapipeline {
-    class SkiaDisplayList;
-}
-
 /**
  * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties.
  *
@@ -312,14 +309,23 @@
      * Returns true if an offscreen layer from any renderPipeline is attached
      * to this node.
      */
-    bool hasLayer() const { return mLayer || mLayerSurface.get(); }
+    bool hasLayer() const { return mLayer || mSkiaLayer.get(); }
 
     /**
      * Used by the RenderPipeline to attach an offscreen surface to the RenderNode.
      * The surface is then will be used to store the contents of a layer.
      */
-    void setLayerSurface(sk_sp<SkSurface> layer) { mLayerSurface = layer; }
-
+    void setLayerSurface(sk_sp<SkSurface> layer) {
+        if (layer.get()) {
+            if (!mSkiaLayer.get()) {
+                mSkiaLayer = std::make_unique<skiapipeline::SkiaLayer>();
+            }
+            mSkiaLayer->layerSurface = std::move(layer);
+            mSkiaLayer->inverseTransformInWindow.loadIdentity();
+        } else {
+            mSkiaLayer.reset();
+        }
+    }
 
     /**
      * If the RenderNode is of type LayerType::RenderLayer then this method will
@@ -330,7 +336,13 @@
      * NOTE: this function is only guaranteed to return accurate results after
      *       prepareTree has been run for this RenderNode
      */
-    SkSurface* getLayerSurface() const { return mLayerSurface.get(); }
+    SkSurface* getLayerSurface() const {
+        return mSkiaLayer.get() ? mSkiaLayer->layerSurface.get() : nullptr;
+    }
+
+    skiapipeline::SkiaLayer* getSkiaLayer() const {
+        return mSkiaLayer.get();
+    }
 
 private:
     /**
@@ -346,7 +358,7 @@
      * An offscreen rendering target used to contain the contents this RenderNode
      * when it has been set to draw as a LayerType::RenderLayer.
      */
-    sk_sp<SkSurface> mLayerSurface;
+    std::unique_ptr<skiapipeline::SkiaLayer> mSkiaLayer;
 }; // class RenderNode
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index b6ac48f..7c97e77 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -546,7 +546,7 @@
 #endif
     const int ptCount = vertexCount >> 1;
     mCanvas->drawVertices(vertexMode, ptCount, (SkPoint*)verts, (SkPoint*)texs,
-                          (SkColor*)colors, NULL, indices, indexCount, paint);
+                          (SkColor*)colors, indices, indexCount, paint);
 }
 
 // ----------------------------------------------------------------------------
@@ -670,7 +670,7 @@
     tmpPaint.setShader(image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode));
 
     mCanvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, (SkPoint*)vertices,
-                         texs, (const SkColor*)colors, NULL, indices,
+                         texs, (const SkColor*)colors, indices,
                          indexCount, tmpPaint);
 }
 
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 863146e..5978abc 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -27,6 +27,7 @@
 #include <SkRRect.h>
 #include <SkRSXform.h>
 #include <SkSurface.h>
+#include <SkTextBlobRunIterator.h>
 
 #include <memory>
 
@@ -140,8 +141,9 @@
 }
 
 void SkiaCanvasProxy::onDrawVertices(VertexMode mode, int vertexCount, const SkPoint vertices[],
-        const SkPoint texs[], const SkColor colors[], SkXfermode*, const uint16_t indices[],
+        const SkPoint texs[], const SkColor colors[], SkBlendMode, const uint16_t indices[],
         int indexCount, const SkPaint& paint) {
+    // TODO: should we pass through blendmode
     if (mFilterHwuiCalls) {
         return;
     }
@@ -370,11 +372,46 @@
 
 void SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
         const SkPaint& paint) {
-    SkDEBUGFAIL("SkiaCanvasProxy::onDrawTextBlob is not supported");
+    SkPaint runPaint = paint;
+
+     SkTextBlobRunIterator it(blob);
+     for (;!it.done(); it.next()) {
+         size_t textLen = it.glyphCount() * sizeof(uint16_t);
+         const SkPoint& offset = it.offset();
+         // applyFontToPaint() always overwrites the exact same attributes,
+         // so it is safe to not re-seed the paint for this reason.
+         it.applyFontToPaint(&runPaint);
+
+         switch (it.positioning()) {
+         case SkTextBlob::kDefault_Positioning:
+             this->drawText(it.glyphs(), textLen, x + offset.x(), y + offset.y(), runPaint);
+             break;
+         case SkTextBlob::kHorizontal_Positioning: {
+             std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
+             for (size_t i = 0; i < it.glyphCount(); i++) {
+                 pts[i].set(x + offset.x() + it.pos()[i], y + offset.y());
+             }
+             this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
+             break;
+         }
+         case SkTextBlob::kFull_Positioning: {
+             std::unique_ptr<SkPoint[]> pts(new SkPoint[it.glyphCount()]);
+             for (size_t i = 0; i < it.glyphCount(); i++) {
+                 const size_t xIndex = i*2;
+                 const size_t yIndex = xIndex + 1;
+                 pts[i].set(x + offset.x() + it.pos()[xIndex], y + offset.y() + it.pos()[yIndex]);
+             }
+             this->drawPosText(it.glyphs(), textLen, pts.get(), runPaint);
+             break;
+         }
+         default:
+             SkFAIL("unhandled positioning mode");
+         }
+     }
 }
 
 void SkiaCanvasProxy::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-        const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+        const SkPoint texCoords[4], SkBlendMode bmode, const SkPaint& paint) {
     if (mFilterHwuiCalls) {
         return;
     }
@@ -388,7 +425,7 @@
     // If it fails to generate the vertices, then we do not draw.
     if (SkPatchUtils::getVertexData(&data, cubics, colors, texCoords, lod.width(), lod.height())) {
         this->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount, data.fPoints,
-                           data.fTexCoords, data.fColors, xmode, data.fIndices, data.fIndexCount,
+                           data.fTexCoords, data.fColors, bmode, data.fIndices, data.fIndexCount,
                            paint);
     }
 }
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index 3ee8c6e..0111815 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -67,7 +67,7 @@
     virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                   const SkRect& dst, const SkPaint*) override;
     virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
-                                const SkPoint texs[], const SkColor colors[], SkXfermode*,
+                                const SkPoint texs[], const SkColor colors[], SkBlendMode,
                                 const uint16_t indices[], int indexCount,
                                 const SkPaint&) override;
 
@@ -87,7 +87,7 @@
                                 const SkPaint& paint) override;
 
     virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
-                             const SkPoint texCoords[4], SkXfermode* xmode,
+                             const SkPoint texCoords[4], SkBlendMode,
                              const SkPaint& paint) override;
 
     virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override;
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 489a306..971c2a3 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -309,10 +309,7 @@
         storeCompose(caches, *rec.fShaderB, *rec.fShaderA,
                 transform, textureUnit, description, outData);
     }
-    if (!SkXfermode::AsMode(rec.fMode, &description->shadersMode)) {
-        // TODO: Support other modes.
-        description->shadersMode = SkXfermode::kSrcOver_Mode;
-    }
+    description->shadersMode = rec.fBlendMode;
     return true;
 }
 
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 5854289..d2f37cd 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -22,7 +22,6 @@
 
 #include <GLES2/gl2.h>
 #include <SkShader.h>
-#include <SkXfermode.h>
 #include <cutils/compiler.h>
 
 namespace android {
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index 0a60a8e..5b5b74e 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -272,7 +272,7 @@
         setDefaultParams = true;
     }
 
-    sk_sp<SkColorSpace> sRGB = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+    sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
     bool needSRGB = bitmap.info().colorSpace() == sRGB.get();
 
     GLint internalFormat, format, type;
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index b50647a..97b7dd7 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -564,7 +564,7 @@
 #ifndef ANDROID_ENABLE_LINEAR_BLENDING
         sk_sp<SkColorSpace> colorSpace = nullptr;
 #else
-        sk_sp<SkColorSpace> colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+        sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
 #endif
         SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType, colorSpace);
         cache.bitmap = Bitmap::allocateHeapBitmap(info);
diff --git a/libs/hwui/debug/GlesDriver.cpp b/libs/hwui/debug/GlesDriver.cpp
index b8ef639..97e8f3a 100644
--- a/libs/hwui/debug/GlesDriver.cpp
+++ b/libs/hwui/debug/GlesDriver.cpp
@@ -36,6 +36,11 @@
     return ret;
 }
 
+sk_sp<const GrGLInterface> GlesDriver::getSkiaInterface() {
+    sk_sp<const GrGLInterface> skiaInterface(GrGLCreateNativeInterface());
+    return skiaInterface;
+}
+
 } // namespace debug
 } // namespace uirenderer
 } // namespace android
diff --git a/libs/hwui/debug/GlesDriver.h b/libs/hwui/debug/GlesDriver.h
index ca6f4b6..3c36487 100644
--- a/libs/hwui/debug/GlesDriver.h
+++ b/libs/hwui/debug/GlesDriver.h
@@ -28,6 +28,7 @@
 #include <GLES3/gl31.h>
 #include <GLES3/gl32.h>
 
+#include <gl/GrGLInterface.h>
 #include <memory>
 
 namespace android {
@@ -39,6 +40,7 @@
 class GlesDriver {
 public:
     virtual ~GlesDriver() {}
+    virtual sk_sp<const GrGLInterface> getSkiaInterface();
 
 #define GL_ENTRY(ret, api, ...) virtual ret api##_(__VA_ARGS__) = 0;
     #include "gles_decls.in"
diff --git a/libs/hwui/debug/NullGlesDriver.cpp b/libs/hwui/debug/NullGlesDriver.cpp
index e9dbc74..8fbe4bf 100644
--- a/libs/hwui/debug/NullGlesDriver.cpp
+++ b/libs/hwui/debug/NullGlesDriver.cpp
@@ -20,6 +20,11 @@
 namespace uirenderer {
 namespace debug {
 
+sk_sp<const GrGLInterface> NullGlesDriver::getSkiaInterface() {
+    sk_sp<const GrGLInterface> skiaInterface(GrGLCreateNullInterface());
+    return skiaInterface;
+}
+
 struct {
     GLboolean scissorEnabled;
 } gState;
diff --git a/libs/hwui/debug/NullGlesDriver.h b/libs/hwui/debug/NullGlesDriver.h
index d731379..37ca8f3 100644
--- a/libs/hwui/debug/NullGlesDriver.h
+++ b/libs/hwui/debug/NullGlesDriver.h
@@ -24,6 +24,8 @@
 
 class NullGlesDriver : public FatalBaseDriver {
 public:
+    virtual sk_sp<const GrGLInterface> getSkiaInterface() override;
+
     virtual void glGenBuffers_(GLsizei n, GLuint *buffers) override;
     virtual void glGenFramebuffers_(GLsizei n, GLuint *framebuffers) override;
     virtual void glGenRenderbuffers_(GLsizei n, GLuint *renderbuffers) override;
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index be0b22e..b8f7d9f 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -217,7 +217,7 @@
         return nullptr;
     }
 
-    sk_sp<SkColorSpace> sRGB = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+    sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
     bool needSRGB = skBitmap.info().colorSpace() == sRGB.get();
     bool hasSRGB = caches.extensions().hasSRGB();
     GLint format, type, internalFormat;
@@ -307,7 +307,7 @@
     }
     mRowBytes = rowBytes;
     if (mColorTable.get() != ctable) {
-        mColorTable.reset(ctable);
+        mColorTable.reset(SkSafeRef(ctable));
     }
 
     // Need to validate the alpha type to filter against the color type
@@ -482,4 +482,4 @@
     return nullptr;
 }
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index 1ea8bd2..2dc8ce8 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -20,6 +20,8 @@
 #include "RenderNode.h"
 #include "MinikinUtils.h"
 #include "Paint.h"
+#include "Properties.h"
+#include "pipeline/skia/SkiaRecordingCanvas.h"
 #include "Typeface.h"
 
 #include <SkDrawFilter.h>
@@ -27,6 +29,9 @@
 namespace android {
 
 Canvas* Canvas::create_recording_canvas(int width, int height, uirenderer::RenderNode* renderNode) {
+    if (uirenderer::Properties::isSkiaEnabled()) {
+        return new uirenderer::skiapipeline::SkiaRecordingCanvas(renderNode, width, height);
+    }
     return new uirenderer::RecordingCanvas(width, height);
 }
 
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index 33ee108..50bc6c3 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -49,62 +49,10 @@
 }
 
 Typeface* gDefaultTypeface = NULL;
-pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;
-
-// This installs a default typeface (from a hardcoded path) that allows
-// layouts to work (not crash on null pointer) before the default
-// typeface is set.
-// TODO: investigate why layouts are being created before Typeface.java
-// class initialization.
-static minikin::FontCollection *makeFontCollection() {
-    std::vector<minikin::FontFamily *>typefaces;
-    const char *fns[] = {
-        "/system/fonts/Roboto-Regular.ttf",
-    };
-
-    minikin::FontFamily *family = new minikin::FontFamily();
-    for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
-        const char *fn = fns[i];
-        ALOGD("makeFontCollection adding %s", fn);
-        sk_sp<SkTypeface> skFace = SkTypeface::MakeFromFile(fn);
-        if (skFace != NULL) {
-            // TODO: might be a nice optimization to get access to the underlying font
-            // data, but would require us opening the file ourselves and passing that
-            // to the appropriate Create method of SkTypeface.
-            minikin::MinikinFont *font = new MinikinFontSkia(std::move(skFace), NULL, 0, 0);
-            family->addFont(font);
-            font->Unref();
-        } else {
-            ALOGE("failed to create font %s", fn);
-        }
-    }
-    typefaces.push_back(family);
-
-    minikin::FontCollection *result = new minikin::FontCollection(typefaces);
-    family->Unref();
-    return result;
-}
-
-static void getDefaultTypefaceOnce() {
-  minikin::Layout::init();
-    if (gDefaultTypeface == NULL) {
-        // We expect the client to set a default typeface, but provide a
-        // default so we can make progress before that happens.
-        gDefaultTypeface = new Typeface;
-        gDefaultTypeface->fFontCollection = makeFontCollection();
-        gDefaultTypeface->fSkiaStyle = SkTypeface::kNormal;
-        gDefaultTypeface->fBaseWeight = 400;
-        resolveStyle(gDefaultTypeface);
-    }
-}
 
 Typeface* Typeface::resolveDefault(Typeface* src) {
-    if (src == NULL) {
-        pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
-        return gDefaultTypeface;
-    } else {
-        return src;
-    }
+    LOG_ALWAYS_FATAL_IF(gDefaultTypeface == nullptr);
+    return src == nullptr ? gDefaultTypeface : src;
 }
 
 Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) {
diff --git a/libs/hwui/hwui_static_deps.mk b/libs/hwui/hwui_static_deps.mk
index 2990952..dca78b3 100644
--- a/libs/hwui/hwui_static_deps.mk
+++ b/libs/hwui/hwui_static_deps.mk
@@ -24,7 +24,8 @@
     libprotobuf-cpp-lite \
     libharfbuzz_ng \
     libft2 \
-    libminikin
+    libminikin \
+    libandroidfw
 
 ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
     LOCAL_SHARED_LIBRARIES += libRS libRScpp
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index f8a181f..13a0ed8 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "LayerDrawable.h"
+#include "SkColorFilter.h"
 #include "gl/GrGLTypes.h"
 
 namespace android {
@@ -40,12 +41,12 @@
     textureDescription.fConfig = kRGBA_8888_GrPixelConfig;
     textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
     textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
-    sk_sp<SkImage> layerImage(SkImage::NewFromTexture(context, textureDescription));
+    sk_sp<SkImage> layerImage = SkImage::MakeFromTexture(context, textureDescription);
     if (layerImage) {
         SkPaint paint;
         paint.setAlpha(mLayer->getAlpha());
         paint.setBlendMode(mLayer->getMode());
-        paint.setColorFilter(mLayer->getColorFilter());
+        paint.setColorFilter(sk_ref_sp(mLayer->getColorFilter()));
         canvas->drawImage(layerImage, 0, 0, &paint);
     }
     // restore the original matrix
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index cefa893..accbabd 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -17,7 +17,7 @@
 #include "RenderNodeDrawable.h"
 #include "RenderNode.h"
 #include "SkiaDisplayList.h"
-#include "SkiaFrameRenderer.h"
+#include "SkiaPipeline.h"
 #include "utils/TraceUtils.h"
 
 namespace android {
@@ -49,15 +49,16 @@
 }
 
 void RenderNodeDrawable::onDraw(SkCanvas* canvas) {
-    //negative and positive Z order are drawn out of order
-    if (MathUtils::isZero(mRenderNode->properties().getZ())) {
+    //negative and positive Z order are drawn out of order, if this render node drawable is in
+    //a reordering section
+    if ((!mInReorderingSection) || MathUtils::isZero(mRenderNode->properties().getZ())) {
         this->forceDraw(canvas);
     }
 }
 
 void RenderNodeDrawable::forceDraw(SkCanvas* canvas) {
     RenderNode* renderNode = mRenderNode.get();
-    if (SkiaFrameRenderer::skpCaptureEnabled()) {
+    if (SkiaPipeline::skpCaptureEnabled()) {
         SkRect dimensions = SkRect::MakeWH(renderNode->getWidth(), renderNode->getHeight());
         canvas->drawAnnotation(dimensions, renderNode->getName(), nullptr);
     }
@@ -130,7 +131,7 @@
             || properties.colorFilter() != nullptr) {
         paint->setAlpha(properties.alpha() * alphaMultiplier);
         paint->setBlendMode(properties.xferMode());
-        paint->setColorFilter(properties.colorFilter());
+        paint->setColorFilter(sk_ref_sp(properties.colorFilter()));
         return true;
     }
     return false;
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.h b/libs/hwui/pipeline/skia/RenderNodeDrawable.h
index 0762f37..a2ffc6c 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.h
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.h
@@ -56,10 +56,12 @@
      *      we should draw into the contents of the layer or compose the existing contents of the
      *      layer into the canvas.
      */
-    explicit RenderNodeDrawable(RenderNode* node, SkCanvas* canvas, bool composeLayer = true)
+    explicit RenderNodeDrawable(RenderNode* node, SkCanvas* canvas, bool composeLayer = true,
+            bool inReorderingSection = false)
             : mRenderNode(node)
             , mRecordedTransform(canvas->getTotalMatrix())
-            , mComposeLayer(composeLayer) {}
+            , mComposeLayer(composeLayer)
+            , mInReorderingSection(inReorderingSection) {}
 
     /**
      * Draws into the canvas this render node and its children. If the node is marked as a
@@ -138,6 +140,11 @@
     std::vector<ProjectedChild>* mNextProjectedChildrenTarget = nullptr;
 
     /*
+     * True if the render node is in a reordering section
+     */
+    bool mInReorderingSection;
+
+    /*
      *  Draw the content into a canvas, depending on the render node layer type and mComposeLayer.
      */
     void drawContent(SkCanvas* canvas) const;
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 8d77938..a204d5c 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -17,13 +17,13 @@
 #include "ReorderBarrierDrawables.h"
 #include "RenderNode.h"
 #include "SkiaDisplayList.h"
-#include "SkiaFrameRenderer.h"
+#include "SkiaPipeline.h"
 
 #include <SkBlurMask.h>
 #include <SkBlurMaskFilter.h>
 #include <SkGaussianEdgeShader.h>
 #include <SkPathOps.h>
-#include <SkRRectsGaussianEdgeShader.h>
+#include <SkRRectsGaussianEdgeMaskFilter.h>
 
 namespace android {
 namespace uirenderer {
@@ -161,7 +161,7 @@
         return;
     }
 
-    const Vector3 lightPos = SkiaFrameRenderer::getLightCenter();
+    const Vector3 lightPos = SkiaPipeline::getLightCenter();
     float zRatio = casterZValue / (lightPos.z - casterZValue);
     // clamp
     if (zRatio < 0.0f) {
@@ -170,7 +170,7 @@
         zRatio = 0.95f;
     }
 
-    float blurRadius = SkiaFrameRenderer::getLightRadius()*zRatio;
+    float blurRadius = SkiaPipeline::getLightRadius()*zRatio;
 
     SkAutoCanvasRestore acr(canvas, true);
 
@@ -276,7 +276,7 @@
     }
 
     if (spotAlpha > 0.0f) {
-        const Vector3 lightPos = SkiaFrameRenderer::getLightCenter();
+        const Vector3 lightPos = SkiaPipeline::getLightCenter();
         float zRatio = casterZValue / (lightPos.z - casterZValue);
         // clamp
         if (zRatio < 0.0f) {
@@ -285,7 +285,7 @@
             zRatio = 0.95f;
         }
 
-        const SkScalar lightWidth = SkiaFrameRenderer::getLightRadius();
+        const SkScalar lightWidth = SkiaPipeline::getLightRadius();
         SkScalar srcSpaceSpotRadius = 2.0f * lightWidth * zRatio;
         // the device-space radius sent to the blur shader must fit in 14.2 fixed point
         if (srcSpaceSpotRadius*scaleFactor > MAX_BLUR_RADIUS) {
@@ -341,7 +341,7 @@
         paint.setAntiAlias(true);
 
         // If the area of the stroked geometry is larger than the fill geometry, just fill it.
-        if (strokedArea > filledArea || casterAlpha < 1.0f) {
+        if (strokedArea > filledArea || casterAlpha < 1.0f || insetAmount < 0.0f) {
             paint.setStyle(SkPaint::kStrokeAndFill_Style);
             paint.setStrokeWidth(srcSpaceSpotRadius);
         } else {
@@ -433,13 +433,13 @@
 
         SkPaint paint;
         paint.setColor(SkColorSetARGB((unsigned char) ambientAlpha, 0, 0, 0));
-        paint.setShader(SkRRectsGaussianEdgeShader::Make(devSpaceAmbientRRect,
-                devSpaceAmbientClipRR, devSpaceAmbientRadius));
+        paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceAmbientRRect,
+            devSpaceAmbientClipRR, devSpaceAmbientRadius));
         canvas->drawRect(cover, paint);
     }
 
     if (spotAlpha > 0.0f) {
-        const Vector3 lightPos = SkiaFrameRenderer::getLightCenter();
+        const Vector3 lightPos = SkiaPipeline::getLightCenter();
         float zRatio = casterZValue / (lightPos.z - casterZValue);
         // clamp
         if (zRatio < 0.0f) {
@@ -448,7 +448,7 @@
             zRatio = 0.95f;
         }
 
-        const SkScalar lightWidth = SkiaFrameRenderer::getLightRadius();
+        const SkScalar lightWidth = SkiaPipeline::getLightRadius();
         const SkScalar srcSpaceSpotRadius = 2.0f * lightWidth * zRatio;
         const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor;
 
@@ -514,8 +514,8 @@
             devSpaceSpotClipRR = SkRRect::MakeRect(devSpaceScaledClipRect);
         }
 
-        paint.setShader(SkRRectsGaussianEdgeShader::Make(devSpaceSpotRRect, devSpaceSpotClipRR,
-                devSpaceSpotRadius));
+        paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceSpotRRect,
+            devSpaceSpotClipRR, devSpaceSpotRadius));
 
         SkRect cover = srcSpaceScaledClipRect;
         if (!cover.intersect(srcSpaceSpotRRect.rect())) {
@@ -556,8 +556,8 @@
         return false;
     }
 
-    // The casterClipRect will contain the casterRect when bounds clipping is disabled
-    bool casterIsClippedByRect = !casterClipRect.contains(casterRect);
+    // The casterClipRect will be empty when bounds clipping is disabled
+    bool casterIsClippedByRect = !casterClipRect.isEmpty();
     bool uniformScale = scaleFactors[0] == scaleFactors[1];
 
     if (revealClip.willClip()) {
@@ -626,8 +626,8 @@
         return;
     }
 
-    float ambientAlpha = SkiaFrameRenderer::getAmbientShadowAlpha()*casterAlpha;
-    float spotAlpha = SkiaFrameRenderer::getSpotShadowAlpha()*casterAlpha;
+    float ambientAlpha = SkiaPipeline::getAmbientShadowAlpha()*casterAlpha;
+    float spotAlpha = SkiaPipeline::getSpotShadowAlpha()*casterAlpha;
     const float casterZValue = casterProperties.getZ();
 
     const RevealClip& revealClip = casterProperties.getRevealClip();
@@ -639,11 +639,15 @@
 
     bool clippedToBounds = casterProperties.getClippingFlags() & CLIP_TO_CLIP_BOUNDS;
 
-    SkRect casterClipRect = SkRect::MakeLargest();
+    SkRect casterClipRect = SkRect::MakeEmpty();
     if (clippedToBounds) {
         Rect clipBounds;
         casterProperties.getClippingRectForFlags(CLIP_TO_CLIP_BOUNDS, &clipBounds);
         casterClipRect = clipBounds.toSkRect();
+        if (casterClipRect.isEmpty()) {
+            // An empty clip rect means nothing is drawn
+            return;
+        }
     }
 
     SkAutoCanvasRestore acr(canvas, true);
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index c734097..4abaa90 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -20,7 +20,7 @@
 #include "VectorDrawable.h"
 
 #include <SkImagePriv.h>
-#include <SkMutex.h>
+
 
 namespace android {
 namespace uirenderer {
@@ -40,7 +40,7 @@
 }
 
 bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) {
-    reset(context ? context->getGrContext() : nullptr, SkRect::MakeEmpty());
+    reset(SkRect::MakeEmpty());
     node->attachAvailableList(this);
     return true;
 }
@@ -53,9 +53,12 @@
 
 bool SkiaDisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
         std::function<void(RenderNode*, TreeInfo&, bool)> childFn) {
-    // force all mutable images to be pinned in the GPU cache for the duration
-    // of this frame
-    pinImages(info.canvasContext.getGrContext());
+    // If the prepare tree is triggered by the UI thread then we must force all
+    // mutable images to be pinned in the GPU cache until the next UI thread
+    // draw
+    if (info.mode == TreeInfo::MODE_FULL) {
+        info.prepareTextures = info.canvasContext.pinImages(mMutableImages);
+    }
 
     for (auto& child : mChildNodes) {
         RenderNode* childNode = child.getRenderNode();
@@ -78,45 +81,7 @@
     return isDirty;
 }
 
-static std::vector<sk_sp<SkImage>> gPinnedImages;
-static SkBaseMutex gLock;
-
-void SkiaDisplayList::pinImages(GrContext* context) {
-    if (mPinnedImages) return;
-    for (SkImage* image : mMutableImages) {
-        SkImage_pinAsTexture(image, context);
-    }
-    mPinnedImages = true;
-}
-
-void SkiaDisplayList::unpinImages(GrContext* context) {
-    if (!mPinnedImages) return;
-    if (context) {
-        for (SkImage* image : mMutableImages) {
-            SkImage_unpinAsTexture(image, context);
-        }
-    } else {
-        gLock.acquire();
-        for (SkImage* image : mMutableImages) {
-            gPinnedImages.emplace_back(sk_ref_sp(image));
-        }
-        gLock.release();
-    }
-    mPinnedImages = false;
-}
-
-void SkiaDisplayList::cleanupImages(GrContext* context) {
-    gLock.acquire();
-    for (auto& image : gPinnedImages) {
-        SkImage_unpinAsTexture(image.get(), context);
-    }
-    gPinnedImages.clear();
-    gLock.release();
-}
-
-void SkiaDisplayList::reset(GrContext* context, SkRect bounds) {
-    unpinImages(context);
-    SkASSERT(!mPinnedImages);
+void SkiaDisplayList::reset(SkRect bounds) {
     mIsProjectionReceiver = false;
 
     mDrawable->reset(bounds);
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 734aae4a..f34b485 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -51,7 +51,7 @@
      * constructed with the provided bounds.  The reuse avoids any overhead
      * associated with destroying the SkLiteDL as well as the deques and vectors.
      */
-    void reset(GrContext* context, SkRect bounds);
+    void reset(SkRect bounds);
 
     /**
      * Use the linear allocator to create any SkDrawables needed by the display
@@ -119,21 +119,6 @@
     void updateChildren(std::function<void(RenderNode*)> updateFn) override;
 
     /**
-     * Pin/Unpin any mutable images to the GPU cache. A pinned images is
-     * guaranteed to be remain in the cache until it has been unpinned which
-     * we leverage to avoid making a CPU copy of the pixels.
-     */
-    void pinImages(GrContext* context);
-    void unpinImages(GrContext* context);
-
-    /**
-     * If a SkiaDisplayList is deleted on the UI thread we cache a list of any
-     * images that need unpinned from the GPU cache and call this function on
-     * a subsequent frame to perform that cleanup.
-     */
-    static void cleanupImages(GrContext* context);
-
-    /**
      * We use std::deque here because (1) we need to iterate through these
      * elements and (2) mDrawable holds pointers to the elements, so they cannot
      * relocate.
@@ -145,9 +130,6 @@
     sk_sp<SkLiteDL> mDrawable;
 
     bool mIsProjectionReceiver = false;
-
-private:
-    bool mPinnedImages = false;
 };
 
 }; // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/SkiaFrameRenderer.h b/libs/hwui/pipeline/skia/SkiaFrameRenderer.h
deleted file mode 100644
index 70207c1..0000000
--- a/libs/hwui/pipeline/skia/SkiaFrameRenderer.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-namespace android {
-namespace uirenderer {
-namespace skiapipeline {
-
-/**
- * TODO: this is a stub that will be added in a subsquent CL
- */
-class SkiaFrameRenderer {
-public:
-
-    static bool skpCaptureEnabled() { return false; }
-
-    // TODO avoids unused compile error but we need to pass this to the reorder drawables!
-    static float getLightRadius() {
-        return 1.0f;
-    }
-
-    static uint8_t getAmbientShadowAlpha() {
-        return 1;
-    }
-
-    static uint8_t getSpotShadowAlpha() {
-        return 1;
-    }
-
-    static Vector3 getLightCenter() {
-        Vector3 result;
-        result.x = result.y = result.z = 1.0f;
-        return result;
-    }
-
-};
-
-}; // namespace skiapipeline
-}; // namespace uirenderer
-}; // namespace android
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/libs/hwui/pipeline/skia/SkiaLayer.h
similarity index 60%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to libs/hwui/pipeline/skia/SkiaLayer.h
index 5f66d16..0988d7e 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/libs/hwui/pipeline/skia/SkiaLayer.h
@@ -14,6 +14,25 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+#pragma once
 
-parcelable PublishConfig;
+#include <SkSurface.h>
+#include "Matrix.h"
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+/**
+ * An offscreen rendering target used to contain the contents a RenderNode.
+ */
+struct SkiaLayer
+{
+    sk_sp<SkSurface> layerSurface;
+    Matrix4 inverseTransformInWindow;
+};
+
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
new file mode 100644
index 0000000..f046e4b
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+#include "SkiaOpenGLPipeline.h"
+
+#include "DeferredLayerUpdater.h"
+#include "renderthread/EglManager.h"
+#include "renderstate/RenderState.h"
+#include "Readback.h"
+#include "SkiaPipeline.h"
+#include "SkiaProfileRenderer.h"
+#include "utils/TraceUtils.h"
+
+#include <android/native_window.h>
+#include <cutils/properties.h>
+#include <strings.h>
+
+using namespace android::uirenderer::renderthread;
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+SkiaOpenGLPipeline::SkiaOpenGLPipeline(RenderThread& thread)
+        : SkiaPipeline(thread)
+        , mEglManager(thread.eglManager()) {
+}
+
+MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() {
+    // TODO: Figure out why this workaround is needed, see b/13913604
+    // In the meantime this matches the behavior of GLRenderer, so it is not a regression
+    EGLint error = 0;
+    if (!mEglManager.makeCurrent(mEglSurface, &error)) {
+        return MakeCurrentResult::AlreadyCurrent;
+    }
+    return error ? MakeCurrentResult::Failed : MakeCurrentResult::Succeeded;
+}
+
+Frame SkiaOpenGLPipeline::getFrame() {
+    LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
+                "drawRenderNode called on a context with no surface!");
+    return mEglManager.beginFrame(mEglSurface);
+}
+
+bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty,
+        const SkRect& dirty,
+        const FrameBuilder::LightGeometry& lightGeometry,
+        LayerUpdateQueue* layerUpdateQueue,
+        const Rect& contentDrawBounds, bool opaque,
+        const BakedOpRenderer::LightInfo& lightInfo,
+        const std::vector<sp<RenderNode>>& renderNodes,
+        FrameInfoVisualizer* profiler) {
+
+    mEglManager.damageFrame(frame, dirty);
+
+    // setup surface for fbo0
+    GrBackendRenderTargetDesc renderTargetDesc;
+    renderTargetDesc.fWidth = frame.width();
+    renderTargetDesc.fHeight = frame.height();
+    renderTargetDesc.fConfig = kRGBA_8888_GrPixelConfig;
+    renderTargetDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
+    renderTargetDesc.fSampleCnt = 0;
+    renderTargetDesc.fStencilBits = STENCIL_BUFFER_SIZE;
+    renderTargetDesc.fRenderTargetHandle = 0;
+
+    SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
+
+    SkASSERT(mRenderThread.getGrContext() != nullptr);
+    sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(
+            mRenderThread.getGrContext(), renderTargetDesc, &props));
+
+    SkiaPipeline::updateLighting(lightGeometry, lightInfo);
+    renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+    layerUpdateQueue->clear();
+
+    // Draw visual debugging features
+    if (CC_UNLIKELY(Properties::showDirtyRegions
+            || ProfileType::None != Properties::getProfileType())) {
+        SkCanvas* profileCanvas = surface->getCanvas();
+        SkiaProfileRenderer profileRenderer(profileCanvas);
+        profiler->draw(profileRenderer);
+        profileCanvas->flush();
+    }
+
+    // Log memory statistics
+    if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
+        dumpResourceCacheUsage();
+    }
+
+    return true;
+}
+
+bool SkiaOpenGLPipeline::swapBuffers(const Frame& frame, bool drew,
+        const SkRect& screenDirty, FrameInfo* currentFrameInfo, bool* requireSwap) {
+
+    GL_CHECKPOINT(LOW);
+
+    // Even if we decided to cancel the frame, from the perspective of jank
+    // metrics the frame was swapped at this point
+    currentFrameInfo->markSwapBuffers();
+
+    *requireSwap = drew || mEglManager.damageRequiresSwap();
+
+    if (*requireSwap && (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty)))) {
+        return false;
+    }
+
+    return *requireSwap;
+}
+
+bool SkiaOpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
+    layer->apply();
+    return Readback::copyTextureLayerInto(mRenderThread, *(layer->backingLayer()), bitmap)
+            == CopyResult::Success;
+}
+
+DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() {
+    mEglManager.initialize();
+    Layer* layer = new Layer(mRenderThread.renderState(), 0, 0);
+    layer->generateTexture();
+    return new DeferredLayerUpdater(layer);
+}
+
+void SkiaOpenGLPipeline::onStop() {
+    if (mEglManager.isCurrent(mEglSurface)) {
+        mEglManager.makeCurrent(EGL_NO_SURFACE);
+    }
+}
+
+bool SkiaOpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior) {
+
+    if (mEglSurface != EGL_NO_SURFACE) {
+        mEglManager.destroySurface(mEglSurface);
+        mEglSurface = EGL_NO_SURFACE;
+    }
+
+    if (surface) {
+        mEglSurface = mEglManager.createSurface(surface);
+    }
+
+    if (mEglSurface != EGL_NO_SURFACE) {
+        const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
+        mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
+        return true;
+    }
+
+    return false;
+}
+
+bool SkiaOpenGLPipeline::isSurfaceReady() {
+    return CC_UNLIKELY(mEglSurface != EGL_NO_SURFACE);
+}
+
+bool SkiaOpenGLPipeline::isContextReady() {
+    return CC_LIKELY(mEglManager.hasEglContext());
+}
+
+void SkiaOpenGLPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
+    DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
+    if (thread.eglManager().hasEglContext()) {
+        mode = DrawGlInfo::kModeProcess;
+    }
+
+    (*functor)(mode, nullptr);
+
+    // If there's no context we don't need to reset as there's no gl state to save/restore
+    if (mode != DrawGlInfo::kModeProcessNoContext) {
+        thread.getGrContext()->resetContext();
+    }
+}
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
new file mode 100644
index 0000000..36685dd
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "SkiaPipeline.h"
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaOpenGLPipeline : public SkiaPipeline {
+public:
+    SkiaOpenGLPipeline(renderthread::RenderThread& thread);
+    virtual ~SkiaOpenGLPipeline() {}
+
+    renderthread::MakeCurrentResult makeCurrent() override;
+    renderthread::Frame getFrame() override;
+    bool draw(const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+            const FrameBuilder::LightGeometry& lightGeometry,
+            LayerUpdateQueue* layerUpdateQueue,
+            const Rect& contentDrawBounds, bool opaque,
+            const BakedOpRenderer::LightInfo& lightInfo,
+            const std::vector< sp<RenderNode> >& renderNodes,
+            FrameInfoVisualizer* profiler) override;
+    bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
+            FrameInfo* currentFrameInfo, bool* requireSwap) override;
+    bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
+    DeferredLayerUpdater* createTextureLayer() override;
+    bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior) override;
+    void onStop() override;
+    bool isSurfaceReady() override;
+    bool isContextReady() override;
+
+    static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
+
+private:
+    renderthread::EglManager& mEglManager;
+    EGLSurface mEglSurface = EGL_NO_SURFACE;
+    bool mBufferPreserved = false;
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
new file mode 100644
index 0000000..a6612c9
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -0,0 +1,285 @@
+/*
+ * 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.
+ */
+
+#include "SkiaPipeline.h"
+
+#include "utils/TraceUtils.h"
+#include <SkOSFile.h>
+#include <SkPicture.h>
+#include <SkPictureRecorder.h>
+#include <SkPixelSerializer.h>
+#include <SkStream.h>
+
+using namespace android::uirenderer::renderthread;
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+float   SkiaPipeline::mLightRadius = 0;
+uint8_t SkiaPipeline::mAmbientShadowAlpha = 0;
+uint8_t SkiaPipeline::mSpotShadowAlpha = 0;
+
+Vector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN};
+
+SkiaPipeline::SkiaPipeline(RenderThread& thread) :  mRenderThread(thread) { }
+
+TaskManager* SkiaPipeline::getTaskManager() {
+    return &mTaskManager;
+}
+
+void SkiaPipeline::onDestroyHardwareResources() {
+    // No need to flush the caches here. There is a timer
+    // which will flush temporary resources over time.
+}
+
+bool SkiaPipeline::pinImages(std::vector<SkImage*>& mutableImages) {
+    for (SkImage* image : mutableImages) {
+        mPinnedImages.emplace_back(sk_ref_sp(image));
+        // TODO: return false if texture creation fails (see b/32691999)
+        SkImage_pinAsTexture(image, mRenderThread.getGrContext());
+    }
+    return true;
+}
+
+void SkiaPipeline::unpinImages() {
+    for (auto& image : mPinnedImages) {
+        SkImage_unpinAsTexture(image.get(), mRenderThread.getGrContext());
+    }
+    mPinnedImages.clear();
+}
+
+void SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
+        LayerUpdateQueue* layerUpdateQueue, bool opaque,
+        const BakedOpRenderer::LightInfo& lightInfo) {
+    updateLighting(lightGeometry, lightInfo);
+    ATRACE_NAME("draw layers");
+    renderLayersImpl(*layerUpdateQueue, opaque);
+    layerUpdateQueue->clear();
+}
+
+void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) {
+    // Render all layers that need to be updated, in order.
+    for (size_t i = 0; i < layers.entries().size(); i++) {
+        RenderNode* layerNode = layers.entries()[i].renderNode;
+        // only schedule repaint if node still on layer - possible it may have been
+        // removed during a dropped frame, but layers may still remain scheduled so
+        // as not to lose info on what portion is damaged
+        if (CC_LIKELY(layerNode->getLayerSurface() != nullptr)) {
+            SkASSERT(layerNode->getLayerSurface());
+            SkASSERT(layerNode->getDisplayList()->isSkiaDL());
+            SkiaDisplayList* displayList = (SkiaDisplayList*)layerNode->getDisplayList();
+            if (!displayList || displayList->isEmpty()) {
+                SkDEBUGF(("%p drawLayers(%s) : missing drawable", this, layerNode->getName()));
+                return;
+            }
+
+            const Rect& layerDamage = layers.entries()[i].damage;
+
+            SkCanvas* layerCanvas = layerNode->getLayerSurface()->getCanvas();
+
+            int saveCount = layerCanvas->save();
+            SkASSERT(saveCount == 1);
+
+            layerCanvas->clipRect(layerDamage.toSkRect(), SkRegion::kReplace_Op);
+
+            auto savedLightCenter = mLightCenter;
+            // map current light center into RenderNode's coordinate space
+            layerNode->getSkiaLayer()->inverseTransformInWindow.mapPoint3d(mLightCenter);
+
+            const RenderProperties& properties = layerNode->properties();
+            const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
+            if (properties.getClipToBounds() && layerCanvas->quickReject(bounds)) {
+                return;
+            }
+
+            layerCanvas->clear(SK_ColorTRANSPARENT);
+
+            RenderNodeDrawable root(layerNode, layerCanvas, false);
+            root.forceDraw(layerCanvas);
+            layerCanvas->restoreToCount(saveCount);
+            layerCanvas->flush();
+            mLightCenter = savedLightCenter;
+        }
+    }
+}
+
+bool SkiaPipeline::createOrUpdateLayer(RenderNode* node,
+        const DamageAccumulator& damageAccumulator) {
+    SkSurface* layer = node->getLayerSurface();
+    if (!layer || layer->width() != node->getWidth() || layer->height() != node->getHeight()) {
+        SkImageInfo info = SkImageInfo::MakeN32Premul(node->getWidth(), node->getHeight());
+        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
+        SkASSERT(mRenderThread.getGrContext() != nullptr);
+        node->setLayerSurface(
+                SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
+                        info, 0, &props));
+        if (node->getLayerSurface()) {
+            // update the transform in window of the layer to reset its origin wrt light source
+            // position
+            Matrix4 windowTransform;
+            damageAccumulator.computeCurrentTransform(&windowTransform);
+            node->getSkiaLayer()->inverseTransformInWindow = windowTransform;
+        }
+        return true;
+    }
+    return false;
+}
+
+void SkiaPipeline::destroyLayer(RenderNode* node) {
+    node->setLayerSurface(nullptr);
+}
+
+void SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
+    GrContext* context = thread.getGrContext();
+    if (context) {
+        ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
+        SkBitmap skiaBitmap;
+        bitmap->getSkBitmap(&skiaBitmap);
+        sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
+        SkImage_pinAsTexture(image.get(), context);
+        SkImage_unpinAsTexture(image.get(), context);
+    }
+}
+
+// Encodes to PNG, unless there is already encoded data, in which case that gets
+// used.
+class PngPixelSerializer : public SkPixelSerializer {
+public:
+    bool onUseEncodedData(const void*, size_t) override { return true; }
+    SkData* onEncode(const SkPixmap& pixmap) override {
+        return SkImageEncoder::EncodeData(pixmap.info(), pixmap.addr(), pixmap.rowBytes(),
+                                          SkImageEncoder::kPNG_Type, 100);
+    }
+};
+
+void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
+        const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
+        sk_sp<SkSurface> surface) {
+
+    // draw all layers up front
+    renderLayersImpl(layers, opaque);
+
+    // initialize the canvas for the current frame
+    SkCanvas* canvas = surface->getCanvas();
+
+    std::unique_ptr<SkPictureRecorder> recorder;
+    bool recordingPicture = false;
+    char prop[PROPERTY_VALUE_MAX];
+    if (skpCaptureEnabled()) {
+        property_get("debug.hwui.capture_frame_as_skp", prop, "0");
+        recordingPicture = prop[0] != '0' && !sk_exists(prop);
+        if (recordingPicture) {
+            recorder.reset(new SkPictureRecorder());
+            canvas = recorder->beginRecording(surface->width(), surface->height(),
+                    nullptr, SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
+        }
+    }
+
+    canvas->clipRect(clip, SkRegion::kReplace_Op);
+
+    if (!opaque) {
+        canvas->clear(SK_ColorTRANSPARENT);
+    }
+
+    // If there are multiple render nodes, they are laid out as follows:
+    // #0 - backdrop (content + caption)
+    // #1 - content (positioned at (0,0) and clipped to - its bounds mContentDrawBounds)
+    // #2 - additional overlay nodes
+    // Usually the backdrop cannot be seen since it will be entirely covered by the content. While
+    // resizing however it might become partially visible. The following render loop will crop the
+    // backdrop against the content and draw the remaining part of it. It will then draw the content
+    // cropped to the backdrop (since that indicates a shrinking of the window).
+    //
+    // Additional nodes will be drawn on top with no particular clipping semantics.
+
+    // The bounds of the backdrop against which the content should be clipped.
+    Rect backdropBounds = contentDrawBounds;
+    // Usually the contents bounds should be mContentDrawBounds - however - we will
+    // move it towards the fixed edge to give it a more stable appearance (for the moment).
+    // If there is no content bounds we ignore the layering as stated above and start with 2.
+    int layer = (contentDrawBounds.isEmpty() || nodes.size() == 1) ? 2 : 0;
+
+    for (const sp<RenderNode>& node : nodes) {
+        if (node->nothingToDraw()) continue;
+
+        SkASSERT(node->getDisplayList()->isSkiaDL());
+
+        int count = canvas->save();
+
+        if (layer == 0) {
+            const RenderProperties& properties = node->properties();
+            Rect targetBounds(properties.getLeft(), properties.getTop(),
+                              properties.getRight(), properties.getBottom());
+            // Move the content bounds towards the fixed corner of the backdrop.
+            const int x = targetBounds.left;
+            const int y = targetBounds.top;
+            // Remember the intersection of the target bounds and the intersection bounds against
+            // which we have to crop the content.
+            backdropBounds.set(x, y, x + backdropBounds.getWidth(), y + backdropBounds.getHeight());
+            backdropBounds.doIntersect(targetBounds);
+        } else if (layer == 1) {
+            // We shift and clip the content to match its final location in the window.
+            const SkRect clip = SkRect::MakeXYWH(contentDrawBounds.left, contentDrawBounds.top,
+                                                 backdropBounds.getWidth(), backdropBounds.getHeight());
+            const float dx = backdropBounds.left - contentDrawBounds.left;
+            const float dy = backdropBounds.top - contentDrawBounds.top;
+            canvas->translate(dx, dy);
+            // It gets cropped against the bounds of the backdrop to stay inside.
+            canvas->clipRect(clip, SkRegion::kIntersect_Op);
+        }
+
+        RenderNodeDrawable root(node.get(), canvas);
+        root.draw(canvas);
+        canvas->restoreToCount(count);
+        layer++;
+    }
+
+    if (skpCaptureEnabled() && recordingPicture) {
+        sk_sp<SkPicture> picture = recorder->finishRecordingAsPicture();
+        if (picture->approximateOpCount() > 0) {
+            SkFILEWStream stream(prop);
+            if (stream.isValid()) {
+                PngPixelSerializer serializer;
+                picture->serialize(&stream, &serializer);
+                stream.flush();
+                SkDebugf("Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(), prop);
+            }
+        }
+        surface->getCanvas()->drawPicture(picture);
+    }
+
+    ATRACE_NAME("flush commands");
+    canvas->flush();
+}
+
+void SkiaPipeline::dumpResourceCacheUsage() const {
+    int resources, maxResources;
+    size_t bytes, maxBytes;
+    mRenderThread.getGrContext()->getResourceCacheUsage(&resources, &bytes);
+    mRenderThread.getGrContext()->getResourceCacheLimits(&maxResources, &maxBytes);
+
+    SkString log("Resource Cache Usage:\n");
+    log.appendf("%8d items out of %d maximum items\n", resources, maxResources);
+    log.appendf("%8zu bytes (%.2f MB) out of %.2f MB maximum\n",
+            bytes, bytes * (1.0f / (1024.0f * 1024.0f)), maxBytes * (1.0f / (1024.0f * 1024.0f)));
+
+    ALOGD("%s", log.c_str());
+}
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
new file mode 100644
index 0000000..c1c8cbe
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "renderthread/CanvasContext.h"
+#include "FrameBuilder.h"
+#include "renderthread/IRenderPipeline.h"
+#include <SkSurface.h>
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaPipeline : public renderthread::IRenderPipeline {
+public:
+    SkiaPipeline(renderthread::RenderThread& thread);
+    virtual ~SkiaPipeline() {}
+
+    TaskManager* getTaskManager() override;
+
+    void onDestroyHardwareResources() override;
+
+    bool pinImages(std::vector<SkImage*>& mutableImages) override;
+    bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override { return false; }
+    void unpinImages() override;
+
+    void renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
+            LayerUpdateQueue* layerUpdateQueue, bool opaque,
+            const BakedOpRenderer::LightInfo& lightInfo) override;
+
+    bool createOrUpdateLayer(RenderNode* node,
+            const DamageAccumulator& damageAccumulator) override;
+
+    void renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
+            const std::vector< sp<RenderNode> >& nodes, bool opaque, const Rect &contentDrawBounds,
+            sk_sp<SkSurface> surface);
+
+    static void destroyLayer(RenderNode* node);
+
+    static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap);
+
+    static void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque);
+
+    static bool skpCaptureEnabled() { return false; }
+
+    static float getLightRadius() {
+        if (CC_UNLIKELY(Properties::overrideLightRadius > 0)) {
+            return Properties::overrideLightRadius;
+        }
+        return mLightRadius;
+    }
+
+    static uint8_t getAmbientShadowAlpha() {
+        if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) {
+            return Properties::overrideAmbientShadowStrength;
+        }
+        return mAmbientShadowAlpha;
+    }
+
+    static uint8_t getSpotShadowAlpha() {
+        if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) {
+            return Properties::overrideSpotShadowStrength;
+        }
+        return mSpotShadowAlpha;
+    }
+
+    static Vector3 getLightCenter() {
+        if (CC_UNLIKELY(Properties::overrideLightPosY > 0 || Properties::overrideLightPosZ > 0)) {
+            Vector3 adjustedLightCenter = mLightCenter;
+            if (CC_UNLIKELY(Properties::overrideLightPosY > 0)) {
+                // negated since this shifts up
+                adjustedLightCenter.y = - Properties::overrideLightPosY;
+            }
+            if (CC_UNLIKELY(Properties::overrideLightPosZ > 0)) {
+                adjustedLightCenter.z = Properties::overrideLightPosZ;
+            }
+            return adjustedLightCenter;
+        }
+        return mLightCenter;
+    }
+
+    static void updateLighting(const FrameBuilder::LightGeometry& lightGeometry,
+            const BakedOpRenderer::LightInfo& lightInfo) {
+        mLightRadius = lightGeometry.radius;
+        mAmbientShadowAlpha = lightInfo.ambientShadowAlpha;
+        mSpotShadowAlpha = lightInfo.spotShadowAlpha;
+        mLightCenter = lightGeometry.center;
+    }
+
+protected:
+    void dumpResourceCacheUsage() const;
+
+    renderthread::RenderThread& mRenderThread;
+
+private:
+    TaskManager mTaskManager;
+    std::vector<sk_sp<SkImage>> mPinnedImages;
+    static float mLightRadius;
+    static uint8_t mAmbientShadowAlpha;
+    static uint8_t mSpotShadowAlpha;
+    static Vector3 mLightCenter;
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaProfileRenderer.cpp b/libs/hwui/pipeline/skia/SkiaProfileRenderer.cpp
new file mode 100644
index 0000000..d97fb37
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaProfileRenderer.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#include "SkiaProfileRenderer.h"
+
+namespace android {
+namespace uirenderer {
+
+void SkiaProfileRenderer::drawRect(float left, float top, float right, float bottom,
+        const SkPaint& paint) {
+    SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+    mCanvas->drawRect(rect, paint);
+}
+
+void SkiaProfileRenderer::drawRects(const float* rects, int count, const SkPaint& paint) {
+    for (int index = 0; index + 4 <= count; index += 4) {
+        SkRect rect = SkRect::MakeLTRB(rects[index + 0], rects[index + 1], rects[index + 2],
+                rects[index + 3]);
+        mCanvas->drawRect(rect, paint);
+    }
+}
+
+uint32_t SkiaProfileRenderer::getViewportWidth() {
+    return mCanvas->imageInfo().width();
+}
+
+uint32_t SkiaProfileRenderer::getViewportHeight() {
+    return mCanvas->imageInfo().height();
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaProfileRenderer.h b/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
new file mode 100644
index 0000000..e6b7f83
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#include "IProfileRenderer.h"
+
+#include "BakedOpRenderer.h"
+
+namespace android {
+namespace uirenderer {
+
+class SkiaProfileRenderer : public IProfileRenderer {
+public:
+    SkiaProfileRenderer(SkCanvas* canvas)
+            : mCanvas(canvas) {}
+
+    void drawRect(float left, float top, float right, float bottom, const SkPaint& paint) override;
+    void drawRects(const float* rects, int count, const SkPaint& paint) override;
+    uint32_t getViewportWidth() override;
+    uint32_t getViewportHeight() override;
+
+    virtual ~SkiaProfileRenderer() {}
+
+private:
+    // Does not have ownership.
+    SkCanvas* mCanvas;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 8a42983..621816a 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -41,7 +41,7 @@
     }
     SkRect bounds = SkRect::MakeWH(width, height);
     if (mDisplayList) {
-        mDisplayList->reset(nullptr, bounds);
+        mDisplayList->reset(bounds);
     } else {
         mDisplayList.reset(new SkiaDisplayList(bounds));
     }
@@ -107,7 +107,7 @@
     }
 
     // record the child node
-    mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas());
+    mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas(), true, mCurrentBarrier);
     drawDrawable(&mDisplayList->mChildNodes.back());
 
     // use staging property, since recording on UI thread
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
new file mode 100644
index 0000000..ba13ca5
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+#include "SkiaVulkanPipeline.h"
+
+#include "DeferredLayerUpdater.h"
+#include "renderthread/EglManager.h" // needed for Frame
+#include "Readback.h"
+#include "renderstate/RenderState.h"
+#include "SkiaPipeline.h"
+#include "SkiaProfileRenderer.h"
+
+#include <SkTypes.h>
+#include <WindowContextFactory_android.h>
+#include <VulkanWindowContext.h>
+
+#include <android/native_window.h>
+#include <cutils/properties.h>
+#include <strings.h>
+
+using namespace android::uirenderer::renderthread;
+using namespace sk_app;
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+MakeCurrentResult SkiaVulkanPipeline::makeCurrent() {
+    return (mWindowContext != nullptr) ?
+        MakeCurrentResult::AlreadyCurrent : MakeCurrentResult::Failed;
+}
+
+Frame SkiaVulkanPipeline::getFrame() {
+    LOG_ALWAYS_FATAL_IF(mWindowContext == nullptr, "Tried to draw into null vulkan context!");
+    mBackbuffer = mWindowContext->getBackbufferSurface();
+    if (mBackbuffer.get() == nullptr) {
+        // try recreating the context?
+        SkDebugf("failed to get backbuffer");
+        return Frame(-1, -1, 0);
+    }
+
+    // TODO: support buffer age if Vulkan API can do it
+    Frame frame(mBackbuffer->width(), mBackbuffer->height(), 0);
+    return frame;
+}
+
+bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty,
+        const SkRect& dirty,
+        const FrameBuilder::LightGeometry& lightGeometry,
+        LayerUpdateQueue* layerUpdateQueue,
+        const Rect& contentDrawBounds, bool opaque,
+        const BakedOpRenderer::LightInfo& lightInfo,
+        const std::vector<sp<RenderNode>>& renderNodes,
+        FrameInfoVisualizer* profiler) {
+
+    if (mBackbuffer.get() == nullptr) {
+        return false;
+    }
+    renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, mBackbuffer);
+    layerUpdateQueue->clear();
+
+    // Draw visual debugging features
+    if (CC_UNLIKELY(Properties::showDirtyRegions
+            || ProfileType::None != Properties::getProfileType())) {
+        SkCanvas* profileCanvas = mBackbuffer->getCanvas();
+        SkiaProfileRenderer profileRenderer(profileCanvas);
+        profiler->draw(profileRenderer);
+        profileCanvas->flush();
+    }
+
+    // Log memory statistics
+    if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
+        dumpResourceCacheUsage();
+    }
+
+    return true;
+}
+
+bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew,
+        const SkRect& screenDirty, FrameInfo* currentFrameInfo, bool* requireSwap) {
+
+    *requireSwap = drew;
+
+    // Even if we decided to cancel the frame, from the perspective of jank
+    // metrics the frame was swapped at this point
+    currentFrameInfo->markSwapBuffers();
+
+    if (*requireSwap) {
+        mWindowContext->swapBuffers();
+    }
+
+    mBackbuffer.reset();
+
+    return *requireSwap;
+}
+
+bool SkiaVulkanPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
+    // TODO: implement copyLayerInto for vulkan.
+    return false;
+}
+
+DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
+    Layer* layer = new Layer(mRenderThread.renderState(), 0, 0);
+    return new DeferredLayerUpdater(layer);
+}
+
+void SkiaVulkanPipeline::onStop() {
+}
+
+bool SkiaVulkanPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior) {
+
+    if (mWindowContext) {
+        delete mWindowContext;
+        mWindowContext = nullptr;
+    }
+
+    if (surface) {
+        DisplayParams displayParams;
+        mWindowContext = window_context_factory::NewVulkanForAndroid(surface, displayParams);
+        if (mWindowContext) {
+            DeviceInfo::initialize(mWindowContext->getGrContext()->caps()->maxRenderTargetSize());
+        }
+    }
+
+
+    // this doesn't work for if there is more than one CanvasContext available at one time!
+    mRenderThread.setGrContext(mWindowContext ? mWindowContext->getGrContext() : nullptr);
+
+    return mWindowContext != nullptr;
+}
+
+bool SkiaVulkanPipeline::isSurfaceReady() {
+    return CC_LIKELY(mWindowContext != nullptr) && mWindowContext->isValid();
+}
+
+bool SkiaVulkanPipeline::isContextReady() {
+    return CC_LIKELY(mWindowContext != nullptr);
+}
+
+void SkiaVulkanPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
+    // TODO: we currently don't support OpenGL WebView's
+    DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
+    (*functor)(mode, nullptr);
+}
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
new file mode 100644
index 0000000..cdc8692
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "SkiaPipeline.h"
+#include <SkSurface.h>
+
+namespace sk_app {
+class WindowContext;
+}
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaVulkanPipeline : public SkiaPipeline {
+public:
+    SkiaVulkanPipeline(renderthread::RenderThread& thread) : SkiaPipeline(thread) {}
+    virtual ~SkiaVulkanPipeline() {}
+
+    renderthread::MakeCurrentResult makeCurrent() override;
+    renderthread::Frame getFrame() override;
+    bool draw(const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+            const FrameBuilder::LightGeometry& lightGeometry,
+            LayerUpdateQueue* layerUpdateQueue,
+            const Rect& contentDrawBounds, bool opaque,
+            const BakedOpRenderer::LightInfo& lightInfo,
+            const std::vector< sp<RenderNode> >& renderNodes,
+            FrameInfoVisualizer* profiler) override;
+    bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
+            FrameInfo* currentFrameInfo, bool* requireSwap) override;
+    bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
+    DeferredLayerUpdater* createTextureLayer() override;
+    bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior) override;
+    void onStop() override;
+    bool isSurfaceReady() override;
+    bool isContextReady() override;
+
+    static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
+
+private:
+    sk_app::WindowContext* mWindowContext = nullptr;
+    sk_sp<SkSurface> mBackbuffer;
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 03deb0a..c561c86 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -28,6 +28,9 @@
 #include "renderstate/Stencil.h"
 #include "protos/hwui.pb.h"
 #include "OpenGLPipeline.h"
+#include "pipeline/skia/SkiaOpenGLPipeline.h"
+#include "pipeline/skia/SkiaPipeline.h"
+#include "pipeline/skia/SkiaVulkanPipeline.h"
 #include "utils/GLUtils.h"
 #include "utils/TimeUtils.h"
 
@@ -69,13 +72,11 @@
             return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
                     std::make_unique<OpenGLPipeline>(thread));
         case RenderPipelineType::SkiaGL:
-            //TODO: implement SKIA GL
-            LOG_ALWAYS_FATAL("skiaGL canvas type not implemented.");
-            break;
+            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
+                    std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
         case RenderPipelineType::SkiaVulkan:
-            //TODO: implement Vulkan
-            LOG_ALWAYS_FATAL("Vulkan canvas type not implemented.");
-            break;
+            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
+                                std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread));
         default:
             LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
             break;
@@ -89,6 +90,10 @@
         case RenderPipelineType::OpenGL:
             OpenGLPipeline::destroyLayer(node);
             break;
+        case RenderPipelineType::SkiaGL:
+        case RenderPipelineType::SkiaVulkan:
+            skiapipeline::SkiaPipeline::destroyLayer(node);
+            break;
         default:
             LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
             break;
@@ -102,6 +107,12 @@
         case RenderPipelineType::OpenGL:
             OpenGLPipeline::invokeFunctor(thread, functor);
             break;
+        case RenderPipelineType::SkiaGL:
+            skiapipeline::SkiaOpenGLPipeline::invokeFunctor(thread, functor);
+            break;
+        case RenderPipelineType::SkiaVulkan:
+            skiapipeline::SkiaVulkanPipeline::invokeFunctor(thread, functor);
+            break;
         default:
             LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
             break;
@@ -114,6 +125,10 @@
         case RenderPipelineType::OpenGL:
             OpenGLPipeline::prepareToDraw(thread, bitmap);
             break;
+        case RenderPipelineType::SkiaGL:
+        case RenderPipelineType::SkiaVulkan:
+            skiapipeline::SkiaPipeline::prepareToDraw(thread, bitmap);
+            break;
         default:
             LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
             break;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index b61eef2..c322efb 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -80,6 +80,26 @@
     }
 
     /**
+     * Pin any mutable images to the GPU cache. A pinned images is guaranteed to
+     * remain in the cache until it has been unpinned. We leverage this feature
+     * to avoid making a CPU copy of the pixels.
+     *
+     * @return true if the images have been successfully pinned to the GPU cache
+     *         and false otherwise (e.g. cache limits have been exceeded).
+     */
+    bool pinImages(std::vector<SkImage*>& mutableImages) {
+        return mRenderPipeline->pinImages(mutableImages);
+    }
+    bool pinImages(LsaVector<sk_sp<Bitmap>>& images) {
+        return mRenderPipeline->pinImages(images);
+    }
+
+    /**
+     * Unpin any image that had be previously pinned to the GPU cache
+     */
+    void unpinImages() { mRenderPipeline->unpinImages(); }
+
+    /**
      * Destroy any layers that have been attached to the provided RenderNode removing
      * any state that may have been set during createOrUpdateLayer().
      */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index e3b6dc6..4ff54a5 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -119,7 +119,7 @@
     int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
     mRenderThread->timeLord().vsyncReceived(vsync);
     bool canDraw = mContext->makeCurrent();
-    Caches::getInstance().textureCache.resetMarkInUse(mContext);
+    mContext->unpinImages();
 
     for (size_t i = 0; i < mLayers.size(); i++) {
         mLayers[i]->apply();
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index beaa85e..de95bee 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -30,6 +30,10 @@
 #include <gl/GrGLInterface.h>
 #include <string>
 
+#ifdef HWUI_GLES_WRAP_ENABLED
+#include "debug/GlesDriver.h"
+#endif
+
 #define GLES_VERSION 2
 
 // Android-specific addition that is used to show when frames began in systrace
@@ -131,7 +135,12 @@
     mRenderThread.renderState().onGLContextCreated();
 
     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
+#ifdef HWUI_GLES_WRAP_ENABLED
+        debug::GlesDriver* driver = debug::GlesDriver::get();
+        sk_sp<const GrGLInterface> glInterface(driver->getSkiaInterface());
+#else
         sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
+#endif
         LOG_ALWAYS_FATAL_IF(!glInterface.get());
 
         GrContextOptions options;
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 7349dcc..b12522e 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -31,6 +31,11 @@
 
 class Frame {
 public:
+    Frame(EGLint width, EGLint height, EGLint bufferAge)
+            : mWidth(width)
+            , mHeight(height)
+            , mBufferAge(bufferAge) { }
+
     EGLint width() const { return mWidth; }
     EGLint height() const { return mHeight; }
 
@@ -39,6 +44,7 @@
     EGLint bufferAge() const { return mBufferAge; }
 
 private:
+    Frame() {}
     friend class EglManager;
 
     EGLSurface mSurface;
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 52894ad..0e4000b 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -73,6 +73,9 @@
     virtual TaskManager* getTaskManager() = 0;
     virtual bool createOrUpdateLayer(RenderNode* node,
             const DamageAccumulator& damageAccumulator) = 0;
+    virtual bool pinImages(std::vector<SkImage*>& mutableImages) = 0;
+    virtual bool pinImages(LsaVector<sk_sp<Bitmap>>& images) = 0;
+    virtual void unpinImages() = 0;
 
     virtual ~IRenderPipeline() {}
 };
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
index cca0fca..afeeef8 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.cpp
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -31,7 +31,8 @@
 namespace renderthread {
 
 OpenGLPipeline::OpenGLPipeline(RenderThread& thread)
-        :  mEglManager(thread.eglManager()), mRenderThread(thread) {
+        :  mEglManager(thread.eglManager())
+        , mRenderThread(thread) {
 }
 
 MakeCurrentResult OpenGLPipeline::makeCurrent() {
@@ -222,6 +223,19 @@
     return transformUpdateNeeded;
 }
 
+bool OpenGLPipeline::pinImages(LsaVector<sk_sp<Bitmap>>& images) {
+    TextureCache& cache = Caches::getInstance().textureCache;
+    bool prefetchSucceeded = true;
+    for (auto& bitmapResource : images) {
+        prefetchSucceeded &= cache.prefetchAndMarkInUse(this, bitmapResource.get());
+    }
+    return prefetchSucceeded;
+}
+
+void OpenGLPipeline::unpinImages() {
+    Caches::getInstance().textureCache.resetMarkInUse(this);
+}
+
 void OpenGLPipeline::destroyLayer(RenderNode* node) {
     if (OffscreenBuffer* layer = node->getLayer()) {
         layer->renderState.layerPool().putOrDelete(layer);
diff --git a/libs/hwui/renderthread/OpenGLPipeline.h b/libs/hwui/renderthread/OpenGLPipeline.h
index 8722d59..6df8be4 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.h
+++ b/libs/hwui/renderthread/OpenGLPipeline.h
@@ -55,6 +55,9 @@
     TaskManager* getTaskManager() override;
     bool createOrUpdateLayer(RenderNode* node,
             const DamageAccumulator& damageAccumulator) override;
+    bool pinImages(std::vector<SkImage*>& mutableImages) override { return false; }
+    bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override;
+    void unpinImages() override;
     static void destroyLayer(RenderNode* node);
     static void prepareToDraw(const RenderThread& thread, Bitmap* bitmap);
     static void invokeFunctor(const RenderThread& thread, Functor* functor);
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 0be5a3b..0ce598d 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -22,6 +22,7 @@
 #include <Rect.h>
 #include <RenderNode.h>
 #include <hwui/Bitmap.h>
+#include <pipeline/skia/SkiaRecordingCanvas.h>
 #include <renderstate/RenderState.h>
 #include <renderthread/RenderThread.h>
 #include <Snapshot.h>
@@ -196,6 +197,35 @@
        node.setStagingDisplayList(canvas->finishRecording(), nullptr);
     }
 
+    static sp<RenderNode> createSkiaNode(int left, int top, int right, int bottom,
+            std::function<void(RenderProperties& props, skiapipeline::SkiaRecordingCanvas& canvas)> setup,
+            const char* name = nullptr, skiapipeline::SkiaDisplayList* displayList = nullptr) {
+    #if HWUI_NULL_GPU
+        // if RenderNodes are being sync'd/used, device info will be needed, since
+        // DeviceInfo::maxTextureSize() affects layer property
+        DeviceInfo::initialize();
+    #endif
+        sp<RenderNode> node = new RenderNode();
+        if (name) {
+            node->setName(name);
+        }
+        RenderProperties& props = node->mutateStagingProperties();
+        props.setLeftTopRightBottom(left, top, right, bottom);
+        if (displayList) {
+            node->setStagingDisplayList(displayList, nullptr);
+        }
+        if (setup) {
+            std::unique_ptr<skiapipeline::SkiaRecordingCanvas> canvas(
+                new skiapipeline::SkiaRecordingCanvas(nullptr,
+                props.getWidth(), props.getHeight()));
+            setup(props, *canvas.get());
+            node->setStagingDisplayList(canvas->finishRecording(), nullptr);
+        }
+        node->setPropertyFieldsDirty(0xFFFFFFFF);
+        TestUtils::syncHierarchyPropertiesAndDisplayList(node);
+        return node;
+    }
+
     /**
      * Forces a sync of a tree of RenderNode, such that every descendant will have its staging
      * properties and DisplayList moved to the render copies.
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/libs/hwui/tests/microbench/RenderNodeBench.cpp
similarity index 61%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to libs/hwui/tests/microbench/RenderNodeBench.cpp
index 5f66d16..a5bed00 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/libs/hwui/tests/microbench/RenderNodeBench.cpp
@@ -14,6 +14,20 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+#include <benchmark/benchmark.h>
 
-parcelable PublishConfig;
+#include "RenderNode.h"
+
+using namespace android;
+using namespace android::uirenderer;
+
+void BM_RenderNode_create(benchmark::State& state) {
+    while (state.KeepRunning()) {
+        auto node = new RenderNode();
+        node->incStrong(0);
+        benchmark::DoNotOptimize(node);
+        node->decStrong(0);
+    }
+}
+BENCHMARK(BM_RenderNode_create);
+
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 134497c..dda432e 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -776,7 +776,7 @@
                 SkShader::TileMode::kRepeat_TileMode);
 
         sk_sp<SkShader> composeShader = SkShader::MakeComposeShader(std::move(shader1), std::move(shader2),
-                SkXfermode::kMultiply_Mode);
+                SkBlendMode::kMultiply);
         paint.setShader(std::move(composeShader));
         canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
     });
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 19c311c..623d971 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -34,34 +34,6 @@
 using namespace android::uirenderer::renderthread;
 using namespace android::uirenderer::skiapipeline;
 
-static sp<RenderNode> createSkiaNode(int left, int top, int right, int bottom,
-        std::function<void(RenderProperties& props, SkiaRecordingCanvas& canvas)> setup,
-        const char* name = nullptr, SkiaDisplayList* displayList = nullptr) {
-#if HWUI_NULL_GPU
-    // if RenderNodes are being sync'd/used, device info will be needed, since
-    // DeviceInfo::maxTextureSize() affects layer property
-    DeviceInfo::initialize();
-#endif
-    sp<RenderNode> node = new RenderNode();
-    if (name) {
-        node->setName(name);
-    }
-    RenderProperties& props = node->mutateStagingProperties();
-    props.setLeftTopRightBottom(left, top, right, bottom);
-    if (displayList) {
-        node->setStagingDisplayList(displayList, nullptr);
-    }
-    if (setup) {
-        std::unique_ptr<SkiaRecordingCanvas> canvas(new SkiaRecordingCanvas(nullptr,
-            props.getWidth(), props.getHeight()));
-        setup(props, *canvas.get());
-        node->setStagingDisplayList(canvas->finishRecording(), nullptr);
-    }
-    node->setPropertyFieldsDirty(0xFFFFFFFF);
-    TestUtils::syncHierarchyPropertiesAndDisplayList(node);
-    return node;
-}
-
 TEST(RenderNodeDrawable, create) {
     auto rootNode = TestUtils::createNode(0, 0, 200, 400,
             [](RenderProperties& props, Canvas& canvas) {
@@ -79,85 +51,56 @@
     ASSERT_EQ(drawable.getRecordedMatrix(), canvas.getTotalMatrix());
 }
 
-TEST(RenderNodeDrawable, drawContent) {
-    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
-    SkCanvas& canvas = *surface->getCanvas();
-    canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
-    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
-
-    //create a RenderNodeDrawable backed by a RenderNode backed by a SkLiteRecorder
-    auto rootNode = createSkiaNode(0, 0, 1, 1,
-        [](RenderProperties& props, SkiaRecordingCanvas& recorder) {
-            recorder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
-        });
-    RenderNodeDrawable drawable(rootNode.get(), &canvas, false);
-
-    //negative and positive Z order are drawn out of order
-    rootNode->animatorProperties().setElevation(10.0f);
-    canvas.drawDrawable(&drawable);
-    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
-    rootNode->animatorProperties().setElevation(-10.0f);
-    canvas.drawDrawable(&drawable);
-    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
-
-    //zero Z are drawn immediately
-    rootNode->animatorProperties().setElevation(0.0f);
-    canvas.drawDrawable(&drawable);
-    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
+static void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) {
+    SkPaint paint;
+    // order put in blue channel, transparent so overlapped content doesn't get rejected
+    paint.setColor(SkColorSetARGB(1, 0, 0, expectedDrawOrder));
+    canvas->drawRect(0, 0, 100, 100, paint);
 }
 
-//TODO: another test that verifies equal z values are drawn in order, and barriers prevent Z
-//intermixing (model after FrameBuilder zReorder)
-TEST(RenderNodeDrawable, drawAndReorder) {
-    //this test exercises StartReorderBarrierDrawable, EndReorderBarrierDrawable and
-    //SkiaRecordingCanvas
-    auto surface = SkSurface::MakeRasterN32Premul(4, 4);
-    SkCanvas& canvas = *surface->getCanvas();
+static void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, float z) {
+    auto node = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [expectedDrawOrder, z](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedRect(&canvas, expectedDrawOrder);
+        props.setTranslationZ(z);
+    });
+    canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
+}
 
-    canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
-    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
+TEST(RenderNodeDrawable, zReorder) {
+    class ZReorderCanvas : public SkCanvas {
+    public:
+        ZReorderCanvas(int width, int height) : SkCanvas(width, height) {}
+        void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+            int expectedOrder = SkColorGetB(paint.getColor()); // extract order from blue channel
+            EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order";
+        }
+        int getIndex() { return mIndex; }
+    protected:
+        int mIndex = 0;
+    };
 
-    //-z draws to all 4 pixels (RED)
-    auto redNode = createSkiaNode(0, 0, 4, 4,
-        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
-            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
-            props.setElevation(-10.0f);
-        }, "redNode");
+    auto parent = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder
+        drawOrderedRect(&canvas, 1);
+        canvas.insertReorderBarrier(true);
+        drawOrderedNode(&canvas, 6, 2.0f);
+        drawOrderedRect(&canvas, 3);
+        drawOrderedNode(&canvas, 4, 0.0f);
+        drawOrderedRect(&canvas, 5);
+        drawOrderedNode(&canvas, 2, -2.0f);
+        drawOrderedNode(&canvas, 7, 2.0f);
+        canvas.insertReorderBarrier(false);
+        drawOrderedRect(&canvas, 8);
+        drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
+    });
 
-    //0z draws to bottom 2 pixels (GREEN)
-    auto bottomHalfGreenNode = createSkiaNode(0, 0, 4, 4,
-            [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) {
-                SkPaint greenPaint;
-                greenPaint.setColor(SK_ColorGREEN);
-                greenPaint.setStyle(SkPaint::kFill_Style);
-                bottomHalfGreenCanvas.drawRect(0, 2, 4, 4, greenPaint);
-                props.setElevation(0.0f);
-            }, "bottomHalfGreenNode");
-
-    //+z draws to right 2 pixels (BLUE)
-    auto rightHalfBlueNode = createSkiaNode(0, 0, 4, 4,
-        [](RenderProperties& props, SkiaRecordingCanvas& rightHalfBlueCanvas) {
-            SkPaint bluePaint;
-            bluePaint.setColor(SK_ColorBLUE);
-            bluePaint.setStyle(SkPaint::kFill_Style);
-            rightHalfBlueCanvas.drawRect(2, 0, 4, 4, bluePaint);
-            props.setElevation(10.0f);
-        }, "rightHalfBlueNode");
-
-    auto rootNode = createSkiaNode(0, 0, 4, 4,
-            [&](RenderProperties& props, SkiaRecordingCanvas& rootRecorder) {
-                rootRecorder.insertReorderBarrier(true);
-                //draw in reverse Z order, so Z alters draw order
-                rootRecorder.drawRenderNode(rightHalfBlueNode.get());
-                rootRecorder.drawRenderNode(bottomHalfGreenNode.get());
-                rootRecorder.drawRenderNode(redNode.get());
-            }, "rootNode");
-
-    RenderNodeDrawable drawable3(rootNode.get(), &canvas, false);
-    canvas.drawDrawable(&drawable3);
-    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
-    ASSERT_EQ(TestUtils::getColor(surface, 0, 3), SK_ColorGREEN);
-    ASSERT_EQ(TestUtils::getColor(surface, 3, 3), SK_ColorBLUE);
+    //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+    ZReorderCanvas canvas(100, 100);
+    RenderNodeDrawable drawable(parent.get(), &canvas, false);
+    canvas.drawDrawable(&drawable);
+    EXPECT_EQ(10, canvas.getIndex());
 }
 
 TEST(RenderNodeDrawable, composeOnLayer)
@@ -167,7 +110,7 @@
     canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
 
-    auto rootNode = createSkiaNode(0, 0, 1, 1,
+    auto rootNode = TestUtils::createSkiaNode(0, 0, 1, 1,
         [](RenderProperties& props, SkiaRecordingCanvas& recorder) {
             recorder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
         });
@@ -176,7 +119,7 @@
     auto surfaceLayer = SkSurface::MakeRasterN32Premul(1, 1);
     auto canvas2 = surfaceLayer->getCanvas();
     canvas2->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
-    rootNode->setLayerSurface( surfaceLayer  );
+    rootNode->setLayerSurface(surfaceLayer);
 
     RenderNodeDrawable drawable1(rootNode.get(), &canvas, false);
     canvas.drawDrawable(&drawable1);
@@ -190,7 +133,7 @@
     canvas.drawDrawable(&drawable3);
     ASSERT_EQ(SK_ColorRED, TestUtils::getColor(surface, 0, 0));
 
-    rootNode->setLayerSurface( sk_sp<SkSurface>()  );
+    rootNode->setLayerSurface(sk_sp<SkSurface>());
 }
 
 //TODO: refactor to cover test cases from FrameBuilderTests_projectionReorder
@@ -203,18 +146,18 @@
     canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
 
-    auto redNode = createSkiaNode(0, 0, 1, 1,
+    auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1,
         [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
             redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
         }, "redNode");
 
-    auto greenNodeWithRedChild = createSkiaNode(0, 0, 1, 1,
+    auto greenNodeWithRedChild = TestUtils::createSkiaNode(0, 0, 1, 1,
         [&](RenderProperties& props, SkiaRecordingCanvas& greenCanvasWithRedChild) {
             greenCanvasWithRedChild.drawRenderNode(redNode.get());
             greenCanvasWithRedChild.drawColor(SK_ColorGREEN, SkBlendMode::kSrcOver);
         }, "greenNodeWithRedChild");
 
-    auto rootNode = createSkiaNode(0, 0, 1, 1,
+    auto rootNode = TestUtils::createSkiaNode(0, 0, 1, 1,
         [&](RenderProperties& props, SkiaRecordingCanvas& rootCanvas) {
             rootCanvas.drawRenderNode(greenNodeWithRedChild.get());
         }, "rootNode");
diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
index 49c4da6..f32d97a 100644
--- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
+++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
@@ -69,10 +69,10 @@
                 SkColorMatrixFilter::MakeLightingFilter(0x11223344, 0));
 
         SkColor observedColor;
-        SkXfermode::Mode observedMode;
+        SkBlendMode observedMode;
         ASSERT_TRUE(filter->asColorMode(&observedColor, &observedMode));
         EXPECT_EQ(0xFF223344, observedColor);
-        EXPECT_EQ(SkXfermode::Mode::kModulate_Mode, observedMode);
+        EXPECT_EQ(SkBlendMode::kModulate, observedMode);
     }
 
     {
@@ -93,7 +93,7 @@
 }
 
 TEST(SkiaBehavior, srgbColorSpaceIsSingleton) {
-    sk_sp<SkColorSpace> sRGB1 = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
-    sk_sp<SkColorSpace> sRGB2 = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+    sk_sp<SkColorSpace> sRGB1 = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
+    sk_sp<SkColorSpace> sRGB2 = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
     ASSERT_EQ(sRGB1.get(), sRGB2.get());
 }
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index fe6cea6..67fb78a 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -58,7 +58,7 @@
     ASSERT_TRUE(skiaDL.mIsProjectionReceiver);
 
     bounds = SkRect::MakeWH(100, 100);
-    skiaDL.reset(nullptr, bounds);
+    skiaDL.reset(bounds);
 
     ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
     ASSERT_TRUE(skiaDL.mChildNodes.empty());
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
new file mode 100644
index 0000000..7a2fa57
--- /dev/null
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <VectorDrawable.h>
+
+#include "AnimationContext.h"
+#include "DamageAccumulator.h"
+#include "IContextFactory.h"
+#include "pipeline/skia/SkiaDisplayList.h"
+#include "pipeline/skia/SkiaRecordingCanvas.h"
+#include "pipeline/skia/SkiaOpenGLPipeline.h"
+#include "renderthread/CanvasContext.h"
+#include "tests/common/TestUtils.h"
+#include "SkiaCanvas.h"
+#include <SkLiteRecorder.h>
+#include <string.h>
+
+using namespace android;
+using namespace android::uirenderer;
+using namespace android::uirenderer::renderthread;
+using namespace android::uirenderer::skiapipeline;
+
+RENDERTHREAD_TEST(SkiaPipeline, renderFrame) {
+    auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1,
+        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+        });
+    LayerUpdateQueue layerUpdateQueue;
+    SkRect dirty = SkRect::MakeLargest();
+    std::vector<sp<RenderNode>> renderNodes;
+    renderNodes.push_back(redNode);
+    bool opaque = true;
+    android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
+    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
+    surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
+}
+
+RENDERTHREAD_TEST(SkiaPipeline, renderFrameCheckBounds) {
+    auto backdropRedNode = TestUtils::createSkiaNode(1, 1, 4, 4,
+        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+        });
+    auto contentGreenNode = TestUtils::createSkiaNode(2, 2, 5, 5,
+        [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) {
+            blueCanvas.drawColor(SK_ColorGREEN, SkBlendMode::kSrcOver);
+        });
+    LayerUpdateQueue layerUpdateQueue;
+    SkRect dirty = SkRect::MakeLargest();
+    std::vector<sp<RenderNode>> renderNodes;
+    renderNodes.push_back(backdropRedNode);  //first node is backdrop
+    renderNodes.push_back(contentGreenNode); //second node is content drawn on top of the backdrop
+    android::uirenderer::Rect contentDrawBounds(1, 1, 3, 3);
+    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+    auto surface = SkSurface::MakeRasterN32Premul(5, 5);
+    surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+    //backdropBounds is (1, 1, 3, 3), content clip is (1, 1, 3, 3), content translate is (0, 0)
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+    ASSERT_EQ(TestUtils::getColor(surface, 1, 1), SK_ColorRED);
+    ASSERT_EQ(TestUtils::getColor(surface, 2, 2), SK_ColorGREEN);
+    ASSERT_EQ(TestUtils::getColor(surface, 3, 3), SK_ColorRED);
+    ASSERT_EQ(TestUtils::getColor(surface, 4, 4), SK_ColorBLUE);
+
+    surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+    contentDrawBounds.set(0, 0, 5, 5);
+    //backdropBounds is (1, 1, 4, 4), content clip is (0, 0, 3, 3), content translate is (1, 1)
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+    ASSERT_EQ(TestUtils::getColor(surface, 1, 1), SK_ColorRED);
+    ASSERT_EQ(TestUtils::getColor(surface, 2, 2), SK_ColorRED);
+    ASSERT_EQ(TestUtils::getColor(surface, 3, 3), SK_ColorGREEN);
+    ASSERT_EQ(TestUtils::getColor(surface, 4, 4), SK_ColorBLUE);
+}
+
+RENDERTHREAD_TEST(SkiaPipeline, renderFrameCheckOpaque) {
+    auto halfGreenNode = TestUtils::createSkiaNode(0, 0, 2, 2,
+        [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) {
+            SkPaint greenPaint;
+            greenPaint.setColor(SK_ColorGREEN);
+            greenPaint.setStyle(SkPaint::kFill_Style);
+            bottomHalfGreenCanvas.drawRect(0, 1, 2, 2, greenPaint);
+        });
+    LayerUpdateQueue layerUpdateQueue;
+    SkRect dirty = SkRect::MakeLargest();
+    std::vector<sp<RenderNode>> renderNodes;
+    renderNodes.push_back(halfGreenNode);
+    android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
+    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+    auto surface = SkSurface::MakeRasterN32Premul(2, 2);
+    surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, contentDrawBounds, surface);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned int)SK_ColorTRANSPARENT);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
+}
+
+RENDERTHREAD_TEST(SkiaPipeline, renderFrameCheckDirtyRect) {
+    auto redNode = TestUtils::createSkiaNode(0, 0, 2, 2,
+        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+        });
+    LayerUpdateQueue layerUpdateQueue;
+    SkRect dirty = SkRect::MakeXYWH(0, 1, 2, 1);
+    std::vector<sp<RenderNode>> renderNodes;
+    renderNodes.push_back(redNode);
+    android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
+    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+    auto surface = SkSurface::MakeRasterN32Premul(2, 2);
+    surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+    ASSERT_EQ(TestUtils::getColor(surface, 1, 0), SK_ColorBLUE);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorRED);
+    ASSERT_EQ(TestUtils::getColor(surface, 1, 1), SK_ColorRED);
+}
+
+RENDERTHREAD_TEST(SkiaPipeline, renderLayer) {
+    auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1,
+        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+        });
+    auto surfaceLayer1 = SkSurface::MakeRasterN32Premul(1, 1);
+    surfaceLayer1->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+    ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorWHITE);
+    redNode->setLayerSurface(surfaceLayer1);
+
+    //create a 2nd 2x2 layer and add it to the queue as well.
+    //make the layer's dirty area one half of the layer and verify only the dirty half is updated.
+    auto blueNode = TestUtils::createSkiaNode(0, 0, 2, 2,
+        [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) {
+            blueCanvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+        });
+    auto surfaceLayer2 = SkSurface::MakeRasterN32Premul(2, 2);
+    surfaceLayer2->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+    ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorWHITE);
+    blueNode->setLayerSurface(surfaceLayer2);
+
+    //attach both layers to the update queue
+    LayerUpdateQueue layerUpdateQueue;
+    SkRect dirty = SkRect::MakeLargest();
+    layerUpdateQueue.enqueueLayerWithDamage(redNode.get(), dirty);
+    layerUpdateQueue.enqueueLayerWithDamage(blueNode.get(), SkRect::MakeWH(2, 1));
+    ASSERT_EQ(layerUpdateQueue.entries().size(), 2UL);
+
+    bool opaque = true;
+    FrameBuilder::LightGeometry lightGeometry;
+    lightGeometry.radius = 1.0f;
+    lightGeometry.center = { 0.0f, 0.0f, 0.0f };
+    BakedOpRenderer::LightInfo lightInfo;
+    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+    pipeline->renderLayers(lightGeometry, &layerUpdateQueue, opaque, lightInfo);
+    ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorRED);
+    ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorBLUE);
+    ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 1), SK_ColorWHITE);
+    ASSERT_TRUE(layerUpdateQueue.entries().empty());
+    redNode->setLayerSurface(sk_sp<SkSurface>());
+    blueNode->setLayerSurface(sk_sp<SkSurface>());
+}
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index 710e063..845a3ea 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -21,7 +21,6 @@
 #include <SkColorFilter.h>
 #include <SkDrawLooper.h>
 #include <SkShader.h>
-#include <SkXfermode.h>
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/utils/TestWindowContext.cpp b/libs/hwui/utils/TestWindowContext.cpp
index 624d207..fa3e13d 100644
--- a/libs/hwui/utils/TestWindowContext.cpp
+++ b/libs/hwui/utils/TestWindowContext.cpp
@@ -110,7 +110,7 @@
     }
 
     bool capturePixels(SkBitmap* bmp) {
-        sk_sp<SkColorSpace> colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+        sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
         SkImageInfo destinationConfig =
             SkImageInfo::Make(mSize.width(), mSize.height(),
                               kRGBA_8888_SkColorType, kPremul_SkAlphaType, colorSpace);
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 89b4fb2..0b22ad5 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -31,7 +31,7 @@
 #include <SkCanvas.h>
 #include <SkColor.h>
 #include <SkPaint.h>
-#include <SkXfermode.h>
+#include <SkBlendMode.h>
 #pragma GCC diagnostic pop
 
 namespace android {
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 6941dba..18ebd47 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -30,7 +30,6 @@
 #include <SkCanvas.h>
 #include <SkColor.h>
 #include <SkPaint.h>
-#include <SkXfermode.h>
 #pragma GCC diagnostic pop
 
 #include <android/native_window.h>
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index 74638e7..fe1ee02 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -553,7 +553,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(MountService, "IMountService")
+IMPLEMENT_META_INTERFACE(MountService, "android.os.storage.IMountService")
 
 // ----------------------------------------------------------------------
 
diff --git a/libs/storage/IMountServiceListener.cpp b/libs/storage/IMountServiceListener.cpp
index 11b53fd..6a093fd 100644
--- a/libs/storage/IMountServiceListener.cpp
+++ b/libs/storage/IMountServiceListener.cpp
@@ -24,6 +24,20 @@
     TRANSACTION_onStorageStateChanged,
 };
 
+class BpMountServiceListener: public BpInterface<IMountServiceListener> {
+public:
+    explicit BpMountServiceListener(const sp<IBinder>& impl)
+            : BpInterface<IMountServiceListener>(impl) { }
+
+    virtual void onUsbMassStorageConnectionChanged(const bool /* connected */) { }
+    virtual void onStorageStateChanged(const String16& /* path */,
+            const String16& /* oldState */, const String16& /* newState */) { }
+};
+
+IMPLEMENT_META_INTERFACE(MountServiceListener, "android.os.storage.IMountServiceListener")
+
+// ----------------------------------------------------------------------
+
 status_t BnMountServiceListener::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
diff --git a/libs/storage/IMountShutdownObserver.cpp b/libs/storage/IMountShutdownObserver.cpp
index a74a768..6114d4a 100644
--- a/libs/storage/IMountShutdownObserver.cpp
+++ b/libs/storage/IMountShutdownObserver.cpp
@@ -23,6 +23,16 @@
     TRANSACTION_onShutDownComplete = IBinder::FIRST_CALL_TRANSACTION,
 };
 
+class BpMountShutdownObserver: public BpInterface<IMountShutdownObserver> {
+public:
+    explicit BpMountShutdownObserver(const sp<IBinder>& impl)
+            : BpInterface<IMountShutdownObserver>(impl) { }
+
+    virtual void onShutDownComplete(const int32_t /* statusCode */) {}
+};
+
+IMPLEMENT_META_INTERFACE(MountShutdownObserver, "android.os.storage.IMountShutdownObserver")
+
 status_t BnMountShutdownObserver::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
diff --git a/libs/storage/IObbActionListener.cpp b/libs/storage/IObbActionListener.cpp
index a71341b..797393ac 100644
--- a/libs/storage/IObbActionListener.cpp
+++ b/libs/storage/IObbActionListener.cpp
@@ -34,7 +34,7 @@
                              const int32_t /* state */) { }
 };
 
-IMPLEMENT_META_INTERFACE(ObbActionListener, "IObbActionListener")
+IMPLEMENT_META_INTERFACE(ObbActionListener, "android.os.storage.IObbActionListener")
 
 // ----------------------------------------------------------------------
 
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index bd68fec..64576ec 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -236,18 +236,16 @@
          */
         public static final int VOICE_CALL = 4;
 
-        /** Microphone audio source with same orientation as camera if available, the main
-         *  device microphone otherwise */
+        /** Microphone audio source tuned for video recording, with the same orientation
+         *  as the camera if available. */
         public static final int CAMCORDER = 5;
 
-        /** Microphone audio source tuned for voice recognition if available, behaves like
-         *  {@link #DEFAULT} otherwise. */
+        /** Microphone audio source tuned for voice recognition. */
         public static final int VOICE_RECOGNITION = 6;
 
         /** Microphone audio source tuned for voice communications such as VoIP. It
          *  will for instance take advantage of echo cancellation or automatic gain control
-         *  if available. It otherwise behaves like {@link #DEFAULT} if no voice processing
-         *  is applied.
+         *  if available.
          */
         public static final int VOICE_COMMUNICATION = 7;
 
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index faefc9f..8d4271f 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -31,6 +31,7 @@
     libutils \
     libbinder \
     libmedia \
+    libmediadrm \
     libskia \
     libui \
     liblog \
@@ -41,7 +42,8 @@
     libcamera_client \
     libmtp \
     libexif \
-    libpiex
+    libpiex \
+    libandroidfw
 
 LOCAL_STATIC_LIBRARIES := \
 
diff --git a/media/jni/audioeffect/Android.mk b/media/jni/audioeffect/Android.mk
index 91dd8a5..777636b 100644
--- a/media/jni/audioeffect/Android.mk
+++ b/media/jni/audioeffect/Android.mk
@@ -11,7 +11,8 @@
     libutils \
     libandroid_runtime \
     libnativehelper \
-    libmedia
+    libmedia \
+    libaudioclient \
 
 LOCAL_MODULE:= libaudioeffect_jni
 
diff --git a/media/jni/soundpool/Android.mk b/media/jni/soundpool/Android.mk
index 2bc41b5..509a59b 100644
--- a/media/jni/soundpool/Android.mk
+++ b/media/jni/soundpool/Android.mk
@@ -12,7 +12,7 @@
     libutils \
     libandroid_runtime \
     libnativehelper \
-    libmedia \
+    libaudioclient \
     libmediandk \
     libbinder
 
diff --git a/media/tests/audiotests/Android.mk b/media/tests/audiotests/Android.mk
index 57be372..01e42bd 100644
--- a/media/tests/audiotests/Android.mk
+++ b/media/tests/audiotests/Android.mk
@@ -15,7 +15,8 @@
     libutils \
     libbinder \
     libhardware_legacy \
-    libmedia
+    libmedia \
+    libaudioclient \
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp
index 0d0c7ad..aa756ed 100644
--- a/media/tests/players/invoke_mock_media_player.cpp
+++ b/media/tests/players/invoke_mock_media_player.cpp
@@ -82,7 +82,7 @@
     virtual status_t    stop() { return OK; }
     virtual status_t    pause() { return OK; }
     virtual bool        isPlaying() { return true; }
-    virtual status_t    seekTo(int /* msec */) { return OK; }
+    virtual status_t    seekTo(int /* msec */, bool /* precise */) { return OK; }
     virtual status_t    getCurrentPosition(int* /* msec */) { return OK; }
     virtual status_t    getDuration(int* /* msec */) { return OK; }
     virtual status_t    reset() {return OK;}
diff --git a/native/graphics/jni/Android.mk b/native/graphics/jni/Android.mk
index 175f730..4c8a9db 100644
--- a/native/graphics/jni/Android.mk
+++ b/native/graphics/jni/Android.mk
@@ -20,7 +20,8 @@
 
 LOCAL_SHARED_LIBRARIES := \
     libandroid_runtime \
-    libskia
+    libskia \
+    libandroidfw
 
 LOCAL_C_INCLUDES += \
     frameworks/base/native/include \
diff --git a/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml b/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml
index 440cb64..2b69d5b 100644
--- a/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml
@@ -24,13 +24,13 @@
     <string name="restore_confirm_text" msgid="7499866728030461776">"একটি সংযুক্ত ডেস্কটপ কম্পিউটার থেকে সমস্ত ডেটার সম্পূর্ণ ব্যাকআপ নেওয়ার অনুরোধ করা হয়েছে৷ আপনি কি এটি করার অনুমতি দিতে চান?\n\nযদি আপনি নিজের থেকে এই ব্যাকআপ নেওয়ার অনুরোধ না করে থাকেন, তবে এই প্রক্রিয়াটিতে অনুমতি প্রদান করবেন না৷ এটি বর্তমানে ডিভাইসটিতে থাকা সমস্ত ডেটাকে প্রতিস্থাপন করবে!"</string>
     <string name="allow_restore_button_label" msgid="3081286752277127827">"আমার ডেটা পুনরুদ্ধার করুন"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"পুনরুদ্ধার করবেন না"</string>
-    <string name="current_password_text" msgid="8268189555578298067">"দয়া করে নীচে আপনার বর্তমান ব্যাকআপের পাসওয়ার্ড দিন:"</string>
-    <string name="device_encryption_restore_text" msgid="1570864916855208992">"দয়া করে নীচে আপনার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷"</string>
-    <string name="device_encryption_backup_text" msgid="5866590762672844664">"দয়া করে নীচে আপানার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷ এছাড়াও ব্যাকআপ সংরক্ষণাগার এনক্রিপ্ট করতে এটি ব্যবহার করা হবে৷"</string>
+    <string name="current_password_text" msgid="8268189555578298067">"দয়া করে নিচে আপনার বর্তমান ব্যাকআপের পাসওয়ার্ড দিন:"</string>
+    <string name="device_encryption_restore_text" msgid="1570864916855208992">"দয়া করে নিচে আপনার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷"</string>
+    <string name="device_encryption_backup_text" msgid="5866590762672844664">"দয়া করে নিচে আপানার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷ এছাড়াও ব্যাকআপ সংরক্ষণাগার এনক্রিপ্ট করতে এটি ব্যবহার করা হবে৷"</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে দয়া করে একটি পাসওয়ার্ড লিখুন৷ যদি এটি খালি রেখে দেওয়া হয় তবে আপনার বর্তমান ব্যাকআপ পাসওয়ার্ডটি ব্যবহার করা হবে:"</string>
-    <string name="backup_enc_password_optional" msgid="1350137345907579306">"আপনি যদি সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে চান তাহলে নীচে একটি পাসওয়ার্ড লিখুন:"</string>
-    <string name="backup_enc_password_required" msgid="7889652203371654149">"আপনার ডিভাইস এনক্রিপ্ট হয়ে থাকার কারণে আপনার ব্যাকআপকে এনক্রিপ্ট করতে হবে। দয়া করে নীচে একটি পাসওয়ার্ড দিন:"</string>
-    <string name="restore_enc_password_text" msgid="6140898525580710823">"যদি পুনরুদ্ধার করা ডেটা এনক্রিপ্ট করা থাকে, তবে দয়া করে নীচে পাসওয়ার্ডটি লিখুন:"</string>
+    <string name="backup_enc_password_optional" msgid="1350137345907579306">"আপনি যদি সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে চান তাহলে নিচে একটি পাসওয়ার্ড লিখুন:"</string>
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"আপনার ডিভাইস এনক্রিপ্ট হয়ে থাকার কারণে আপনার ব্যাকআপকে এনক্রিপ্ট করতে হবে। দয়া করে নিচে একটি পাসওয়ার্ড দিন:"</string>
+    <string name="restore_enc_password_text" msgid="6140898525580710823">"যদি পুনরুদ্ধার করা ডেটা এনক্রিপ্ট করা থাকে, তবে দয়া করে নিচে পাসওয়ার্ডটি লিখুন:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"ব্যাকআপ নেওয়া শুরু হয়েছে..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"ব্যাকআপ নেওয়া সম্পূর্ণ হয়েছে"</string>
     <string name="toast_restore_started" msgid="7881679218971277385">"পুনরুদ্ধার করা শুরু হচ্ছে..."</string>
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 4e6f3d0..9af20d0 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -445,7 +445,7 @@
     }
 
     @Override
-    public Path findPath(String childDocId, @Nullable String parentDocId)
+    public Path findDocumentPath(String childDocId, @Nullable String parentDocId)
             throws FileNotFoundException {
         LinkedList<String> path = new LinkedList<>();
 
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 96f91d9..6b2c1ee 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -347,6 +347,34 @@
                 throw new UnsupportedOperationException(
                         "Writing operation is not supported by the device.");
             }
+
+            final int parentObjectHandle;
+            final int storageId;
+            switch (parentId.mDocumentType) {
+                case MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE:
+                    final String[] storageDocumentIds =
+                            mDatabase.getStorageDocumentIds(parentId.mDocumentId);
+                    if (storageDocumentIds.length == 1) {
+                        final String newDocumentId =
+                                createDocument(storageDocumentIds[0], mimeType, displayName);
+                        notifyChildDocumentsChange(parentDocumentId);
+                        return newDocumentId;
+                    } else {
+                        throw new UnsupportedOperationException(
+                                "Cannot create a file under the device.");
+                    }
+                case MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE:
+                    storageId = parentId.mStorageId;
+                    parentObjectHandle = -1;
+                    break;
+                case MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT:
+                    storageId = parentId.mStorageId;
+                    parentObjectHandle = parentId.mObjectHandle;
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unexpected document type.");
+            }
+
             pipe = ParcelFileDescriptor.createReliablePipe();
             int objectHandle = -1;
             MtpObjectInfo info = null;
@@ -357,8 +385,8 @@
                         MtpConstants.FORMAT_ASSOCIATION :
                         MediaFile.getFormatCode(displayName, mimeType);
                 info = new MtpObjectInfo.Builder()
-                        .setStorageId(parentId.mStorageId)
-                        .setParent(parentId.mObjectHandle)
+                        .setStorageId(storageId)
+                        .setParent(parentObjectHandle)
                         .setFormat(formatCode)
                         .setName(displayName)
                         .build();
@@ -413,7 +441,7 @@
     }
 
     @Override
-    public Path findPath(String childDocumentId, String parentDocumentId)
+    public Path findDocumentPath(String childDocumentId, String parentDocumentId)
             throws FileNotFoundException {
         final LinkedList<String> ids = new LinkedList<>();
         final Identifier childIdentifier = mDatabase.createIdentifier(childDocumentId);
@@ -457,6 +485,24 @@
         }
     }
 
+    @Override
+    public boolean isChildDocument(String parentDocumentId, String documentId) {
+        try {
+            Identifier identifier = mDatabase.createIdentifier(documentId);
+            while (true) {
+                if (parentDocumentId.equals(identifier.mDocumentId)) {
+                    return true;
+                }
+                if (identifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE) {
+                    return false;
+                }
+                identifier = mDatabase.getParentIdentifier(identifier.mDocumentId);
+            }
+        } catch (FileNotFoundException error) {
+            return false;
+        }
+    }
+
     void openDevice(int deviceId) throws IOException {
         synchronized (mDeviceListLock) {
             if (mDeviceToolkits.containsKey(deviceId)) {
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index a29e27d..ef2e0a5 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -549,7 +549,7 @@
     public void testOpenDocument_writing() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         setupRoots(0, new MtpRoot[] {
-                new MtpRoot(0, 0, "Storage", 0, 0, "")
+                new MtpRoot(0, 100, "Storage", 0, 0, "")
         });
         final String documentId = mProvider.createDocument("2", "text/plain", "test.txt");
         {
@@ -692,6 +692,29 @@
         }
     }
 
+    public void testCreateDocument() throws Exception {
+        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
+        setupRoots(0, new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage A", 100, 100, null)
+        });
+        final String documentId = mProvider.createDocument("1", "text/plain", "note.txt");
+        final Uri deviceUri = DocumentsContract.buildChildDocumentsUri(
+                MtpDocumentsProvider.AUTHORITY, "1");
+        final Uri storageUri = DocumentsContract.buildChildDocumentsUri(
+                MtpDocumentsProvider.AUTHORITY, "2");
+        mResolver.waitForNotification(storageUri, 1);
+        mResolver.waitForNotification(deviceUri, 1);
+        try (final Cursor cursor = mProvider.queryDocument(documentId, null)) {
+            assertTrue(cursor.moveToNext());
+            assertEquals(
+                    "note.txt",
+                    cursor.getString(cursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME)));
+            assertEquals(
+                    "text/plain",
+                    cursor.getString(cursor.getColumnIndex(Document.COLUMN_MIME_TYPE)));
+        }
+    }
+
     public void testCreateDocument_noWritingSupport() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         mMtpManager.addValidDevice(new MtpDeviceRecord(
@@ -773,12 +796,12 @@
         assertEquals(0x400000000L, cursor.getLong(0));
     }
 
-    public void testFindPath_singleStorage_toRoot() throws Exception {
+    public void testFindDocumentPath_singleStorage_toRoot() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
         setupHierarchyDocuments("1");
 
-        final Path path = mProvider.findPath("15", null);
+        final Path path = mProvider.findDocumentPath("15", null);
         assertEquals("1", path.getRootId());
         assertEquals(4, path.getPath().size());
         assertEquals("1", path.getPath().get(0));
@@ -787,12 +810,12 @@
         assertEquals("15", path.getPath().get(3));
     }
 
-    public void testFindPath_singleStorage_toDoc() throws Exception {
+    public void testFindDocumentPath_singleStorage_toDoc() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
         setupHierarchyDocuments("1");
 
-        final Path path = mProvider.findPath("18", "3");
+        final Path path = mProvider.findDocumentPath("18", "3");
         assertNull(path.getRootId());
         assertEquals(3, path.getPath().size());
         assertEquals("3", path.getPath().get(0));
@@ -800,14 +823,14 @@
         assertEquals("18", path.getPath().get(2));
     }
 
-    public void testFindPath_multiStorage_toRoot() throws Exception {
+    public void testFindDocumentPath_multiStorage_toRoot() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         setupRoots(0, new MtpRoot[] {
                 new MtpRoot(0, 0, "Storage A", 1000, 1000, ""),
                 new MtpRoot(0, 1, "Storage B", 1000, 1000, "") });
         setupHierarchyDocuments("2");
 
-        final Path path = mProvider.findPath("16", null);
+        final Path path = mProvider.findDocumentPath("16", null);
         assertEquals("2", path.getRootId());
         assertEquals(4, path.getPath().size());
         assertEquals("2", path.getPath().get(0));
@@ -816,14 +839,14 @@
         assertEquals("16", path.getPath().get(3));
     }
 
-    public void testFindPath_multiStorage_toDoc() throws Exception {
+    public void testFindDocumentPath_multiStorage_toDoc() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         setupRoots(0, new MtpRoot[] {
                 new MtpRoot(0, 0, "Storage A", 1000, 1000, ""),
                 new MtpRoot(0, 1, "Storage B", 1000, 1000, "") });
         setupHierarchyDocuments("2");
 
-        final Path path = mProvider.findPath("19", "4");
+        final Path path = mProvider.findDocumentPath("19", "4");
         assertNull(path.getRootId());
         assertEquals(3, path.getPath().size());
         assertEquals("4", path.getPath().get(0));
@@ -831,6 +854,18 @@
         assertEquals("19", path.getPath().get(2));
     }
 
+    public void testIsChildDocument() throws Exception {
+        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
+        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
+        setupHierarchyDocuments("1");
+        assertTrue(mProvider.isChildDocument("1", "1"));
+        assertTrue(mProvider.isChildDocument("1", "14"));
+        assertTrue(mProvider.isChildDocument("2", "14"));
+        assertTrue(mProvider.isChildDocument("5", "14"));
+        assertFalse(mProvider.isChildDocument("3", "14"));
+        assertFalse(mProvider.isChildDocument("6", "14"));
+    }
+
     private void setupProvider(int flag) {
         mDatabase = new MtpDatabase(getContext(), flag);
         mProvider = new MtpDocumentsProvider();
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 30d529a..f20bbec 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -26,6 +26,7 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
+import junit.framework.Assert;
 
 public class TestMtpManager extends MtpManager {
     public static final int CREATED_DOCUMENT_HANDLE = 1000;
@@ -151,6 +152,9 @@
     @Override
     int createDocument(int deviceId, MtpObjectInfo objectInfo, ParcelFileDescriptor source)
             throws IOException {
+        Assert.assertNotSame(0, objectInfo.getStorageId());
+        Assert.assertNotSame(-1, objectInfo.getStorageId());
+        Assert.assertNotSame(0, objectInfo.getParent());
         final String key = pack(deviceId, CREATED_DOCUMENT_HANDLE);
         if (mObjectInfos.containsKey(key)) {
             throw new IOException();
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
index c1f5660..e07856e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
@@ -15,6 +15,9 @@
  */
 package com.android.settingslib.drawer;
 
+import java.util.HashMap;
+import java.util.Map;
+
 public final class CategoryKey {
 
     // Activities in this category shows up in Settings homepage.
@@ -33,4 +36,17 @@
     public static final String CATEGORY_SECURITY = "com.android.settings.category.ia.security";
     public static final String CATEGORY_ACCOUNT = "com.android.settings.category.ia.accounts";
     public static final String CATEGORY_SYSTEM = "com.android.settings.category.ia.system";
+    public static final String CATEGORY_SYSTEM_INPUT = "com.android.settings.category.ia.input";
+    public static final String CATEGORY_SYSTEM_LANGUAGE =
+            "com.android.settings.category.ia.language";
+
+    public static final Map<String, String> KEY_COMPAT_MAP;
+
+    static {
+        KEY_COMPAT_MAP = new HashMap<>();
+        KEY_COMPAT_MAP.put("com.android.settings.category.wireless", CATEGORY_NETWORK);
+        KEY_COMPAT_MAP.put("com.android.settings.category.device", CATEGORY_SYSTEM);
+        KEY_COMPAT_MAP.put("com.android.settings.category.personal", CATEGORY_SYSTEM);
+        KEY_COMPAT_MAP.put("com.android.settings.category.system", CATEGORY_SYSTEM);
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
index a51ad76..ed411be 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
@@ -17,14 +17,18 @@
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.support.annotation.VisibleForTesting;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Pair;
 
 import com.android.settingslib.applications.InterestingConfigChanges;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 public class CategoryManager {
@@ -106,7 +110,57 @@
             for (DashboardCategory category : mCategories) {
                 mCategoryByKeyMap.put(category.key, category);
             }
+            backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap);
         }
     }
 
+    @VisibleForTesting
+    synchronized void backwardCompatCleanupForCategory(
+            Map<Pair<String, String>, Tile> tileByComponentCache,
+            Map<String, DashboardCategory> categoryByKeyMap) {
+        // A package can use a) CategoryKey, b) old category keys, c) both.
+        // Check if a package uses old category key only.
+        // If yes, map them to new category key.
+
+        // Build a package name -> tile map first.
+        final Map<String, List<Tile>> packageToTileMap = new HashMap<>();
+        for (Entry<Pair<String, String>, Tile> tileEntry : tileByComponentCache.entrySet()) {
+            final String packageName = tileEntry.getKey().first;
+            List<Tile> tiles = packageToTileMap.get(packageName);
+            if (tiles == null) {
+                tiles = new ArrayList<>();
+                packageToTileMap.put(packageName, tiles);
+            }
+            tiles.add(tileEntry.getValue());
+        }
+
+        for (Entry<String, List<Tile>> entry : packageToTileMap.entrySet()) {
+            final List<Tile> tiles = entry.getValue();
+            // Loop map, find if all tiles from same package uses old key only.
+            boolean useNewKey = false;
+            boolean useOldKey = false;
+            for (Tile tile : tiles) {
+                if (CategoryKey.KEY_COMPAT_MAP.containsKey(tile.category)) {
+                    useOldKey = true;
+                } else {
+                    useNewKey = true;
+                    break;
+                }
+            }
+            // Uses only old key, map them to new keys one by one.
+            if (useOldKey && !useNewKey) {
+                for (Tile tile : tiles) {
+                    final String newCategoryKey = CategoryKey.KEY_COMPAT_MAP.get(tile.category);
+                    tile.category = newCategoryKey;
+                    // move tile to new category.
+                    DashboardCategory newCategory = categoryByKeyMap.get(newCategoryKey);
+                    if (newCategory == null) {
+                        newCategory = new DashboardCategory();
+                        categoryByKeyMap.put(newCategoryKey, newCategory);
+                    }
+                    newCategory.tiles.add(tile);
+                }
+            }
+        }
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index ac10ca8..9442458 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -65,6 +65,13 @@
             "com.android.settings.action.EXTRA_SETTINGS";
 
     /**
+     * @See {@link #EXTRA_SETTINGS_ACTION}.
+     */
+    private static final String IA_SETTINGS_ACTION =
+            "com.android.settings.action.IA_SETTINGS";
+
+
+    /**
      * Same as #EXTRA_SETTINGS_ACTION but used for the platform Settings activities.
      */
     private static final String SETTINGS_ACTION =
@@ -148,6 +155,7 @@
             }
             if (setup) {
                 getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false);
+                getTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false);
             }
         }
 
diff --git a/packages/SettingsLib/tests/Android.mk b/packages/SettingsLib/tests/Android.mk
index 4208522..333c41d 100644
--- a/packages/SettingsLib/tests/Android.mk
+++ b/packages/SettingsLib/tests/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2015 The Android Open Source Project
+# 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.
@@ -15,20 +15,5 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
-
-LOCAL_PACKAGE_NAME := SettingsLibTests
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
-    espresso-core \
-    mockito-target-minus-junit4
-
-include frameworks/base/packages/SettingsLib/common.mk
-
-include $(BUILD_PACKAGE)
+# Include all makefiles in subdirectories
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
new file mode 100644
index 0000000..4208522
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2015 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
+
+LOCAL_PACKAGE_NAME := SettingsLibTests
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    espresso-core \
+    mockito-target-minus-junit4
+
+include frameworks/base/packages/SettingsLib/common.mk
+
+include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/tests/AndroidManifest.xml b/packages/SettingsLib/tests/integ/AndroidManifest.xml
similarity index 100%
rename from packages/SettingsLib/tests/AndroidManifest.xml
rename to packages/SettingsLib/tests/integ/AndroidManifest.xml
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/BaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/BaseTest.java
similarity index 100%
rename from packages/SettingsLib/tests/src/com/android/settingslib/BaseTest.java
rename to packages/SettingsLib/tests/integ/src/com/android/settingslib/BaseTest.java
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java
similarity index 100%
rename from packages/SettingsLib/tests/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java
rename to packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
similarity index 100%
rename from packages/SettingsLib/tests/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
rename to packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/users/AppRestrictionsHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
similarity index 100%
rename from packages/SettingsLib/tests/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
rename to packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
similarity index 100%
rename from packages/SettingsLib/tests/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
rename to packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/utils/ZoneGetterTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java
similarity index 100%
rename from packages/SettingsLib/tests/src/com/android/settingslib/utils/ZoneGetterTest.java
rename to packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
similarity index 100%
rename from packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java
rename to packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
similarity index 100%
rename from packages/SettingsLib/tests/src/com/android/settingslib/wifi/WifiTrackerTest.java
rename to packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
new file mode 100644
index 0000000..c1108f6
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -0,0 +1,82 @@
+# 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.
+
+
+############################################################
+# SettingsLib Shell app just for Robolectric test target.  #
+############################################################
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := SettingsLibShell
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_JAVA_LIBRARIES := \
+    junit4-target \
+    platform-robolectric-prebuilt
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    platform-system-robolectric \
+    truth-prebuilt
+
+LOCAL_AAPT_FLAGS := --auto-add-overlay \
+
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src)
+
+include frameworks/base/packages/SettingsLib/common.mk
+
+include $(BUILD_PACKAGE)
+
+#############################################
+# SettingsLib Robolectric test target. #
+#############################################
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Include the testing libraries (JUnit4 + Robolectric libs).
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    platform-system-robolectric \
+    truth-prebuilt
+
+LOCAL_JAVA_LIBRARIES := \
+    junit4-target \
+    platform-robolectric-prebuilt
+
+LOCAL_INSTRUMENTATION_FOR := SettingsLibShell
+LOCAL_MODULE := SettingsLibRoboTests
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+#############################################################
+# SettingsLib runner target to run the previous target. #
+#############################################################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := RunSettingsLibRoboTests
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    SettingsLibRoboTests
+
+LOCAL_TEST_PACKAGE := SettingsLibShell
+
+include prebuilts/misc/common/robolectric/run_robotests.mk
diff --git a/packages/SettingsLib/tests/robotests/AndroidManifest.xml b/packages/SettingsLib/tests/robotests/AndroidManifest.xml
new file mode 100644
index 0000000..9e92fa9
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          coreApp="true"
+          package="com.android.settingslib.robotests">
+
+    <application/>
+
+</manifest>
diff --git a/packages/SettingsLib/tests/robotests/readme.md b/packages/SettingsLib/tests/robotests/readme.md
new file mode 100644
index 0000000..fefe3bf
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/readme.md
@@ -0,0 +1,6 @@
+Unit test suite for SettingsLib using Robolectric.
+
+```
+$ croot
+$ make RunSettingsLibRoboTests -j40
+```
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
similarity index 71%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
index 5f66d16..22fd83c 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package com.android.settingslib;
 
-parcelable PublishConfig;
+public class TestConfig {
+    public static final int SDK_VERSION = 23;
+    public static final String MANIFEST_PATH =
+            "frameworks/base/packages/SettingsLib/robotests/AndroidManifest.xml";
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
new file mode 100644
index 0000000..a0254cd
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.settingslib.drawer;
+
+import android.util.ArraySet;
+
+import com.android.settingslib.TestConfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import java.util.Set;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class CategoryKeyTest {
+
+    @Test
+    public void testKeyCompatMap_allOldCategoryKeyAreMapped() {
+        assertThat(CategoryKey.KEY_COMPAT_MAP.size()).isEqualTo(4);
+    }
+
+    @Test
+    public void removingAnyKeyBreaksCompiler() {
+        // The keys in this test can be added but cannot be removed. Removing any key will remove
+        // categories from Settings app. Bad things will happen.
+        final Set<String> allKeys = new ArraySet<>();
+
+        // DO NOT REMOVE ANYTHING BELOW
+        allKeys.add(CategoryKey.CATEGORY_HOMEPAGE);
+        allKeys.add(CategoryKey.CATEGORY_DEVICE);
+        allKeys.add(CategoryKey.CATEGORY_APPS);
+        allKeys.add(CategoryKey.CATEGORY_APPS_DEFAULT);
+        allKeys.add(CategoryKey.CATEGORY_BATTERY);
+        allKeys.add(CategoryKey.CATEGORY_DISPLAY);
+        allKeys.add(CategoryKey.CATEGORY_SOUND);
+        allKeys.add(CategoryKey.CATEGORY_STORAGE);
+        allKeys.add(CategoryKey.CATEGORY_SECURITY);
+        allKeys.add(CategoryKey.CATEGORY_ACCOUNT);
+        allKeys.add(CategoryKey.CATEGORY_SYSTEM);
+        allKeys.add(CategoryKey.CATEGORY_SYSTEM_INPUT);
+        allKeys.add(CategoryKey.CATEGORY_SYSTEM_LANGUAGE);
+        // DO NOT REMOVE ANYTHING ABOVE
+
+        assertThat(allKeys.size()).isEqualTo(13);
+    }
+
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java
new file mode 100644
index 0000000..380f622
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.settingslib.drawer;
+
+import android.content.Context;
+import android.util.Pair;
+
+import com.android.settingslib.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class CategoryManagerTest {
+
+    private Context mContext;
+    private CategoryManager mCategoryManager;
+    private Map<Pair<String, String>, Tile> mTileByComponentCache;
+    private Map<String, DashboardCategory> mCategoryByKeyMap;
+
+    @Before
+    public void setUp() {
+        mContext = ShadowApplication.getInstance().getApplicationContext();
+        mTileByComponentCache = new HashMap<>();
+        mCategoryByKeyMap = new HashMap<>();
+        mCategoryManager = CategoryManager.get(mContext);
+    }
+
+    @Test
+    public void getInstance_shouldBeSingleton() {
+        assertThat(mCategoryManager).isSameAs(CategoryManager.get(mContext));
+    }
+
+    @Test
+    public void backwardCompatCleanupForCategory_shouldNotChangeCategoryForNewKeys() {
+        final Tile tile1 = new Tile();
+        final Tile tile2 = new Tile();
+        tile1.category = CategoryKey.CATEGORY_ACCOUNT;
+        tile2.category = CategoryKey.CATEGORY_ACCOUNT;
+        final DashboardCategory category = new DashboardCategory();
+        category.addTile(tile1);
+        category.addTile(tile2);
+        mCategoryByKeyMap.put(CategoryKey.CATEGORY_ACCOUNT, category);
+        mTileByComponentCache.put(new Pair<>("PACKAGE", "1"), tile1);
+        mTileByComponentCache.put(new Pair<>("PACKAGE", "2"), tile2);
+
+        mCategoryManager.backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap);
+
+        assertThat(mCategoryByKeyMap.size()).isEqualTo(1);
+        assertThat(mCategoryByKeyMap.get(CategoryKey.CATEGORY_ACCOUNT)).isNotNull();
+    }
+
+    @Test
+    public void backwardCompatCleanupForCategory_shouldNotChangeCategoryForMixedKeys() {
+        final Tile tile1 = new Tile();
+        final Tile tile2 = new Tile();
+        final String oldCategory = "com.android.settings.category.wireless";
+        tile1.category = CategoryKey.CATEGORY_ACCOUNT;
+        tile2.category = oldCategory;
+        final DashboardCategory category1 = new DashboardCategory();
+        category1.addTile(tile1);
+        final DashboardCategory category2 = new DashboardCategory();
+        category2.addTile(tile2);
+        mCategoryByKeyMap.put(CategoryKey.CATEGORY_ACCOUNT, category1);
+        mCategoryByKeyMap.put(oldCategory, category2);
+        mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS1"), tile1);
+        mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS2"), tile2);
+
+        mCategoryManager.backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap);
+
+        assertThat(mCategoryByKeyMap.size()).isEqualTo(2);
+        assertThat(mCategoryByKeyMap.get(CategoryKey.CATEGORY_ACCOUNT).tiles.size()).isEqualTo(1);
+        assertThat(mCategoryByKeyMap.get(oldCategory).tiles.size()).isEqualTo(1);
+    }
+
+    @Test
+    public void backwardCompatCleanupForCategory_shouldChangeCategoryForOldKeys() {
+        final Tile tile1 = new Tile();
+        final String oldCategory = "com.android.settings.category.wireless";
+        tile1.category = oldCategory;
+        final DashboardCategory category1 = new DashboardCategory();
+        category1.addTile(tile1);
+        mCategoryByKeyMap.put(oldCategory, category1);
+        mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS1"), tile1);
+
+        mCategoryManager.backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap);
+
+        // Added 1 more category to category map.
+        assertThat(mCategoryByKeyMap.size()).isEqualTo(2);
+        // The new category map has CATEGORY_NETWORK type now, which contains 1 tile.
+        assertThat(mCategoryByKeyMap.get(CategoryKey.CATEGORY_NETWORK).tiles.size()).isEqualTo(1);
+        // Old category still exists.
+        assertThat(mCategoryByKeyMap.get(oldCategory).tiles.size()).isEqualTo(1);
+    }
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index d55bb4f..dd543a3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1310,10 +1310,6 @@
                 loadFractionSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
                         R.fraction.def_accessibility_display_magnification_scale, 1);
                 stmt.close();
-                stmt = db.compileStatement("INSERT INTO secure(name,value) VALUES(?,?);");
-                loadBooleanSetting(stmt,
-                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
-                        R.bool.def_accessibility_display_magnification_auto_update);
 
                 db.setTransactionSuccessful();
             } finally {
@@ -2508,10 +2504,6 @@
             loadFractionSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
                     R.fraction.def_accessibility_display_magnification_scale, 1);
 
-            loadBooleanSetting(stmt,
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
-                    R.bool.def_accessibility_display_magnification_auto_update);
-
             loadBooleanSetting(stmt, Settings.Secure.USER_SETUP_COMPLETE,
                     R.bool.def_user_setup_complete);
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index e7f5f4f..88ee33c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -42,7 +42,6 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Debug;
 import android.os.DropBoxManager;
 import android.os.Environment;
 import android.os.Handler;
@@ -53,6 +52,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SELinux;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
@@ -62,6 +62,7 @@
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
@@ -75,6 +76,7 @@
 import java.io.FileNotFoundException;
 import java.io.PrintWriter;
 import java.security.SecureRandom;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -114,7 +116,7 @@
  */
 @SuppressWarnings("deprecation")
 public class SettingsProvider extends ContentProvider {
-    private static final boolean DEBUG = false;
+    static final boolean DEBUG = false;
 
     private static final boolean DROP_DATABASE_ON_MIGRATION = true;
 
@@ -264,6 +266,7 @@
         }
         registerBroadcastReceivers();
         startWatchingUserRestrictionChanges();
+        ServiceManager.addService("settings", new SettingsService(this));
         return true;
     }
 
@@ -560,16 +563,14 @@
         return cacheDir;
     }
 
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
         synchronized (mLock) {
             final long identity = Binder.clearCallingIdentity();
             try {
-                List<UserInfo> users = mUserManager.getUsers(true);
+                SparseBooleanArray users = mSettingsRegistry.getKnownUsersLocked();
                 final int userCount = users.size();
                 for (int i = 0; i < userCount; i++) {
-                    UserInfo user = users.get(i);
-                    dumpForUserLocked(user.id, pw);
+                    dumpForUserLocked(users.keyAt(i), pw);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -580,49 +581,53 @@
     private void dumpForUserLocked(int userId, PrintWriter pw) {
         if (userId == UserHandle.USER_SYSTEM) {
             pw.println("GLOBAL SETTINGS (user " + userId + ")");
-            Cursor globalCursor = getAllGlobalSettings(ALL_COLUMNS);
-            dumpSettings(globalCursor, pw);
-            pw.println();
-
             SettingsState globalSettings = mSettingsRegistry.getSettingsLocked(
                     SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
+            if (globalSettings != null) {
+                dumpSettingsLocked(globalSettings, pw);
+            }
+            pw.println();
+
             globalSettings.dumpHistoricalOperations(pw);
         }
 
         pw.println("SECURE SETTINGS (user " + userId + ")");
-        Cursor secureCursor = getAllSecureSettings(userId, ALL_COLUMNS);
-        dumpSettings(secureCursor, pw);
-        pw.println();
-
         SettingsState secureSettings = mSettingsRegistry.getSettingsLocked(
                 SETTINGS_TYPE_SECURE, userId);
+        if (secureSettings != null) {
+            dumpSettingsLocked(secureSettings, pw);
+        }
+        pw.println();
+
         secureSettings.dumpHistoricalOperations(pw);
 
         pw.println("SYSTEM SETTINGS (user " + userId + ")");
-        Cursor systemCursor = getAllSystemSettings(userId, ALL_COLUMNS);
-        dumpSettings(systemCursor, pw);
-        pw.println();
-
         SettingsState systemSettings = mSettingsRegistry.getSettingsLocked(
                 SETTINGS_TYPE_SYSTEM, userId);
+        if (systemSettings != null) {
+            dumpSettingsLocked(systemSettings, pw);
+        }
+        pw.println();
+
         systemSettings.dumpHistoricalOperations(pw);
     }
 
-    private void dumpSettings(Cursor cursor, PrintWriter pw) {
-        if (cursor == null || !cursor.moveToFirst()) {
-            return;
-        }
+    private void dumpSettingsLocked(SettingsState settingsState, PrintWriter pw) {
+        List<String> names = settingsState.getSettingNamesLocked();
 
-        final int idColumnIdx = cursor.getColumnIndex(Settings.NameValueTable._ID);
-        final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
-        final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
+        final int nameCount = names.size();
 
-        do {
-            pw.append("_id:").append(toDumpString(cursor.getString(idColumnIdx)));
-            pw.append(" name:").append(toDumpString(cursor.getString(nameColumnIdx)));
-            pw.append(" value:").append(toDumpString(cursor.getString(valueColumnIdx)));
+        for (int i = 0; i < nameCount; i++) {
+            String name = names.get(i);
+            Setting setting = settingsState.getSettingLocked(name);
+            pw.print("_id:"); pw.print(toDumpString(setting.getId()));
+            pw.print(" name:"); pw.print(toDumpString(name));
+            if (setting.getPackageName() != null) {
+                pw.print(" pkg:"); pw.print(toDumpString(setting.getPackageName()));
+            }
+            pw.print(" value:"); pw.print(toDumpString(setting.getValue()));
             pw.println();
-        } while (cursor.moveToNext());
+        }
     }
 
     private static String toDumpString(String s) {
@@ -916,8 +921,9 @@
 
         // Special case for location (sigh).
         if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
-            return mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_SECURE,
-                    owningUserId).getNullSetting();
+            SettingsState settings = mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_SECURE,
+                    owningUserId);
+            return settings != null ? settings.getNullSetting() : null;
         }
 
         // Get the value.
@@ -1267,7 +1273,8 @@
                 && (parentId = getGroupParentLocked(userId)) != userId) {
             // The setting has a dependency and the profile has a parent
             String dependency = sSystemCloneFromParentOnDependency.get(setting);
-            if (getSecureSetting(dependency, userId).getValue().equals("1")) {
+            Setting settingObj = getSecureSetting(dependency, userId);
+            if (settingObj != null && settingObj.getValue().equals("1")) {
                 return parentId;
             }
         }
@@ -1405,6 +1412,9 @@
 
         Setting settingValue = getSecureSetting(
                 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
+        if (settingValue == null) {
+            return false;
+        }
 
         String oldProviders = (settingValue != null) ? settingValue.getValue() : "";
 
@@ -1491,14 +1501,14 @@
     private Bundle packageValueForCallResult(Setting setting,
             boolean trackingGeneration) {
         if (!trackingGeneration) {
-            if (setting.isNull()) {
+            if (setting == null || setting.isNull()) {
                 return NULL_SETTING_BUNDLE;
             }
             return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue());
         }
         Bundle result = new Bundle();
         result.putString(Settings.NameValueTable.VALUE,
-                !setting.isNull() ? setting.getValue() : null);
+                setting != null && !setting.isNull() ? setting.getValue() : null);
         mSettingsRegistry.mGenerationRegistry.addGenerationData(result, setting.getkey());
         return result;
     }
@@ -1554,7 +1564,7 @@
     }
 
     private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) {
-        if (setting.isNull()) {
+        if (setting == null || setting.isNull()) {
             return;
         }
         final int columnCount = cursor.getColumnCount();
@@ -1700,15 +1710,32 @@
         public List<String> getSettingsNamesLocked(int type, int userId) {
             final int key = makeKey(type, userId);
             SettingsState settingsState = peekSettingsStateLocked(key);
+            if (settingsState == null) {
+                return new ArrayList<String>();
+            }
             return settingsState.getSettingNamesLocked();
         }
 
+        public SparseBooleanArray getKnownUsersLocked() {
+            SparseBooleanArray users = new SparseBooleanArray();
+            for (int i = mSettingsStates.size()-1; i >= 0; i--) {
+                users.put(getUserIdFromKey(mSettingsStates.keyAt(i)), true);
+            }
+            return users;
+        }
+
         public SettingsState getSettingsLocked(int type, int userId) {
             final int key = makeKey(type, userId);
             return peekSettingsStateLocked(key);
         }
 
-        public void ensureSettingsForUserLocked(int userId) {
+        public boolean ensureSettingsForUserLocked(int userId) {
+            // First make sure this user actually exists.
+            if (mUserManager.getUserInfo(userId) == null) {
+                Slog.wtf(LOG_TAG, "Requested user " + userId + " does not exist");
+                return false;
+            }
+
             // Migrate the setting for this user if needed.
             migrateLegacySettingsForUserIfNeededLocked(userId);
 
@@ -1733,6 +1760,7 @@
             // Upgrade the settings to the latest version.
             UpgradeController upgrader = new UpgradeController(userId);
             upgrader.upgradeIfNeededLocked();
+            return true;
         }
 
         private void ensureSettingsStateLocked(int key) {
@@ -1790,7 +1818,8 @@
             final int key = makeKey(type, userId);
 
             SettingsState settingsState = peekSettingsStateLocked(key);
-            final boolean success = settingsState.insertSettingLocked(name, value, packageName);
+            final boolean success = settingsState != null
+                    && settingsState.insertSettingLocked(name, value, packageName);
 
             if (forceNotify || success) {
                 notifyForSettingsChange(key, name);
@@ -1802,6 +1831,9 @@
             final int key = makeKey(type, userId);
 
             SettingsState settingsState = peekSettingsStateLocked(key);
+            if (settingsState == null) {
+                return false;
+            }
             final boolean success = settingsState.deleteSettingLocked(name);
 
             if (forceNotify || success) {
@@ -1814,6 +1846,9 @@
             final int key = makeKey(type, userId);
 
             SettingsState settingsState = peekSettingsStateLocked(key);
+            if (settingsState == null) {
+                return null;
+            }
             return settingsState.getSettingLocked(name);
         }
 
@@ -1822,7 +1857,8 @@
             final int key = makeKey(type, userId);
 
             SettingsState settingsState = peekSettingsStateLocked(key);
-            final boolean success = settingsState.updateSettingLocked(name, value, packageName);
+            final boolean success = settingsState != null
+                    && settingsState.updateSettingLocked(name, value, packageName);
 
             if (forceNotify || success) {
                 notifyForSettingsChange(key, name);
@@ -1850,7 +1886,9 @@
                 return settingsState;
             }
 
-            ensureSettingsForUserLocked(getUserIdFromKey(key));
+            if (!ensureSettingsForUserLocked(getUserIdFromKey(key))) {
+                return null;
+            }
             return mSettingsStates.get(key);
         }
 
@@ -2137,7 +2175,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 134;
+            private static final int SETTINGS_VERSION = 135;
 
             private final int mUserId;
 
@@ -2507,6 +2545,14 @@
                     currentVersion = 134;
                 }
 
+                if (currentVersion == 134) {
+                    // Remove setting that specifies if magnification values should be preserved.
+                    // This setting defaulted to true and never has a UI.
+                    getSecureSettingsLocked(userId).deleteSettingLocked(
+                            Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE);
+                    currentVersion = 135;
+                }
+
                 if (currentVersion != newVersion) {
                     Slog.wtf("SettingsProvider", "warning: upgrading settings database to version "
                             + newVersion + " left it at "
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
new file mode 100644
index 0000000..169b01f
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -0,0 +1,375 @@
+/*
+ * 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.providers.settings;
+
+import android.app.ActivityManagerNative;
+import android.content.IContentProvider;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+final public class SettingsService extends Binder {
+    final SettingsProvider mProvider;
+
+    public SettingsService(SettingsProvider provider) {
+        mProvider = provider;
+    }
+
+    @Override
+    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+        (new MyShellCommand(mProvider, false)).exec(
+                this, in, out, err, args, callback, resultReceiver);
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mProvider.getContext().checkCallingPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump SettingsProvider from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " without permission "
+                    + android.Manifest.permission.DUMP);
+            return;
+        }
+
+        int opti = 0;
+        while (opti < args.length) {
+            String opt = args[opti];
+            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
+                break;
+            }
+            opti++;
+            if ("-h".equals(opt)) {
+                MyShellCommand.dumpHelp(pw, true);
+                return;
+            } else {
+                pw.println("Unknown argument: " + opt + "; use -h for help");
+            }
+        }
+
+        long caller = Binder.clearCallingIdentity();
+        try {
+            mProvider.dumpInternal(fd, pw, args);
+        } finally {
+            Binder.restoreCallingIdentity(caller);
+        }
+    }
+
+    final static class MyShellCommand extends ShellCommand {
+        final SettingsProvider mProvider;
+        final boolean mDumping;
+
+        enum CommandVerb {
+            UNSPECIFIED,
+            GET,
+            PUT,
+            DELETE,
+            LIST,
+        }
+
+        int mUser = -1;     // unspecified
+        CommandVerb mVerb = CommandVerb.UNSPECIFIED;
+        String mTable = null;
+        String mKey = null;
+        String mValue = null;
+
+
+        MyShellCommand(SettingsProvider provider, boolean dumping) {
+            mProvider = provider;
+            mDumping = dumping;
+        }
+
+        @Override
+        public int onCommand(String cmd) {
+            if (cmd == null) {
+                return handleDefaultCommands(cmd);
+            }
+
+            final PrintWriter perr = getErrPrintWriter();
+
+            boolean valid = false;
+            String arg = cmd;
+            do {
+                if ("--user".equals(arg)) {
+                    if (mUser != -1) {
+                        // --user specified more than once; invalid
+                        break;
+                    }
+                    arg = getNextArgRequired();
+                    if ("current".equals(arg) || "cur".equals(arg)) {
+                        mUser = UserHandle.USER_CURRENT;
+                    } else {
+                        mUser = Integer.parseInt(arg);
+                    }
+                } else if (mVerb == CommandVerb.UNSPECIFIED) {
+                    if ("get".equalsIgnoreCase(arg)) {
+                        mVerb = CommandVerb.GET;
+                    } else if ("put".equalsIgnoreCase(arg)) {
+                        mVerb = CommandVerb.PUT;
+                    } else if ("delete".equalsIgnoreCase(arg)) {
+                        mVerb = CommandVerb.DELETE;
+                    } else if ("list".equalsIgnoreCase(arg)) {
+                        mVerb = CommandVerb.LIST;
+                    } else {
+                        // invalid
+                        perr.println("Invalid command: " + arg);
+                        return -1;
+                    }
+                } else if (mTable == null) {
+                    if (!"system".equalsIgnoreCase(arg)
+                            && !"secure".equalsIgnoreCase(arg)
+                            && !"global".equalsIgnoreCase(arg)) {
+                        perr.println("Invalid namespace '" + arg + "'");
+                        return -1;
+                    }
+                    mTable = arg.toLowerCase();
+                    if (mVerb == CommandVerb.LIST) {
+                        valid = true;
+                        break;
+                    }
+                } else if (mVerb == CommandVerb.GET || mVerb == CommandVerb.DELETE) {
+                    mKey = arg;
+                    if (peekNextArg() == null) {
+                        valid = true;
+                    } else {
+                        perr.println("Too many arguments");
+                        return -1;
+                    }
+                    break;
+                } else if (mKey == null) {
+                    mKey = arg;
+                    // keep going; there's another PUT arg
+                } else {    // PUT, final arg
+                    mValue = arg;
+                    if (peekNextArg() == null) {
+                        valid = true;
+                    } else {
+                        perr.println("Too many arguments");
+                        return -1;
+                    }
+                    break;
+                }
+            } while ((arg = getNextArg()) != null);
+
+            if (!valid) {
+                perr.println("Bad arguments");
+                return -1;
+            }
+
+            if (mUser == UserHandle.USER_CURRENT) {
+                try {
+                    mUser = ActivityManagerNative.getDefault().getCurrentUser().id;
+                } catch (RemoteException e) {
+                    throw new RuntimeException("Failed in IPC", e);
+                }
+            }
+            if (mUser < 0) {
+                mUser = UserHandle.USER_SYSTEM;
+            } else if (mVerb == CommandVerb.DELETE || mVerb == CommandVerb.LIST) {
+                perr.println("--user not supported for delete and list.");
+                return -1;
+            }
+            UserManager userManager = UserManager.get(mProvider.getContext());
+            if (userManager.getUserInfo(mUser) == null) {
+                perr.println("Invalid user: " + mUser);
+                return -1;
+            }
+
+            final IContentProvider iprovider = mProvider.getIContentProvider();
+            final PrintWriter pout = getOutPrintWriter();
+            switch (mVerb) {
+                case GET:
+                    pout.println(getForUser(iprovider, mUser, mTable, mKey));
+                    break;
+                case PUT:
+                    putForUser(iprovider, mUser, mTable, mKey, mValue);
+                    break;
+                case DELETE:
+                    pout.println("Deleted "
+                            + deleteForUser(iprovider, mUser, mTable, mKey) + " rows");
+                    break;
+                case LIST:
+                    for (String line : listForUser(iprovider, mUser, mTable)) {
+                        pout.println(line);
+                    }
+                    break;
+                default:
+                    perr.println("Unspecified command");
+                    return -1;
+            }
+
+            return 0;
+        }
+
+        private List<String> listForUser(IContentProvider provider, int userHandle, String table) {
+            final Uri uri = "system".equals(table) ? Settings.System.CONTENT_URI
+                    : "secure".equals(table) ? Settings.Secure.CONTENT_URI
+                    : "global".equals(table) ? Settings.Global.CONTENT_URI
+                    : null;
+            final ArrayList<String> lines = new ArrayList<String>();
+            if (uri == null) {
+                return lines;
+            }
+            try {
+                final Cursor cursor = provider.query(resolveCallingPackage(), uri, null, null, null,
+                        null, null);
+                try {
+                    while (cursor != null && cursor.moveToNext()) {
+                        lines.add(cursor.getString(1) + "=" + cursor.getString(2));
+                    }
+                } finally {
+                    if (cursor != null) {
+                        cursor.close();
+                    }
+                }
+                Collections.sort(lines);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+            return lines;
+        }
+
+        String getForUser(IContentProvider provider, int userHandle,
+                final String table, final String key) {
+            final String callGetCommand;
+            if ("system".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SYSTEM;
+            else if ("secure".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_SECURE;
+            else if ("global".equals(table)) callGetCommand = Settings.CALL_METHOD_GET_GLOBAL;
+            else {
+                getErrPrintWriter().println("Invalid table; no put performed");
+                throw new IllegalArgumentException("Invalid table " + table);
+            }
+
+            String result = null;
+            try {
+                Bundle arg = new Bundle();
+                arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+                Bundle b = provider.call(resolveCallingPackage(), callGetCommand, key, arg);
+                if (b != null) {
+                    result = b.getPairValue();
+                }
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+            return result;
+        }
+
+        void putForUser(IContentProvider provider, int userHandle,
+                final String table, final String key, final String value) {
+            final String callPutCommand;
+            if ("system".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
+            else if ("secure".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SECURE;
+            else if ("global".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_GLOBAL;
+            else {
+                getErrPrintWriter().println("Invalid table; no put performed");
+                return;
+            }
+
+            try {
+                Bundle arg = new Bundle();
+                arg.putString(Settings.NameValueTable.VALUE, value);
+                arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
+                provider.call(resolveCallingPackage(), callPutCommand, key, arg);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+        }
+
+        int deleteForUser(IContentProvider provider, int userHandle,
+                final String table, final String key) {
+            Uri targetUri;
+            if ("system".equals(table)) targetUri = Settings.System.getUriFor(key);
+            else if ("secure".equals(table)) targetUri = Settings.Secure.getUriFor(key);
+            else if ("global".equals(table)) targetUri = Settings.Global.getUriFor(key);
+            else {
+                getErrPrintWriter().println("Invalid table; no delete performed");
+                throw new IllegalArgumentException("Invalid table " + table);
+            }
+
+            int num = 0;
+            try {
+                num = provider.delete(resolveCallingPackage(), targetUri, null, null);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Failed in IPC", e);
+            }
+            return num;
+        }
+
+        public static String resolveCallingPackage() {
+            switch (Binder.getCallingUid()) {
+                case Process.ROOT_UID: {
+                    return "root";
+                }
+
+                case Process.SHELL_UID: {
+                    return "com.android.shell";
+                }
+
+                default: {
+                    return null;
+                }
+            }
+        }
+
+        @Override
+        public void onHelp() {
+            PrintWriter pw = getOutPrintWriter();
+            dumpHelp(pw, mDumping);
+        }
+
+        static void dumpHelp(PrintWriter pw, boolean dumping) {
+            if (dumping) {
+                pw.println("Settings provider dump options:");
+                pw.println("  [-h]");
+                pw.println("  -h: print this help.");
+            } else {
+                pw.println("Settings provider (settings) commands:");
+                pw.println("  help");
+                pw.println("      Print this help text.");
+                pw.println("  get [--user <USER_ID> | current] NAMESPACE KEY");
+                pw.println("      Retrieve the current value of KEY.");
+                pw.println("  put [--user <USER_ID> | current] NAMESPACE KEY VALUE");
+                pw.println("      Change the contents of KEY to VALUE.");
+                pw.println("  delete NAMESPACE KEY");
+                pw.println("      Delete the entry for KEY.");
+                pw.println("  list NAMESPACE");
+                pw.println("      Print all defined keys.");
+                pw.println();
+                pw.println("  NAMESPACE is one of {system, secure, global}, case-insensitive");
+            }
+        }
+    }
+}
+
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 832c9d9..d682fe9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -350,8 +350,11 @@
                 pw.print(" ");
                 pw.print(operation.mOperation);
                 if (operation.mSetting != null) {
-                    pw.print("  ");
-                    pw.print(operation.mSetting);
+                    pw.print(" ");
+                    // Only print the name of the setting, since we don't know the
+                    // historical package and values for it so they would be misleading
+                    // to print here (all we could print is what the current data is).
+                    pw.print(operation.mSetting.getName());
                 }
                 pw.println();
             }
diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml
index b33da19..9bef2db 100644
--- a/packages/Shell/res/values-tr/strings.xml
+++ b/packages/Shell/res/values-tr/strings.xml
@@ -22,7 +22,7 @@
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Hata raporuna ayrıntılar ekleniyor"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lütfen bekleyin…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Hata raporu kısa süre içinde telefonda görüntülenecektir"</string>
-    <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Hata raporunuzu paylaşmak için hafifçe dokunun"</string>
+    <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Hata raporunuzu paylaşmak için dokunun"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Hata raporunu ekran görüntüsüz paylaşmak için dokunun veya bitirmek için ekran görüntüsünü bekleyin"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Hata raporunu ekran görüntüsüz paylaşmak için dokunun veya bitirmek için ekran görüntüsünü bekleyin"</string>
     <string name="bugreport_confirm" msgid="5917407234515812495">"Hata raporları, sistemin çeşitli günlük dosyalarından veriler içerir. Bu günlükler, hassas olarak kabul ettiğiniz verileri (uygulama kullanımı ve konum verileri gibi) içerebilir. Hata raporlarını yalnızca güvendiğiniz kişiler ve uygulamalarla paylaşın."</string>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4d59d57..e07d865 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -285,6 +285,22 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".recents.grid.RecentsGridActivity"
+                  android:label="@string/accessibility_desc_recent_apps"
+                  android:exported="false"
+                  android:launchMode="singleInstance"
+                  android:excludeFromRecents="true"
+                  android:stateNotNeeded="true"
+                  android:resumeWhilePausing="true"
+                  android:screenOrientation="behind"
+                  android:resizeableActivity="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+                  android:theme="@style/RecentsTheme.Wallpaper">
+            <intent-filter>
+                <action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
+            </intent-filter>
+        </activity>
+
         <activity android:name=".recents.tv.RecentsTvActivity"
                   android:label="@string/accessibility_desc_recent_apps"
                   android:exported="false"
@@ -415,6 +431,18 @@
             android:launchMode="singleTop"
             android:excludeFromRecents="true" />
 
+        <activity
+            android:name=".pip.phone.PipMenuActivity"
+            android:theme="@style/PipPhoneOverlayControlTheme"
+            android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+            android:excludeFromRecents="true"
+            android:exported="false"
+            android:resizeableActivity="true"
+            android:supportsPictureInPicture="true"
+            android:stateNotNeeded="true"
+            android:taskAffinity=""
+            androidprv:alwaysFocusable="true" />
+
         <!-- platform logo easter egg activity -->
         <activity
             android:name=".DessertCase"
diff --git a/packages/SystemUI/plugin/Android.mk b/packages/SystemUI/plugin/Android.mk
index 5e6dcc0..86527db 100644
--- a/packages/SystemUI/plugin/Android.mk
+++ b/packages/SystemUI/plugin/Android.mk
@@ -27,7 +27,3 @@
 LOCAL_JAR_EXCLUDE_FILES := none
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
-
-ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)
-    include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/packages/SystemUI/res/layout-sw600dp/recents_grid.xml b/packages/SystemUI/res/layout-sw600dp/recents_grid.xml
new file mode 100644
index 0000000..c8b4fd0
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/recents_grid.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:id="@+id/recents_container">
+    <include layout="@layout/recents_stack_action_button" />
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/recents_view"
+        android:layout_marginLeft="12dp"
+        android:layout_marginTop="10dp"
+        android:layout_marginRight="12dp"
+        android:layout_marginBottom="5dp"
+        android:gravity="center">
+    </FrameLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
new file mode 100644
index 0000000..88e6e72
--- /dev/null
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#33000000">
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center">
+        <Button
+            android:id="@+id/expand_pip"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:textSize="14sp"
+            android:textColor="#ffffffff"
+            android:text="@string/pip_phone_expand"
+            android:fontFamily="sans-serif" />
+    </LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 1131b2a..ea070b3 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Maak <xliff:g id="ID_1">%s</xliff:g>-instellings oop."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Wysig volgorde van instellings."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Bladsy <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 0dc05e6..837d677 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"የ<xliff:g id="ID_1">%s</xliff:g> ቅንብሮችን ክፈት።"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"የቅንብሮድ ቅደም-ተከተል አርትዕ።"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ገጽ <xliff:g id="ID_1">%1$d</xliff:g> ከ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 755438e..f207dbc1 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -656,4 +656,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"فتح إعدادات <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"تعديل ترتيب الإعدادات."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"الصفحة <xliff:g id="ID_1">%1$d</xliff:g> من <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 87b4433..c4b0f73 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ayarlarını açın."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Ayarların sıralanmasını redaktə edin."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> səhifədən <xliff:g id="ID_1">%1$d</xliff:g> səhifə"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index e173890..e70e485 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvori podešavanja za <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Izmeni redosled podešavanja."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. strana od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index 207e223..7f7a67f 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -654,4 +654,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Адкрыць налады <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Змяніць парадак налад."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Старонка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 16c94d7..16dfeeb 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Отваряне на настройките за <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Редактиране на подредбата на настройките."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> от <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index feaa453..f8ee362 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -528,7 +528,7 @@
     <string name="keyboard_key_home" msgid="2243500072071305073">"হোম"</string>
     <string name="keyboard_key_back" msgid="2337450286042721351">"ফিরুন"</string>
     <string name="keyboard_key_dpad_up" msgid="5584144111755734686">"উপরে"</string>
-    <string name="keyboard_key_dpad_down" msgid="7331518671788337815">"নীচে"</string>
+    <string name="keyboard_key_dpad_down" msgid="7331518671788337815">"নিচে"</string>
     <string name="keyboard_key_dpad_left" msgid="1346446024676962251">"বাম"</string>
     <string name="keyboard_key_dpad_right" msgid="3317323247127515341">"ডান"</string>
     <string name="keyboard_key_dpad_center" msgid="2566737770049304658">"কেন্দ্র"</string>
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> সেটিংস খুলুন৷"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ক্রম বা সেটিংস সম্পাদনা করুন৷"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>টির মধ্যে <xliff:g id="ID_1">%1$d</xliff:g> নং পৃষ্ঠা"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index f361b93..0e91713 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -652,4 +652,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvori postavke za: <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Urediti raspored postavki."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 8bedecd..d258943 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Obre la configuració per a <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edita l\'ordre de la configuració."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pàgina <xliff:g id="ID_1">%1$d</xliff:g> (<xliff:g id="ID_2">%2$d</xliff:g> en total)"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 0ff0f93..845c8b5 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -654,4 +654,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otevřít nastavení aplikace <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Upravit pořadí nastavení."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stránka <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index b112405..bb340a6 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Åbn <xliff:g id="ID_1">%s</xliff:g>-indstillinger."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Rediger rækkefølgen af indstillinger."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Side <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 9721362..faabbfa 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Einstellungen für <xliff:g id="ID_1">%s</xliff:g> öffnen."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Reihenfolge der Einstellungen bearbeiten."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Seite <xliff:g id="ID_1">%1$d</xliff:g> von <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 276b856..0f5f447 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Άνοιγμα ρυθμίσεων <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Επεξεργασία σειράς ρυθμίσεων."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Σελίδα <xliff:g id="ID_1">%1$d</xliff:g> από <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index ca2e5b3..14d2a19 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Open <xliff:g id="ID_1">%s</xliff:g> settings."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit order of settings."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index ca2e5b3..14d2a19 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Open <xliff:g id="ID_1">%s</xliff:g> settings."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit order of settings."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index ca2e5b3..14d2a19 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Open <xliff:g id="ID_1">%s</xliff:g> settings."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit order of settings."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 81696f6..3b92a3a 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir configuración de <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editar orden de configuración"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index aa9578a..600d7d5 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir ajustes de <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Cambiar el orden de los ajustes."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index ab81af5..884eac5 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ava teenuse <xliff:g id="ID_1">%s</xliff:g> seaded."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Muuda seadete järjestust."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Leht <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 3617074..b5e6696 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ireki <xliff:g id="ID_1">%s</xliff:g> ezarpenak."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editatu ezarpenen ordena."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g> orria"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 48f0b954..866904c 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"باز کردن تنظیمات <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ویرایش ترتیب تنظیمات."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحه <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 5e1ca4b..144704d 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Avaa kohteen <xliff:g id="ID_1">%s</xliff:g> asetukset."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Muokkaa asetusten järjestystä."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sivu <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 765e0aa..b5c227e 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ouvrir les paramètres <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Modifier l\'ordre des paramètres."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index e66d342..008d061 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ouvrir les paramètres <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Modifier l\'ordre des paramètres."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 5ccf4a0..cca60a8 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir a configuración de <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editar a orde das opcións de configuración."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Páxina <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 84f9105..558a90a 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> સેટિંગ્સ ખોલો."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"સેટિંગ્સનો ક્રમ સંપાદિત કરો."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> માંથી <xliff:g id="ID_1">%1$d</xliff:g> પૃષ્ઠ"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 89b5a6f..1fff051 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> सेटिंग खोलें."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"सेटिंग का क्रम संपादित करें."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"पृष्ठ <xliff:g id="ID_2">%2$d</xliff:g> में से <xliff:g id="ID_1">%1$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 3c5812f..ae7e0c4 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvaranje postavki za <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Uređivanje redoslijeda postavki."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index f83ba28..ec62e1c 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"A(z) <xliff:g id="ID_1">%s</xliff:g> beállításainak megnyitása."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Beállítások sorrendjének szerkesztése."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. oldal, összesen: <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 4ce22e4..80cb977 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Բացել <xliff:g id="ID_1">%s</xliff:g> կարգավորումները:"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Խմբագրել կարգավորումների հերթականությունը:"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Էջ <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 4efffc56..93960e8 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Buka setelan <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit urutan setelan."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> dari <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 4875888..71ef4bb 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Opna <xliff:g id="ID_1">%s</xliff:g> stillingar."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Breyta röð stillinga."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Blaðsíða <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 98a2424..12d0ed6 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Apri le impostazioni <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Modifica l\'ordine delle impostazioni."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> di <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ce73705..f565603 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -652,4 +652,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"פתיחת הגדרות של <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"עריכת סדר ההגדרות."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"דף <xliff:g id="ID_1">%1$d</xliff:g> מתוך <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index c45fa4f..37bea17 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> の設定を開きます。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"設定の順序を編集します。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ページ <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index a151b8f..15f5d63 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> პარამეტრების გახსნა."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"პარამეტრების მიმდევრობის რედაქტირება."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"გვერდი <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>-დან"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 6c0c967..477ab82 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> параметрлерін ашу."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Параметрлер тәртібін өзгерту."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ішінен <xliff:g id="ID_1">%1$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index d3e97cc..45771d9 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"បើការកំណត់ <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"កែលំដាប់ការកំណត់"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ទំព័រ <xliff:g id="ID_1">%1$d</xliff:g> នៃ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index cbd71f9..87c48dd 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಕ್ರಮವನ್ನು ಎಡಿಟ್ ಮಾಡಿ."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="ID_1">%1$d</xliff:g> ಪುಟ"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3827dba..3e0cdfe 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> 설정 열기"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"설정 순서 수정"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>페이지 중 <xliff:g id="ID_1">%1$d</xliff:g>페이지"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 56c8360..2d8be38 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> жөндөөлөрүн ачуу."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Жөндөөлөрдүн иретин өзгөртүү."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ичинен <xliff:g id="ID_1">%1$d</xliff:g>-бет"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 47a49da..93098ad 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"ເປີດການຕັ້ງຄ່າ <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ແກ້ໄຂລຳດັບການຕັ້ງຄ່າ."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g> ຈາກທັງໝົດ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index c4676fa..02e614c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -652,4 +652,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Atidaryti „<xliff:g id="ID_1">%s</xliff:g>“ nustatymus."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Redaguoti nustatymų tvarką."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g> psl. iš <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index a8266dd..82f5f22 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Atvērt <xliff:g id="ID_1">%s</xliff:g> iestatījumus."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Rediģēt iestatījumu secību."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. lpp. no <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index c5e2500..fcaa26f 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Отворете ги поставките на <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Уредете го редоследот на поставките."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index a1a3b31..44d76d5 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ക്രമീകരണം തുറക്കുക."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ക്രമീകരണ ക്രമം എഡിറ്റുചെയ്യുക."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"പേജ് <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 9b83058..1c7bc38 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> тохиргоог нээнэ үү."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Тохиргооны дарааллыг өөрчилнө үү."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>-н <xliff:g id="ID_1">%1$d</xliff:g>-р хуудас"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 8003890..71d6677 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> सेटिंग्ज उघडा."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"सेटिंग्जचा क्रम संपादित करा."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"पृष्ठ <xliff:g id="ID_2">%2$d</xliff:g> पैकी <xliff:g id="ID_1">%1$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 1a16967..bc9d79f 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Buka tetapan <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit susunan tetapan."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> daripada <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 17b6802..37c002c 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ဆက်တင်များကို ဖွင့်ပါ။"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ဆက်တင်များ၏ အစီအစဉ်ကို တည်းဖြတ်ပါ။"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"စာမျက်နှာ <xliff:g id="ID_2">%2$d</xliff:g> အနက်မှ စာမျက်နှာ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index cb691c5..025c270 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Åpne <xliff:g id="ID_1">%s</xliff:g>-innstillingene."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Endre rekkefølgen på innstillingene."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Side <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 97f5f5e..3ed5782 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> सम्बन्धी सेटिङहरूलाई खोल्नुहोस्।"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"सेटिङहरूको क्रमलाई सम्पादन गर्नुहोस्।"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> मध्ये पृष्ठ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 43c577d..13ef0f6 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g>-instellingen openen."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Volgorde van instellingen bewerken."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 6ef8674..553b604 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ।"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ਸੈਟਿੰਗਾਂ ਦੇ ਕ੍ਰਮ ਦਾ ਸੰਪਾਦਨ ਕਰੋ।"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ਦਾ <xliff:g id="ID_1">%1$d</xliff:g> ਪੰਨਾ"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 03e599c..cc5b693 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -652,4 +652,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otwórz ustawienia: <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edytuj kolejność ustawień."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Strona <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 0ae421d..ef07edc 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir configurações de <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editar ordem das configurações."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 6ad19f9..5c7ea4f 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir as definições de <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editar a ordem das definições."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 0ae421d..ef07edc 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir configurações de <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editar ordem das configurações."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 70ef6ea..0d42645 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -652,4 +652,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Deschideți setările <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editați ordinea setărilor."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> din <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 41ec367..9adc9fe 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -654,4 +654,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Открыть настройки <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Изменить порядок быстрых настроек."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> из <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 8f65531..6739ea1 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> සැකසීම් විවෘත කරන්න."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"සැකසීම්වල අනුපිළිවෙළ සංංස්කරණය කරන්න."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> න් <xliff:g id="ID_1">%1$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 276c266..44881bd 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -654,4 +654,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvoriť nastavenia <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Upraviť poradie nastavení"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Strana <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index cda2ac9..cc11704 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -654,4 +654,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Odpri nastavitve za <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Uredi vrstni red nastavitev."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. stran od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 33b2d5b..55598bd 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Hap cilësimet e <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Modifiko rendin e cilësimeve."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Faqja <xliff:g id="ID_1">%1$d</xliff:g> nga <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 11d05b7..22bd853 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Отвори подешавања за <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Измени редослед подешавања."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. страна од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 46e3f05..87acdb3 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Öppna <xliff:g id="ID_1">%s</xliff:g>-inställningarna."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Ändra ordning på inställningarna."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sida <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 43aa36d..cc4391ce 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Fungua mipangilio ya <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Badilisha orodha ya mipangilio."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Ukurasa wa <xliff:g id="ID_1">%1$d</xliff:g> kati ya <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 364173e..2d3c27f 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> அமைப்புகளைத் திற."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"அமைப்புகளின் வரிசை முறையைத் திருத்து."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"பக்கம் <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index c1e55c8..9fa3f86 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> సెట్టింగ్‌లను తెరవండి."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"సెట్టింగ్‌ల క్రమాన్ని సవరించండి."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>లో <xliff:g id="ID_1">%1$d</xliff:g>వ పేజీ"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index f2b1772..f59e69b 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"เปิดการตั้งค่า <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"แก้ไขลำดับการตั้งค่า"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"หน้า <xliff:g id="ID_1">%1$d</xliff:g> จาก <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index f58ed17..2d978c4 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Buksan ang mga setting ng <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"I-edit ang pagkakasunud-sunod ng mga setting."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> ng <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index e7b1abb..e3827f7 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ayarlarını aç."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Ayarların sırasını düzenle."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sayfa <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 886a138..fd627cc 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -654,4 +654,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Відкрити налаштування <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Змінити порядок налаштувань."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Сторінка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 31d90e2..415c5b6 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ترتیبات کھولیں۔"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ترتیبات کی ترتیب میں ترمیم کریں۔"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحہ <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 78ad148..aaea5e5 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> sozlamalarini ochish."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Sozlamalar tartibini o‘zgartirish."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>-sahifa, jami: <xliff:g id="ID_2">%2$d</xliff:g> ta sahifa"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index ba49055..4ae3370 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Mở cài đặt <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Chỉnh sửa thứ tự cài đặt."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Trang <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7a7991f..7c7bc4a 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"打开<xliff:g id="ID_1">%s</xliff:g>设置。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"修改设置顺序。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 页,共 <xliff:g id="ID_2">%2$d</xliff:g> 页"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 4f7ffe5..e41a24b 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -650,4 +650,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"開啟<xliff:g id="ID_1">%s</xliff:g>設定頁面。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"編輯設定次序。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁 (共 <xliff:g id="ID_2">%2$d</xliff:g> 頁)"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 2de07e3..51e27a3 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"開啟「<xliff:g id="ID_1">%s</xliff:g>」設定。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"編輯設定順序。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 6be736a..887da2e 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -648,4 +648,6 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Vula izilungiselelo ze-<xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Hlela uhlelo lwezilungiselelo."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Ikhasi <xliff:g id="ID_1">%1$d</xliff:g> kwangu-<xliff:g id="ID_2">%2$d</xliff:g>"</string>
+    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d8c8b82..37a7e38 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1675,6 +1675,9 @@
         not appear on production builds ever. -->
     <string name="tuner_doze_always_on" translatable="false">Always on</string>
 
+    <!-- Making the PIP fullscreen -->
+    <string name="pip_phone_expand">Expand</string>
+
     <!-- PIP section of the tuner. Non-translatable since it should
         not appear on production builds ever. -->
     <string name="picture_in_picture" translatable="false">Picture-in-Picture</string>
@@ -1695,4 +1698,20 @@
         not appear on production builds ever. -->
     <string name="pip_drag_to_dismiss_summary" translatable="false">Drag to the dismiss target at the bottom of the screen to close the PIP</string>
 
+    <!-- PIP tap once to break through to the activity. Non-translatable since it should
+        not appear on production builds ever. -->
+    <string name="pip_tap_through_title" translatable="false">Tap to interact</string>
+
+    <!-- PIP tap once to break through to the activity. Non-translatable since it should
+        not appear on production builds ever. -->
+    <string name="pip_tap_through_summary" translatable="false">Tap once to interact with the activity</string>
+
+    <!-- PIP snap to closest edge. Non-translatable since it should
+        not appear on production builds ever. -->
+    <string name="pip_snap_mode_edge_title" translatable="false">Snap to closest edge</string>
+
+    <!-- PIP snap to closest edge. Non-translatable since it should
+        not appear on production builds ever. -->
+    <string name="pip_snap_mode_edge_summary" translatable="false">Snap to the closest edge</string>
+
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index e5bc8b9..6661f07 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -56,6 +56,24 @@
         <item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item>
     </style>
 
+    <style name="PipPhoneOverlayControlTheme" parent="@android:style/Theme.Material">
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowBackground">@drawable/forced_resizable_background</item>
+        <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:statusBarColor">@color/transparent</item>
+        <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item>
+    </style>
+
+    <style name="Animation.PipPhoneOverlayControl" parent="@android:style/Animation">
+        <item name="android:activityOpenEnterAnimation">@anim/forced_resizable_enter</item>
+
+        <!-- If the target stack doesn't have focus, we do a task to front animation. -->
+        <item name="android:taskToFrontEnterAnimation">@anim/forced_resizable_enter</item>
+        <item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item>
+    </style>
+
     <style name="TextAppearance.StatusBar.HeadsUp"
         parent="@*android:style/TextAppearance.StatusBar">
     </style>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 942f847..f09d6e9 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -137,6 +137,18 @@
           android:summary="@string/pip_drag_to_dismiss_summary"
           sysui:defValue="true" />
 
+        <com.android.systemui.tuner.TunerSwitch
+            android:key="pip_tap_through"
+            android:title="@string/pip_tap_through_title"
+            android:summary="@string/pip_tap_through_summary"
+            sysui:defValue="false" />
+
+        <com.android.systemui.tuner.TunerSwitch
+            android:key="pip_snap_mode_edge"
+            android:title="@string/pip_snap_mode_edge_title"
+            android:summary="@string/pip_snap_mode_edge_summary"
+            sysui:defValue="false" />
+
     </PreferenceScreen>
 
     <PreferenceScreen
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
new file mode 100644
index 0000000..4cfc811
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -0,0 +1,83 @@
+/*
+ * 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.systemui.doze;
+
+import android.app.Application;
+import android.content.Context;
+import android.hardware.SensorManager;
+import android.os.Handler;
+import android.os.PowerManager;
+
+import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.systemui.SystemUIApplication;
+import com.android.systemui.statusbar.phone.DozeParameters;
+
+public class DozeFactory {
+
+    /** Creates a DozeMachine with its parts for {@code dozeService}. */
+    public static DozeMachine assembleMachine(DozeService dozeService) {
+        Context context = dozeService;
+        SensorManager sensorManager = context.getSystemService(SensorManager.class);
+        PowerManager powerManager = context.getSystemService(PowerManager.class);
+
+        DozeHost host = getHost(dozeService);
+        AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(context);
+        DozeParameters params = new DozeParameters(context);
+        Handler handler = new Handler();
+        DozeFactory.WakeLock wakeLock = new DozeFactory.WakeLock(powerManager.newWakeLock(
+                PowerManager.PARTIAL_WAKE_LOCK, "Doze"));
+
+        DozeMachine machine = new DozeMachine(dozeService, params, wakeLock);
+        machine.setParts(new DozeMachine.Part[]{
+                new DozeTriggers(context, machine, host, config, params,
+                        sensorManager, handler, wakeLock),
+                new DozeUi(context, machine, wakeLock, host),
+        });
+
+        return machine;
+    }
+
+    private static DozeHost getHost(DozeService service) {
+        Application appCandidate = service.getApplication();
+        final SystemUIApplication app = (SystemUIApplication) appCandidate;
+        return app.getComponent(DozeHost.class);
+    }
+
+    /** A wrapper around {@link PowerManager.WakeLock} for testability. */
+    public static class WakeLock {
+        private final PowerManager.WakeLock mInner;
+
+        public WakeLock(PowerManager.WakeLock inner) {
+            mInner = inner;
+        }
+
+        /** @see PowerManager.WakeLock#acquire() */
+        public void acquire() {
+            mInner.acquire();
+        }
+
+        /** @see PowerManager.WakeLock#release() */
+        public void release() {
+            mInner.release();
+        }
+
+        /** @see PowerManager.WakeLock#wrap(Runnable) */
+        public Runnable wrap(Runnable runnable) {
+            return mInner.wrap(runnable);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 02a98b0..fb940b5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -24,7 +24,7 @@
 public interface DozeHost {
     void addCallback(@NonNull Callback callback);
     void removeCallback(@NonNull Callback callback);
-    void startDozing(@NonNull Runnable ready);
+    void startDozing();
     void pulseWhileDozing(@NonNull PulseCallback callback, int reason);
     void stopDozing();
     void dozeTimeTick();
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
new file mode 100644
index 0000000..c633aa1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -0,0 +1,283 @@
+/*
+ * 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.systemui.doze;
+
+import android.annotation.MainThread;
+import android.util.Log;
+import android.view.Display;
+
+import com.android.internal.util.Preconditions;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.util.Assert;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Orchestrates all things doze.
+ *
+ * DozeMachine implements a state machine that orchestrates how the UI and triggers work and
+ * interfaces with the power and screen states.
+ *
+ * During state transitions and in certain states, DozeMachine holds a wake lock.
+ */
+public class DozeMachine {
+
+    static final String TAG = "DozeMachine";
+    static final boolean DEBUG = DozeService.DEBUG;
+
+    enum State {
+        /** Default state. Transition to INITIALIZED to get Doze going. */
+        UNINITIALIZED,
+        /** Doze components are set up. Followed by transition to DOZE or DOZE_AOD. */
+        INITIALIZED,
+        /** Regular doze. Device is asleep and listening for pulse triggers. */
+        DOZE,
+        /** Always-on doze. Device is asleep, showing UI and listening for pulse triggers. */
+        DOZE_AOD,
+        /** Pulse has been requested. Device is awake and preparing UI */
+        DOZE_REQUEST_PULSE,
+        /** Pulse is showing. Device is awake and showing UI. */
+        DOZE_PULSING,
+        /** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */
+        DOZE_PULSE_DONE,
+        /** Doze is done. DozeService is finished. */
+        FINISH,
+    }
+
+    private final Service mDozeService;
+    private final DozeFactory.WakeLock mWakeLock;
+    private final DozeParameters mParams;
+    private Part[] mParts;
+
+    private final ArrayList<State> mQueuedRequests = new ArrayList<>();
+    private State mState = State.UNINITIALIZED;
+    private boolean mWakeLockHeldForCurrentState = false;
+
+    public DozeMachine(Service service, DozeParameters params, DozeFactory.WakeLock wakeLock) {
+        mDozeService = service;
+        mParams = params;
+        mWakeLock = wakeLock;
+    }
+
+    /** Initializes the set of {@link Part}s. Must be called exactly once after construction. */
+    public void setParts(Part[] parts) {
+        Preconditions.checkState(mParts == null);
+        mParts = parts;
+    }
+
+    /**
+     * Requests transitioning to {@code requestedState}.
+     *
+     * This can be called during a state transition, in which case it will be queued until all
+     * queued state transitions are done.
+     *
+     * A wake lock is held while the transition is happening.
+     *
+     * Note that {@link #transitionPolicy} can modify what state will be transitioned to.
+     */
+    @MainThread
+    public void requestState(State requestedState) {
+        Assert.isMainThread();
+        if (DEBUG) {
+            Log.i(TAG, "request: current=" + mState + " req=" + requestedState,
+                    new Throwable("here"));
+        }
+
+        boolean runNow = !isExecutingTransition();
+        mQueuedRequests.add(requestedState);
+        if (runNow) {
+            mWakeLock.acquire();
+            for (int i = 0; i < mQueuedRequests.size(); i++) {
+                // Transitions in Parts can call back into requestState, which will
+                // cause mQueuedRequests to grow.
+                transitionTo(mQueuedRequests.get(i));
+            }
+            mQueuedRequests.clear();
+            mWakeLock.release();
+        }
+    }
+
+    /**
+     * @return the current state.
+     *
+     * This must not be called during a transition.
+     */
+    @MainThread
+    public State getState() {
+        Assert.isMainThread();
+        Preconditions.checkState(!isExecutingTransition());
+        return mState;
+    }
+
+    private boolean isExecutingTransition() {
+        return !mQueuedRequests.isEmpty();
+    }
+
+    private void transitionTo(State requestedState) {
+        State newState = transitionPolicy(requestedState);
+
+        if (DEBUG) {
+            Log.i(TAG, "transition: old=" + mState + " req=" + requestedState + " new=" + newState);
+        }
+
+        if (newState == mState) {
+            return;
+        }
+
+        validateTransition(newState);
+
+        State oldState = mState;
+        mState = newState;
+
+        performTransitionOnComponents(oldState, newState);
+        updateScreenState(newState);
+        updateWakeLockState(newState);
+
+        resolveIntermediateState(newState);
+    }
+
+    private void performTransitionOnComponents(State oldState, State newState) {
+        for (Part p : mParts) {
+            p.transitionTo(oldState, newState);
+        }
+
+        switch (newState) {
+            case FINISH:
+                mDozeService.finish();
+                break;
+            default:
+        }
+    }
+
+    private void validateTransition(State newState) {
+        switch (mState) {
+            case FINISH:
+                Preconditions.checkState(newState == State.FINISH);
+                break;
+            case UNINITIALIZED:
+                Preconditions.checkState(newState == State.INITIALIZED);
+                break;
+        }
+        switch (newState) {
+            case UNINITIALIZED:
+                throw new IllegalArgumentException("can't go to UNINITIALIZED");
+            case INITIALIZED:
+                Preconditions.checkState(mState == State.UNINITIALIZED);
+                break;
+            case DOZE_PULSING:
+                Preconditions.checkState(mState == State.DOZE_REQUEST_PULSE);
+                break;
+            case DOZE_PULSE_DONE:
+                Preconditions.checkState(mState == State.DOZE_PULSING);
+                break;
+            default:
+                break;
+        }
+    }
+
+    private int screenPolicy(State newState) {
+        switch (newState) {
+            case UNINITIALIZED:
+            case INITIALIZED:
+            case DOZE:
+                return Display.STATE_OFF;
+            case DOZE_PULSING:
+            case DOZE_AOD:
+                return Display.STATE_DOZE; // TODO: use STATE_ON if appropriate.
+            default:
+                return Display.STATE_UNKNOWN;
+        }
+    }
+
+    private boolean wakeLockPolicy(State newState) {
+        switch (newState) {
+            case DOZE_REQUEST_PULSE:
+            case DOZE_PULSING:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private State transitionPolicy(State requestedState) {
+        if (mState == State.FINISH) {
+            return State.FINISH;
+        }
+        return requestedState;
+    }
+
+    private void updateWakeLockState(State newState) {
+        boolean newPolicy = wakeLockPolicy(newState);
+        if (mWakeLockHeldForCurrentState && !newPolicy) {
+            mWakeLock.release();
+        } else if (!mWakeLockHeldForCurrentState && newPolicy) {
+            mWakeLock.acquire();
+        }
+    }
+
+    private void updateScreenState(State newState) {
+        int state = screenPolicy(newState);
+        if (state != Display.STATE_UNKNOWN) {
+            mDozeService.setDozeScreenState(state);
+        }
+    }
+
+    private void resolveIntermediateState(State state) {
+        switch (state) {
+            case INITIALIZED:
+            case DOZE_PULSE_DONE:
+                transitionTo(mParams.getAlwaysOn()
+                        ? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE);
+                break;
+            default:
+                break;
+        }
+    }
+
+    /** Dumps the current state */
+    public void dump(PrintWriter pw) {
+        pw.print(" state="); pw.println(mState);
+        pw.print(" wakeLockHeldForCurrentState="); pw.println(mWakeLockHeldForCurrentState);
+        pw.println("Parts:");
+        for (Part p : mParts) {
+            p.dump(pw);
+        }
+    }
+
+    /** A part of the DozeMachine that needs to be notified about state changes. */
+    public interface Part {
+        /**
+         * Transition from {@code oldState} to {@code newState}.
+         *
+         * This method is guaranteed to only be called while a wake lock is held.
+         */
+        void transitionTo(State oldState, State newState);
+
+        /** Dump current state. For debugging only. */
+        default void dump(PrintWriter pw) {}
+    }
+
+    /** A wrapper interface for {@link android.service.dreams.DreamService} */
+    public interface Service {
+        /** Finish dreaming. */
+        void finish();
+
+        /** Request a display state. See {@link android.view.Display#STATE_DOZE}. */
+        void setDozeScreenState(int state);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 81dfafc..bb4ea2d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -11,16 +11,11 @@
  * 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
+ * limitations under the License.
  */
 
 package com.android.systemui.doze;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
-import com.android.systemui.statusbar.phone.DozeParameters;
-
 import android.annotation.AnyThread;
 import android.app.ActivityManager;
 import android.content.ContentResolver;
@@ -32,12 +27,17 @@
 import android.hardware.TriggerEventListener;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.PowerManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto;
+import com.android.systemui.statusbar.phone.DozeParameters;
+
+import java.io.PrintWriter;
 import java.util.List;
 
 public class DozeSensors {
@@ -53,14 +53,14 @@
     private final TriggerSensor mPickupSensor;
     private final DozeParameters mDozeParameters;
     private final AmbientDisplayConfiguration mConfig;
-    private final PowerManager.WakeLock mWakeLock;
+    private final DozeFactory.WakeLock mWakeLock;
     private final Callback mCallback;
 
     private final Handler mHandler = new Handler();
 
 
     public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters,
-            AmbientDisplayConfiguration config, PowerManager.WakeLock wakeLock, Callback callback) {
+            AmbientDisplayConfiguration config, DozeFactory.WakeLock wakeLock, Callback callback) {
         mContext = context;
         mSensorManager = sensorManager;
         mDozeParameters = dozeParameters;
@@ -144,6 +144,13 @@
         mPickupSensor.setDisabled(disable);
     }
 
+    /** Dump current state */
+    public void dump(PrintWriter pw) {
+        for (TriggerSensor s : mSensors) {
+            pw.print("Sensor: "); pw.println(s.toString());
+        }
+    }
+
     private class TriggerSensor extends TriggerEventListener {
         final Sensor mSensor;
         final boolean mConfigured;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 2bb1d6a..94cbdd4 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -16,468 +16,46 @@
 
 package com.android.systemui.doze;
 
-import android.app.AlarmManager;
-import android.app.UiModeManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.Handler;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.os.UserHandle;
 import android.service.dreams.DreamService;
 import android.util.Log;
-import android.view.Display;
-
-import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.systemui.SystemUIApplication;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.util.Assert;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
 
-public class DozeService extends DreamService implements DozeSensors.Callback {
+public class DozeService extends DreamService implements DozeMachine.Service {
     private static final String TAG = "DozeService";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private static final String ACTION_BASE = "com.android.systemui.doze";
-    private static final String PULSE_ACTION = ACTION_BASE + ".pulse";
-
-    /**
-     * If true, reregisters all trigger sensors when the screen turns off.
-     */
-    private static final boolean REREGISTER_ALL_SENSORS_ON_SCREEN_OFF = true;
-
-    private final String mTag = String.format(TAG + ".%08x", hashCode());
-    private final Context mContext = this;
-    private final DozeParameters mDozeParameters = new DozeParameters(mContext);
-    private final Handler mHandler = new Handler();
-
-    private DozeHost mHost;
-    private DozeSensors mDozeSensors;
-    private SensorManager mSensorManager;
-    private PowerManager mPowerManager;
-    private PowerManager.WakeLock mWakeLock;
-    private UiModeManager mUiModeManager;
-    private boolean mDreaming;
-    private boolean mPulsing;
-    private boolean mBroadcastReceiverRegistered;
-    private boolean mDisplayStateSupported;
-    private boolean mPowerSaveActive;
-    private boolean mCarMode;
-    private long mNotificationPulseTime;
-
-    private AmbientDisplayConfiguration mConfig;
-    private AlarmManager mAlarmManager;
+    private DozeMachine mDozeMachine;
 
     public DozeService() {
-        if (DEBUG) Log.d(mTag, "new DozeService()");
         setDebug(DEBUG);
     }
 
     @Override
-    protected void dumpOnHandler(FileDescriptor fd, PrintWriter pw, String[] args) {
-        super.dumpOnHandler(fd, pw, args);
-        pw.print("  mDreaming: "); pw.println(mDreaming);
-        pw.print("  mPulsing: "); pw.println(mPulsing);
-        pw.print("  mWakeLock: held="); pw.println(mWakeLock.isHeld());
-        pw.print("  mHost: "); pw.println(mHost);
-        pw.print("  mBroadcastReceiverRegistered: "); pw.println(mBroadcastReceiverRegistered);
-        pw.print("  mDisplayStateSupported: "); pw.println(mDisplayStateSupported);
-        pw.print("  mPowerSaveActive: "); pw.println(mPowerSaveActive);
-        pw.print("  mCarMode: "); pw.println(mCarMode);
-        pw.print("  mNotificationPulseTime: "); pw.println(
-                DozeLog.FORMAT.format(new Date(mNotificationPulseTime
-                        - SystemClock.elapsedRealtime() + System.currentTimeMillis())));
-        mDozeParameters.dump(pw);
-    }
-
-    @Override
     public void onCreate() {
-        if (DEBUG) Log.d(mTag, "onCreate");
         super.onCreate();
 
-        if (getApplication() instanceof SystemUIApplication) {
-            final SystemUIApplication app = (SystemUIApplication) getApplication();
-            mHost = app.getComponent(DozeHost.class);
-        }
-        if (mHost == null) Log.w(TAG, "No doze service host found.");
-
         setWindowless(true);
 
-        mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
-        mAlarmManager = (AlarmManager) mContext.getSystemService(AlarmManager.class);
-        mConfig = new AmbientDisplayConfiguration(mContext);
-        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
-        mWakeLock.setReferenceCounted(true);
-        mDisplayStateSupported = mDozeParameters.getDisplayStateSupported();
-        mUiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
-        turnDisplayOff();
-        mDozeSensors = new DozeSensors(mContext, mSensorManager, mDozeParameters,
-                mConfig, mWakeLock, this);
-    }
-
-    @Override
-    public void onAttachedToWindow() {
-        if (DEBUG) Log.d(mTag, "onAttachedToWindow");
-        super.onAttachedToWindow();
+        mDozeMachine = DozeFactory.assembleMachine(this);
     }
 
     @Override
     public void onDreamingStarted() {
         super.onDreamingStarted();
-
-        if (mHost == null) {
-            finish();
-            return;
-        }
-
-        mPowerSaveActive = mHost.isPowerSaveActive();
-        mCarMode = mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR;
-        if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze() + " mPowerSaveActive="
-                + mPowerSaveActive + " mCarMode=" + mCarMode);
-        if (mPowerSaveActive) {
-            finishToSavePower();
-            return;
-        }
-        if (mCarMode) {
-            finishForCarMode();
-            return;
-        }
-
-        mDreaming = true;
-        listenForPulseSignals(true);
-
-        // Ask the host to get things ready to start dozing.
-        // Once ready, we call startDozing() at which point the CPU may suspend
-        // and we will need to acquire a wakelock to do work.
-        mHost.startDozing(mWakeLock.wrap(() -> {
-            if (mDreaming) {
-                startDozing();
-
-                // From this point until onDreamingStopped we will need to hold a
-                // wakelock whenever we are doing work.  Note that we never call
-                // stopDozing because can we just keep dozing until the bitter end.
-            }
-        }));
-
-        if (mDozeParameters.getAlwaysOn()) {
-            mTimeTick.onAlarm();
-        }
+        mDozeMachine.requestState(DozeMachine.State.INITIALIZED);
+        startDozing();
     }
 
     @Override
     public void onDreamingStopped() {
-        if (DEBUG) Log.d(mTag, "onDreamingStopped isDozing=" + isDozing());
         super.onDreamingStopped();
-
-        if (mHost == null) {
-            return;
-        }
-
-        mDreaming = false;
-        listenForPulseSignals(false);
-
-        // Tell the host that it's over.
-        mHost.stopDozing();
-        mAlarmManager.cancel(mTimeTick);
-    }
-
-    private void requestPulse(final int reason) {
-        requestPulse(reason, false /* performedProxCheck */);
-    }
-
-    private void requestPulse(final int reason, boolean performedProxCheck) {
-        Assert.isMainThread();
-        if (mHost != null && mDreaming && !mPulsing) {
-            // Let the host know we want to pulse.  Wait for it to be ready, then
-            // turn the screen on.  When finished, turn the screen off again.
-            // Here we need a wakelock to stay awake until the pulse is finished.
-            mWakeLock.acquire();
-            mPulsing = true;
-            if (!mDozeParameters.getProxCheckBeforePulse()) {
-                // skip proximity check
-                continuePulsing(reason);
-                return;
-            }
-            final long start = SystemClock.uptimeMillis();
-            if (performedProxCheck) {
-                // the caller already performed a successful proximity check; we'll only do one to
-                // capture statistics, continue pulsing immediately.
-                continuePulsing(reason);
-            }
-            // perform a proximity check
-            new ProximityCheck() {
-                @Override
-                public void onProximityResult(int result) {
-                    final boolean isNear = result == RESULT_NEAR;
-                    final long end = SystemClock.uptimeMillis();
-                    DozeLog.traceProximityResult(mContext, isNear, end - start, reason);
-                    if (performedProxCheck) {
-                        // we already continued
-                        return;
-                    }
-                    // avoid pulsing in pockets
-                    if (isNear) {
-                        mPulsing = false;
-                        mWakeLock.release();
-                        return;
-                    }
-
-                    // not in-pocket, continue pulsing
-                    continuePulsing(reason);
-                }
-            }.check();
-        }
-    }
-
-    private void continuePulsing(int reason) {
-        if (mHost.isPulsingBlocked()) {
-            mPulsing = false;
-            mWakeLock.release();
-            return;
-        }
-        mHost.pulseWhileDozing(new DozeHost.PulseCallback() {
-            @Override
-            public void onPulseStarted() {
-                if (mPulsing && mDreaming) {
-                    turnDisplayOn();
-                }
-            }
-
-            @Override
-            public void onPulseFinished() {
-                if (mPulsing && mDreaming) {
-                    mPulsing = false;
-                    if (REREGISTER_ALL_SENSORS_ON_SCREEN_OFF) {
-                        mDozeSensors.reregisterAllSensors();
-                    }
-                    turnDisplayOff();
-                }
-                mWakeLock.release(); // needs to be unconditional to balance acquire
-            }
-        }, reason);
-    }
-
-    private void turnDisplayOff() {
-        if (DEBUG) Log.d(mTag, "Display off");
-        if (mDozeParameters.getAlwaysOn()) {
-            turnDisplayOn();
-        } else {
-            setDozeScreenState(Display.STATE_OFF);
-        }
-    }
-
-    private void turnDisplayOn() {
-        if (DEBUG) Log.d(mTag, "Display on");
-        setDozeScreenState(mDisplayStateSupported ? Display.STATE_DOZE : Display.STATE_ON);
-    }
-
-    private void finishToSavePower() {
-        Log.w(mTag, "Exiting ambient mode due to low power battery saver");
-        finish();
-    }
-
-    private void finishForCarMode() {
-        Log.w(mTag, "Exiting ambient mode, not allowed in car mode");
-        finish();
-    }
-
-    private void listenForPulseSignals(boolean listen) {
-        if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen);
-        mDozeSensors.setListening(listen);
-        listenForBroadcasts(listen);
-        listenForNotifications(listen);
-    }
-
-    private void listenForBroadcasts(boolean listen) {
-        if (listen) {
-            final IntentFilter filter = new IntentFilter(PULSE_ACTION);
-            filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
-            filter.addAction(Intent.ACTION_USER_SWITCHED);
-            mContext.registerReceiver(mBroadcastReceiver, filter);
-
-            mBroadcastReceiverRegistered = true;
-        } else {
-            if (mBroadcastReceiverRegistered) {
-                mContext.unregisterReceiver(mBroadcastReceiver);
-            }
-            mBroadcastReceiverRegistered = false;
-        }
-    }
-
-    private void listenForNotifications(boolean listen) {
-        if (listen) {
-            mHost.addCallback(mHostCallback);
-        } else {
-            mHost.removeCallback(mHostCallback);
-        }
-    }
-
-    private void requestNotificationPulse() {
-        if (DEBUG) Log.d(mTag, "requestNotificationPulse");
-        if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) return;
-        mNotificationPulseTime = SystemClock.elapsedRealtime();
-        requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
+        mDozeMachine.requestState(DozeMachine.State.FINISH);
     }
 
     @Override
-    public void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck) {
-        requestPulse(pulseReason, sensorPerformedProxCheck);
-
-        if (pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP) {
-            final long timeSinceNotification =
-                    SystemClock.elapsedRealtime() - mNotificationPulseTime;
-            final boolean withinVibrationThreshold =
-                    timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
-            DozeLog.tracePickupPulse(mContext, withinVibrationThreshold);
-        }
-
-    }
-
-    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (PULSE_ACTION.equals(intent.getAction())) {
-                if (DEBUG) Log.d(mTag, "Received pulse intent");
-                requestPulse(DozeLog.PULSE_REASON_INTENT);
-            }
-            if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
-                mCarMode = true;
-                if (mCarMode && mDreaming) {
-                    finishForCarMode();
-                }
-            }
-            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
-                mDozeSensors.onUserSwitched();
-            }
-        }
-    };
-
-    private AlarmManager.OnAlarmListener mTimeTick = new AlarmManager.OnAlarmListener() {
-        @Override
-        public void onAlarm() {
-            mHost.dozeTimeTick();
-
-            // Keep wakelock until a frame has been pushed.
-            mHandler.post(mWakeLock.wrap(()->{}));
-
-            Calendar calendar = GregorianCalendar.getInstance();
-            calendar.setTimeInMillis(System.currentTimeMillis());
-            calendar.set(Calendar.MILLISECOND, 0);
-            calendar.set(Calendar.SECOND, 0);
-            calendar.add(Calendar.MINUTE, 1);
-
-            long delta = calendar.getTimeInMillis() - System.currentTimeMillis();
-            mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                    SystemClock.elapsedRealtime() + delta, "doze_time_tick", mTimeTick, mHandler);
-        }
-    };
-
-    private final DozeHost.Callback mHostCallback = new DozeHost.Callback() {
-        @Override
-        public void onNewNotifications() {
-            if (DEBUG) Log.d(mTag, "onNewNotifications (noop)");
-            // noop for now
-        }
-
-        @Override
-        public void onBuzzBeepBlinked() {
-            if (DEBUG) Log.d(mTag, "onBuzzBeepBlinked");
-            requestNotificationPulse();
-        }
-
-        @Override
-        public void onNotificationLight(boolean on) {
-            if (DEBUG) Log.d(mTag, "onNotificationLight (noop) on=" + on);
-            // noop for now
-        }
-
-        @Override
-        public void onPowerSaveChanged(boolean active) {
-            mPowerSaveActive = active;
-            if (mPowerSaveActive && mDreaming) {
-                finishToSavePower();
-            }
-        }
-    };
-
-    private abstract class ProximityCheck implements SensorEventListener, Runnable {
-        private static final int TIMEOUT_DELAY_MS = 500;
-
-        protected static final int RESULT_UNKNOWN = 0;
-        protected static final int RESULT_NEAR = 1;
-        protected static final int RESULT_FAR = 2;
-
-        private final String mTag = DozeService.this.mTag + ".ProximityCheck";
-
-        private boolean mRegistered;
-        private boolean mFinished;
-        private float mMaxRange;
-
-        abstract public void onProximityResult(int result);
-
-        public void check() {
-            if (mFinished || mRegistered) return;
-            final Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
-            if (sensor == null) {
-                if (DEBUG) Log.d(mTag, "No sensor found");
-                finishWithResult(RESULT_UNKNOWN);
-                return;
-            }
-            mDozeSensors.setDisableSensorsInterferingWithProximity(true);
-
-            mMaxRange = sensor.getMaximumRange();
-            mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
-                    mHandler);
-            mHandler.postDelayed(this, TIMEOUT_DELAY_MS);
-            mRegistered = true;
-        }
-
-        @Override
-        public void onSensorChanged(SensorEvent event) {
-            if (event.values.length == 0) {
-                if (DEBUG) Log.d(mTag, "Event has no values!");
-                finishWithResult(RESULT_UNKNOWN);
-            } else {
-                if (DEBUG) Log.d(mTag, "Event: value=" + event.values[0] + " max=" + mMaxRange);
-                final boolean isNear = event.values[0] < mMaxRange;
-                finishWithResult(isNear ? RESULT_NEAR : RESULT_FAR);
-            }
-        }
-
-        @Override
-        public void run() {
-            if (DEBUG) Log.d(mTag, "No event received before timeout");
-            finishWithResult(RESULT_UNKNOWN);
-        }
-
-        private void finishWithResult(int result) {
-            if (mFinished) return;
-            if (mRegistered) {
-                mHandler.removeCallbacks(this);
-                mSensorManager.unregisterListener(this);
-                mDozeSensors.setDisableSensorsInterferingWithProximity(false);
-                mRegistered = false;
-            }
-            onProximityResult(result);
-            mFinished = true;
-        }
-
-        @Override
-        public void onAccuracyChanged(Sensor sensor, int accuracy) {
-            // noop
-        }
+    protected void dumpOnHandler(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mDozeMachine.dump(pw);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
new file mode 100644
index 0000000..9df8113
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -0,0 +1,329 @@
+/*
+ * 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.systemui.doze;
+
+import android.app.UiModeManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.text.format.Formatter;
+import android.util.Log;
+
+import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.internal.util.Preconditions;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.util.Assert;
+
+import java.io.PrintWriter;
+
+/**
+ * Handles triggers for ambient state changes.
+ */
+public class DozeTriggers implements DozeMachine.Part {
+
+    private static final String TAG = "DozeTriggers";
+
+    /** adb shell am broadcast -a com.android.systemui.doze.pulse com.android.systemui */
+    private static final String PULSE_ACTION = "com.android.systemui.doze.pulse";
+
+    private final Context mContext;
+    private final DozeMachine mMachine;
+    private final DozeSensors mDozeSensors;
+    private final DozeHost mDozeHost;
+    private final AmbientDisplayConfiguration mConfig;
+    private final DozeParameters mDozeParameters;
+    private final SensorManager mSensorManager;
+    private final Handler mHandler;
+    private final DozeFactory.WakeLock mWakeLock;
+    private final UiModeManager mUiModeManager;
+    private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
+
+    private long mNotificationPulseTime;
+    private boolean mPulsePending;
+
+
+    public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
+            AmbientDisplayConfiguration config,
+            DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
+            DozeFactory.WakeLock wakeLock) {
+        mContext = context;
+        mMachine = machine;
+        mDozeHost = dozeHost;
+        mConfig = config;
+        mDozeParameters = dozeParameters;
+        mSensorManager = sensorManager;
+        mHandler = handler;
+        mWakeLock = wakeLock;
+        mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters, config,
+                wakeLock, this::onSensor);
+        mUiModeManager = mContext.getSystemService(UiModeManager.class);
+    }
+
+    private void onNotification() {
+        if (DozeMachine.DEBUG) Log.d(TAG, "requestNotificationPulse");
+        mNotificationPulseTime = SystemClock.elapsedRealtime();
+        if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) return;
+        requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */);
+    }
+
+    private void onWhisper() {
+        requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */);
+    }
+
+    private void onSensor(int pulseReason, boolean sensorPerformedProxCheck) {
+        requestPulse(pulseReason, sensorPerformedProxCheck);
+
+        if (pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP) {
+            final long timeSinceNotification =
+                    SystemClock.elapsedRealtime() - mNotificationPulseTime;
+            final boolean withinVibrationThreshold =
+                    timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
+            DozeLog.tracePickupPulse(mContext, withinVibrationThreshold);
+        }
+    }
+
+    private void onCarMode() {
+        mMachine.requestState(DozeMachine.State.FINISH);
+    }
+
+    private void onPowerSave() {
+        mMachine.requestState(DozeMachine.State.FINISH);
+    }
+
+    @Override
+    public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+        switch (newState) {
+            case INITIALIZED:
+                mBroadcastReceiver.register(mContext);
+                mDozeHost.addCallback(mHostCallback);
+                checkTriggersAtInit();
+                break;
+            case DOZE:
+            case DOZE_AOD:
+                mDozeSensors.setListening(true);
+                if (oldState != DozeMachine.State.INITIALIZED) {
+                    mDozeSensors.reregisterAllSensors();
+                }
+                break;
+            case FINISH:
+                mBroadcastReceiver.unregister(mContext);
+                mDozeHost.removeCallback(mHostCallback);
+                mDozeSensors.setListening(false);
+                break;
+            default:
+        }
+    }
+
+    private void checkTriggersAtInit() {
+        if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) {
+            onCarMode();
+        }
+        if (mDozeHost.isPowerSaveActive()) {
+            onPowerSave();
+        }
+    }
+
+    private void requestPulse(final int reason, boolean performedProxCheck) {
+        Assert.isMainThread();
+        if (mPulsePending || !canPulse()) {
+            return;
+        }
+
+        mPulsePending = true;
+        if (!mDozeParameters.getProxCheckBeforePulse() || performedProxCheck) {
+            // skip proximity check
+            continuePulseRequest(reason);
+            return;
+        }
+
+        final long start = SystemClock.uptimeMillis();
+        new ProximityCheck() {
+            @Override
+            public void onProximityResult(int result) {
+                final long end = SystemClock.uptimeMillis();
+                DozeLog.traceProximityResult(mContext, result == RESULT_NEAR,
+                        end - start, reason);
+                if (performedProxCheck) {
+                    // we already continued
+                    return;
+                }
+                // avoid pulsing in pockets
+                if (result == RESULT_NEAR) {
+                    return;
+                }
+
+                // not in-pocket, continue pulsing
+                continuePulseRequest(reason);
+            }
+        }.check();
+    }
+
+    private boolean canPulse() {
+        return mMachine.getState() == DozeMachine.State.DOZE
+                || mMachine.getState() == DozeMachine.State.DOZE_AOD;
+    }
+
+    private void continuePulseRequest(int reason) {
+        mPulsePending = false;
+        if (mDozeHost.isPulsingBlocked() || !canPulse()) {
+            return;
+        }
+        mMachine.requestState(DozeMachine.State.DOZE_REQUEST_PULSE);
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.print(" notificationPulseTime=");
+        pw.println(Formatter.formatShortElapsedTime(mContext, mNotificationPulseTime));
+
+        pw.print(" pulsePending="); pw.println(mPulsePending);
+        pw.println("DozeSensors:");
+        mDozeSensors.dump(pw);
+    }
+
+    private abstract class ProximityCheck implements SensorEventListener, Runnable {
+        private static final int TIMEOUT_DELAY_MS = 500;
+
+        protected static final int RESULT_UNKNOWN = 0;
+        protected static final int RESULT_NEAR = 1;
+        protected static final int RESULT_FAR = 2;
+
+        private boolean mRegistered;
+        private boolean mFinished;
+        private float mMaxRange;
+
+        protected abstract void onProximityResult(int result);
+
+        public void check() {
+            Preconditions.checkState(!mFinished && !mRegistered);
+            final Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+            if (sensor == null) {
+                if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: No sensor found");
+                finishWithResult(RESULT_UNKNOWN);
+                return;
+            }
+            mDozeSensors.setDisableSensorsInterferingWithProximity(true);
+
+            mMaxRange = sensor.getMaximumRange();
+            mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
+                    mHandler);
+            mHandler.postDelayed(this, TIMEOUT_DELAY_MS);
+            mWakeLock.acquire();
+            mRegistered = true;
+        }
+
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            if (event.values.length == 0) {
+                if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: Event has no values!");
+                finishWithResult(RESULT_UNKNOWN);
+            } else {
+                if (DozeMachine.DEBUG) {
+                    Log.d(TAG, "ProxCheck: Event: value=" + event.values[0] + " max=" + mMaxRange);
+                }
+                final boolean isNear = event.values[0] < mMaxRange;
+                finishWithResult(isNear ? RESULT_NEAR : RESULT_FAR);
+            }
+        }
+
+        @Override
+        public void run() {
+            if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: No event received before timeout");
+            finishWithResult(RESULT_UNKNOWN);
+        }
+
+        private void finishWithResult(int result) {
+            if (mFinished) return;
+            boolean wasRegistered = mRegistered;
+            if (mRegistered) {
+                mHandler.removeCallbacks(this);
+                mSensorManager.unregisterListener(this);
+                mDozeSensors.setDisableSensorsInterferingWithProximity(false);
+                mRegistered = false;
+            }
+            onProximityResult(result);
+            if (wasRegistered) {
+                mWakeLock.release();
+            }
+            mFinished = true;
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+            // noop
+        }
+    }
+
+    private class TriggerReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (PULSE_ACTION.equals(intent.getAction())) {
+                if (DozeMachine.DEBUG) Log.d(TAG, "Received pulse intent");
+                requestPulse(DozeLog.PULSE_REASON_INTENT, false /* performedProxCheck */);
+            }
+            if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
+                onCarMode();
+            }
+            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
+                mDozeSensors.onUserSwitched();
+            }
+        }
+
+        public void register(Context context) {
+            IntentFilter filter = new IntentFilter(PULSE_ACTION);
+            filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
+            filter.addAction(Intent.ACTION_USER_SWITCHED);
+            context.registerReceiver(this, filter);
+        }
+
+        public void unregister(Context context) {
+            context.unregisterReceiver(this);
+        }
+    }
+
+    private DozeHost.Callback mHostCallback = new DozeHost.Callback() {
+        @Override
+        public void onNewNotifications() {
+        }
+
+        @Override
+        public void onBuzzBeepBlinked() {
+            onNotification();
+        }
+
+        @Override
+        public void onNotificationLight(boolean on) {
+
+        }
+
+        @Override
+        public void onPowerSaveChanged(boolean active) {
+            if (active) {
+                onPowerSave();
+            }
+        }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
new file mode 100644
index 0000000..95e49ce
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -0,0 +1,68 @@
+/*
+ * 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.systemui.doze;
+
+import android.content.Context;
+
+/**
+ * The policy controlling doze.
+ */
+public class DozeUi implements DozeMachine.Part {
+
+    private final Context mContext;
+    private final DozeHost mHost;
+    private DozeFactory.WakeLock mWakeLock;
+    private DozeMachine mMachine;
+
+    public DozeUi(Context context, DozeMachine machine, DozeFactory.WakeLock wakeLock,
+            DozeHost host) {
+        mContext = context;
+        mMachine = machine;
+        mWakeLock = wakeLock;
+        mHost = host;
+    }
+
+    private void pulseWhileDozing(int reason) {
+        mHost.pulseWhileDozing(
+                new DozeHost.PulseCallback() {
+                    @Override
+                    public void onPulseStarted() {
+                        mMachine.requestState(DozeMachine.State.DOZE_PULSING);
+                    }
+
+                    @Override
+                    public void onPulseFinished() {
+                        mMachine.requestState(DozeMachine.State.DOZE_PULSE_DONE);
+                    }
+                }, reason);
+    }
+
+    @Override
+    public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+        switch (newState) {
+            case DOZE_REQUEST_PULSE:
+                pulseWhileDozing(DozeLog.PULSE_REASON_NOTIFICATION /* TODO */);
+                break;
+            case INITIALIZED:
+                mHost.startDozing();
+                break;
+            case FINISH:
+                mHost.stopDozing();
+                break;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index f9a4f7c..7b8d27e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -34,6 +34,7 @@
     private IActivityManager mActivityManager;
     private IWindowManager mWindowManager;
 
+    private PipMenuActivityController mMenuController;
     private PipTouchHandler mTouchHandler;
 
     private PipManager() {}
@@ -46,7 +47,9 @@
         mActivityManager = ActivityManagerNative.getDefault();
         mWindowManager = WindowManagerGlobal.getWindowManagerService();
 
-        mTouchHandler = new PipTouchHandler(context, mActivityManager, mWindowManager);
+        mMenuController = new PipMenuActivityController(context, mActivityManager, mWindowManager);
+        mTouchHandler = new PipTouchHandler(context, mMenuController, mActivityManager,
+                mWindowManager);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
new file mode 100644
index 0000000..bfe5cff
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -0,0 +1,137 @@
+/*
+ * 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.systemui.pip.phone;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.View;
+import com.android.systemui.R;
+
+/**
+ * Translucent activity that gets started on top of a task in PIP to allow the user to control it.
+ */
+public class PipMenuActivity extends Activity {
+
+    private static final String TAG = "PipMenuActivity";
+
+    public static final int MESSAGE_FINISH_SELF = 2;
+
+    private static final long INITIAL_DISMISS_DELAY = 2000;
+    private static final long POST_INTERACTION_DISMISS_DELAY = 1500;
+
+    private Messenger mToControllerMessenger;
+    private Messenger mMessenger = new Messenger(new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_FINISH_SELF:
+                    finish();
+                    break;
+            }
+        }
+    });
+
+    private final Runnable mFinishRunnable = new Runnable() {
+        @Override
+        public void run() {
+            finish();
+        }
+    };
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Intent startingIntet = getIntent();
+        mToControllerMessenger = startingIntet.getParcelableExtra(
+                PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER);
+
+        setContentView(R.layout.pip_menu_activity);
+        findViewById(R.id.expand_pip).setOnClickListener((view) -> {
+            finish();
+            notifyExpandPip();
+        });
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        notifyActivityVisibility(true);
+        repostDelayedFinish(INITIAL_DISMISS_DELAY);
+    }
+
+    @Override
+    public void onUserInteraction() {
+        repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        finish();
+    }
+
+    @Override
+    public void finish() {
+        View v = getWindow().getDecorView();
+        v.removeCallbacks(mFinishRunnable);
+        notifyActivityVisibility(false);
+        super.finish();
+        overridePendingTransition(0, R.anim.forced_resizable_exit);
+    }
+
+    @Override
+    public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
+        // Do nothing
+    }
+
+    private void notifyActivityVisibility(boolean visible) {
+        Message m = Message.obtain();
+        m.what = PipMenuActivityController.MESSAGE_ACTIVITY_VISIBILITY_CHANGED;
+        m.arg1 = visible ? 1 : 0;
+        m.replyTo = visible ? mMessenger : null;
+        try {
+            mToControllerMessenger.send(m);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not notify controller of PIP menu visibility", e);
+        }
+    }
+
+    private void notifyExpandPip() {
+        Message m = Message.obtain();
+        m.what = PipMenuActivityController.MESSAGE_EXPAND_PIP;
+        try {
+            mToControllerMessenger.send(m);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not notify controller to expand PIP", e);
+        }
+    }
+
+    private void repostDelayedFinish(long delay) {
+        View v = getWindow().getDecorView();
+        v.removeCallbacks(mFinishRunnable);
+        v.postDelayed(mFinishRunnable, delay);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
new file mode 100644
index 0000000..d1bce0c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -0,0 +1,126 @@
+package com.android.systemui.pip.phone;
+
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.view.WindowManager.INPUT_CONSUMER_PIP;
+
+import android.app.ActivityManager.StackInfo;
+import android.app.ActivityOptions;
+import android.app.IActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.view.IWindowManager;
+
+import java.util.ArrayList;
+
+public class PipMenuActivityController {
+
+    private static final String TAG = "PipMenuActivityController";
+
+    public static final String EXTRA_CONTROLLER_MESSENGER = "messenger";
+    public static final int MESSAGE_ACTIVITY_VISIBILITY_CHANGED = 1;
+    public static final int MESSAGE_EXPAND_PIP = 3;
+
+    /**
+     * A listener interface to receive notification on changes in PIP.
+     */
+    public interface Listener {
+        /**
+         * Called when the PIP menu visibility changes.
+         */
+        void onPipMenuVisibilityChanged(boolean visible);
+    }
+
+    private Context mContext;
+    private IActivityManager mActivityManager;
+    private IWindowManager mWindowManager;
+    private ArrayList<Listener> mListeners = new ArrayList<>();
+
+    private Messenger mToActivityMessenger;
+    private Messenger mMessenger = new Messenger(new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_ACTIVITY_VISIBILITY_CHANGED: {
+                    boolean visible = msg.arg1 > 0;
+                    int listenerCount = mListeners.size();
+                    for (int i = 0; i < listenerCount; i++) {
+                        mListeners.get(i).onPipMenuVisibilityChanged(visible);
+                    }
+                    mToActivityMessenger = msg.replyTo;
+                    break;
+                }
+                case MESSAGE_EXPAND_PIP: {
+                    try {
+                        mActivityManager.resizeStack(PINNED_STACK_ID, null, true, true, true, 225);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Error showing PIP menu activity", e);
+                    }
+                    break;
+                }
+            }
+        }
+    });
+
+    public PipMenuActivityController(Context context, IActivityManager activityManager,
+            IWindowManager windowManager) {
+        mContext = context;
+        mActivityManager = activityManager;
+        mWindowManager = windowManager;
+    }
+
+    /**
+     * Adds a new menu activity listener.
+     */
+    public void addListener(Listener listener) {
+        if (!mListeners.contains(listener)) {
+            mListeners.add(listener);
+        }
+    }
+
+    /**
+     * Shows the menu activity.
+     */
+    public void showMenu() {
+        // Start the menu activity on the top task of the pinned stack
+        try {
+            StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+            if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
+                    pinnedStackInfo.taskIds.length > 0) {
+                Intent intent = new Intent(mContext, PipMenuActivity.class);
+                intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
+                ActivityOptions options = ActivityOptions.makeBasic();
+                options.setLaunchTaskId(
+                        pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
+                options.setTaskOverlay(true);
+                mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
+            } else {
+                Log.e(TAG, "No PIP tasks found");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error showing PIP menu activity", e);
+        }
+    }
+
+    /**
+     * Hides the menu activity.
+     */
+    public void hideMenu() {
+        if (mToActivityMessenger != null) {
+            Message m = Message.obtain();
+            m.what = PipMenuActivity.MESSAGE_FINISH_SELF;
+            try {
+                mToActivityMessenger.send(m);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Could not notify menu activity to finish", e);
+            }
+            mToActivityMessenger = null;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 7f2d415..a359380 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -32,6 +32,7 @@
 import android.content.Context;
 import android.graphics.PointF;
 import android.graphics.Rect;
+import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.util.Log;
@@ -61,6 +62,8 @@
 
     private static final String TUNER_KEY_SWIPE_TO_DISMISS = "pip_swipe_to_dismiss";
     private static final String TUNER_KEY_DRAG_TO_DISMISS = "pip_drag_to_dismiss";
+    private static final String TUNER_KEY_TAP_THROUGH = "pip_tap_through";
+    private static final String TUNER_KEY_SNAP_MODE_EDGE = "pip_snap_mode_edge";
 
     private static final int SNAP_STACK_DURATION = 225;
     private static final int DISMISS_STACK_DURATION = 375;
@@ -70,17 +73,20 @@
     private final IActivityManager mActivityManager;
     private final IWindowManager mWindowManager;
     private final ViewConfiguration mViewConfig;
-    private final InputChannel mInputChannel = new InputChannel();
     private final PinnedStackListener mPinnedStackListener = new PinnedStackListener();
+    private final PipMenuListener mMenuListener = new PipMenuListener();
     private IPinnedStackController mPinnedStackController;
 
-    private final PipInputEventReceiver mInputEventReceiver;
+    private PipInputEventReceiver mInputEventReceiver;
+    private PipMenuActivityController mMenuController;
     private PipDismissViewController mDismissViewController;
-    private PipSnapAlgorithm mSnapAlgorithm;
+    private final PipSnapAlgorithm mSnapAlgorithm;
     private PipMotionHelper mMotionHelper;
 
     private boolean mEnableSwipeToDismiss = true;
     private boolean mEnableDragToDismiss = true;
+    private boolean mEnableTapThrough = false;
+    private boolean mEnableSnapToEdge = false;
 
     private final Rect mPinnedStackBounds = new Rect();
     private final Rect mBoundedPinnedStackBounds = new Rect();
@@ -97,6 +103,7 @@
     private final PointF mLastTouch = new PointF();
     private boolean mIsDragging;
     private boolean mIsSwipingToDismiss;
+    private boolean mIsTappingThrough;
     private int mActivePointerId;
 
     private final FlingAnimationUtils mFlingAnimationUtils;
@@ -120,7 +127,7 @@
                 // To be implemented for input handling over Pip windows
                 if (event instanceof MotionEvent) {
                     MotionEvent ev = (MotionEvent) event;
-                    handleTouchEvent(ev);
+                    handled = handleTouchEvent(ev);
                 }
             } finally {
                 finishInputEvent(event, handled);
@@ -144,13 +151,26 @@
         }
     }
 
-    public PipTouchHandler(Context context, IActivityManager activityManager,
-            IWindowManager windowManager) {
+    /**
+     * A listener for the PIP menu activity.
+     */
+    private class PipMenuListener implements PipMenuActivityController.Listener {
+        @Override
+        public void onPipMenuVisibilityChanged(boolean visible) {
+            if (!visible) {
+                mIsTappingThrough = false;
+                registerInputConsumer();
+            } else {
+                unregisterInputConsumer();
+            }
+        }
+    }
+
+    public PipTouchHandler(Context context, PipMenuActivityController menuController,
+            IActivityManager activityManager, IWindowManager windowManager) {
 
         // Initialize the Pip input consumer
         try {
-            windowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
-            windowManager.createInputConsumer(INPUT_CONSUMER_PIP, mInputChannel);
             windowManager.registerPinnedStackListener(DEFAULT_DISPLAY, mPinnedStackListener);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to create PIP input consumer", e);
@@ -159,21 +179,29 @@
         mActivityManager = activityManager;
         mWindowManager = windowManager;
         mViewConfig = ViewConfiguration.get(context);
-        mInputEventReceiver = new PipInputEventReceiver(mInputChannel, Looper.myLooper());
-        if (mEnableDragToDismiss) {
-            mDismissViewController = new PipDismissViewController(context);
-        }
+        mMenuController = menuController;
+        mMenuController.addListener(mMenuListener);
+        mDismissViewController = new PipDismissViewController(context);
+        mSnapAlgorithm = new PipSnapAlgorithm(mContext);
         mFlingAnimationUtils = new FlingAnimationUtils(context, 2f);
         mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
+        registerInputConsumer();
 
         // Register any tuner settings changes
         TunerService.get(context).addTunable(this, TUNER_KEY_SWIPE_TO_DISMISS,
-            TUNER_KEY_DRAG_TO_DISMISS);
+            TUNER_KEY_DRAG_TO_DISMISS, TUNER_KEY_TAP_THROUGH, TUNER_KEY_SNAP_MODE_EDGE);
     }
 
     @Override
     public void onTuningChanged(String key, String newValue) {
         if (newValue == null) {
+            // Reset back to default
+            mEnableSwipeToDismiss = true;
+            mEnableDragToDismiss = true;
+            mEnableTapThrough = false;
+            mIsTappingThrough = false;
+            mEnableSnapToEdge = false;
+            setSnapToEdge(false);
             return;
         }
         switch (key) {
@@ -183,17 +211,26 @@
             case TUNER_KEY_DRAG_TO_DISMISS:
                 mEnableDragToDismiss = Integer.parseInt(newValue) != 0;
                 break;
+            case TUNER_KEY_TAP_THROUGH:
+                mEnableTapThrough = Integer.parseInt(newValue) != 0;
+                mIsTappingThrough = false;
+                break;
+            case TUNER_KEY_SNAP_MODE_EDGE:
+                mEnableSnapToEdge = Integer.parseInt(newValue) != 0;
+                setSnapToEdge(mEnableSnapToEdge);
+                break;
         }
     }
 
     public void onConfigurationChanged() {
-        updateBoundedPinnedStackBounds();
+        mSnapAlgorithm.onConfigurationChanged();
+        updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */);
     }
 
-    private void handleTouchEvent(MotionEvent ev) {
+    private boolean handleTouchEvent(MotionEvent ev) {
         // Skip touch handling until we are bound to the controller
         if (mPinnedStackController == null) {
-            return;
+            return true;
         }
 
         switch (ev.getAction()) {
@@ -203,7 +240,7 @@
                     mPinnedStackBoundsAnimator.cancel();
                 }
 
-                updateBoundedPinnedStackBounds();
+                updateBoundedPinnedStackBounds(true /* updatePinnedStackBounds */);
                 initOrResetVelocityTracker();
                 mVelocityTracker.addMovement(ev);
                 mActivePointerId = ev.getPointerId(0);
@@ -237,6 +274,8 @@
                     float movement = PointF.length(mDownTouch.x - x, mDownTouch.y - y);
                     if (movement > mViewConfig.getScaledTouchSlop()) {
                         mIsDragging = true;
+                        mIsTappingThrough = false;
+                        mMenuController.hideMenu();
                         if (mEnableSwipeToDismiss) {
                             // TODO: this check can have some buffer so that we only start swiping
                             //       after a significant move out of bounds
@@ -299,6 +338,10 @@
                 float velocityY = mVelocityTracker.getYVelocity();
                 float velocity = PointF.length(velocityX, velocityY);
 
+                // Update the movement bounds again if the state has changed since the user started
+                // dragging (ie. when the IME shows)
+                updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */);
+
                 if (mIsSwipingToDismiss) {
                     if (Math.abs(velocityX) > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
                         flingToDismiss(velocityX);
@@ -322,7 +365,14 @@
                         }
                     }
                 } else {
-                    expandPinnedStackToFullscreen();
+                    if (mEnableTapThrough) {
+                        if (!mIsTappingThrough) {
+                            mMenuController.showMenu();
+                            mIsTappingThrough = true;
+                        }
+                    } else {
+                        expandPinnedStackToFullscreen();
+                    }
                 }
                 if (mEnableDragToDismiss) {
                     mDismissViewController.destroyDismissTarget();
@@ -342,6 +392,7 @@
                 break;
             }
         }
+        return !mIsTappingThrough;
     }
 
     private void initOrResetVelocityTracker() {
@@ -360,6 +411,44 @@
     }
 
     /**
+     * Registers the input consumer.
+     */
+    private void registerInputConsumer() {
+        final InputChannel inputChannel = new InputChannel();
+        try {
+            mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
+            mWindowManager.createInputConsumer(INPUT_CONSUMER_PIP, inputChannel);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to create PIP input consumer", e);
+        }
+        mInputEventReceiver = new PipInputEventReceiver(inputChannel, Looper.myLooper());
+    }
+
+    /**
+     * Unregisters the input consumer.
+     */
+    private void unregisterInputConsumer() {
+        try {
+            mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to destroy PIP input consumer", e);
+        }
+        mInputEventReceiver.dispose();
+    }
+
+    /**
+     * Sets the snap-to-edge state.
+     */
+    private void setSnapToEdge(boolean snapToEdge) {
+        mSnapAlgorithm.setSnapToEdge(snapToEdge);
+        try {
+            mPinnedStackController.setSnapToEdge(snapToEdge);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not set snap mode to edge", e);
+        }
+    }
+
+    /**
      * Flings the PIP to the closest snap target.
      */
     private void flingToSnapTarget(float velocity, float velocityX, float velocityY) {
@@ -462,14 +551,15 @@
     /**
      * Updates the movement bounds of the pinned stack.
      */
-    private void updateBoundedPinnedStackBounds() {
+    private void updateBoundedPinnedStackBounds(boolean updatePinnedStackBounds) {
         try {
             StackInfo info = mActivityManager.getStackInfo(PINNED_STACK_ID);
             if (info != null) {
-                mPinnedStackBounds.set(info.bounds);
+                if (updatePinnedStackBounds) {
+                    mPinnedStackBounds.set(info.bounds);
+                }
                 mBoundedPinnedStackBounds.set(mWindowManager.getPictureInPictureMovementBounds(
                         info.displayId));
-                mSnapAlgorithm = new PipSnapAlgorithm(mContext);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Could not fetch PIP movement bounds.", e);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 484e008..dc68112 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -44,6 +44,9 @@
 import com.android.systemui.statusbar.phone.QSTileHost;
 import libcore.util.Objects;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+
 public class CustomTile extends QSTile<QSTile.State> implements TileChangeListener {
     public static final String PREFIX = "custom(";
 
@@ -171,7 +174,7 @@
         mIsShowingDialog = false;
         try {
             if (DEBUG) Log.d(TAG, "Removing token");
-            mWindowManager.removeWindowToken(mToken);
+            mWindowManager.removeWindowToken(mToken, DEFAULT_DISPLAY);
         } catch (RemoteException e) {
         }
     }
@@ -193,7 +196,7 @@
                 if (mIsTokenGranted && !mIsShowingDialog) {
                     try {
                         if (DEBUG) Log.d(TAG, "Removing token");
-                        mWindowManager.removeWindowToken(mToken);
+                        mWindowManager.removeWindowToken(mToken, DEFAULT_DISPLAY);
                     } catch (RemoteException e) {
                     }
                     mIsTokenGranted = false;
@@ -212,7 +215,7 @@
         if (mIsTokenGranted) {
             try {
                 if (DEBUG) Log.d(TAG, "Removing token");
-                mWindowManager.removeWindowToken(mToken);
+                mWindowManager.removeWindowToken(mToken, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
             }
         }
@@ -252,7 +255,7 @@
         }
         try {
             if (DEBUG) Log.d(TAG, "Adding token");
-            mWindowManager.addWindowToken(mToken, WindowManager.LayoutParams.TYPE_QS_DIALOG);
+            mWindowManager.addWindowToken(mToken, TYPE_QS_DIALOG, DEFAULT_DISPLAY);
             mIsTokenGranted = true;
         } catch (RemoteException e) {
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 3c245b4..e203c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -57,10 +57,13 @@
 import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.RecentsTaskLoader;
+import com.android.systemui.recents.grid.RecentsGridImpl;
 import com.android.systemui.recents.tv.RecentsTvImpl;
 import com.android.systemui.stackdivider.Divider;
 
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
 
 
 /**
@@ -77,6 +80,13 @@
     public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000;
     public final static int RECENTS_GROW_TARGET_INVALID = -1;
 
+    public final static Set<String> RECENTS_ACTIVITIES = new HashSet<>();
+    static {
+        RECENTS_ACTIVITIES.add(RecentsImpl.RECENTS_ACTIVITY);
+        RECENTS_ACTIVITIES.add(RecentsTvImpl.RECENTS_TV_ACTIVITY);
+        RECENTS_ACTIVITIES.add(RecentsGridImpl.RECENTS_MOSAIC_ACTIVITY);
+    }
+
     // Purely for experimentation
     private final static String RECENTS_OVERRIDE_SYSPROP_KEY = "persist.recents_override_pkg";
     private final static String ACTION_SHOW_RECENTS = "com.android.systemui.recents.ACTION_SHOW";
@@ -197,6 +207,8 @@
                 getSystemService(Context.UI_MODE_SERVICE);
         if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
             mImpl = new RecentsTvImpl(mContext);
+        } else if (SystemProperties.getBoolean("ro.recents.grid", false) == true) {
+            mImpl = new RecentsGridImpl(mContext);
         } else {
             mImpl = new RecentsImpl(mContext);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java b/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
new file mode 100644
index 0000000..96644b5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
@@ -0,0 +1,316 @@
+/*
+ * 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.systemui.recents.grid;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsActivity;
+import com.android.systemui.recents.RecentsActivityLaunchState;
+import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsImpl;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
+import com.android.systemui.recents.events.activity.HideRecentsEvent;
+import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
+import com.android.systemui.recents.events.activity.LaunchTaskEvent;
+import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
+import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
+import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
+import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
+import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
+import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
+import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.misc.Utilities;
+import com.android.systemui.recents.model.RecentsTaskLoadPlan;
+import com.android.systemui.recents.model.RecentsTaskLoader;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.views.TaskView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * The main grid recents activity started by the RecentsImpl.
+ */
+public class RecentsGridActivity extends Activity implements ViewTreeObserver.OnPreDrawListener {
+    private final static String TAG = "RecentsGridActivity";
+
+    private TaskStack mTaskStack;
+    private List<Task> mTasks = new ArrayList<>();
+    private List<View> mTaskViews = new ArrayList<>();
+    private FrameLayout mRecentsView;
+    private TextView mEmptyView;
+    private View mClearAllButton;
+    private int mDisplayOrientation = Configuration.ORIENTATION_UNDEFINED;
+    private Rect mDisplayRect = new Rect();
+    private LayoutInflater mInflater;
+    private boolean mTouchExplorationEnabled;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.recents_grid);
+        SystemServicesProxy ssp = Recents.getSystemServices();
+
+        mInflater = LayoutInflater.from(this);
+        mDisplayOrientation = Utilities.getAppConfiguration(this).orientation;
+        mDisplayRect = ssp.getDisplayRect();
+        mTouchExplorationEnabled = ssp.isTouchExplorationEnabled();
+
+        mRecentsView = (FrameLayout) findViewById(R.id.recents_view);
+        LinearLayout recentsContainer = (LinearLayout) findViewById(R.id.recents_container);
+        mEmptyView = (TextView) mInflater.inflate(R.layout.recents_empty, recentsContainer, false);
+        mClearAllButton = findViewById(R.id.button);
+
+        FrameLayout.LayoutParams emptyViewLayoutParams = new FrameLayout.LayoutParams(
+            FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
+        emptyViewLayoutParams.gravity = Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL;
+        mEmptyView.setLayoutParams(emptyViewLayoutParams);
+        mRecentsView.addView(mEmptyView);
+
+        mClearAllButton.setVisibility(View.VISIBLE);
+        LinearLayout.LayoutParams lp =
+                (LinearLayout.LayoutParams) mClearAllButton.getLayoutParams();
+        lp.gravity = Gravity.END;
+
+        mClearAllButton.setOnClickListener(v -> {
+            EventBus.getDefault().send(new DismissAllTaskViewsEvent());
+        });
+
+        mRecentsView.setOnClickListener(v -> {
+            EventBus.getDefault().send(new HideRecentsEvent(
+                    false /* triggeredFromAltTab */, false /* triggeredFromHomeKey */));
+        });
+
+        EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY);
+    }
+
+    private TaskView createView() {
+        return (TaskView) mInflater.inflate(R.layout.recents_task_view, mRecentsView, false);
+    }
+
+    private void clearTaskViews() {
+        for (View taskView : mTaskViews) {
+            ViewGroup parent = (ViewGroup) taskView.getParent();
+            if (parent != null) {
+                parent.removeView(taskView);
+            }
+        }
+        mTaskViews.clear();
+    }
+
+    private void updateControlVisibility() {
+        boolean empty = (mTasks.size() == 0);
+        mClearAllButton.setVisibility(empty ? View.INVISIBLE : View.VISIBLE);
+        mEmptyView.setVisibility(empty ? View.VISIBLE : View.INVISIBLE);
+        if (empty) {
+            mEmptyView.bringToFront();
+        }
+    }
+
+    private void updateRecentsTasks() {
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoadPlan plan = RecentsImpl.consumeInstanceLoadPlan();
+        if (plan == null) {
+            plan = loader.createLoadPlan(this);
+        }
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
+        if (!plan.hasTasks()) {
+            loader.preloadTasks(plan, -1, !launchState.launchedFromHome);
+        }
+        int numVisibleTasks = 9;
+        mTaskStack = plan.getTaskStack();
+        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
+        loadOpts.runningTaskId = launchState.launchedToTaskId;
+        loadOpts.numVisibleTasks = numVisibleTasks;
+        loadOpts.numVisibleTaskThumbnails = numVisibleTasks;
+        loader.loadTasks(this, plan, loadOpts);
+
+        List<Task> stackTasks = mTaskStack.getStackTasks();
+        Collections.reverse(stackTasks);
+        mTasks = stackTasks;
+
+        updateControlVisibility();
+
+        clearTaskViews();
+        for (int i = 0; i < mTasks.size(); i++) {
+            Task task = mTasks.get(i);
+            TaskView taskView = createView();
+            taskView.onTaskBound(task, mTouchExplorationEnabled, mDisplayOrientation, mDisplayRect);
+            Recents.getTaskLoader().loadTaskData(task);
+            taskView.setTouchEnabled(true);
+            // Show dismiss button right away.
+            taskView.startNoUserInteractionAnimation();
+            mTaskViews.add(taskView);
+        }
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
+        mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateRecentsTasks();
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        EventBus.getDefault().unregister(this);
+    }
+
+    @Override
+    public void onBackPressed() {
+        // Back behaves like the recents button so just trigger a toggle event.
+        EventBus.getDefault().send(new ToggleRecentsEvent());
+    }
+
+    @Override
+    public boolean onPreDraw() {
+        mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
+        int width = mRecentsView.getWidth();
+        int height = mRecentsView.getHeight();
+
+        List<Rect> rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
+            mTasks.size(), width, height, false /* allowLineOfThree */, 30 /* padding */);
+        for (int i = 0; i < rects.size(); i++) {
+            Rect rect = rects.get(i);
+            View taskView = mTaskViews.get(i);
+            taskView.setLayoutParams(new FrameLayout.LayoutParams(rect.width(), rect.height()));
+            taskView.setTranslationX(rect.left);
+            taskView.setTranslationY(rect.top);
+            mRecentsView.addView(taskView);
+        }
+        return true;
+    }
+
+    void dismissRecentsToHome() {
+        Intent startMain = new Intent(Intent.ACTION_MAIN);
+        startMain.addCategory(Intent.CATEGORY_HOME);
+        startActivity(startMain);
+    }
+
+    /**** EventBus events ****/
+
+    public final void onBusEvent(HideRecentsEvent event) {
+        if (event.triggeredFromAltTab) {
+            // Do nothing for now.
+        } else if (event.triggeredFromHomeKey) {
+            dismissRecentsToHome();
+        }
+    }
+
+    public final void onBusEvent(ToggleRecentsEvent event) {
+        // Always go back home for simplicity for now. If recents is entered from another app, this
+        // code will eventually need to go back to the original app.
+        dismissRecentsToHome();
+    }
+
+    public final void onBusEvent(DismissTaskViewEvent event) {
+        int taskIndex = mTaskViews.indexOf(event.taskView);
+        if (taskIndex != -1) {
+            mTasks.remove(taskIndex);
+            ((ViewGroup) event.taskView.getParent()).removeView(event.taskView);
+            mTaskViews.remove(taskIndex);
+            EventBus.getDefault().send(
+                    new TaskViewDismissedEvent(event.taskView.getTask(), event.taskView, null));
+        }
+    }
+
+    public final void onBusEvent(TaskViewDismissedEvent event) {
+        mRecentsView.announceForAccessibility(this.getString(
+            R.string.accessibility_recents_item_dismissed, event.task.title));
+        updateControlVisibility();
+
+        EventBus.getDefault().send(new DeleteTaskDataEvent(event.task));
+
+        MetricsLogger.action(this, MetricsEvent.OVERVIEW_DISMISS,
+                event.task.key.getComponent().toString());
+    }
+
+    public final void onBusEvent(DeleteTaskDataEvent event) {
+        // Remove any stored data from the loader.
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+        loader.deleteTaskData(event.task, false);
+
+        // Remove the task from activity manager.
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        ssp.removeTask(event.task.key.id);
+    }
+
+    public final void onBusEvent(final DismissAllTaskViewsEvent event) {
+        // Keep track of the tasks which will have their data removed.
+        ArrayList<Task> tasks = new ArrayList<>(mTaskStack.getStackTasks());
+        mRecentsView.announceForAccessibility(this.getString(
+                R.string.accessibility_recents_all_items_dismissed));
+        mTaskStack.removeAllTasks();
+        for (int i = tasks.size() - 1; i >= 0; i--) {
+            EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i)));
+        }
+        mTasks = new ArrayList<>();
+        updateRecentsTasks();
+
+        MetricsLogger.action(this, MetricsEvent.OVERVIEW_DISMISS_ALL);
+    }
+
+    public final void onBusEvent(AllTaskViewsDismissedEvent event) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (!ssp.hasDockedTask()) {
+            dismissRecentsToHome();
+        }
+    }
+
+    public final void onBusEvent(LaunchNextTaskRequestEvent event) {
+        // Always go back home for simplicity for now. Quick switch will be supported soon.
+        EventBus.getDefault().send(new HideRecentsEvent(false, true));
+    }
+
+    public final void onBusEvent(LaunchTaskEvent event) {
+        startActivity(event.task.key.baseIntent);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridImpl.java b/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridImpl.java
new file mode 100644
index 0000000..41acaa0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridImpl.java
@@ -0,0 +1,47 @@
+/*
+ * 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.systemui.recents.grid;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+
+import com.android.systemui.recents.RecentsImpl;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
+
+public class RecentsGridImpl extends RecentsImpl {
+    public static final String RECENTS_MOSAIC_ACTIVITY =
+            "com.android.systemui.recents.grid.RecentsGridActivity";
+
+    public RecentsGridImpl(Context context) {
+        super(context);
+    }
+
+    @Override
+    protected void startRecentsActivity(ActivityManager.RunningTaskInfo runningTask,
+            boolean isHomeStackVisible, boolean animate, int growTarget) {
+        Intent intent = new Intent();
+        intent.setClassName(RECENTS_PACKAGE, RECENTS_MOSAIC_ACTIVITY);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+                | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+
+        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+        EventBus.getDefault().send(new RecentsActivityStartingEvent());
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithm.java
new file mode 100644
index 0000000..057aa54
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithm.java
@@ -0,0 +1,109 @@
+/*
+ * 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.systemui.recents.grid;
+
+import android.graphics.Rect;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class TaskGridLayoutAlgorithm {
+
+    private static final String TAG = "TaskGridLayoutAlgorithm";
+
+    static List<Rect> getRectsForTaskCount(int count, int containerWidth, int containerHeight,
+            boolean allowLineOfThree, int padding) {
+        return getRectsForTaskCount(count, containerWidth, containerHeight, allowLineOfThree,
+                padding, null);
+    }
+
+    static List<Rect> getRectsForTaskCount(int count, int containerWidth, int containerHeight,
+            boolean allowLineOfThree, int padding, Rect preCalculatedTile) {
+        int singleLineMaxCount = allowLineOfThree ? 3 : 2;
+        List<Rect> rects = new ArrayList<>(count);
+        boolean landscape = (containerWidth > containerHeight);
+
+        // We support at most 9 tasks in this layout.
+        count = Math.min(count, 9);
+
+        if (count == 0) {
+            return rects;
+        }
+        if (count <= singleLineMaxCount) {
+            if (landscape) {
+                // Single line.
+                int taskWidth = 0;
+                int emptySpace = 0;
+                if (preCalculatedTile != null) {
+                    taskWidth = preCalculatedTile.width();
+                    emptySpace = containerWidth - (count * taskWidth) - (count - 1) * padding;
+                } else {
+                    // Divide available space in equal parts.
+                    taskWidth = (containerWidth - (count - 1) * padding) / count;
+                }
+                for (int i = 0; i < count; i++) {
+                    int left = emptySpace / 2 + i * taskWidth + i * padding;
+                    rects.add(new Rect(left, 0, left + taskWidth, containerHeight));
+                }
+            } else {
+                // Single column. Divide available space in equal parts.
+                int taskHeight = (containerHeight - (count - 1) * padding) / count;
+                for (int i = 0; i < count; i++) {
+                    int top = i * taskHeight + i * padding;
+                    rects.add(new Rect(0, top, containerWidth, top + taskHeight));
+                }
+            }
+        } else if (count < 7) {
+            // Two lines.
+            int lineHeight = (containerHeight - padding) / 2;
+            int lineTaskCount = (int) Math.ceil((double) count / 2);
+            List<Rect> rectsA = getRectsForTaskCount(
+                    lineTaskCount, containerWidth, lineHeight, true /* allowLineOfThree */, padding,
+                            null);
+            List<Rect> rectsB = getRectsForTaskCount(
+                    count - lineTaskCount, containerWidth, lineHeight, true /* allowLineOfThree */,
+                            padding, rectsA.get(0));
+            for (Rect rect : rectsB) {
+                rect.offset(0, lineHeight + padding);
+            }
+            rects.addAll(rectsA);
+            rects.addAll(rectsB);
+        } else {
+            // Three lines.
+            int lineHeight = (containerHeight - 2 * padding) / 3;
+            int lineTaskCount = (int) Math.ceil((double) count / 3);
+            List<Rect> rectsA = getRectsForTaskCount(
+                lineTaskCount, containerWidth, lineHeight, true /* allowLineOfThree */, padding, null);
+            List<Rect> rectsB = getRectsForTaskCount(
+                lineTaskCount, containerWidth, lineHeight, true /* allowLineOfThree */, padding,
+                        rectsA.get(0));
+            List<Rect> rectsC = getRectsForTaskCount(
+                count - (2 * lineTaskCount), containerWidth, lineHeight,
+                         true /* allowLineOfThree */, padding, rectsA.get(0));
+            for (Rect rect : rectsB) {
+                rect.offset(0, lineHeight + padding);
+            }
+            for (Rect rect : rectsC) {
+                rect.offset(0, 2 * (lineHeight + padding));
+            }
+            rects.addAll(rectsA);
+            rects.addAll(rectsB);
+            rects.addAll(rectsC);
+        }
+        return rects;
+    }
+}
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 c91b060..ea9714f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -81,10 +81,10 @@
 import com.android.systemui.R;
 import com.android.systemui.pip.tv.PipMenuActivity;
 import com.android.systemui.pip.tv.PipOnboardingActivity;
+import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.RecentsImpl;
 import com.android.systemui.recents.model.Task;
-import com.android.systemui.recents.tv.RecentsTvImpl;
 import com.android.systemui.recents.model.ThumbnailData;
 
 import java.io.IOException;
@@ -416,8 +416,7 @@
             }
             return (homeStackVisibleNotOccluded && topActivity != null
                     && topActivity.getPackageName().equals(RecentsImpl.RECENTS_PACKAGE)
-                    && (topActivity.getClassName().equals(RecentsImpl.RECENTS_ACTIVITY)
-                        || topActivity.getClassName().equals(RecentsTvImpl.RECENTS_TV_ACTIVITY)));
+                    && Recents.RECENTS_ACTIVITIES.contains(topActivity.getClassName()));
         } catch (RemoteException e) {
             e.printStackTrace();
         }
@@ -659,11 +658,9 @@
      * Sends a message to close other system windows.
      */
     public void sendCloseSystemWindows(String reason) {
-        if (ActivityManagerNative.isSystemReady()) {
-            try {
-                mIam.closeSystemDialogs(reason);
-            } catch (RemoteException e) {
-            }
+        try {
+            mIam.closeSystemDialogs(reason);
+        } catch (RemoteException e) {
         }
     }
 
@@ -1018,7 +1015,8 @@
         if (mIam == null) return;
 
         try {
-            mIam.startInPlaceAnimationOnFrontMostApplication(opts);
+            mIam.startInPlaceAnimationOnFrontMostApplication(
+                    opts == null ? null : opts.toBundle());
         } catch (Exception e) {
             e.printStackTrace();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 99d98bc..14f545e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -362,12 +362,12 @@
     }
 
     /** Enables/disables handling touch on this task view. */
-    void setTouchEnabled(boolean enabled) {
+    public void setTouchEnabled(boolean enabled) {
         setOnClickListener(enabled ? this : null);
     }
 
     /** Animates this task view if the user does not interact with the stack after a certain time. */
-    void startNoUserInteractionAnimation() {
+    public void startNoUserInteractionAnimation() {
         mHeaderView.startNoUserInteractionAnimation();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 70e21d6..23acb1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1320,11 +1320,9 @@
     }
 
     protected void sendCloseSystemWindows(String reason) {
-        if (ActivityManagerNative.isSystemReady()) {
-            try {
-                ActivityManagerNative.getDefault().closeSystemDialogs(reason);
-            } catch (RemoteException e) {
-            }
+        try {
+            ActivityManagerNative.getDefault().closeSystemDialogs(reason);
+        } catch (RemoteException e) {
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index b141454..01ffe01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -105,9 +105,7 @@
         // be invoked when we're done so that the caller can drop the pulse wakelock.
         mPulseCallback = callback;
         mPulseReason = reason;
-        if (mDozeParameters.getAlwaysOn()) {
-            mHandler.post(mPulseIn);
-        }
+        mHandler.post(mPulseIn);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 669a512..c33d91a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -5059,7 +5059,6 @@
         private static final long PROCESSING_TIME = 500;
 
         private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
-        private final H mHandler = new H();
 
         // Keeps the last reported state by fireNotificationLight.
         private boolean mNotificationLightOn;
@@ -5105,18 +5104,39 @@
         }
 
         @Override
-        public void startDozing(@NonNull Runnable ready) {
-            mHandler.obtainMessage(H.MSG_START_DOZING, ready).sendToTarget();
+        public void startDozing() {
+            if (!mDozingRequested) {
+                mDozingRequested = true;
+                DozeLog.traceDozing(mContext, mDozing);
+                updateDozing();
+            }
         }
 
         @Override
         public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) {
-            mHandler.obtainMessage(H.MSG_PULSE_WHILE_DOZING, reason, 0, callback).sendToTarget();
+            mDozeScrimController.pulse(new PulseCallback() {
+
+                @Override
+                public void onPulseStarted() {
+                    callback.onPulseStarted();
+                    mStackScroller.setPulsing(true);
+                }
+
+                @Override
+                public void onPulseFinished() {
+                    callback.onPulseFinished();
+                    mStackScroller.setPulsing(false);
+                }
+            }, reason);
         }
 
         @Override
         public void stopDozing() {
-            mHandler.obtainMessage(H.MSG_STOP_DOZING).sendToTarget();
+            if (mDozingRequested) {
+                mDozingRequested = false;
+                DozeLog.traceDozing(mContext, mDozing);
+                updateDozing();
+            }
         }
 
         @Override
@@ -5140,59 +5160,5 @@
             return mNotificationLightOn;
         }
 
-        private void handleStartDozing(@NonNull Runnable ready) {
-            if (!mDozingRequested) {
-                mDozingRequested = true;
-                DozeLog.traceDozing(mContext, mDozing);
-                updateDozing();
-            }
-            ready.run();
-        }
-
-        private void handlePulseWhileDozing(@NonNull PulseCallback callback, int reason) {
-            mDozeScrimController.pulse(new PulseCallback() {
-
-                @Override
-                public void onPulseStarted() {
-                    callback.onPulseStarted();
-                    mStackScroller.setPulsing(true);
-                }
-
-                @Override
-                public void onPulseFinished() {
-                    callback.onPulseFinished();
-                    mStackScroller.setPulsing(false);
-                }
-            }, reason);
-        }
-
-        private void handleStopDozing() {
-            if (mDozingRequested) {
-                mDozingRequested = false;
-                DozeLog.traceDozing(mContext, mDozing);
-                updateDozing();
-            }
-        }
-
-        private final class H extends Handler {
-            private static final int MSG_START_DOZING = 1;
-            private static final int MSG_PULSE_WHILE_DOZING = 2;
-            private static final int MSG_STOP_DOZING = 3;
-
-            @Override
-            public void handleMessage(Message msg) {
-                switch (msg.what) {
-                    case MSG_START_DOZING:
-                        handleStartDozing((Runnable) msg.obj);
-                        break;
-                    case MSG_PULSE_WHILE_DOZING:
-                        handlePulseWhileDozing((PulseCallback) msg.obj, msg.arg1);
-                        break;
-                    case MSG_STOP_DOZING:
-                        handleStopDozing();
-                        break;
-                }
-            }
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index d296498..f5c5e56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -48,7 +48,7 @@
 public class StatusBarKeyguardViewManager implements RemoteInputController.Callback {
 
     // When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
-    private static final long HIDE_TIMING_CORRECTION_MS = -3 * 16;
+    private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3;
 
     // Delay for showing the navigation bar when the bouncer appears. This should be kept in sync
     // with the appear animations of the PIN/pattern/password views.
@@ -396,7 +396,8 @@
                 if (endRunnable != null) {
                     endRunnable.run();
                 }
-                mStatusBarWindowManager.setKeyguardFadingAway(false);
+                mContainer.postDelayed(() -> mStatusBarWindowManager.setKeyguardFadingAway(false),
+                        100);
                 mPhoneStatusBar.finishKeyguardFadingAway();
                 mFingerprintUnlockController.finishKeyguardFadingAway();
                 WindowManagerGlobal.getInstance().trimMemory(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index a7a792b..4a2d5dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -137,8 +137,7 @@
 
     private void applyFocusableFlag(State state) {
         boolean panelFocusable = state.statusBarFocusable && state.panelExpanded;
-        if (state.keyguardShowing && state.keyguardNeedsInput && state.bouncerShowing
-                || BaseStatusBar.ENABLE_REMOTE_INPUT && state.remoteInputActive) {
+        if (state.bouncerShowing || BaseStatusBar.ENABLE_REMOTE_INPUT && state.remoteInputActive) {
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
new file mode 100644
index 0000000..ba7c923
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -0,0 +1,257 @@
+/*
+ * 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.systemui.doze;
+
+import static com.android.systemui.doze.DozeMachine.State.DOZE;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE;
+import static com.android.systemui.doze.DozeMachine.State.FINISH;
+import static com.android.systemui.doze.DozeMachine.State.INITIALIZED;
+import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Display;
+
+import com.android.systemui.statusbar.phone.DozeParameters;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DozeMachineTest {
+
+    DozeMachine mMachine;
+
+    private DozeServiceFake mServiceFake;
+    private WakeLockFake mWakeLockFake;
+    private DozeParameters mParamsMock;
+    private DozeMachine.Part mPartMock;
+
+    @Before
+    public void setUp() {
+        mServiceFake = new DozeServiceFake();
+        mWakeLockFake = new WakeLockFake();
+        mParamsMock = mock(DozeParameters.class);
+        mPartMock = mock(DozeMachine.Part.class);
+
+        mMachine = new DozeMachine(mServiceFake, mParamsMock, mWakeLockFake);
+
+        mMachine.setParts(new DozeMachine.Part[]{mPartMock});
+    }
+
+    @Test
+    @UiThreadTest
+    public void testInitialize_initializesParts() {
+        mMachine.requestState(INITIALIZED);
+
+        verify(mPartMock).transitionTo(UNINITIALIZED, INITIALIZED);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testInitialize_goesToDoze() {
+        when(mParamsMock.getAlwaysOn()).thenReturn(false);
+
+        mMachine.requestState(INITIALIZED);
+
+        verify(mPartMock).transitionTo(INITIALIZED, DOZE);
+        assertEquals(DOZE, mMachine.getState());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testInitialize_goesToAod() {
+        when(mParamsMock.getAlwaysOn()).thenReturn(true);
+
+        mMachine.requestState(INITIALIZED);
+
+        verify(mPartMock).transitionTo(INITIALIZED, DOZE_AOD);
+        assertEquals(DOZE_AOD, mMachine.getState());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testPulseDone_goesToDoze() {
+        when(mParamsMock.getAlwaysOn()).thenReturn(false);
+        mMachine.requestState(INITIALIZED);
+        mMachine.requestState(DOZE_REQUEST_PULSE);
+        mMachine.requestState(DOZE_PULSING);
+
+        mMachine.requestState(DOZE_PULSE_DONE);
+
+        verify(mPartMock).transitionTo(DOZE_PULSE_DONE, DOZE);
+        assertEquals(DOZE, mMachine.getState());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testPulseDone_goesToAoD() {
+        when(mParamsMock.getAlwaysOn()).thenReturn(true);
+        mMachine.requestState(INITIALIZED);
+        mMachine.requestState(DOZE_REQUEST_PULSE);
+        mMachine.requestState(DOZE_PULSING);
+
+        mMachine.requestState(DOZE_PULSE_DONE);
+
+        verify(mPartMock).transitionTo(DOZE_PULSE_DONE, DOZE_AOD);
+        assertEquals(DOZE_AOD, mMachine.getState());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testFinished_staysFinished() {
+        mMachine.requestState(INITIALIZED);
+        mMachine.requestState(FINISH);
+        reset(mPartMock);
+
+        mMachine.requestState(DOZE);
+
+        verify(mPartMock, never()).transitionTo(any(), any());
+        assertEquals(FINISH, mMachine.getState());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testFinish_finishesService() {
+        mMachine.requestState(INITIALIZED);
+
+        mMachine.requestState(FINISH);
+
+        assertTrue(mServiceFake.finished);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testWakeLock_heldInTransition() {
+        doAnswer((inv) -> {
+            assertTrue(mWakeLockFake.isHeld());
+            return null;
+        }).when(mPartMock).transitionTo(any(), any());
+
+        mMachine.requestState(INITIALIZED);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testWakeLock_heldInPulseStates() {
+        mMachine.requestState(INITIALIZED);
+
+        mMachine.requestState(DOZE_REQUEST_PULSE);
+        assertTrue(mWakeLockFake.isHeld());
+
+        mMachine.requestState(DOZE_PULSING);
+        assertTrue(mWakeLockFake.isHeld());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testWakeLock_notHeldInDozeStates() {
+        mMachine.requestState(INITIALIZED);
+
+        mMachine.requestState(DOZE);
+        assertFalse(mWakeLockFake.isHeld());
+
+        mMachine.requestState(DOZE_AOD);
+        assertFalse(mWakeLockFake.isHeld());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testScreen_offInDoze() {
+        mMachine.requestState(INITIALIZED);
+
+        mMachine.requestState(DOZE);
+
+        assertEquals(Display.STATE_OFF, mServiceFake.screenState);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testScreen_onInAod() {
+        mMachine.requestState(INITIALIZED);
+
+        mMachine.requestState(DOZE_AOD);
+
+        assertEquals(Display.STATE_DOZE, mServiceFake.screenState);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testScreen_onInPulse() {
+        mMachine.requestState(INITIALIZED);
+
+        mMachine.requestState(DOZE_REQUEST_PULSE);
+        mMachine.requestState(DOZE_PULSING);
+
+        assertEquals(Display.STATE_DOZE, mServiceFake.screenState);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testScreen_offInRequestPulseWithoutAoD() {
+        mMachine.requestState(INITIALIZED);
+
+        mMachine.requestState(DOZE);
+        mMachine.requestState(DOZE_REQUEST_PULSE);
+
+        assertEquals(Display.STATE_OFF, mServiceFake.screenState);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testScreen_onInRequestPulseWithoutAoD() {
+        mMachine.requestState(INITIALIZED);
+
+        mMachine.requestState(DOZE_AOD);
+        mMachine.requestState(DOZE_REQUEST_PULSE);
+
+        assertEquals(Display.STATE_DOZE, mServiceFake.screenState);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testTransitions_canRequestTransitions() {
+        mMachine.requestState(INITIALIZED);
+        mMachine.requestState(DOZE);
+        doAnswer(inv -> {
+            mMachine.requestState(DOZE_PULSING);
+            return null;
+        }).when(mPartMock).transitionTo(any(), eq(DOZE_REQUEST_PULSE));
+
+        mMachine.requestState(DOZE_REQUEST_PULSE);
+
+        assertEquals(DOZE_PULSING, mMachine.getState());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
new file mode 100644
index 0000000..d12fc2c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
@@ -0,0 +1,44 @@
+/*
+ * 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.systemui.doze;
+
+import android.view.Display;
+
+public class DozeServiceFake implements DozeMachine.Service {
+
+    public boolean finished;
+    public int screenState;
+
+    public DozeServiceFake() {
+        reset();
+    }
+
+    @Override
+    public void finish() {
+        finished = true;
+    }
+
+    @Override
+    public void setDozeScreenState(int state) {
+        screenState = state;
+    }
+
+    public void reset() {
+        finished = false;
+        screenState = Display.STATE_UNKNOWN;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/WakeLockFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/WakeLockFake.java
new file mode 100644
index 0000000..7c04fe2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/WakeLockFake.java
@@ -0,0 +1,55 @@
+/*
+ * 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.systemui.doze;
+
+import com.android.internal.util.Preconditions;
+
+public class WakeLockFake extends DozeFactory.WakeLock {
+
+    private int mAcquired = 0;
+
+    public WakeLockFake() {
+        super(null);
+    }
+
+    @Override
+    public void acquire() {
+        mAcquired++;
+    }
+
+    @Override
+    public void release() {
+        Preconditions.checkState(mAcquired > 0);
+        mAcquired--;
+    }
+
+    @Override
+    public Runnable wrap(Runnable runnable) {
+        acquire();
+        return () -> {
+            try {
+                runnable.run();
+            } finally {
+                release();
+            }
+        };
+    }
+
+    public boolean isHeld() {
+        return mAcquired > 0;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithmTest.java
new file mode 100644
index 0000000..74b6127
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithmTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.systemui.recents.grid;
+
+import android.graphics.Rect;
+import android.test.suitebuilder.annotation.SmallTest;
+import com.android.systemui.SysuiTestCase;
+
+import java.util.List;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+@SmallTest
+public class TaskGridLayoutAlgorithmTest extends SysuiTestCase {
+
+    public void testMethodName_ExpectedBehavior() {
+        assertTrue(true);
+    }
+
+    public void testOneTile() {
+        List<Rect> rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
+                1, 1000, 500, false /* allowLineOfThree */, 0 /* padding */);
+        assertEquals(1, rects.size());
+        Rect singleRect = rects.get(0);
+        assertEquals(1000, singleRect.width());
+    }
+
+    public void testTwoTilesLandscape() {
+        List<Rect> rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
+                2, 1200, 500, false /* allowLineOfThree */, 0 /* padding */);
+        assertEquals(2, rects.size());
+        for (Rect rect : rects) {
+            assertEquals(600, rect.width());
+            assertEquals(500, rect.height());
+        }
+    }
+
+    public void testTwoTilesLandscapeWithPadding() {
+        List<Rect> rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
+                2, 1200, 500, false /* allowLineOfThree */, 10 /* padding */);
+        assertEquals(2, rects.size());
+        Rect rectA = rects.get(0);
+        Rect rectB = rects.get(1);
+        assertEquals(595, rectA.width());
+        assertEquals(595, rectB.width());
+        assertEquals(605, rectB.left);
+    }
+
+    public void testTwoTilesPortrait() {
+        List<Rect> rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
+                2, 500, 1200, false /* allowLineOfThree */, 0 /* padding */);
+        assertEquals(2, rects.size());
+        for (Rect rect : rects) {
+            assertEquals(500, rect.width());
+            assertEquals(600, rect.height());
+        }
+    }
+
+    public void testThreeTiles() {
+        List<Rect> rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
+                3, 1200, 500, false /* allowLineOfThree */, 0 /* padding */);
+        assertEquals(3, rects.size());
+        for (Rect rect : rects) {
+            assertEquals(600, rect.width());
+            assertEquals(250, rect.height());
+        }
+        // The third tile should be on the second line, in the middle.
+        Rect rectC = rects.get(2);
+        assertEquals(300, rectC.left);
+        assertEquals(250, rectC.top);
+    }
+
+    public void testFourTiles() {
+        List<Rect> rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
+                4, 1200, 500, false /* allowLineOfThree */, 0 /* padding */);
+        assertEquals(4, rects.size());
+        for (Rect rect : rects) {
+            assertEquals(600, rect.width());
+            assertEquals(250, rect.height());
+        }
+        Rect rectD = rects.get(3);
+        assertEquals(600, rectD.left);
+        assertEquals(250, rectD.top);
+    }
+
+    public void testNineTiles() {
+        List<Rect> rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
+                9, 1200, 600, false /* allowLineOfThree */, 0 /* padding */);
+        assertEquals(9, rects.size());
+        for (Rect rect : rects) {
+            assertEquals(400, rect.width());
+            assertEquals(200, rect.height());
+        }
+        Rect rectE = rects.get(4);
+        assertEquals(400, rectE.left);
+        assertEquals(200, rectE.top);
+        Rect rectI = rects.get(8);
+        assertEquals(800, rectI.left);
+        assertEquals(400, rectI.top);
+    }}
+
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index ba0725e..48bc27e 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -689,6 +689,7 @@
     ACTION_WIFI_ADD_NETWORK = 134;
 
     // ACTION: Settings > Wi-Fi > [Long press network] > Connect to network
+    //   SUBTYPE: true if connecting to a saved network, false if not
     // CATEGORY: SETTINGS
     // OS: 6.0
     ACTION_WIFI_CONNECT = 135;
@@ -704,6 +705,7 @@
     ACTION_WIFI_FORGET = 137;
 
     // ACTION: Settings > Wi-Fi > Toggle off
+    //   SUBTYPE: true if connected to network before toggle, false if not
     // CATEGORY: SETTINGS
     // OS: 6.0
     ACTION_WIFI_OFF = 138;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 4819c0a..ab111a0 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -17,6 +17,8 @@
 package com.android.server.accessibility;
 
 import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 
 import android.Manifest;
 import android.accessibilityservice.AccessibilityService;
@@ -827,9 +829,10 @@
      * @param centerX the new screen-relative center X coordinate
      * @param centerY the new screen-relative center Y coordinate
      */
-    void notifyMagnificationChanged(@NonNull Region region,
+    public void notifyMagnificationChanged(@NonNull Region region,
             float scale, float centerX, float centerY) {
         synchronized (mLock) {
+            notifyClearAccessibilityCacheLocked();
             notifyMagnificationChangedLocked(region, scale, centerX, centerY);
         }
     }
@@ -899,10 +902,6 @@
         mSecurityPolicy.onTouchInteractionEnd();
     }
 
-    void onMagnificationStateChanged() {
-        notifyClearAccessibilityCacheLocked();
-    }
-
     private void switchUser(int userId) {
         synchronized (mLock) {
             if (mCurrentUserId == userId && mInitialized) {
@@ -2928,8 +2927,8 @@
                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
                     } return true;
                     case AccessibilityService.GLOBAL_ACTION_RECENTS: {
-                        openRecents();
-                    } return true;
+                        return openRecents();
+                    }
                     case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
                         expandNotifications();
                     } return true;
@@ -3129,7 +3128,7 @@
             final long identity = Binder.clearCallingIdentity();
             try {
                 mWindowManagerService.addWindowToken(mOverlayWindowToken,
-                        WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY);
+                        TYPE_ACCESSIBILITY_OVERLAY, DEFAULT_DISPLAY);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -3138,7 +3137,7 @@
         public void onRemoved() {
             final long identity = Binder.clearCallingIdentity();
             try {
-                mWindowManagerService.removeWindowToken(mOverlayWindowToken, true);
+                mWindowManagerService.removeWindowToken(mOverlayWindowToken, true, DEFAULT_DISPLAY);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -3422,14 +3421,19 @@
             Binder.restoreCallingIdentity(token);
         }
 
-        private void openRecents() {
+        private boolean openRecents() {
             final long token = Binder.clearCallingIdentity();
-
-            StatusBarManagerInternal statusBarService = LocalServices.getService(
-                    StatusBarManagerInternal.class);
-            statusBarService.toggleRecentApps();
-
-            Binder.restoreCallingIdentity(token);
+            try {
+                StatusBarManagerInternal statusBarService = LocalServices.getService(
+                        StatusBarManagerInternal.class);
+                if (statusBarService == null) {
+                    return false;
+                }
+                statusBarService.toggleRecentApps();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+            return true;
         }
 
         private void showGlobalActions() {
@@ -3668,7 +3672,7 @@
                     return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER;
                 }
 
-                case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: {
+                case TYPE_ACCESSIBILITY_OVERLAY: {
                     return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
                 }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index 7886b9e..f65046c 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -21,8 +21,6 @@
 import com.android.internal.os.SomeArgs;
 import com.android.server.LocalServices;
 
-import android.animation.ObjectAnimator;
-import android.animation.TypeEvaluator;
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.content.BroadcastReceiver;
@@ -34,12 +32,10 @@
 import android.graphics.Region;
 import android.os.AsyncTask;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.Message;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.MathUtils;
-import android.util.Property;
 import android.util.Slog;
 import android.view.MagnificationSpec;
 import android.view.View;
@@ -53,27 +49,29 @@
  * from the accessibility manager and related classes. It is responsible for
  * holding the current state of magnification and animation, and it handles
  * communication between the accessibility manager and window manager.
+ *
+ * Magnification is limited to the range [MIN_SCALE, MAX_SCALE], and can only occur inside the
+ * magnification region. If a value is out of bounds, it will be adjusted to guarantee these
+ * constraints.
  */
-class MagnificationController {
+class MagnificationController implements Handler.Callback {
     private static final String LOG_TAG = "MagnificationController";
 
-    private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false;
+    public static final float MIN_SCALE = 1.0f;
+    public static final float MAX_SCALE = 5.0f;
 
-    private static final int DEFAULT_SCREEN_MAGNIFICATION_AUTO_UPDATE = 1;
+    private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false;
 
     private static final int INVALID_ID = -1;
 
     private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
 
-    private static final float MIN_SCALE = 1.0f;
-    private static final float MAX_SCALE = 5.0f;
-
-    /**
-     * The minimum scaling factor that can be persisted to secure settings.
-     * This must be > 1.0 to ensure that magnification is actually set to an
-     * enabled state when the scaling factor is restored from settings.
-     */
-    private static final float MIN_PERSISTED_SCALE = 2.0f;
+    // Messages
+    private static final int MSG_SEND_SPEC_TO_ANIMATION = 1;
+    private static final int MSG_SCREEN_TURNED_OFF = 2;
+    private static final int MSG_ON_MAGNIFIED_BOUNDS_CHANGED = 3;
+    private static final int MSG_ON_RECTANGLE_ON_SCREEN_REQUESTED = 4;
+    private static final int MSG_ON_USER_CONTEXT_CHANGED = 5;
 
     private final Object mLock;
 
@@ -90,46 +88,95 @@
     private final Rect mTempRect1 = new Rect();
 
     private final AccessibilityManagerService mAms;
-    private final ContentResolver mContentResolver;
+
+    private final SettingsBridge mSettingsBridge;
 
     private final ScreenStateObserver mScreenStateObserver;
-    private final WindowStateObserver mWindowStateObserver;
 
     private final SpecAnimationBridge mSpecAnimationBridge;
 
+    private final WindowManagerInternal.MagnificationCallbacks mWMCallbacks =
+            new WindowManagerInternal.MagnificationCallbacks () {
+                @Override
+                public void onMagnificationRegionChanged(Region region) {
+                    final SomeArgs args = SomeArgs.obtain();
+                    args.arg1 = Region.obtain(region);
+                    mHandler.obtainMessage(MSG_ON_MAGNIFIED_BOUNDS_CHANGED, args).sendToTarget();
+                }
+
+                @Override
+                public void onRectangleOnScreenRequested(int left, int top, int right, int bottom) {
+                    final SomeArgs args = SomeArgs.obtain();
+                    args.argi1 = left;
+                    args.argi2 = top;
+                    args.argi3 = right;
+                    args.argi4 = bottom;
+                    mHandler.obtainMessage(MSG_ON_RECTANGLE_ON_SCREEN_REQUESTED, args)
+                            .sendToTarget();
+                }
+
+                @Override
+                public void onRotationChanged(int rotation) {
+                    // Treat as context change and reset
+                    mHandler.sendEmptyMessage(MSG_ON_USER_CONTEXT_CHANGED);
+                }
+
+                @Override
+                public void onUserContextChanged() {
+                    mHandler.sendEmptyMessage(MSG_ON_USER_CONTEXT_CHANGED);
+                }
+            };
+
     private int mUserId;
 
+    private final long mMainThreadId;
+
+    private Handler mHandler;
+
     private int mIdOfLastServiceToMagnify = INVALID_ID;
 
+    private final WindowManagerInternal mWindowManager;
+
     // Flag indicating that we are registered with window manager.
     private boolean mRegistered;
 
     private boolean mUnregisterPending;
 
     public MagnificationController(Context context, AccessibilityManagerService ams, Object lock) {
+        this(context, ams, lock, null, LocalServices.getService(WindowManagerInternal.class),
+                new ValueAnimator(), new SettingsBridge(context.getContentResolver()));
+        mHandler = new Handler(context.getMainLooper(), this);
+    }
+
+    public MagnificationController(Context context, AccessibilityManagerService ams, Object lock,
+            Handler handler, WindowManagerInternal windowManagerInternal,
+            ValueAnimator valueAnimator, SettingsBridge settingsBridge) {
+        mHandler = handler;
+        mWindowManager = windowManagerInternal;
+        mMainThreadId = context.getMainLooper().getThread().getId();
         mAms = ams;
-        mContentResolver = context.getContentResolver();
         mScreenStateObserver = new ScreenStateObserver(context, this);
-        mWindowStateObserver = new WindowStateObserver(context, this);
         mLock = lock;
-        mSpecAnimationBridge = new SpecAnimationBridge(context, mLock);
+        mSpecAnimationBridge = new SpecAnimationBridge(
+                context, mLock, mWindowManager, valueAnimator);
+        mSettingsBridge = settingsBridge;
     }
 
     /**
      * Start tracking the magnification region for services that control magnification and the
      * magnification gesture handler.
      *
-     * This tracking imposes a cost on the system, so we avoid tracking this data
-     * unless it's required.
+     * This tracking imposes a cost on the system, so we avoid tracking this data unless it's
+     * required.
      */
     public void register() {
         synchronized (mLock) {
             if (!mRegistered) {
                 mScreenStateObserver.register();
-                mWindowStateObserver.register();
+                mWindowManager.setMagnificationCallbacks(mWMCallbacks);
                 mSpecAnimationBridge.setEnabled(true);
                 // Obtain initial state.
-                mWindowStateObserver.getMagnificationRegion(mMagnificationRegion);
+                mWindowManager.getMagnificationRegion(mMagnificationRegion);
                 mMagnificationRegion.getBounds(mMagnificationBounds);
                 mRegistered = true;
             }
@@ -164,7 +211,7 @@
         if (mRegistered) {
             mSpecAnimationBridge.setEnabled(false);
             mScreenStateObserver.unregister();
-            mWindowStateObserver.unregister();
+            mWindowManager.setMagnificationCallbacks(null);
             mMagnificationRegion.setEmpty();
             mRegistered = false;
         }
@@ -183,40 +230,22 @@
      * Update our copy of the current magnification region
      *
      * @param magnified the magnified region
-     * @param updateSpec {@code true} to update the scale and center based on
-     *                   the region bounds, {@code false} to leave them as-is
      */
-    private void onMagnificationRegionChanged(Region magnified, boolean updateSpec) {
+    private void onMagnificationRegionChanged(Region magnified) {
         synchronized (mLock) {
             if (!mRegistered) {
                 // Don't update if we've unregistered
                 return;
             }
-            boolean magnificationChanged = false;
-            boolean boundsChanged = false;
-
             if (!mMagnificationRegion.equals(magnified)) {
                 mMagnificationRegion.set(magnified);
                 mMagnificationRegion.getBounds(mMagnificationBounds);
-                boundsChanged = true;
-            }
-            if (updateSpec) {
-                final MagnificationSpec sentSpec = mSpecAnimationBridge.mSentMagnificationSpec;
-                final float scale = sentSpec.scale;
-                final float offsetX = sentSpec.offsetX;
-                final float offsetY = sentSpec.offsetY;
-
-                // Compute the new center and update spec as needed.
-                final float centerX = (mMagnificationBounds.width() / 2.0f
-                        + mMagnificationBounds.left - offsetX) / scale;
-                final float centerY = (mMagnificationBounds.height() / 2.0f
-                        + mMagnificationBounds.top - offsetY) / scale;
-                magnificationChanged = setScaleAndCenterLocked(
-                        scale, centerX, centerY, false, INVALID_ID);
-            }
-
-            // If magnification changed we already notified for the change.
-            if (boundsChanged && updateSpec && !magnificationChanged) {
+                // It's possible that our magnification spec is invalid with the new bounds.
+                // Adjust the current spec's offsets if necessary.
+                if (updateCurrentSpecWithOffsetsLocked(
+                        mCurrentMagnificationSpec.offsetX, mCurrentMagnificationSpec.offsetY)) {
+                    sendSpecToAnimation(mCurrentMagnificationSpec, false);
+                }
                 onMagnificationChangedLocked();
             }
         }
@@ -328,7 +357,7 @@
      *
      * @return the scale currently used by the window manager
      */
-    public float getSentScale() {
+    private float getSentScale() {
         return mSpecAnimationBridge.mSentMagnificationSpec.scale;
     }
 
@@ -339,7 +368,7 @@
      *
      * @return the X offset currently used by the window manager
      */
-    public float getSentOffsetX() {
+    private float getSentOffsetX() {
         return mSpecAnimationBridge.mSentMagnificationSpec.offsetX;
     }
 
@@ -350,7 +379,7 @@
      *
      * @return the Y offset currently used by the window manager
      */
-    public float getSentOffsetY() {
+    private float getSentOffsetY() {
         return mSpecAnimationBridge.mSentMagnificationSpec.offsetY;
     }
 
@@ -380,7 +409,7 @@
             onMagnificationChangedLocked();
         }
         mIdOfLastServiceToMagnify = INVALID_ID;
-        mSpecAnimationBridge.updateSentSpec(spec, animate);
+        sendSpecToAnimation(spec, animate);
         return changed;
     }
 
@@ -475,7 +504,7 @@
     private boolean setScaleAndCenterLocked(float scale, float centerX, float centerY,
             boolean animate, int id) {
         final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
-        mSpecAnimationBridge.updateSentSpec(mCurrentMagnificationSpec, animate);
+        sendSpecToAnimation(mCurrentMagnificationSpec, animate);
         if (isMagnifying() && (id != INVALID_ID)) {
             mIdOfLastServiceToMagnify = id;
         }
@@ -483,27 +512,28 @@
     }
 
     /**
-     * Offsets the center of the magnified region.
+     * Offsets the magnified region. Note that the offsetX and offsetY values actually move in the
+     * opposite direction as the offsets passed in here.
      *
-     * @param offsetX the amount in pixels to offset the X center
-     * @param offsetY the amount in pixels to offset the Y center
+     * @param offsetX the amount in pixels to offset the region in the X direction, in current
+     * screen pixels.
+     * @param offsetY the amount in pixels to offset the region in the Y direction, in current
+     * screen pixels.
      * @param id the ID of the service requesting the change
      */
-    public void offsetMagnifiedRegionCenter(float offsetX, float offsetY, int id) {
+    public void offsetMagnifiedRegion(float offsetX, float offsetY, int id) {
         synchronized (mLock) {
             if (!mRegistered) {
                 return;
             }
 
-            final MagnificationSpec currSpec = mCurrentMagnificationSpec;
-            final float nonNormOffsetX = currSpec.offsetX - offsetX;
-            currSpec.offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
-            final float nonNormOffsetY = currSpec.offsetY - offsetY;
-            currSpec.offsetY = MathUtils.constrain(nonNormOffsetY, getMinOffsetYLocked(), 0);
+            final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
+            final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
+            updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY);
             if (id != INVALID_ID) {
                 mIdOfLastServiceToMagnify = id;
             }
-            mSpecAnimationBridge.updateSentSpec(currSpec, false);
+            sendSpecToAnimation(mCurrentMagnificationSpec, false);
         }
     }
 
@@ -517,7 +547,6 @@
     }
 
     private void onMagnificationChangedLocked() {
-        mAms.onMagnificationStateChanged();
         mAms.notifyMagnificationChanged(mMagnificationRegion,
                 getScale(), getCenterX(), getCenterY());
         if (mUnregisterPending && !isMagnifying()) {
@@ -535,8 +564,7 @@
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
-                Settings.Secure.putFloatForUser(mContentResolver,
-                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale, userId);
+                mSettingsBridge.putMagnificationScale(scale, userId);
                 return null;
             }
         }.execute();
@@ -550,9 +578,7 @@
      *         scale if none is available
      */
     public float getPersistedScale() {
-        return Settings.Secure.getFloatForUser(mContentResolver,
-                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
-                DEFAULT_MAGNIFICATION_SCALE, mUserId);
+        return mSettingsBridge.getMagnificationScale(mUserId);
     }
 
     /**
@@ -578,36 +604,20 @@
             scale = getScale();
         }
 
-        // Ensure requested center is within the magnification region.
-        if (!magnificationRegionContains(centerX, centerY)) {
-            return false;
-        }
-
         // Compute changes.
-        final MagnificationSpec currSpec = mCurrentMagnificationSpec;
         boolean changed = false;
 
         final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
-        if (Float.compare(currSpec.scale, normScale) != 0) {
-            currSpec.scale = normScale;
+        if (Float.compare(mCurrentMagnificationSpec.scale, normScale) != 0) {
+            mCurrentMagnificationSpec.scale = normScale;
             changed = true;
         }
 
         final float nonNormOffsetX = mMagnificationBounds.width() / 2.0f
-                + mMagnificationBounds.left - centerX * scale;
-        final float offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
-        if (Float.compare(currSpec.offsetX, offsetX) != 0) {
-            currSpec.offsetX = offsetX;
-            changed = true;
-        }
-
+                + mMagnificationBounds.left - centerX * normScale;
         final float nonNormOffsetY = mMagnificationBounds.height() / 2.0f
-                + mMagnificationBounds.top - centerY * scale;
-        final float offsetY = MathUtils.constrain(nonNormOffsetY, getMinOffsetYLocked(), 0);
-        if (Float.compare(currSpec.offsetY, offsetY) != 0) {
-            currSpec.offsetY = offsetY;
-            changed = true;
-        }
+                + mMagnificationBounds.top - centerY * normScale;
+        changed |= updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY);
 
         if (changed) {
             onMagnificationChangedLocked();
@@ -616,6 +626,21 @@
         return changed;
     }
 
+    private boolean updateCurrentSpecWithOffsetsLocked(float nonNormOffsetX, float nonNormOffsetY) {
+        boolean changed = false;
+        final float offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
+        if (Float.compare(mCurrentMagnificationSpec.offsetX, offsetX) != 0) {
+            mCurrentMagnificationSpec.offsetX = offsetX;
+            changed = true;
+        }
+        final float offsetY = MathUtils.constrain(nonNormOffsetY, getMinOffsetYLocked(), 0);
+        if (Float.compare(mCurrentMagnificationSpec.offsetY, offsetY) != 0) {
+            mCurrentMagnificationSpec.offsetY = offsetY;
+            changed = true;
+        }
+        return changed;
+    }
+
     private float getMinOffsetXLocked() {
         final float viewportWidth = mMagnificationBounds.width();
         return viewportWidth - viewportWidth * mCurrentMagnificationSpec.scale;
@@ -643,12 +668,6 @@
         }
     }
 
-    private boolean isScreenMagnificationAutoUpdateEnabled() {
-        return (Settings.Secure.getInt(mContentResolver,
-                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
-                DEFAULT_SCREEN_MAGNIFICATION_AUTO_UPDATE) == 1);
-    }
-
     /**
      * Resets magnification if magnification and auto-update are both enabled.
      *
@@ -658,7 +677,7 @@
      */
     boolean resetIfNeeded(boolean animate) {
         synchronized (mLock) {
-            if (isMagnifying() && isScreenMagnificationAutoUpdateEnabled()) {
+            if (isMagnifying()) {
                 reset(animate);
                 return true;
             }
@@ -715,18 +734,61 @@
             }
 
             final float scale = getScale();
-            offsetMagnifiedRegionCenter(scrollX * scale, scrollY * scale, INVALID_ID);
+            offsetMagnifiedRegion(scrollX * scale, scrollY * scale, INVALID_ID);
         }
     }
 
+    private void sendSpecToAnimation(MagnificationSpec spec, boolean animate) {
+        if (Thread.currentThread().getId() == mMainThreadId) {
+            mSpecAnimationBridge.updateSentSpecMainThread(spec, animate);
+        } else {
+            mHandler.obtainMessage(MSG_SEND_SPEC_TO_ANIMATION,
+                    animate ? 1 : 0, 0, spec).sendToTarget();
+        }
+    }
+
+    private void onScreenTurnedOff() {
+        mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_OFF);
+    }
+
+    public boolean handleMessage(Message msg) {
+        switch (msg.what) {
+            case MSG_SEND_SPEC_TO_ANIMATION:
+                final boolean animate = msg.arg1 == 1;
+                final MagnificationSpec spec = (MagnificationSpec) msg.obj;
+                mSpecAnimationBridge.updateSentSpecMainThread(spec, animate);
+                break;
+            case MSG_SCREEN_TURNED_OFF:
+                resetIfNeeded(false);
+                break;
+            case MSG_ON_MAGNIFIED_BOUNDS_CHANGED: {
+                final SomeArgs args = (SomeArgs) msg.obj;
+                final Region magnifiedBounds = (Region) args.arg1;
+                onMagnificationRegionChanged(magnifiedBounds);
+                magnifiedBounds.recycle();
+                args.recycle();
+            } break;
+            case MSG_ON_RECTANGLE_ON_SCREEN_REQUESTED: {
+                final SomeArgs args = (SomeArgs) msg.obj;
+                final int left = args.argi1;
+                final int top = args.argi2;
+                final int right = args.argi3;
+                final int bottom = args.argi4;
+                requestRectangleOnScreen(left, top, right, bottom);
+                args.recycle();
+            } break;
+            case MSG_ON_USER_CONTEXT_CHANGED:
+                resetIfNeeded(true);
+                break;
+        }
+        return true;
+    }
+
     /**
      * Class responsible for animating spec on the main thread and sending spec
      * updates to the window manager.
      */
-    private static class SpecAnimationBridge {
-        private static final int ACTION_UPDATE_SPEC = 1;
-
-        private final Handler mHandler;
+    private static class SpecAnimationBridge implements ValueAnimator.AnimatorUpdateListener {
         private final WindowManagerInternal mWindowManager;
 
         /**
@@ -735,34 +797,33 @@
          */
         private final MagnificationSpec mSentMagnificationSpec = MagnificationSpec.obtain();
 
-        /**
-         * The animator that updates the sent spec. This should only be accessed
-         * and modified on the main (e.g. animation) thread.
-         */
-        private final ValueAnimator mTransformationAnimator;
+        private final MagnificationSpec mStartMagnificationSpec = MagnificationSpec.obtain();
 
-        private final long mMainThreadId;
+        private final MagnificationSpec mEndMagnificationSpec = MagnificationSpec.obtain();
+
+        private final MagnificationSpec mTmpMagnificationSpec = MagnificationSpec.obtain();
+
+        /**
+         * The animator should only be accessed and modified on the main (e.g. animation) thread.
+         */
+        private final ValueAnimator mValueAnimator;
+
         private final Object mLock;
 
         @GuardedBy("mLock")
         private boolean mEnabled = false;
 
-        private SpecAnimationBridge(Context context, Object lock) {
+        private SpecAnimationBridge(Context context, Object lock, WindowManagerInternal wm,
+                ValueAnimator animator) {
             mLock = lock;
-            final Looper mainLooper = context.getMainLooper();
-            mMainThreadId = mainLooper.getThread().getId();
-
-            mHandler = new UpdateHandler(context);
-            mWindowManager = LocalServices.getService(WindowManagerInternal.class);
-
-            final MagnificationSpecProperty property = new MagnificationSpecProperty();
-            final MagnificationSpecEvaluator evaluator = new MagnificationSpecEvaluator();
+            mWindowManager = wm;
             final long animationDuration = context.getResources().getInteger(
                     R.integer.config_longAnimTime);
-            mTransformationAnimator = ObjectAnimator.ofObject(this, property, evaluator,
-                    mSentMagnificationSpec);
-            mTransformationAnimator.setDuration(animationDuration);
-            mTransformationAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
+            mValueAnimator = animator;
+            mValueAnimator.setDuration(animationDuration);
+            mValueAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
+            mValueAnimator.setFloatValues(0.0f, 1.0f);
+            mValueAnimator.addUpdateListener(this);
         }
 
         /**
@@ -781,22 +842,9 @@
             }
         }
 
-        public void updateSentSpec(MagnificationSpec spec, boolean animate) {
-            if (Thread.currentThread().getId() == mMainThreadId) {
-                // Already on the main thread, don't bother proxying.
-                updateSentSpecInternal(spec, animate);
-            } else {
-                mHandler.obtainMessage(ACTION_UPDATE_SPEC,
-                        animate ? 1 : 0, 0, spec).sendToTarget();
-            }
-        }
-
-        /**
-         * Updates the sent spec.
-         */
-        private void updateSentSpecInternal(MagnificationSpec spec, boolean animate) {
-            if (mTransformationAnimator.isRunning()) {
-                mTransformationAnimator.cancel();
+        public void updateSentSpecMainThread(MagnificationSpec spec, boolean animate) {
+            if (mValueAnimator.isRunning()) {
+                mValueAnimator.cancel();
             }
 
             // If the current and sent specs don't match, update the sent spec.
@@ -812,11 +860,6 @@
             }
         }
 
-        private void animateMagnificationSpecLocked(MagnificationSpec toSpec) {
-            mTransformationAnimator.setObjectValues(mSentMagnificationSpec, toSpec);
-            mTransformationAnimator.start();
-        }
-
         private void setMagnificationSpecLocked(MagnificationSpec spec) {
             if (mEnabled) {
                 if (DEBUG_SET_MAGNIFICATION_SPEC) {
@@ -828,71 +871,40 @@
             }
         }
 
-        private class UpdateHandler extends Handler {
-            public UpdateHandler(Context context) {
-                super(context.getMainLooper());
-            }
-
-            @Override
-            public void handleMessage(Message msg) {
-                switch (msg.what) {
-                    case ACTION_UPDATE_SPEC:
-                        final boolean animate = msg.arg1 == 1;
-                        final MagnificationSpec spec = (MagnificationSpec) msg.obj;
-                        updateSentSpecInternal(spec, animate);
-                        break;
-                }
-            }
+        private void animateMagnificationSpecLocked(MagnificationSpec toSpec) {
+            mEndMagnificationSpec.setTo(toSpec);
+            mStartMagnificationSpec.setTo(mSentMagnificationSpec);
+            mValueAnimator.start();
         }
 
-        private static class MagnificationSpecProperty
-                extends Property<SpecAnimationBridge, MagnificationSpec> {
-            public MagnificationSpecProperty() {
-                super(MagnificationSpec.class, "spec");
-            }
-
-            @Override
-            public MagnificationSpec get(SpecAnimationBridge object) {
-                synchronized (object.mLock) {
-                    return object.mSentMagnificationSpec;
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            synchronized (mLock) {
+                if (mEnabled) {
+                    float fract = animation.getAnimatedFraction();
+                    mTmpMagnificationSpec.scale = mStartMagnificationSpec.scale +
+                            (mEndMagnificationSpec.scale - mStartMagnificationSpec.scale) * fract;
+                    mTmpMagnificationSpec.offsetX = mStartMagnificationSpec.offsetX +
+                            (mEndMagnificationSpec.offsetX - mStartMagnificationSpec.offsetX)
+                                    * fract;
+                    mTmpMagnificationSpec.offsetY = mStartMagnificationSpec.offsetY +
+                            (mEndMagnificationSpec.offsetY - mStartMagnificationSpec.offsetY)
+                                    * fract;
+                    synchronized (mLock) {
+                        setMagnificationSpecLocked(mTmpMagnificationSpec);
+                    }
                 }
             }
-
-            @Override
-            public void set(SpecAnimationBridge object, MagnificationSpec value) {
-                synchronized (object.mLock) {
-                    object.setMagnificationSpecLocked(value);
-                }
-            }
-        }
-
-        private static class MagnificationSpecEvaluator
-                implements TypeEvaluator<MagnificationSpec> {
-            private final MagnificationSpec mTempSpec = MagnificationSpec.obtain();
-
-            @Override
-            public MagnificationSpec evaluate(float fraction, MagnificationSpec fromSpec,
-                    MagnificationSpec toSpec) {
-                final MagnificationSpec result = mTempSpec;
-                result.scale = fromSpec.scale + (toSpec.scale - fromSpec.scale) * fraction;
-                result.offsetX = fromSpec.offsetX + (toSpec.offsetX - fromSpec.offsetX) * fraction;
-                result.offsetY = fromSpec.offsetY + (toSpec.offsetY - fromSpec.offsetY) * fraction;
-                return result;
-            }
         }
     }
 
     private static class ScreenStateObserver extends BroadcastReceiver {
-        private static final int MESSAGE_ON_SCREEN_STATE_CHANGE = 1;
-
         private final Context mContext;
         private final MagnificationController mController;
-        private final Handler mHandler;
 
         public ScreenStateObserver(Context context, MagnificationController controller) {
             mContext = context;
             mController = controller;
-            mHandler = new StateChangeHandler(context);
         }
 
         public void register() {
@@ -905,151 +917,27 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
-            mHandler.obtainMessage(MESSAGE_ON_SCREEN_STATE_CHANGE,
-                    intent.getAction()).sendToTarget();
-        }
-
-        private void handleOnScreenStateChange() {
-            mController.resetIfNeeded(false);
-        }
-
-        private class StateChangeHandler extends Handler {
-            public StateChangeHandler(Context context) {
-                super(context.getMainLooper());
-            }
-
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MESSAGE_ON_SCREEN_STATE_CHANGE:
-                        handleOnScreenStateChange();
-                        break;
-                }
-            }
+            mController.onScreenTurnedOff();
         }
     }
 
-    /**
-     * This class handles the screen magnification when accessibility is enabled.
-     */
-    private static class WindowStateObserver
-            implements WindowManagerInternal.MagnificationCallbacks {
-        private static final int MESSAGE_ON_MAGNIFIED_BOUNDS_CHANGED = 1;
-        private static final int MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED = 2;
-        private static final int MESSAGE_ON_USER_CONTEXT_CHANGED = 3;
-        private static final int MESSAGE_ON_ROTATION_CHANGED = 4;
+    // Extra class to get settings so tests can mock it
+    public static class SettingsBridge {
+        private final ContentResolver mContentResolver;
 
-        private final MagnificationController mController;
-        private final WindowManagerInternal mWindowManager;
-        private final Handler mHandler;
-
-        private boolean mSpecIsDirty;
-
-        public WindowStateObserver(Context context, MagnificationController controller) {
-            mController = controller;
-            mWindowManager = LocalServices.getService(WindowManagerInternal.class);
-            mHandler = new CallbackHandler(context);
+        public SettingsBridge(ContentResolver contentResolver) {
+            mContentResolver = contentResolver;
         }
 
-        public void register() {
-            mWindowManager.setMagnificationCallbacks(this);
+        public void putMagnificationScale(float value, int userId) {
+            Settings.Secure.putFloatForUser(mContentResolver,
+                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, value, userId);
         }
 
-        public void unregister() {
-            mWindowManager.setMagnificationCallbacks(null);
-        }
-
-        @Override
-        public void onMagnificationRegionChanged(Region magnificationRegion) {
-            final SomeArgs args = SomeArgs.obtain();
-            args.arg1 = Region.obtain(magnificationRegion);
-            mHandler.obtainMessage(MESSAGE_ON_MAGNIFIED_BOUNDS_CHANGED, args).sendToTarget();
-        }
-
-        private void handleOnMagnifiedBoundsChanged(Region magnificationRegion) {
-            mController.onMagnificationRegionChanged(magnificationRegion, mSpecIsDirty);
-            mSpecIsDirty = false;
-        }
-
-        @Override
-        public void onRectangleOnScreenRequested(int left, int top, int right, int bottom) {
-            final SomeArgs args = SomeArgs.obtain();
-            args.argi1 = left;
-            args.argi2 = top;
-            args.argi3 = right;
-            args.argi4 = bottom;
-            mHandler.obtainMessage(MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED, args).sendToTarget();
-        }
-
-        private void handleOnRectangleOnScreenRequested(int left, int top, int right, int bottom) {
-            mController.requestRectangleOnScreen(left, top, right, bottom);
-        }
-
-        @Override
-        public void onRotationChanged(int rotation) {
-            mHandler.obtainMessage(MESSAGE_ON_ROTATION_CHANGED, rotation, 0).sendToTarget();
-        }
-
-        private void handleOnRotationChanged() {
-            // If there was a rotation and magnification is still enabled,
-            // we'll need to rewrite the spec to reflect the new screen
-            // configuration. Conveniently, we'll receive a callback from
-            // the window manager with updated bounds for the magnified
-            // region.
-            mSpecIsDirty = !mController.resetIfNeeded(true);
-        }
-
-        @Override
-        public void onUserContextChanged() {
-            mHandler.sendEmptyMessage(MESSAGE_ON_USER_CONTEXT_CHANGED);
-        }
-
-        private void handleOnUserContextChanged() {
-            mController.resetIfNeeded(true);
-        }
-
-        /**
-         * This method is used to get the magnification region in the tiny time slice between
-         * registering the callbacks and handling the message.
-         * TODO: Elimiante this extra path, perhaps by processing the message immediately
-         *
-         * @param outMagnificationRegion
-         */
-        public void getMagnificationRegion(@NonNull Region outMagnificationRegion) {
-            mWindowManager.getMagnificationRegion(outMagnificationRegion);
-        }
-
-        private class CallbackHandler extends Handler {
-            public CallbackHandler(Context context) {
-                super(context.getMainLooper());
-            }
-
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MESSAGE_ON_MAGNIFIED_BOUNDS_CHANGED: {
-                        final SomeArgs args = (SomeArgs) message.obj;
-                        final Region magnifiedBounds = (Region) args.arg1;
-                        handleOnMagnifiedBoundsChanged(magnifiedBounds);
-                        magnifiedBounds.recycle();
-                    } break;
-                    case MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED: {
-                        final SomeArgs args = (SomeArgs) message.obj;
-                        final int left = args.argi1;
-                        final int top = args.argi2;
-                        final int right = args.argi3;
-                        final int bottom = args.argi4;
-                        handleOnRectangleOnScreenRequested(left, top, right, bottom);
-                        args.recycle();
-                    } break;
-                    case MESSAGE_ON_USER_CONTEXT_CHANGED: {
-                        handleOnUserContextChanged();
-                    } break;
-                    case MESSAGE_ON_ROTATION_CHANGED: {
-                        handleOnRotationChanged();
-                    } break;
-                }
-            }
+        public float getMagnificationScale(int userId) {
+            return Settings.Secure.getFloatForUser(mContentResolver,
+                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+                    DEFAULT_MAGNIFICATION_SCALE, userId);
         }
     }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
index 39bc809..f6e5340 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
@@ -381,7 +381,7 @@
                 Slog.i(LOG_TAG, "Panned content by scrollX: " + distanceX
                         + " scrollY: " + distanceY);
             }
-            mMagnificationController.offsetMagnifiedRegionCenter(distanceX, distanceY,
+            mMagnificationController.offsetMagnifiedRegion(distanceX, distanceY,
                     AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
             return true;
         }
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 11586ee..88a8385 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -19,8 +19,9 @@
 LOCAL_JAVA_LIBRARIES := \
     services.net \
     telephony-common \
+    android.hardware.light@2.0-java \
     android.hardware.power@1.0-java \
-    android.hardware.light@2.0-java
+    android.hardware.tv.cec@1.0-java
 
 LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
 
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 20cca16..8e01e9e 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -938,7 +938,7 @@
 
         try {
             ActivityManagerNative.getDefault().registerUidObserver(new UidObserver(),
-                    ActivityManager.UID_OBSERVER_IDLE);
+                    ActivityManager.UID_OBSERVER_IDLE, null);
         } catch (RemoteException e) {
             // ignored; both services live in system_server
         }
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index d2cfb6d..b88a45e 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.app.ActivityManagerInternal;
 import android.database.ContentObserver;
 import android.os.BatteryStats;
 
@@ -148,6 +149,8 @@
 
     private boolean mSentLowBatteryBroadcast = false;
 
+    private ActivityManagerInternal mActivityManagerInternal;
+
     public BatteryService(Context context) {
         super(context);
 
@@ -155,6 +158,7 @@
         mHandler = new Handler(true /*async*/);
         mLed = new Led(context, getLocalService(LightsManager.class));
         mBatteryStats = BatteryStatsService.getService();
+        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
 
         mCriticalBatteryLevel = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_criticalBatteryWarningLevel);
@@ -279,7 +283,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    if (ActivityManagerNative.isSystemReady()) {
+                    if (mActivityManagerInternal.isSystemReady()) {
                         Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
                         intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
                         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -298,7 +302,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    if (ActivityManagerNative.isSystemReady()) {
+                    if (mActivityManagerInternal.isSystemReady()) {
                         Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
                         intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
                         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index df1b6f5..2698f95 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -15,6 +15,10 @@
 
 package com.android.server;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import com.android.internal.content.PackageMonitor;
@@ -44,6 +48,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
 import android.app.AppGlobals;
@@ -111,6 +116,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.Window;
 import android.view.WindowManager;
 import android.view.WindowManagerInternal;
 import android.view.inputmethod.EditorInfo;
@@ -466,6 +472,7 @@
 
     private AlertDialog.Builder mDialogBuilder;
     private AlertDialog mSwitchingDialog;
+    private IBinder mSwitchingDialogToken = new Binder();
     private View mSwitchingDialogTitleView;
     private Toast mSubtypeSwitchedByShortCutToast;
     private InputMethodInfo[] mIms;
@@ -1481,8 +1488,7 @@
             mCurToken = new Binder();
             try {
                 if (true || DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
-                mIWindowManager.addWindowToken(mCurToken,
-                        WindowManager.LayoutParams.TYPE_INPUT_METHOD);
+                mIWindowManager.addWindowToken(mCurToken, TYPE_INPUT_METHOD, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
             }
             return new InputBindResult(null, null, mCurId, mCurSeq,
@@ -1590,7 +1596,7 @@
                     // The current IME is shown. Hence an IME switch (transition) is happening.
                     mWindowManagerInternal.saveLastInputMethodWindowForTransition();
                 }
-                mIWindowManager.removeWindowToken(mCurToken);
+                mIWindowManager.removeWindowToken(mCurToken, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
             }
             mCurToken = null;
@@ -2050,7 +2056,7 @@
             // setSelectedInputMethodAndSubtypeLocked().
             mCurMethodId = id;
 
-            if (ActivityManagerNative.isSystemReady()) {
+            if (LocalServices.getService(ActivityManagerInternal.class).isSystemReady()) {
                 Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
                 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
                 intent.putExtra("input_method_id", id);
@@ -3287,11 +3293,16 @@
 
             mSwitchingDialog = mDialogBuilder.create();
             mSwitchingDialog.setCanceledOnTouchOutside(true);
-            mSwitchingDialog.getWindow().setType(
-                    WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
-            mSwitchingDialog.getWindow().getAttributes().privateFlags |=
-                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-            mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method");
+            final Window w = mSwitchingDialog.getWindow();
+            final WindowManager.LayoutParams attrs = w.getAttributes();
+            w.setType(TYPE_INPUT_METHOD_DIALOG);
+            // Use an alternate token for the dialog for that window manager can group the token
+            // with other IME windows based on type vs. grouping based on whichever token happens
+            // to get selected by the system later on.
+            attrs.token = mSwitchingDialogToken;
+            attrs.privateFlags |= PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            attrs.setTitle("Select input method");
+            w.setAttributes(attrs);
             updateSystemUi(mCurToken, mImeWindowVis, mBackDisposition);
             mSwitchingDialog.show();
         }
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 0cad814..a2207b2 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -585,6 +585,20 @@
                     Slog.e(TAG, "Unable to remove tied profile key", e);
                 }
             }
+
+            boolean isWatch = mContext.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_WATCH);
+            // Wear used to set DISABLE_LOCKSCREEN to 'true', but because Wear now allows accounts
+            // and device management the lockscreen must be re-enabled now for users that upgrade.
+            if (isWatch && getString("migrated_wear_lockscreen_disabled", null, 0) == null) {
+                final int userCount = users.size();
+                for (int i = 0; i < userCount; i++) {
+                    int id = users.get(i).id;
+                    setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
+                }
+                setString("migrated_wear_lockscreen_disabled", "true", 0);
+                Slog.i(TAG, "Migrated lockscreen_disabled for Wear devices");
+            }
         } catch (RemoteException re) {
             Slog.e(TAG, "Unable to migrate old data", re);
         }
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 8bb9326..8b7b6a0 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -201,6 +201,15 @@
     // Disable this since it messes up long-running cryptfs operations.
     private static final boolean WATCHDOG_ENABLE = false;
 
+    /**
+     * Our goal is for all Android devices to be usable as development devices,
+     * which includes the new Direct Boot mode added in N. For devices that
+     * don't have native FBE support, we offer an emulation mode for developer
+     * testing purposes, but if it's prohibitively difficult to support this
+     * mode, it can be disabled for specific products using this flag.
+     */
+    private static final boolean EMULATE_FBE_SUPPORTED = true;
+
     private static final String TAG = "MountService";
 
     private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
@@ -1978,9 +1987,13 @@
         waitForReady();
 
         if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
+            if (!EMULATE_FBE_SUPPORTED) {
+                throw new IllegalStateException(
+                        "Emulation not supported on this device");
+            }
             if (StorageManager.isFileEncryptedNativeOnly()) {
                 throw new IllegalStateException(
-                        "Emulation not available on device with native FBE");
+                        "Emulation not supported on device with native FBE");
             }
             if (mLockPatternUtils.isCredentialRequiredToDecrypt(false)) {
                 throw new IllegalStateException(
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5d41d36..2d6832d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16,8 +16,11 @@
 
 package com.android.server.am;
 
-import android.app.ApplicationThreadConstants;
 import android.annotation.Nullable;
+import android.app.ApplicationThreadConstants;
+import android.app.ContentProviderHolder;
+import android.app.IActivityManager;
+import android.app.WaitResult;
 import android.os.IDeviceIdentifiersPolicyService;
 import android.util.Size;
 import android.util.TypedValue;
@@ -81,7 +84,6 @@
 import android.app.ActivityManager.TaskThumbnailInfo;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerInternal.SleepToken;
-import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
 import android.app.AlertDialog;
@@ -381,7 +383,7 @@
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
-public class ActivityManagerService extends ActivityManagerNative
+public class ActivityManagerService extends IActivityManager.Stub
         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerService" : TAG_AM;
@@ -8867,12 +8869,12 @@
     // =========================================================
 
     @Override
-    public List<IAppTask> getAppTasks(String callingPackage) {
+    public List<IBinder> getAppTasks(String callingPackage) {
         int callingUid = Binder.getCallingUid();
         long ident = Binder.clearCallingIdentity();
 
         synchronized(this) {
-            ArrayList<IAppTask> list = new ArrayList<IAppTask>();
+            ArrayList<IBinder> list = new ArrayList<IBinder>();
             try {
                 if (DEBUG_ALL) Slog.v(TAG, "getAppTasks");
 
@@ -8893,7 +8895,7 @@
                     ActivityManager.RecentTaskInfo taskInfo =
                             createRecentTaskInfoFromTaskRecord(tr);
                     AppTaskImpl taskImpl = new AppTaskImpl(taskInfo.persistentId, callingUid);
-                    list.add(taskImpl);
+                    list.add(taskImpl.asBinder());
                 }
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -9345,16 +9347,17 @@
     }
 
     @Override
-    public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts)
+    public void startInPlaceAnimationOnFrontMostApplication(Bundle opts)
             throws RemoteException {
-        if (opts.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE ||
-                opts.getCustomInPlaceResId() == 0) {
+        final ActivityOptions activityOptions = ActivityOptions.fromBundle(opts);
+        if (activityOptions.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE ||
+                activityOptions.getCustomInPlaceResId() == 0) {
             throw new IllegalArgumentException("Expected in-place ActivityOption " +
                     "with valid animation");
         }
         mWindowManager.prepareAppTransition(TRANSIT_TASK_IN_PLACE, false);
-        mWindowManager.overridePendingAppTransitionInPlace(opts.getPackageName(),
-                opts.getCustomInPlaceResId());
+        mWindowManager.overridePendingAppTransitionInPlace(activityOptions.getPackageName(),
+                activityOptions.getCustomInPlaceResId());
         mWindowManager.executeAppTransition();
     }
 
@@ -9513,6 +9516,22 @@
     }
 
     @Override
+    public void moveStackToDisplay(int stackId, int displayId) {
+        enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveStackToDisplay()");
+
+        synchronized (this) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                if (DEBUG_STACK) Slog.d(TAG_STACK, "moveStackToDisplay: moving stackId=" + stackId
+                        + " to displayId=" + displayId);
+                mStackSupervisor.moveStackToDisplayLocked(stackId, displayId);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    @Override
     public boolean removeTask(int taskId) {
         enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS, "removeTask()");
         synchronized (this) {
@@ -10042,7 +10061,7 @@
     }
 
     @Override
-    public void startLockTaskMode(int taskId) {
+    public void startLockTaskModeById(int taskId) {
         synchronized (this) {
             final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
             if (task != null) {
@@ -10052,7 +10071,7 @@
     }
 
     @Override
-    public void startLockTaskMode(IBinder token) {
+    public void startLockTaskModeByToken(IBinder token) {
         synchronized (this) {
             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
             if (r == null) {
@@ -10072,7 +10091,7 @@
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
-                startLockTaskMode(taskId);
+                startLockTaskModeById(taskId);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -11392,9 +11411,10 @@
         }
     }
 
-    public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
+    public ParcelFileDescriptor openContentUri(String uriString) throws RemoteException {
         enforceNotIsolatedCaller("openContentUri");
         final int userId = UserHandle.getCallingUserId();
+        final Uri uri = Uri.parse(uriString);
         String name = uri.getAuthority();
         ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null, userId);
         ParcelFileDescriptor pfd = null;
@@ -12225,9 +12245,11 @@
     }
 
     @Override
-    public void registerUidObserver(IUidObserver observer, int which) {
-        enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
-                "registerUidObserver()");
+    public void registerUidObserver(IUidObserver observer, int which, String callingPackage) {
+        if (!hasUsageStatsPermission(callingPackage)) {
+            enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+                    "registerUidObserver");
+        }
         synchronized (this) {
             mUidObservers.register(observer, which);
         }
@@ -12263,7 +12285,7 @@
     }
 
     @Override
-    public boolean convertToTranslucent(IBinder token, ActivityOptions options) {
+    public boolean convertToTranslucent(IBinder token, Bundle options) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
@@ -12274,7 +12296,7 @@
                 int index = r.task.mActivities.lastIndexOf(r);
                 if (index > 0) {
                     ActivityRecord under = r.task.mActivities.get(index - 1);
-                    under.returningOptions = options;
+                    under.returningOptions = ActivityOptions.fromBundle(options);
                 }
                 final boolean translucentChanged = r.changeWindowTranslucency(false);
                 if (translucentChanged) {
@@ -12322,7 +12344,7 @@
     }
 
     @Override
-    public ActivityOptions getActivityOptions(IBinder token) {
+    public Bundle getActivityOptions(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
@@ -12330,7 +12352,7 @@
                 if (r != null) {
                     final ActivityOptions activityOptions = r.pendingOptions;
                     r.pendingOptions = null;
-                    return activityOptions;
+                    return activityOptions == null ? null : activityOptions.toBundle();
                 }
                 return null;
             }
@@ -12986,11 +13008,6 @@
         }
     }
 
-    public boolean testIsSystemReady() {
-        // no need to synchronize(this) just to read & return the value
-        return mSystemReady;
-    }
-
     public void systemReady(final Runnable goingCallback) {
         synchronized(this) {
             if (mSystemReady) {
@@ -13184,7 +13201,8 @@
      * @param app object of the crashing app, null for the system server
      * @param crashInfo describing the exception
      */
-    public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
+    public void handleApplicationCrash(IBinder app,
+            ApplicationErrorReport.ParcelableCrashInfo crashInfo) {
         ProcessRecord r = findAppProcess(app, "Crash");
         final String processName = app == null ? "system_server"
                 : (r == null ? "unknown" : r.processName);
@@ -13396,7 +13414,7 @@
      * @return true if the process should exit immediately (WTF is fatal)
      */
     public boolean handleApplicationWtf(final IBinder app, final String tag, boolean system,
-            final ApplicationErrorReport.CrashInfo crashInfo) {
+            final ApplicationErrorReport.ParcelableCrashInfo crashInfo) {
         final int callingUid = Binder.getCallingUid();
         final int callingPid = Binder.getCallingPid();
 
@@ -22053,6 +22071,12 @@
                 callback.run();
             }
         }
+
+        @Override
+        public boolean isSystemReady() {
+            // no need to synchronize(this) just to read & return the value
+            return mSystemReady;
+        }
     }
 
     private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 8234f35..abeea74 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -27,6 +27,7 @@
 import android.app.Instrumentation;
 import android.app.ProfilerInfo;
 import android.app.UiAutomationConnection;
+import android.app.WaitResult;
 import android.app.usage.ConfigurationStats;
 import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageStatsManager;
@@ -40,7 +41,9 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.content.res.AssetManager;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Rect;
 import android.os.Binder;
 import android.os.Build;
@@ -55,6 +58,7 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.DebugUtils;
+import android.util.DisplayMetrics;
 import android.view.IWindowManager;
 
 import com.android.internal.util.HexDump;
@@ -215,6 +219,8 @@
                     return runGetInactive(pw);
                 case "send-trim-memory":
                     return runSendTrimMemory(pw);
+                case "display":
+                    return runDisplay(pw);
                 case "stack":
                     return runStack(pw);
                 case "task":
@@ -223,6 +229,8 @@
                     return runWrite(pw);
                 case "attach-agent":
                     return runAttachAgent(pw);
+                case "supports-multiwindow":
+                    return runSupportsMultiwindow(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -342,7 +350,7 @@
             pw.flush();
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
-            IActivityManager.WaitResult result = null;
+            WaitResult result = null;
             int res;
             final long startTime = SystemClock.uptimeMillis();
             ActivityOptions options = null;
@@ -431,7 +439,7 @@
             out.flush();
             if (mWaitOption && launched) {
                 if (result == null) {
-                    result = new IActivityManager.WaitResult();
+                    result = new WaitResult();
                     result.who = intent.getComponent();
                 }
                 pw.println("Status: " + (result.timeout ? "timeout" : "ok"));
@@ -1631,12 +1639,23 @@
         return 0;
     }
 
+    int runDisplay(PrintWriter pw) throws RemoteException {
+        String op = getNextArgRequired();
+        switch (op) {
+            case "move-stack":
+                return runDisplayMoveStack(pw);
+            default:
+                getErrPrintWriter().println("Error: unknown command '" + op + "'");
+                return -1;
+        }
+    }
+
     int runStack(PrintWriter pw) throws RemoteException {
         String op = getNextArgRequired();
         switch (op) {
             case "start":
                 return runStackStart(pw);
-            case "movetask":
+            case "move-task":
                 return runStackMoveTask(pw);
             case "resize":
                 return runStackResize(pw);
@@ -1691,6 +1710,15 @@
         return new Rect(left, top, right, bottom);
     }
 
+    int runDisplayMoveStack(PrintWriter pw) throws RemoteException {
+        String stackIdStr = getNextArgRequired();
+        int stackId = Integer.parseInt(stackIdStr);
+        String displayIdStr = getNextArgRequired();
+        int displayId = Integer.parseInt(displayIdStr);
+        mInterface.moveStackToDisplay(stackId, displayId);
+        return 0;
+    }
+
     int runStackStart(PrintWriter pw) throws RemoteException {
         String displayIdStr = getNextArgRequired();
         int displayId = Integer.parseInt(displayIdStr);
@@ -1960,7 +1988,7 @@
             mInterface.stopLockTaskMode();
         } else {
             int taskId = Integer.parseInt(taskIdStr);
-            mInterface.startLockTaskMode(taskId);
+            mInterface.startLockTaskModeById(taskId);
         }
         pw.println("Activity manager is " + (mInterface.isInLockTaskMode() ? "" : "not ") +
                 "in lockTaskMode");
@@ -2262,6 +2290,23 @@
         return 0;
     }
 
+    int runSupportsMultiwindow(PrintWriter pw) throws RemoteException {
+        // system resources does not contain all the device configuration, construct it manually.
+        Configuration config = mInterface.getConfiguration();
+        if (config == null) {
+            pw.println("Error: Activity manager has no configuration");
+            return -1;
+        }
+
+        final DisplayMetrics metrics = new DisplayMetrics();
+        metrics.setToDefaults();
+
+        Resources res = new Resources(AssetManager.getSystem(), metrics, config);
+
+        pw.println(res.getBoolean(com.android.internal.R.bool.config_supportsMultiWindow));
+        return 0;
+    }
+
     @Override
     public void onHelp() {
         PrintWriter pw = getOutPrintWriter();
@@ -2441,6 +2486,8 @@
             pw.println("    Attach an agent to the specified <PROCESS>, which may be either a process name or a PID.");
             pw.println("  get-config");
             pw.println("      Rtrieve the configuration and any recent configurations of the device.");
+            pw.println("  supports-multiwindow");
+            pw.println("      Returns true if the device supports multiwindow.");
             pw.println("  suppress-resize-config-changes <true|false>");
             pw.println("      Suppresses configuration changes due to user resizing an activity/task.");
             pw.println("  set-inactive [--user <USER_ID>] <PACKAGE> true|false");
@@ -2450,10 +2497,13 @@
             pw.println("  send-trim-memory [--user <USER_ID>] <PROCESS>");
             pw.println("          [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]");
             pw.println("      Send a memory trim event to a <PROCESS>.");
+            pw.println("  display [COMMAND] [...]: sub-commands for operating on displays.");
+            pw.println("       move-stack <STACK_ID> <DISPLAY_ID>");
+            pw.println("           Move <STACK_ID> from its current display to <DISPLAY_ID>.");
             pw.println("  stack [COMMAND] [...]: sub-commands for operating on activity stacks.");
             pw.println("       start <DISPLAY_ID> <INTENT>");
             pw.println("           Start a new activity on <DISPLAY_ID> using <INTENT>");
-            pw.println("       movetask <TASK_ID> <STACK_ID> [true|false]");
+            pw.println("       move-task <TASK_ID> <STACK_ID> [true|false]");
             pw.println("           Move <TASK_ID> from its current stack to the top (true) or");
             pw.println("           bottom (false) of <STACK_ID>.");
             pw.println("       resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>");
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index ffe2185..0d79980 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -449,10 +449,23 @@
                 ? new LaunchingTaskPositioner() : null;
     }
 
-    void attachDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) {
+    /** Adds the stack to specified display and calls WindowManager to do the same. */
+    void addToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) {
+        final Rect bounds = mWindowManager.addStackToDisplay(mStackId, activityDisplay.mDisplayId,
+                onTop);
+        postAddToDisplay(activityDisplay, bounds);
+    }
+
+    /**
+     * Updates internal state after adding to new display.
+     * @param activityDisplay New display to which this stack was attached.
+     * @param bounds Updated bounds.
+     */
+    private void postAddToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay,
+            Rect bounds) {
         mDisplayId = activityDisplay.mDisplayId;
         mStacks = activityDisplay.mStacks;
-        mBounds = mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId, onTop);
+        mBounds = bounds;
         mFullscreen = mBounds == null;
         if (mTaskPositioner != null) {
             mTaskPositioner.setDisplay(activityDisplay.mDisplay);
@@ -468,7 +481,21 @@
         }
     }
 
-    void remove() {
+    /**
+     * Moves the stack to specified display.
+     * @param activityDisplay Target display to move the stack to.
+     */
+    void moveToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay) {
+        removeFromDisplay();
+        final Rect bounds = mWindowManager.moveStackToDisplay(mStackId, activityDisplay.mDisplayId);
+        postAddToDisplay(activityDisplay, bounds);
+    }
+
+    /**
+     * Updates the inner state of the stack to remove it from its current parent, so it can be
+     * either destroyed completely or re-parented.
+     */
+    private void removeFromDisplay() {
         mDisplayId = Display.INVALID_DISPLAY;
         mStacks = null;
         if (mTaskPositioner != null) {
@@ -480,6 +507,11 @@
             mStackSupervisor.resizeDockedStackLocked(
                     null, null, null, null, null, PRESERVE_WINDOWS);
         }
+    }
+
+    /** Removes the stack completely. Also calls WindowManager to do the same on its side. */
+    void remove() {
+        removeFromDisplay();
         mStackSupervisor.deleteActivityContainerRecord(mStackId);
         mWindowManager.removeStack(mStackId);
         onParentChanged();
@@ -696,11 +728,7 @@
         }
 
         mStacks.add(addIndex, this);
-
-        // TODO(multi-display): Needs to also work if focus is moving to the non-home display.
-        if (isOnHomeDisplay()) {
-            mStackSupervisor.setFocusStackUnchecked(reason, this);
-        }
+        mStackSupervisor.setFocusStackUnchecked(reason, this);
         if (task != null) {
             insertTaskAtTop(task, null);
             return;
@@ -3714,7 +3742,7 @@
         r.state = ActivityState.DESTROYED;
         if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
         r.app = null;
-        mWindowManager.removeAppToken(r.appToken);
+        mWindowManager.removeAppToken(r.appToken, r.getDisplayId());
         final TaskRecord task = r.task;
         if (task != null && task.removeActivity(r)) {
             if (DEBUG_STACK) Slog.i(TAG_STACK,
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index eed8dd7..8bb0e1a 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -100,11 +100,10 @@
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.IActivityContainerCallback;
-import android.app.IActivityManager;
-import android.app.IActivityManager.WaitResult;
 import android.app.ProfilerInfo;
 import android.app.ResultInfo;
 import android.app.StatusBarManager;
+import android.app.WaitResult;
 import android.app.admin.IDevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -317,10 +316,10 @@
     final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<>();
 
     /** List of processes waiting to find out about the next visible activity. */
-    final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible = new ArrayList<>();
+    final ArrayList<WaitResult> mWaitingActivityVisible = new ArrayList<>();
 
     /** List of processes waiting to find out about the next launched activity. */
-    final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched = new ArrayList<>();
+    final ArrayList<WaitResult> mWaitingActivityLaunched = new ArrayList<>();
 
     /** List of activities that are ready to be stopped, but waiting for the next activity to
      * settle down before doing so. */
@@ -2300,7 +2299,7 @@
 
         ActivityContainer activityContainer = new ActivityContainer(stackId);
         mActivityContainers.put(stackId, activityContainer);
-        activityContainer.attachToDisplayLocked(activityDisplay, onTop);
+        activityContainer.addToDisplayLocked(activityDisplay, onTop);
         return activityContainer.mStack;
     }
 
@@ -2364,6 +2363,40 @@
     }
 
     /**
+     * Move stack with all its existing content to specified display.
+     * @param stackId Id of stack to move.
+     * @param displayId Id of display to move stack to.
+     */
+    void moveStackToDisplayLocked(int stackId, int displayId) {
+        final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+        if (activityDisplay == null) {
+            throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown displayId="
+                    + displayId);
+        }
+        final ActivityContainer activityContainer = mActivityContainers.get(stackId);
+        if (activityContainer != null) {
+            if (activityContainer.isAttachedLocked()) {
+                if (activityContainer.getDisplayId() == displayId) {
+                    throw new IllegalArgumentException("Trying to move stackId=" + stackId
+                            + " to its current displayId=" + displayId);
+                }
+
+                activityContainer.moveToDisplayLocked(activityDisplay);
+            } else {
+                throw new IllegalStateException("moveStackToDisplayLocked: Stack with stackId="
+                        + stackId + " is not attached to any display.");
+            }
+        } else {
+            throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown stackId="
+                    + stackId);
+        }
+
+        ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
+                !PRESERVE_WINDOWS);
+        // TODO(multi-display): resize stacks properly if moved from split-screen.
+    }
+
+    /**
      * Moves the specified task record to the input stack id.
      * WARNING: This method performs an unchecked/raw move of the task and
      * can leave the system in an unstable state if used incorrectly.
@@ -4032,22 +4065,33 @@
             }
         }
 
-        void attachToDisplayLocked(ActivityDisplay activityDisplay, boolean onTop) {
-            if (DEBUG_STACK) Slog.d(TAG_STACK, "attachToDisplayLocked: " + this
+        /**
+         * Adds the stack to specified display. Also calls WindowManager to do the same from
+         * {@link ActivityStack#addToDisplay(ActivityDisplay, boolean)}.
+         * @param activityDisplay The display to add the stack to.
+         * @param onTop If true the stack will be place at the top of the display, else at the
+         *              bottom.
+         */
+        void addToDisplayLocked(ActivityDisplay activityDisplay, boolean onTop) {
+            if (DEBUG_STACK) Slog.d(TAG_STACK, "addToDisplayLocked: " + this
                     + " to display=" + activityDisplay + " onTop=" + onTop);
+            if (mActivityDisplay != null) {
+                throw new IllegalStateException("ActivityContainer is already attached, " +
+                        "displayId=" + mActivityDisplay.mDisplayId);
+            }
             mActivityDisplay = activityDisplay;
-            mStack.attachDisplay(activityDisplay, onTop);
+            mStack.addToDisplay(activityDisplay, onTop);
             activityDisplay.attachActivities(mStack, onTop);
         }
 
         @Override
-        public void attachToDisplay(int displayId) {
+        public void addToDisplay(int displayId) {
             synchronized (mService) {
                 ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
                 if (activityDisplay == null) {
                     return;
                 }
-                attachToDisplayLocked(activityDisplay, true);
+                addToDisplayLocked(activityDisplay, true);
             }
         }
 
@@ -4103,16 +4147,44 @@
             }
         }
 
+        /** Remove the stack completely. */
         void removeLocked() {
             if (DEBUG_STACK) Slog.d(TAG_STACK, "removeLocked: " + this + " from display="
                     + mActivityDisplay + " Callers=" + Debug.getCallers(2));
             if (mActivityDisplay != null) {
-                mActivityDisplay.detachActivitiesLocked(mStack);
-                mActivityDisplay = null;
+                removeFromDisplayLocked();
             }
             mStack.remove();
         }
 
+        /**
+         * Remove the stack from its current {@link ActivityDisplay}, so it can be either destroyed
+         * completely or re-parented.
+         */
+        private void removeFromDisplayLocked() {
+            if (DEBUG_STACK) Slog.d(TAG_STACK, "removeFromDisplayLocked: " + this
+                    + " current displayId=" + mActivityDisplay.mDisplayId);
+
+            mActivityDisplay.detachActivitiesLocked(mStack);
+            mActivityDisplay = null;
+        }
+
+        /**
+         * Move the stack to specified display.
+         * @param activityDisplay Target display to move the stack to.
+         */
+        void moveToDisplayLocked(ActivityDisplay activityDisplay) {
+            if (DEBUG_STACK) Slog.d(TAG_STACK, "moveToDisplayLocked: " + this + " from display="
+                    + mActivityDisplay + " to display=" + activityDisplay
+                    + " Callers=" + Debug.getCallers(2));
+
+            removeFromDisplayLocked();
+
+            mActivityDisplay = activityDisplay;
+            mStack.moveToDisplay(activityDisplay);
+            activityDisplay.attachActivities(mStack, ON_TOP);
+        }
+
         @Override
         public final int startActivity(Intent intent) {
             return mService.startActivity(intent, this);
@@ -4232,7 +4304,7 @@
                         new VirtualActivityDisplay(width, height, density);
                 mActivityDisplay = virtualActivityDisplay;
                 mActivityDisplays.put(virtualActivityDisplay.mDisplayId, virtualActivityDisplay);
-                attachToDisplayLocked(virtualActivityDisplay, true);
+                addToDisplayLocked(virtualActivityDisplay, true);
             }
 
             if (mSurface != null) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index db73048..e4ec169 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -81,11 +81,11 @@
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
 import android.app.IActivityContainer;
-import android.app.IActivityManager;
 import android.app.IApplicationThread;
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
 import android.app.ProfilerInfo;
+import android.app.WaitResult;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.IIntentSender;
@@ -707,7 +707,7 @@
             String callingPackage, Intent intent, String resolvedType,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
             IBinder resultTo, String resultWho, int requestCode, int startFlags,
-            ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult,
+            ProfilerInfo profilerInfo, WaitResult outResult,
             Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
             IActivityContainer iContainer, TaskRecord inTask) {
         // Refuse possible leaked file descriptors
diff --git a/services/core/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java
index dceadf4..7b9b659 100644
--- a/services/core/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/core/java/com/android/server/am/ContentProviderRecord.java
@@ -16,7 +16,7 @@
 
 package com.android.server.am;
 
-import android.app.IActivityManager.ContentProviderHolder;
+import android.app.ContentProviderHolder;
 import android.content.ComponentName;
 import android.content.IContentProvider;
 import android.content.pm.ApplicationInfo;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 0f351f6..eb5e603 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -403,6 +403,7 @@
 
     /** Interface for UserManagerService. */
     private final UserManagerInternal mUserManagerInternal;
+    private final ActivityManagerInternal mActivityManagerInternal;
 
     private final UserRestrictionsListener mUserRestrictionsListener =
             new AudioServiceUserRestrictionsListener();
@@ -612,6 +613,7 @@
         mIsSingleVolume = AudioSystem.isSingleVolume(context);
 
         mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
+        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
 
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
@@ -3109,14 +3111,28 @@
         boolean success =
             handleDeviceConnection(connected, outDevice, address, btDeviceName) &&
             handleDeviceConnection(connected, inDevice, address, btDeviceName);
-        if (success) {
-            synchronized (mScoClients) {
-                if (connected) {
-                    mBluetoothHeadsetDevice = btDevice;
-                } else {
-                    mBluetoothHeadsetDevice = null;
-                    resetBluetoothSco();
-                }
+
+        if (!success) {
+          return;
+        }
+
+        /* When one BT headset is disconnected while another BT headset
+         * is connected, don't mess with the headset device.
+         */
+        if ((state == BluetoothProfile.STATE_DISCONNECTED ||
+            state == BluetoothProfile.STATE_DISCONNECTING) &&
+            mBluetoothHeadset != null &&
+            mBluetoothHeadset.getAudioState(btDevice) == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
+            Log.w(TAG, "SCO connected through another device, returning");
+            return;
+        }
+
+        synchronized (mScoClients) {
+            if (connected) {
+                mBluetoothHeadsetDevice = btDevice;
+            } else {
+                mBluetoothHeadsetDevice = null;
+                resetBluetoothSco();
             }
         }
     }
@@ -3677,7 +3693,7 @@
 
     private void broadcastVibrateSetting(int vibrateType) {
         // Send broadcast
-        if (ActivityManagerNative.isSystemReady()) {
+        if (mActivityManagerInternal.isSystemReady()) {
             Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
             broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
             broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
@@ -4046,21 +4062,23 @@
                 mIndexMap.put(device, index);
 
                 changed = oldIndex != index;
-                if (changed) {
-                    // Apply change to all streams using this one as alias
-                    // if changing volume of current device, also change volume of current
-                    // device on aliased stream
-                    boolean currentDevice = (device == getDeviceForStream(mStreamType));
-                    int numStreamTypes = AudioSystem.getNumStreamTypes();
-                    for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
-                        if (streamType != mStreamType &&
-                                mStreamVolumeAlias[streamType] == mStreamType) {
-                            int scaledIndex = rescaleIndex(index, mStreamType, streamType);
-                            mStreamStates[streamType].setIndex(scaledIndex, device, caller);
-                            if (currentDevice) {
-                                mStreamStates[streamType].setIndex(scaledIndex,
-                                        getDeviceForStream(streamType), caller);
-                            }
+                // Apply change to all streams using this one as alias if:
+                // - the index actually changed OR
+                // - there is no volume index stored for this device on alias stream.
+                // If changing volume of current device, also change volume of current
+                // device on aliased stream
+                final boolean currentDevice = (device == getDeviceForStream(mStreamType));
+                final int numStreamTypes = AudioSystem.getNumStreamTypes();
+                for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+                    final VolumeStreamState aliasStreamState = mStreamStates[streamType];
+                    if (streamType != mStreamType &&
+                            mStreamVolumeAlias[streamType] == mStreamType &&
+                            (changed || !aliasStreamState.hasIndexForDevice(device))) {
+                        final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
+                        aliasStreamState.setIndex(scaledIndex, device, caller);
+                        if (currentDevice) {
+                            aliasStreamState.setIndex(scaledIndex,
+                                    getDeviceForStream(streamType), caller);
                         }
                     }
                 }
@@ -4097,6 +4115,12 @@
             }
         }
 
+        public boolean hasIndexForDevice(int device) {
+            synchronized (VolumeStreamState.class) {
+                return (mIndexMap.get(device, -1) != -1);
+            }
+        }
+
         public int getMaxIndex() {
             return mIndexMax;
         }
@@ -5264,7 +5288,6 @@
                 state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                                                BluetoothProfile.STATE_DISCONNECTED);
                 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
                 setBtScoDeviceConnectionState(btDevice, state);
             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                 boolean broadcast = false;
@@ -5412,8 +5435,7 @@
         // when the user switches back. For managed profiles, we should kill all recording apps
         ComponentName homeActivityName = null;
         if (!oldUser.isManagedProfile()) {
-            homeActivityName = LocalServices.getService(ActivityManagerInternal.class)
-                    .getHomeActivityForUser(oldUser.id);
+            homeActivityName = mActivityManagerInternal.getHomeActivityForUser(oldUser.id);
         }
         final String[] permissions = { Manifest.permission.RECORD_AUDIO };
         List<PackageInfo> packages;
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 1625aef..74a1f4f 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -46,7 +46,7 @@
     public static final String SERVICE_NAME = "netd_listener";
 
     private static final String TAG = NetdEventListenerService.class.getSimpleName();
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean VDBG = false;
 
     // TODO: read this constant from system property
@@ -88,7 +88,7 @@
             byte[] returnCodes = Arrays.copyOf(mReturnCodes, mEventCount);
             int[] latenciesMs = Arrays.copyOf(mLatenciesMs, mEventCount);
             mMetricsLog.log(new DnsEvent(mNetId, eventTypes, returnCodes, latenciesMs));
-            maybeLog(String.format("Logging %d results for netId %d", mEventCount, mNetId));
+            maybeLog("Logging %d results for netId %d", mEventCount, mNetId);
             mEventCount = 0;
         }
 
@@ -155,8 +155,7 @@
     public synchronized void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs,
             String hostname, String[] ipAddresses, int ipAddressesCount, int uid)
             throws RemoteException {
-        maybeVerboseLog(String.format("onDnsEvent(%d, %d, %d, %d)",
-                netId, eventType, returnCode, latencyMs));
+        maybeVerboseLog("onDnsEvent(%d, %d, %d, %dms)", netId, eventType, returnCode, latencyMs);
 
         DnsEventBatch batch = mEventBatches.get(netId);
         if (batch == null) {
@@ -174,9 +173,9 @@
     @Override
     // Called concurrently by multiple binder threads.
     // This method must not block or perform long-running operations.
-    public synchronized void onConnectEvent(int netId, int latencyMs, String ipAddr, int port,
+    public synchronized void onConnectEvent(int netId, int error, int latencyMs, String ipAddr, int port,
             int uid) throws RemoteException {
-        maybeVerboseLog(String.format("onConnectEvent(%d, %d)", netId, latencyMs));
+        maybeVerboseLog("onConnectEvent(%d, %d, %dms)", netId, error, latencyMs);
 
         if (mNetdEventCallback != null) {
             mNetdEventCallback.onConnectEvent(ipAddr, port, System.currentTimeMillis(), uid);
@@ -193,11 +192,11 @@
         pw.decreaseIndent();
     }
 
-    private static void maybeLog(String s) {
-        if (DBG) Log.d(TAG, s);
+    private static void maybeLog(String s, Object... args) {
+        if (DBG) Log.d(TAG, String.format(s, args));
     }
 
-    private static void maybeVerboseLog(String s) {
-        if (VDBG) Log.d(TAG, s);
+    private static void maybeVerboseLog(String s, Object... args) {
+        if (VDBG) Log.d(TAG, String.format(s, args));
     }
 }
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index fa6a7e7..3da49d8 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -86,8 +86,14 @@
     private final int mScreenBrightnessRangeMaximum;
     private final float mDozeScaleFactor;
 
-    // Light sensor event rate in milliseconds.
-    private final int mLightSensorRate;
+    // Initial light sensor event rate in milliseconds.
+    private final int mInitialLightSensorRate;
+
+    // Steady-state light sensor event rate in milliseconds.
+    private final int mNormalLightSensorRate;
+
+    // The current light sensor event rate in milliseconds.
+    private int mCurrentLightSensorRate;
 
     // Stability requirements in milliseconds for accepting a new brightness level.  This is used
     // for debouncing the light sensor.  Different constants are used to debounce the light sensor
@@ -185,7 +191,7 @@
     public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
             SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,
             int brightnessMin, int brightnessMax, float dozeScaleFactor,
-            int lightSensorRate, long brighteningLightDebounceConfig,
+            int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
             long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
             int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma,
             HysteresisLevels dynamicHysteresis) {
@@ -197,7 +203,9 @@
         mScreenBrightnessRangeMaximum = brightnessMax;
         mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime;
         mDozeScaleFactor = dozeScaleFactor;
-        mLightSensorRate = lightSensorRate;
+        mNormalLightSensorRate = lightSensorRate;
+        mInitialLightSensorRate = initialLightSensorRate;
+        mCurrentLightSensorRate = -1;
         mBrighteningLightDebounceConfig = brighteningLightDebounceConfig;
         mDarkeningLightDebounceConfig = darkeningLightDebounceConfig;
         mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
@@ -208,9 +216,9 @@
 
         mHandler = new AutomaticBrightnessHandler(looper);
         mAmbientLightRingBuffer =
-            new AmbientLightRingBuffer(mLightSensorRate, mAmbientLightHorizon);
+            new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);
         mInitialHorizonAmbientLightRingBuffer =
-            new AmbientLightRingBuffer(mLightSensorRate, mAmbientLightHorizon);
+            new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);
 
         if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
             mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
@@ -293,8 +301,9 @@
             if (!mLightSensorEnabled) {
                 mLightSensorEnabled = true;
                 mLightSensorEnableTime = SystemClock.uptimeMillis();
+                mCurrentLightSensorRate = mInitialLightSensorRate;
                 mSensorManager.registerListener(mLightSensorListener, mLightSensor,
-                        mLightSensorRate * 1000, mHandler);
+                        mCurrentLightSensorRate * 1000, mHandler);
                 return true;
             }
         } else {
@@ -304,6 +313,7 @@
                 mRecentLightSamples = 0;
                 mAmbientLightRingBuffer.clear();
                 mInitialHorizonAmbientLightRingBuffer.clear();
+                mCurrentLightSensorRate = -1;
                 mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
                 mSensorManager.unregisterListener(mLightSensorListener);
             }
@@ -314,6 +324,10 @@
     private void handleLightSensorEvent(long time, float lux) {
         mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
 
+        if (mAmbientLightRingBuffer.size() == 0) {
+            // switch to using the steady-state sample rate after grabbing the initial light sample
+            adjustLightSensorRate(mNormalLightSensorRate);
+        }
         applyLightSensorMeasurement(time, lux);
         updateAmbientLux(time);
     }
@@ -333,6 +347,20 @@
         mLastObservedLuxTime = time;
     }
 
+    private void adjustLightSensorRate(int lightSensorRate) {
+        // if the light sensor rate changed, update the sensor listener
+        if (lightSensorRate != mCurrentLightSensorRate) {
+            if (DEBUG) {
+                Slog.d(TAG, "adjustLightSensorRate: previousRate=" + mCurrentLightSensorRate
+                    + ", currentRate=" + lightSensorRate);
+            }
+            mCurrentLightSensorRate = lightSensorRate;
+            mSensorManager.unregisterListener(mLightSensorListener);
+            mSensorManager.registerListener(mLightSensorListener, mLightSensor,
+                    lightSensorRate * 1000, mHandler);
+        }
+    }
+
     private boolean setScreenAutoBrightnessAdjustment(float adjustment) {
         if (adjustment != mScreenAutoBrightnessAdjustment) {
             mScreenAutoBrightnessAdjustment = adjustment;
@@ -468,7 +496,7 @@
         // should be enough time to decide whether we should actually transition to the new
         // weighted ambient lux or not.
         nextTransitionTime =
-                nextTransitionTime > time ? nextTransitionTime : time + mLightSensorRate;
+                nextTransitionTime > time ? nextTransitionTime : time + mNormalLightSensorRate;
         if (DEBUG) {
             Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for "
                     + nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime));
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 3b2dc34..477ecdf 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -310,6 +310,15 @@
 
         int lightSensorRate = resources.getInteger(
                 com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
+        int initialLightSensorRate = resources.getInteger(
+                com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate);
+        if (initialLightSensorRate == -1) {
+          initialLightSensorRate = lightSensorRate;
+        } else if (initialLightSensorRate > lightSensorRate) {
+          Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate ("
+                  + initialLightSensorRate + ") to be less than or equal to "
+                  + "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");
+        }
         long brighteningLightDebounce = resources.getInteger(
                 com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
         long darkeningLightDebounce = resources.getInteger(
@@ -366,7 +375,7 @@
                         handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
                         lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
                         mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
-                        brighteningLightDebounce, darkeningLightDebounce,
+                        initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
                         autoBrightnessResetAmbientLuxAfterWarmUp, ambientLightHorizon,
                         autoBrightnessAdjustmentMaxGamma, dynamicHysteresis);
             }
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 3072f43..393199d 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -44,6 +44,9 @@
 import java.io.PrintWriter;
 import java.util.NoSuchElementException;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+
 /**
  * Internal controller for starting and stopping the current dream and managing related state.
  *
@@ -138,7 +141,7 @@
                     mCurrentDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
 
             try {
-                mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
+                mIWindowManager.addWindowToken(token, TYPE_DREAM, DEFAULT_DISPLAY);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "Unable to add window token for dream.", ex);
                 stopDream(true /*immediate*/);
@@ -236,7 +239,7 @@
             oldDream.releaseWakeLockIfNeeded();
 
             try {
-                mIWindowManager.removeWindowToken(oldDream.mToken);
+                mIWindowManager.removeWindowToken(oldDream.mToken, DEFAULT_DISPLAY);
             } catch (RemoteException ex) {
                 Slog.w(TAG, "Error removing window token for dream.", ex);
             }
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 603402e..a2a55e5 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -188,12 +188,6 @@
     static final int INVALID_PHYSICAL_ADDRESS = HdmiDeviceInfo.PATH_INVALID;
     static final int PATH_INTERNAL = HdmiDeviceInfo.PATH_INTERNAL;
 
-    // Send result codes. It should be consistent with hdmi_cec.h's send_message error code.
-    static final int SEND_RESULT_SUCCESS = 0;
-    static final int SEND_RESULT_NAK = 1;
-    static final int SEND_RESULT_BUSY = 2;
-    static final int SEND_RESULT_FAILURE = 3;
-
     // Strategy for device polling.
     // Should use "OR(|) operation of POLL_STRATEGY_XXX and POLL_ITERATION_XXX.
     static final int POLL_STRATEGY_MASK = 0x3;  // first and second bit.
@@ -231,26 +225,7 @@
     static final int RECORDING_TYPE_OWN_SOURCE = 4;
 
     // Definitions used for setOption(). These should be in sync with the definition
-    // in hardware/libhardware/include/hardware/{hdmi_cec.h,mhl.h}.
-
-    // TV gets turned on by incoming <Text/Image View On>. enabled by default.
-    // If set to disabled, TV won't turn on automatically.
-    static final int OPTION_CEC_AUTO_WAKEUP = 1;
-
-    // If set to disabled, all CEC commands are discarded.
-    static final int OPTION_CEC_ENABLE = 2;
-
-    // If set to disabled, system service yields control of CEC to sub-microcontroller.
-    // If enabled, it takes the control back.
-    static final int OPTION_CEC_SERVICE_CONTROL = 3;
-
-    // Put other devices to standby when TV goes to standby. enabled by default.
-    // If set to disabled, TV doesn't send <Standby> to other devices.
-    static final int OPTION_CEC_AUTO_DEVICE_OFF = 4;
-
-    // Passes the language used in the system when updated. The value to use is the 3 byte
-    // code as defined in ISO/FDIS 639-2.
-    static final int OPTION_CEC_SET_LANGUAGE = 5;
+    // in hardware/libhardware/include/hardware/mhl.h.
 
     // If set to disabled, TV does not switch ports when mobile device is connected.
     static final int OPTION_MHL_INPUT_SWITCHING = 101;
diff --git a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
index 5a1d896..c684a56 100644
--- a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
@@ -16,13 +16,13 @@
 
 package com.android.server.hdmi;
 
-import android.hardware.hdmi.HdmiDeviceInfo;
 import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.HdmiDeviceInfo;
 import android.hardware.hdmi.HdmiTvClient;
 import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.os.RemoteException;
 import android.util.Slog;
-
 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
 
 /**
@@ -95,7 +95,7 @@
         sendCommand(mGivePowerStatus, new SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error != Constants.SEND_RESULT_SUCCESS) {
+                if (error != SendMessageResult.SUCCESS) {
                     invokeCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
                     finish();
                     return;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 687aaa1..461a9b0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -17,23 +17,23 @@
 package com.android.server.hdmi;
 
 import android.hardware.hdmi.HdmiPortInfo;
+import android.hardware.tv.cec.V1_0.Result;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.util.Slog;
 import android.util.SparseArray;
-
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Predicate;
 import com.android.server.hdmi.HdmiAnnotations.IoThreadOnly;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 import com.android.server.hdmi.HdmiControlService.DevicePollingCallback;
-
-import libcore.util.EmptyArray;
-
 import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
+import libcore.util.EmptyArray;
+import sun.util.locale.LanguageTag;
 
 /**
  * Manages HDMI-CEC command and behaviors. It converts user's command into CEC command
@@ -256,7 +256,7 @@
         if (HdmiUtils.isValidAddress(newLogicalAddress)) {
             return nativeAddLogicalAddress(mNativePtr, newLogicalAddress);
         } else {
-            return -1;
+            return Result.FAILURE_INVALID_ARGS;
         }
     }
 
@@ -320,13 +320,27 @@
      * Set an option to CEC HAL.
      *
      * @param flag key of option
-     * @param value value of option
+     * @param enabled whether to enable/disable the given option.
      */
     @ServiceThreadOnly
-    void setOption(int flag, int value) {
+    void setOption(int flag, boolean enabled) {
         assertRunOnServiceThread();
-        HdmiLogger.debug("setOption: [flag:%d, value:%d]", flag, value);
-        nativeSetOption(mNativePtr, flag, value);
+        HdmiLogger.debug("setOption: [flag:%d, enabled:%b]", flag, enabled);
+        nativeSetOption(mNativePtr, flag, enabled);
+    }
+
+    /**
+     * Informs CEC HAL about the current system language.
+     *
+     * @param language Three-letter code defined in ISO/FDIS 639-2. Must be lowercase letters.
+     */
+    @ServiceThreadOnly
+    void setLanguage(String language) {
+        assertRunOnServiceThread();
+        if (!LanguageTag.isLanguage(language)) {
+            return;
+        }
+        nativeSetLanguage(mNativePtr, language);
     }
 
     /**
@@ -336,9 +350,9 @@
      * @param enabled whether to enable/disable ARC
      */
     @ServiceThreadOnly
-    void setAudioReturnChannel(int port, boolean enabled) {
+    void enableAudioReturnChannel(int port, boolean enabled) {
         assertRunOnServiceThread();
-        nativeSetAudioReturnChannel(mNativePtr, port, enabled);
+        nativeEnableAudioReturnChannel(mNativePtr, port, enabled);
     }
 
     /**
@@ -472,9 +486,9 @@
             // <Polling Message> is a message which has empty body.
             int ret =
                     nativeSendCecCommand(mNativePtr, sourceAddress, destinationAddress, EMPTY_BODY);
-            if (ret == Constants.SEND_RESULT_SUCCESS) {
+            if (ret == SendMessageResult.SUCCESS) {
                 return true;
-            } else if (ret != Constants.SEND_RESULT_NAK) {
+            } else if (ret != SendMessageResult.NACK) {
                 // Unusual failure
                 HdmiLogger.warning("Failed to send a polling message(%d->%d) with return code %d",
                         sourceAddress, destinationAddress, ret);
@@ -572,17 +586,17 @@
                 HdmiLogger.debug("[S]:" + cecMessage);
                 byte[] body = buildBody(cecMessage.getOpcode(), cecMessage.getParams());
                 int i = 0;
-                int errorCode = Constants.SEND_RESULT_SUCCESS;
+                int errorCode = SendMessageResult.SUCCESS;
                 do {
                     errorCode = nativeSendCecCommand(mNativePtr, cecMessage.getSource(),
                             cecMessage.getDestination(), body);
-                    if (errorCode == Constants.SEND_RESULT_SUCCESS) {
+                    if (errorCode == SendMessageResult.SUCCESS) {
                         break;
                     }
                 } while (i++ < HdmiConfig.RETRANSMISSION_COUNT);
 
                 final int finalError = errorCode;
-                if (finalError != Constants.SEND_RESULT_SUCCESS) {
+                if (finalError != SendMessageResult.SUCCESS) {
                     Slog.w(TAG, "Failed to send " + cecMessage);
                 }
                 if (callback != null) {
@@ -636,7 +650,8 @@
     private static native int nativeGetVersion(long controllerPtr);
     private static native int nativeGetVendorId(long controllerPtr);
     private static native HdmiPortInfo[] nativeGetPortInfos(long controllerPtr);
-    private static native void nativeSetOption(long controllerPtr, int flag, int value);
-    private static native void nativeSetAudioReturnChannel(long controllerPtr, int port, boolean flag);
+    private static native void nativeSetOption(long controllerPtr, int flag, boolean enabled);
+    private static native void nativeSetLanguage(long controllerPtr, String language);
+    private static native void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag);
     private static native boolean nativeIsConnected(long controllerPtr, int port);
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 43d8bac..c85d979 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -36,6 +36,7 @@
 import android.hardware.hdmi.HdmiRecordSources;
 import android.hardware.hdmi.HdmiTimerRecordSources;
 import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.media.tv.TvInputInfo;
@@ -46,7 +47,6 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
-
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
@@ -57,9 +57,9 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.HashMap;
 
 /**
  * Represent a logical device of type TV residing in Android system.
@@ -910,7 +910,7 @@
         HdmiLogger.debug("Set Arc Status[old:%b new:%b]", mArcEstablished, enabled);
         boolean oldStatus = mArcEstablished;
         // 1. Enable/disable ARC circuit.
-        setAudioReturnChannel(enabled);
+        enableAudioReturnChannel(enabled);
         // 2. Notify arc status to audio service.
         notifyArcStatusToAudioService(enabled);
         // 3. Update arc status;
@@ -922,11 +922,11 @@
      * Switch hardware ARC circuit in the system.
      */
     @ServiceThreadOnly
-    void setAudioReturnChannel(boolean enabled) {
+    void enableAudioReturnChannel(boolean enabled) {
         assertRunOnServiceThread();
         HdmiDeviceInfo avr = getAvrDeviceInfo();
         if (avr != null) {
-            mService.setAudioReturnChannel(avr.getPortId(), enabled);
+            mService.enableAudioReturnChannel(avr.getPortId(), enabled);
         }
     }
 
@@ -1870,7 +1870,7 @@
         mService.sendCecCommand(message, new SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error != Constants.SEND_RESULT_SUCCESS) {
+                if (error != SendMessageResult.SUCCESS) {
                     announceClearTimerRecordingResult(recorderAddress,
                             CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE);
                 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 72ee218..18f1b6c 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -20,10 +20,6 @@
 import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE;
 import static com.android.server.hdmi.Constants.DISABLED;
 import static com.android.server.hdmi.Constants.ENABLED;
-import static com.android.server.hdmi.Constants.OPTION_CEC_AUTO_WAKEUP;
-import static com.android.server.hdmi.Constants.OPTION_CEC_ENABLE;
-import static com.android.server.hdmi.Constants.OPTION_CEC_SERVICE_CONTROL;
-import static com.android.server.hdmi.Constants.OPTION_CEC_SET_LANGUAGE;
 import static com.android.server.hdmi.Constants.OPTION_MHL_ENABLE;
 import static com.android.server.hdmi.Constants.OPTION_MHL_INPUT_SWITCHING;
 import static com.android.server.hdmi.Constants.OPTION_MHL_POWER_CHARGE;
@@ -49,6 +45,8 @@
 import android.hardware.hdmi.IHdmiRecordListener;
 import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
 import android.hardware.hdmi.IHdmiVendorCommandListener;
+import android.hardware.tv.cec.V1_0.OptionKey;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.media.AudioManager;
 import android.media.tv.TvInputManager;
 import android.media.tv.TvInputManager.TvInputCallback;
@@ -69,7 +67,6 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
-
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.SystemService;
@@ -77,11 +74,6 @@
 import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
 import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource;
 import com.android.server.hdmi.HdmiCecLocalDevice.PendingActionClearedCallback;
-import com.android.server.hdmi.SelectRequestBuffer.DeviceSelectRequest;
-import com.android.server.hdmi.SelectRequestBuffer.PortSelectRequest;
-
-import libcore.util.EmptyArray;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -89,6 +81,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import libcore.util.EmptyArray;
 
 /**
  * Provides a service for sending and processing HDMI control messages,
@@ -123,9 +116,10 @@
          *
          * @param error result of send request.
          * <ul>
-         * <li>{@link Constants#SEND_RESULT_SUCCESS}
-         * <li>{@link Constants#SEND_RESULT_NAK}
-         * <li>{@link Constants#SEND_RESULT_FAILURE}
+         * <li>{@link SendMessageResult#SUCCESS}
+         * <li>{@link SendMessageResult#NACK}
+         * <li>{@link SendMessageResult#BUSY}
+         * <li>{@link SendMessageResult#FAIL}
          * </ul>
          */
         void onSendCompleted(int error);
@@ -466,7 +460,7 @@
         mWakeUpMessageReceived = false;
 
         if (isTvDeviceEnabled()) {
-            mCecController.setOption(OPTION_CEC_AUTO_WAKEUP, toInt(tv().getAutoWakeup()));
+            mCecController.setOption(OptionKey.WAKEUP, tv().getAutoWakeup());
         }
         int reason = -1;
         switch (initiatedBy) {
@@ -519,7 +513,7 @@
                     if (isTvDeviceEnabled()) {
                         tv().setAutoWakeup(enabled);
                     }
-                    setCecOption(OPTION_CEC_AUTO_WAKEUP, toInt(enabled));
+                    setCecOption(OptionKey.WAKEUP, enabled);
                     break;
                 case Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED:
                     for (int type : mLocalDevices) {
@@ -556,8 +550,8 @@
 
     private void initializeCec(int initiatedBy) {
         mAddressAllocated = false;
-        mCecController.setOption(OPTION_CEC_SERVICE_CONTROL, ENABLED);
-        mCecController.setOption(OPTION_CEC_SET_LANGUAGE, HdmiUtils.languageToInt(mLanguage));
+        mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true);
+        mCecController.setLanguage(mLanguage);
         initializeLocalDevices(initiatedBy);
     }
 
@@ -842,7 +836,7 @@
         } else {
             HdmiLogger.error("Invalid message type:" + command);
             if (callback != null) {
-                callback.onSendCompleted(Constants.SEND_RESULT_FAILURE);
+                callback.onSendCompleted(SendMessageResult.FAIL);
             }
         }
     }
@@ -884,8 +878,8 @@
         return dispatchMessageToLocalDevice(message);
     }
 
-    void setAudioReturnChannel(int portId, boolean enabled) {
-        mCecController.setAudioReturnChannel(portId, enabled);
+    void enableAudioReturnChannel(int portId, boolean enabled) {
+        mCecController.enableAudioReturnChannel(portId, enabled);
     }
 
     @ServiceThreadOnly
@@ -2079,7 +2073,7 @@
 
         if (isTvDeviceEnabled()) {
             tv().broadcastMenuLanguage(language);
-            mCecController.setOption(OPTION_CEC_SET_LANGUAGE, HdmiUtils.languageToInt(language));
+            mCecController.setLanguage(language);
         }
     }
 
@@ -2123,7 +2117,7 @@
         }
         mStandbyMessageReceived = false;
         mAddressAllocated = false;
-        mCecController.setOption(OPTION_CEC_SERVICE_CONTROL, DISABLED);
+        mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, false);
         mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, DISABLED);
     }
 
@@ -2216,7 +2210,7 @@
     }
 
     @ServiceThreadOnly
-    void setCecOption(int key, int value) {
+    void setCecOption(int key, boolean value) {
         assertRunOnServiceThread();
         mCecController.setOption(key, value);
     }
@@ -2249,7 +2243,7 @@
 
     @ServiceThreadOnly
     private void enableHdmiControlService() {
-        mCecController.setOption(OPTION_CEC_ENABLE, ENABLED);
+        mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true);
         mMhlController.setOption(OPTION_MHL_ENABLE, ENABLED);
 
         initializeCec(INITIATED_BY_ENABLE_CEC);
@@ -2264,7 +2258,7 @@
                 mCecController.flush(new Runnable() {
                     @Override
                     public void run() {
-                        mCecController.setOption(OPTION_CEC_ENABLE, DISABLED);
+                        mCecController.setOption(OptionKey.ENABLE_CEC, false);
                         mMhlController.setOption(OPTION_MHL_ENABLE, DISABLED);
                         clearLocalDevices();
                     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index 9aa9290..8b16411 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -291,18 +291,4 @@
                 info.getPhysicalAddress(), info.getPortId(), info.getDeviceType(),
                 info.getVendorId(), info.getDisplayName(), newPowerStatus);
     }
-
-    /**
-     * Convert 3 byte-long language code in string to integer representation.
-     * English(eng), for example, is converted to 0x656e67.
-     *
-     * @param language language code in string
-     * @return language code in integer representation
-     */
-    static int languageToInt(String language) {
-        String normalized = language.toLowerCase();
-        return ((normalized.charAt(0) & 0xFF) << 16)
-                | ((normalized.charAt(1) & 0xFF) << 8)
-                | (normalized.charAt(2) & 0xFF);
-    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index 5f2d651..e1bcd99 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -265,7 +265,7 @@
         // Turn off system audio mode and update settings.
         tv().setSystemAudioMode(false, true);
         if (tv().isArcEstablished()) {
-            tv().setAudioReturnChannel(false);
+            tv().enableAudioReturnChannel(false);
             addAndStartAction(new RequestArcTerminationAction(localDevice(), address));
         }
     }
diff --git a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
index d80b81f6..39de8ff 100644
--- a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
+++ b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
@@ -22,8 +22,8 @@
 import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE;
 import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT;
 
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.util.Slog;
-
 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
 
 /**
@@ -62,7 +62,7 @@
                 @Override
                     public void onSendCompleted(int error) {
                         // if failed to send <Record On>, display error message and finish action.
-                        if (error != Constants.SEND_RESULT_SUCCESS) {
+                        if (error != SendMessageResult.SUCCESS) {
                             tv().announceOneTouchRecordResult(
                                     mRecorderAddress,
                                     ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
diff --git a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
index fd7a7f9..6893012 100644
--- a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
+++ b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
@@ -18,10 +18,9 @@
 import static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_UNKNOWN;
 
 import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.util.SparseIntArray;
-
 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
-
 import java.util.List;
 
 /**
@@ -123,7 +122,7 @@
                         public void onSendCompleted(int error) {
                             // If fails to send <Give Device Power Status>,
                             // update power status into UNKNOWN.
-                            if (error != Constants.SEND_RESULT_SUCCESS) {
+                            if (error != SendMessageResult.SUCCESS) {
                                updatePowerStatus(logicalAddress, POWER_STATUS_UNKNOWN, true);
                             }
                         }
diff --git a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
index f69f975..4eb220f 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
@@ -16,6 +16,8 @@
 
 package com.android.server.hdmi;
 
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+
 /**
  * Feature action that handles ARC action initiated by TV devices.
  *
@@ -44,7 +46,7 @@
         sendCommand(command, new HdmiControlService.SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error != Constants.SEND_RESULT_SUCCESS) {
+                if (error != SendMessageResult.SUCCESS) {
                     // Turn off ARC status if <Request ARC Initiation> fails.
                     tv().setArcStatus(false);
                     finish();
diff --git a/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
index f5a0115..8b5a2931 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
@@ -16,6 +16,8 @@
 
 package com.android.server.hdmi;
 
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+
 /**
  * Feature action to handle <Request ARC Termination>.
  *
@@ -43,7 +45,7 @@
         sendCommand(command, new HdmiControlService.SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error != Constants.SEND_RESULT_SUCCESS) {
+                if (error != SendMessageResult.SUCCESS) {
                     // If failed to send <Request ARC Termination>, start "Disabled" ARC
                     // transmission action.
                     disableArcTransmission();
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index 9b4950b..6633789 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -17,6 +17,7 @@
 package com.android.server.hdmi;
 
 import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.util.Slog;
 
 /**
@@ -81,14 +82,14 @@
             @Override
             public void onSendCompleted(int error) {
                 switch (error) {
-                    case Constants.SEND_RESULT_SUCCESS:
-                    case Constants.SEND_RESULT_BUSY:
-                    case Constants.SEND_RESULT_FAILURE:
+                    case SendMessageResult.SUCCESS:
+                    case SendMessageResult.BUSY:
+                    case SendMessageResult.FAIL:
                         // The result of the command transmission, unless it is an obvious
                         // failure indicated by the target device (or lack thereof), should
                         // not affect the ARC status. Ignores it silently.
                         break;
-                    case Constants.SEND_RESULT_NAK:
+                    case SendMessageResult.NACK:
                         // If <Report ARC Initiated> is negatively ack'ed, disable ARC and
                         // send <Report ARC Terminated> directly.
                         setArcStatus(false);
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
index a209cd0..af1a85d 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -17,12 +17,12 @@
 package com.android.server.hdmi;
 
 import android.annotation.Nullable;
-import android.hardware.hdmi.HdmiDeviceInfo;
 import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.HdmiDeviceInfo;
 import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.os.RemoteException;
 import android.util.Slog;
-
 import java.util.List;
 
 /**
@@ -96,7 +96,7 @@
         sendCommand(command, new HdmiControlService.SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error != Constants.SEND_RESULT_SUCCESS) {
+                if (error != SendMessageResult.SUCCESS) {
                     HdmiLogger.debug("Failed to send <System Audio Mode Request>:" + error);
                     setSystemAudioMode(false);
                     finishWithCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
index 78b40fd..01063b7 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
@@ -16,6 +16,7 @@
 
 package com.android.server.hdmi;
 
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
 
 /**
@@ -48,7 +49,7 @@
                 mAvrAddress), new SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error != Constants.SEND_RESULT_SUCCESS) {
+                if (error != SendMessageResult.SUCCESS) {
                     tv().setSystemAudioMode(false, true);
                     finish();
                 }
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
index 2ae5c97..cab8439 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
@@ -19,9 +19,9 @@
 import android.annotation.Nullable;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.os.RemoteException;
 import android.util.Slog;
-
 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
 
 /**
@@ -56,7 +56,7 @@
                 new SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error != Constants.SEND_RESULT_SUCCESS) {
+                if (error != SendMessageResult.SUCCESS) {
                     handleSendGiveAudioStatusFailure();
                 }
             }
diff --git a/services/core/java/com/android/server/hdmi/TimerRecordingAction.java b/services/core/java/com/android/server/hdmi/TimerRecordingAction.java
index 16fc25f..525e223 100644
--- a/services/core/java/com/android/server/hdmi/TimerRecordingAction.java
+++ b/services/core/java/com/android/server/hdmi/TimerRecordingAction.java
@@ -22,10 +22,9 @@
 import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_DIGITAL;
 import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_EXTERNAL;
 
+import android.hardware.tv.cec.V1_0.SendMessageResult;
 import android.util.Slog;
-
 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
-
 import java.util.Arrays;
 
 /**
@@ -82,7 +81,7 @@
         sendCommand(message, new SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error != Constants.SEND_RESULT_SUCCESS) {
+                if (error != SendMessageResult.SUCCESS) {
                     tv().announceTimerRecordingResult(mRecorderAddress,
                             TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
                     finish();
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 970da99..a37dfed 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -824,7 +824,7 @@
             try {
                 ActivityManagerNative.getDefault().registerUidObserver(mUidObserver,
                         ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE
-                        | ActivityManager.UID_OBSERVER_IDLE);
+                        | ActivityManager.UID_OBSERVER_IDLE, null);
             } catch (RemoteException e) {
                 // ignored; both services live in system_server
             }
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 9ae496f..45f54a9 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -415,6 +415,12 @@
 
     private int mYearOfHardware = 0;
 
+    // Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
+    // stops output right at 600m/s, depriving this of the information of a device that reaches
+    // greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
+    private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F;
+    private boolean mItarSpeedLimitExceeded = false;
+
     private final IGnssStatusProvider mGnssStatusProvider = new IGnssStatusProvider.Stub() {
         @Override
         public void registerGnssStatusCallback(IGnssStatusListener callback) {
@@ -1400,6 +1406,12 @@
             mStarted = true;
             mSingleShot = singleShot;
             mPositionMode = GPS_POSITION_MODE_STANDALONE;
+            // Notify about suppressed output, if speed limit was previously exceeded.
+            // Elsewhere, we check again with every speed output reported.
+            if (mItarSpeedLimitExceeded) {
+                Log.i(TAG, "startNavigating with ITAR limit in place. Output limited  " +
+                        "until slow enough speed reported.");
+            }
 
             boolean agpsEnabled =
                     (Settings.Global.getInt(mContext.getContentResolver(),
@@ -1486,7 +1498,17 @@
      * called from native code to update our position.
      */
     private void reportLocation(int flags, double latitude, double longitude, double altitude,
-            float speed, float bearing, float accuracy, long timestamp) {
+            float speedMetersPerSecond, float bearing, float accuracy, long timestamp) {
+        if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
+            mItarSpeedLimitExceeded = speedMetersPerSecond > ITAR_SPEED_LIMIT_METERS_PER_SECOND;
+        }
+
+        if (mItarSpeedLimitExceeded) {
+            Log.i(TAG, "Hal reported a speed in excess of ITAR limit." +
+                    "  GPS/GNSS Navigation output blocked.");
+            return;  // No output of location allowed
+        }
+
         if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
                 " timestamp: " + timestamp);
 
@@ -1506,7 +1528,7 @@
                 mLocation.removeAltitude();
             }
             if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
-                mLocation.setSpeed(speed);
+                mLocation.setSpeed(speedMetersPerSecond);
             } else {
                 mLocation.removeSpeed();
             }
@@ -1690,23 +1712,29 @@
      * called from native code to report NMEA data received
      */
     private void reportNmea(long timestamp) {
-        int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
-        String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
-        mListenerHelper.onNmeaReceived(timestamp, nmea);
+        if (!mItarSpeedLimitExceeded) {
+            int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
+            String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
+            mListenerHelper.onNmeaReceived(timestamp, nmea);
+        }
     }
 
     /**
      * called from native code - Gps measurements callback
      */
     private void reportMeasurementData(GnssMeasurementsEvent event) {
-        mGnssMeasurementsProvider.onMeasurementsAvailable(event);
+        if (!mItarSpeedLimitExceeded) {
+            mGnssMeasurementsProvider.onMeasurementsAvailable(event);
+        }
     }
 
     /**
      * called from native code - GPS navigation message callback
      */
     private void reportNavigationMessage(GnssNavigationMessage event) {
-        mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
+        if (!mItarSpeedLimitExceeded) {
+            mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java
index 959a823..c48f430 100644
--- a/services/core/java/com/android/server/net/NetworkIdentitySet.java
+++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java
@@ -91,6 +91,19 @@
         }
     }
 
+    /** @return whether any {@link NetworkIdentity} in this set is considered metered. */
+    public boolean isAnyMemberMetered() {
+        if (isEmpty()) {
+            return false;
+        }
+        for (NetworkIdentity ident : this) {
+            if (ident.getMetered()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /** @return whether any {@link NetworkIdentity} in this set is considered roaming. */
     public boolean isAnyMemberRoaming() {
         if (isEmpty()) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 2bccfee..d8103fc 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -611,7 +611,8 @@
 
             try {
                 mActivityManager.registerUidObserver(mUidObserver,
-                        ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE);
+                        ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE,
+                        null);
                 mNetworkManager.registerObserver(mAlertObserver);
             } catch (RemoteException e) {
                 // ignored; both services live in system_server
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 673dd8f..c45b416 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -17,6 +17,8 @@
 package com.android.server.net;
 
 import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.METERED_YES;
 import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.ROAMING_YES;
 import static android.net.NetworkStats.SET_ALL;
@@ -242,6 +244,7 @@
                 entry.uid = key.uid;
                 entry.set = key.set;
                 entry.tag = key.tag;
+                entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO;
                 entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO;
                 entry.rxBytes = historyEntry.rxBytes;
                 entry.rxPackets = historyEntry.rxPackets;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d782211..6ebdb3c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -43,6 +43,8 @@
 import static android.service.notification.NotificationListenerService.TRIM_FULL;
 import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 
 import android.Manifest;
@@ -1402,8 +1404,7 @@
                         }
 
                         Binder token = new Binder();
-                        mWindowManagerInternal.addWindowToken(token,
-                                WindowManager.LayoutParams.TYPE_TOAST);
+                        mWindowManagerInternal.addWindowToken(token, TYPE_TOAST, DEFAULT_DISPLAY);
                         record = new ToastRecord(callingPid, pkg, callback, duration, token);
                         mToastQueue.add(record);
                         index = mToastQueue.size() - 1;
@@ -3253,7 +3254,7 @@
         }
 
         ToastRecord lastToast = mToastQueue.remove(index);
-        mWindowManagerInternal.removeWindowToken(lastToast.token, true);
+        mWindowManagerInternal.removeWindowToken(lastToast.token, true, DEFAULT_DISPLAY);
 
         keepProcessAliveIfNeededLocked(record.pid);
         if (mToastQueue.size() > 0) {
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index d11d4de..1bb8b3b 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -151,8 +151,6 @@
                 if (TAG_PACKAGE.equals(tag)) {
                     int uid = safeInt(parser, ATT_UID, Record.UNKNOWN_UID);
                     String name = parser.getAttributeValue(null, ATT_NAME);
-                    int importance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
-
                     if (!TextUtils.isEmpty(name)) {
                         if (forRestore) {
                             try {
@@ -232,8 +230,8 @@
             } else {
                 mRecords.put(key, r);
             }
+            clampDefaultChannel(r);
         }
-        clampDefaultChannel(r);
         return r;
     }
 
@@ -241,14 +239,18 @@
     // unless the user has already changed the importance.
     private void clampDefaultChannel(Record r) {
         try {
-            final ApplicationInfo applicationInfo = mPm.getApplicationInfo(r.pkg, 0);
-            if (applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
-                final NotificationChannel defaultChannel =
-                        r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID);
-                if ((defaultChannel.getUserLockedFields()
-                        & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0) {
-                    defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-                    updateConfig();
+            if (r.uid != Record.UNKNOWN_UID) {
+                int userId = UserHandle.getUserId(r.uid);
+                final ApplicationInfo applicationInfo =
+                        mPm.getApplicationInfoAsUser(r.pkg, 0, userId);
+                if (applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+                    final NotificationChannel defaultChannel =
+                            r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID);
+                    if ((defaultChannel.getUserLockedFields()
+                            & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0) {
+                        defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+                        updateConfig();
+                    }
                 }
             }
         } catch (NameNotFoundException e) {
@@ -733,7 +735,15 @@
                     // noop
                 }
             }
+            try {
+                Record fullRecord = getRecord(pkg,
+                        mPm.getPackageUidAsUser(pkg, UserHandle.USER_SYSTEM));
+                if (fullRecord != null) {
+                    clampDefaultChannel(fullRecord);
+                }
+            } catch (NameNotFoundException e) {}
         }
+
         if (updated) {
             updateConfig();
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 57aa38d..ca77335 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1670,8 +1670,6 @@
             }
 
             final String packageName = res.pkg.applicationInfo.packageName;
-            Bundle extras = new Bundle(1);
-            extras.putInt(Intent.EXTRA_UID, res.uid);
 
             // Determine the set of users who are adding this package for
             // the first time vs. those who are seeing an update.
@@ -1701,11 +1699,14 @@
                 mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(res.pkg.baseCodePath);
 
                 // Send added for users that see the package for the first time
-                sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
-                        extras, 0 /*flags*/, null /*targetPackage*/,
-                        null /*finishedReceiver*/, firstUsers);
+                // sendPackageAddedForNewUsers also deals with system apps
+                int appId = UserHandle.getAppId(res.uid);
+                boolean isSystem = res.pkg.applicationInfo.isSystemApp();
+                sendPackageAddedForNewUsers(packageName, isSystem, appId, firstUsers);
 
                 // Send added for users that don't see the package for the first time
+                Bundle extras = new Bundle(1);
+                extras.putInt(Intent.EXTRA_UID, res.uid);
                 if (update) {
                     extras.putBoolean(Intent.EXTRA_REPLACING, true);
                 }
@@ -11787,31 +11788,57 @@
     private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetting,
             int userId) {
         final boolean isSystem = isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
-        sendPackageAddedForUser(packageName, isSystem, pkgSetting.appId, userId);
+        sendPackageAddedForNewUsers(packageName, isSystem, pkgSetting.appId, userId);
     }
 
-    private void sendPackageAddedForUser(String packageName, boolean isSystem,
-            int appId, int userId) {
+    private void sendPackageAddedForNewUsers(String packageName, boolean isSystem,
+            int appId, int... userIds) {
+        if (ArrayUtils.isEmpty(userIds)) {
+            return;
+        }
         Bundle extras = new Bundle(1);
-        extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, appId));
+        // Set to UID of the first user, EXTRA_UID is automatically updated in sendPackageBroadcast
+        extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userIds[0], appId));
 
         sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
-                packageName, extras, 0, null, null, new int[] {userId});
+                packageName, extras, 0, null, null, userIds);
+        if (isSystem) {
+            mHandler.post(() -> {
+                        for (int userId : userIds) {
+                            sendBootCompletedBroadcastToSystemApp(packageName, userId);
+                        }
+                    }
+            );
+        }
+    }
+
+    /**
+     * The just-installed/enabled app is bundled on the system, so presumed to be able to run
+     * automatically without needing an explicit launch.
+     * Send it a LOCKED_BOOT_COMPLETED/BOOT_COMPLETED if it would ordinarily have gotten ones.
+     */
+    private void sendBootCompletedBroadcastToSystemApp(String packageName, int userId) {
+        // If user is not running, the app didn't miss any broadcast
+        if (!mUserManagerInternal.isUserRunning(userId)) {
+            return;
+        }
+        final IActivityManager am = ActivityManagerNative.getDefault();
         try {
-            IActivityManager am = ActivityManagerNative.getDefault();
-            if (isSystem && am.isUserRunning(userId, 0)) {
-                // The just-installed/enabled app is bundled on the system, so presumed
-                // to be able to run automatically without needing an explicit launch.
-                // Send it a BOOT_COMPLETED if it would ordinarily have gotten one.
-                Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED)
-                        .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
-                        .setPackage(packageName);
-                am.broadcastIntent(null, bcIntent, null, null, 0, null, null, null,
+            // Deliver LOCKED_BOOT_COMPLETED first
+            Intent lockedBcIntent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)
+                    .setPackage(packageName);
+            final String[] requiredPermissions = {Manifest.permission.RECEIVE_BOOT_COMPLETED};
+            am.broadcastIntent(null, lockedBcIntent, null, null, 0, null, null, requiredPermissions,
+                    android.app.AppOpsManager.OP_NONE, null, false, false, userId);
+
+            // Deliver BOOT_COMPLETED only if user is unlocked
+            if (mUserManagerInternal.isUserUnlockingOrUnlocked(userId)) {
+                Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED).setPackage(packageName);
+                am.broadcastIntent(null, bcIntent, null, null, 0, null, null, requiredPermissions,
                         android.app.AppOpsManager.OP_NONE, null, false, false, userId);
             }
         } catch (RemoteException e) {
-            // shouldn't happen
-            Slog.w(TAG, "Unable to bootstrap installed package", e);
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -15941,10 +15968,8 @@
                     ? appearedChildPackages.size() : 0;
             for (int i = 0; i < packageCount; i++) {
                 PackageInstalledInfo installedInfo = appearedChildPackages.valueAt(i);
-                for (int userId : installedInfo.newUsers) {
-                    sendPackageAddedForUser(installedInfo.name, true,
-                            UserHandle.getAppId(installedInfo.uid), userId);
-                }
+                sendPackageAddedForNewUsers(installedInfo.name, true,
+                        UserHandle.getAppId(installedInfo.uid), installedInfo.newUsers);
             }
         }
 
@@ -21236,6 +21261,11 @@
             PackageManagerService.this.revokeRuntimePermission(packageName, name, userId,
                     overridePolicy);
         }
+
+        @Override
+        public String getNameForUid(int uid) {
+            return PackageManagerService.this.getNameForUid(uid);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 2176eb1..442a4f4 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -65,8 +65,8 @@
     // Append privapp to existing seinfo label
     private static final String PRIVILEGED_APP_STR = ":privapp";
 
-    // Append autoplay to existing seinfo label
-    private static final String AUTOPLAY_APP_STR = ":autoplayapp";
+    // Append ephemeral to existing seinfo label
+    private static final String EPHEMERAL_APP_STR = ":ephemeralapp";
 
     /**
      * Load the mac_permissions.xml file containing all seinfo assignments used to
@@ -281,8 +281,8 @@
             }
         }
 
-        if (pkg.applicationInfo.isAutoPlayApp())
-            pkg.applicationInfo.seinfo += AUTOPLAY_APP_STR;
+        if (pkg.applicationInfo.isEphemeralApp())
+            pkg.applicationInfo.seinfo += EPHEMERAL_APP_STR;
 
         if (pkg.applicationInfo.isPrivilegedApp())
             pkg.applicationInfo.seinfo += PRIVILEGED_APP_STR;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6d514e4..42cc3a8 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4263,7 +4263,6 @@
         ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS, "HAS_DOMAIN_URLS",
         ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE, "DEFAULT_TO_DEVICE_PROTECTED_STORAGE",
         ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE, "DIRECT_BOOT_AWARE",
-        ApplicationInfo.PRIVATE_FLAG_AUTOPLAY, "AUTOPLAY",
         ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE, "PARTIALLY_DIRECT_BOOT_AWARE",
         ApplicationInfo.PRIVATE_FLAG_EPHEMERAL, "EPHEMERAL",
         ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 3b5abe8..37acf5c 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -3677,7 +3677,7 @@
     @VisibleForTesting
     void injectRegisterUidObserver(IUidObserver observer, int which) {
         try {
-            ActivityManagerNative.getDefault().registerUidObserver(observer, which);
+            ActivityManagerNative.getDefault().registerUidObserver(observer, which, null);
         } catch (RemoteException shouldntHappen) {
         }
     }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a15af3c..67488ce 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1487,8 +1487,7 @@
         // Skip over users being removed
         for (int i = 0; i < totalUserCount; i++) {
             UserInfo user = mUsers.valueAt(i).info;
-            if (!mRemovingUserIds.get(user.id)
-                    && !user.isGuest() && !user.partial) {
+            if (!mRemovingUserIds.get(user.id) && !user.isGuest()) {
                 aliveUserCount++;
             }
         }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f9e1575..b7067d2 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -81,6 +81,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
 import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
+import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
@@ -2278,6 +2279,7 @@
             case TYPE_DREAM:
             case TYPE_INPUT_METHOD:
             case TYPE_WALLPAPER:
+            case TYPE_PRESENTATION:
             case TYPE_PRIVATE_PRESENTATION:
             case TYPE_VOICE_INTERACTION:
             case TYPE_ACCESSIBILITY_OVERLAY:
@@ -2382,6 +2384,7 @@
             case TYPE_STATUS_BAR_SUB_PANEL:
             case TYPE_SYSTEM_DIALOG:
             case TYPE_VOLUME_OVERLAY:
+            case TYPE_PRESENTATION:
             case TYPE_PRIVATE_PRESENTATION:
             case TYPE_DOCK_DIVIDER:
                 break;
@@ -2546,10 +2549,11 @@
             return 2;
         }
         switch (type) {
-        case TYPE_PRIVATE_PRESENTATION:
-            return 2;
         case TYPE_WALLPAPER:
             // wallpaper is at the bottom, though the window manager may move it.
+            return 1;
+        case TYPE_PRESENTATION:
+        case TYPE_PRIVATE_PRESENTATION:
             return 2;
         case TYPE_DOCK_DIVIDER:
             return 2;
@@ -5085,12 +5089,12 @@
 
         // Dock windows carve out the bottom of the screen, so normal windows
         // can't appear underneath them.
-        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleOrBehindKeyguardLw()
-                && win.isDisplayedLw() && !win.getGivenInsetsPendingLw()) {
+        if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw()
+                && !win.getGivenInsetsPendingLw()) {
             setLastInputMethodWindowLw(null, null);
             offsetInputMethodWindowLw(win);
         }
-        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleOrBehindKeyguardLw()
+        if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
                 && !win.getGivenInsetsPendingLw()) {
             offsetVoiceInputWindowLw(win);
         }
@@ -5164,12 +5168,11 @@
     @Override
     public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
             WindowState attached, WindowState imeTarget) {
-        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
-                + win.isVisibleOrBehindKeyguardLw());
+        final boolean visible = win.isVisibleLw();
+        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
         applyKeyguardPolicyLw(win, imeTarget);
         final int fl = PolicyControl.getWindowFlags(win, attrs);
-        if (mTopFullscreenOpaqueWindowState == null
-                && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
+        if (mTopFullscreenOpaqueWindowState == null && visible && attrs.type == TYPE_INPUT_METHOD) {
             mForcingShowNavBar = true;
             mForcingShowNavBarLayer = win.getSurfaceLayer();
         }
@@ -5185,8 +5188,7 @@
         boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
                 && attrs.type < FIRST_SYSTEM_WINDOW;
         final int stackId = win.getStackId();
-        if (mTopFullscreenOpaqueWindowState == null &&
-                win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
+        if (mTopFullscreenOpaqueWindowState == null && visible) {
             if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
                 mForceStatusBar = true;
             }
@@ -5217,10 +5219,8 @@
             }
         }
 
-        final boolean reallyVisible = win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw();
-
         // Voice interaction overrides both top fullscreen and top docked.
-        if (reallyVisible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
+        if (visible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
             if (mTopFullscreenOpaqueWindowState == null) {
                 mTopFullscreenOpaqueWindowState = win;
                 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
@@ -5236,7 +5236,7 @@
         }
 
         // Keep track of the window if it's dimming but not necessarily fullscreen.
-        if (mTopFullscreenOpaqueOrDimmingWindowState == null && reallyVisible
+        if (mTopFullscreenOpaqueOrDimmingWindowState == null && visible
                 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
             mTopFullscreenOpaqueOrDimmingWindowState = win;
         }
@@ -5244,7 +5244,7 @@
         // We need to keep track of the top "fullscreen" opaque window for the docked stack
         // separately, because both the "real fullscreen" opaque window and the one for the docked
         // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
-        if (mTopDockedOpaqueWindowState == null && reallyVisible && appWindow && attached == null
+        if (mTopDockedOpaqueWindowState == null && visible && appWindow && attached == null
                 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
             mTopDockedOpaqueWindowState = win;
             if (mTopDockedOpaqueOrDimmingWindowState == null) {
@@ -5254,7 +5254,7 @@
 
         // Also keep track of any windows that are dimming but not necessarily fullscreen in the
         // docked stack.
-        if (mTopDockedOpaqueOrDimmingWindowState == null && reallyVisible && win.isDimming()
+        if (mTopDockedOpaqueOrDimmingWindowState == null && visible && win.isDimming()
                 && stackId == DOCKED_STACK_ID) {
             mTopDockedOpaqueOrDimmingWindowState = win;
         }
@@ -6209,7 +6209,7 @@
     }
 
     void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
-        if (ActivityManagerNative.isSystemReady()) {
+        if (mActivityManagerInternal.isSystemReady()) {
             MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true);
         }
     }
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 4e9f5a2..00700b8 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -648,7 +648,7 @@
             Slog.d(TAG, "Sending wake up broadcast.");
         }
 
-        if (ActivityManagerNative.isSystemReady()) {
+        if (mActivityManagerInternal.isSystemReady()) {
             mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
                     mWakeUpBroadcastDone, mHandler, 0, null, null);
         } else {
@@ -671,7 +671,7 @@
             Slog.d(TAG, "Sending go to sleep broadcast.");
         }
 
-        if (ActivityManagerNative.isSystemReady()) {
+        if (mActivityManagerInternal.isSystemReady()) {
             mContext.sendOrderedBroadcastAsUser(mScreenOffIntent, UserHandle.ALL, null,
                     mGoToSleepBroadcastDone, mHandler, 0, null, null);
         } else {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 6b967a2..d755e58 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2631,9 +2631,18 @@
                 state = new UidState(uid);
                 mUidState.put(uid, state);
             }
+            final boolean oldShouldAllow = state.mProcState
+                    <= ActivityManager.PROCESS_STATE_RECEIVER;
             state.mProcState = procState;
-            if (mDeviceIdleMode && state.mNumWakeLocks > 0) {
-                handleUidStateChangeLocked();
+            if (state.mNumWakeLocks > 0) {
+                if (mDeviceIdleMode) {
+                    handleUidStateChangeLocked();
+                } else if (!state.mActive && oldShouldAllow !=
+                        (procState <= ActivityManager.PROCESS_STATE_RECEIVER)) {
+                    // If this uid is not active, but the process state has changed such
+                    // that we may still want to allow it to hold a wake lock, then take care of it.
+                    handleUidStateChangeLocked();
+                }
             }
         }
     }
@@ -2721,7 +2730,8 @@
                         disabled = true;
                     }
                 } else {
-                    disabled = !wakeLock.mUidState.mActive;
+                    disabled = !wakeLock.mUidState.mActive &&
+                            wakeLock.mUidState.mProcState > ActivityManager.PROCESS_STATE_RECEIVER;
                 }
             }
             if (wakeLock.mDisabled != disabled) {
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index badee82..a920d54 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -17,7 +17,6 @@
 
 package com.android.server.power;
 
-import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.IActivityManager;
@@ -415,7 +414,7 @@
         Log.i(TAG, "Shutting down activity manager...");
 
         final IActivityManager am =
-            ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
+                IActivityManager.Stub.asInterface(ServiceManager.checkService("activity"));
         if (am != null) {
             try {
                 am.shutdown(MAX_BROADCAST_TIME);
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 353d663..62f5468 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -1014,6 +1014,9 @@
                     synchronized (mDeviceLockedForUser) {
                         mDeviceLockedForUser.delete(userId);
                     }
+                    synchronized (mTrustUsuallyManagedForUser) {
+                        mTrustUsuallyManagedForUser.delete(userId);
+                    }
                     refreshAgentList(userId);
                     refreshDeviceLockedForUser(userId);
                 }
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 7439f535..96662b5 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -22,6 +22,8 @@
 import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
 import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
 import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
@@ -1692,8 +1694,7 @@
                 if (wallpaper.userId == mCurrentUserId) {
                     if (DEBUG)
                         Slog.v(TAG, "Adding window token: " + newConn.mToken);
-                    mIWindowManager.addWindowToken(newConn.mToken,
-                            WindowManager.LayoutParams.TYPE_WALLPAPER);
+                    mIWindowManager.addWindowToken(newConn.mToken, TYPE_WALLPAPER, DEFAULT_DISPLAY);
                     mLastWallpaper = wallpaper;
                 }
             } catch (RemoteException e) {
@@ -1728,7 +1729,7 @@
             try {
                 if (DEBUG)
                     Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
-                mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
+                mIWindowManager.removeWindowToken(wallpaper.connection.mToken, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
             }
             wallpaper.connection.mService = null;
@@ -1745,7 +1746,7 @@
     void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
         try {
             conn.mService.attach(conn, conn.mToken,
-                    WindowManager.LayoutParams.TYPE_WALLPAPER, false,
+                    TYPE_WALLPAPER, false,
                     wallpaper.width, wallpaper.height, wallpaper.padding);
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index 9f0f11a..302f9f6 100644
--- a/services/core/java/com/android/server/webkit/SystemImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.UserInfo;
 import android.content.res.XmlResourceParser;
+import android.database.ContentObserver;
 import android.os.Build;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -270,8 +271,21 @@
     }
 
     @Override
-    public void setMultiprocessEnabled(boolean enabled) {
-        WebViewZygote.setMultiprocessEnabled(enabled);
+    public void setMultiProcessEnabledFromContext(Context context) {
+        boolean enableMultiProcess = false;
+        try {
+            enableMultiProcess = Settings.Global.getInt(context.getContentResolver(),
+                    Settings.Global.WEBVIEW_MULTIPROCESS) == 1;
+        } catch (Settings.SettingNotFoundException ex) {
+        }
+        WebViewZygote.setMultiprocessEnabled(enableMultiProcess);
+    }
+
+    @Override
+    public void registerContentObserver(Context context, ContentObserver contentObserver) {
+        context.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.WEBVIEW_MULTIPROCESS),
+                false, contentObserver);
     }
 
     // flags declaring we want extra info from the package manager for webview providers
diff --git a/services/core/java/com/android/server/webkit/SystemInterface.java b/services/core/java/com/android/server/webkit/SystemInterface.java
index 7c934fc..2d7a998 100644
--- a/services/core/java/com/android/server/webkit/SystemInterface.java
+++ b/services/core/java/com/android/server/webkit/SystemInterface.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.ContentObserver;
 import android.webkit.WebViewProviderInfo;
 
 /**
@@ -49,5 +50,6 @@
     public PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo)
             throws NameNotFoundException;
 
-    public void setMultiprocessEnabled(boolean enabled);
+    public void setMultiProcessEnabledFromContext(Context context);
+    public void registerContentObserver(Context context, ContentObserver contentObserver);
 }
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index 57cd768..453e745 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -20,12 +20,10 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.Signature;
-import android.content.ContentResolver;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.util.Base64;
 import android.util.Slog;
 import android.webkit.WebViewFactory;
@@ -79,7 +77,7 @@
     private SystemInterface mSystemInterface;
     private WebViewUpdater mWebViewUpdater;
     private SettingsObserver mSettingsObserver;
-    private Context mContext;
+    final private Context mContext;
 
     public WebViewUpdateServiceImpl(Context context, SystemInterface systemInterface) {
         mContext = context;
@@ -725,15 +723,10 @@
      * appropriately.
      */
     private class SettingsObserver extends ContentObserver {
-        private final ContentResolver mResolver;
-
         SettingsObserver() {
             super(new Handler());
 
-            mResolver = mContext.getContentResolver();
-            mResolver.registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.WEBVIEW_MULTIPROCESS),
-                    false, this);
+            mSystemInterface.registerContentObserver(mContext, this);
 
             // Push the current value of the setting immediately.
             notifyZygote();
@@ -745,15 +738,7 @@
         }
 
         private void notifyZygote() {
-            boolean enableMultiprocess = false;
-
-            try {
-                enableMultiprocess = Settings.Global.getInt(mResolver,
-                        Settings.Global.WEBVIEW_MULTIPROCESS) == 1;
-            } catch (Settings.SettingNotFoundException ex) {
-            }
-
-            mSystemInterface.setMultiprocessEnabled(enableMultiprocess);
+            mSystemInterface.setMultiProcessEnabledFromContext(mContext);
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index a44c8aa..622eece 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -26,22 +26,27 @@
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
 import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowManagerService.logWithStack;
 
+import android.os.Debug;
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.wm.WindowManagerService.H;
 
@@ -398,6 +403,63 @@
         return super.checkCompleteDeferredRemoval();
     }
 
+    void onRemovedFromDisplay() {
+        AppWindowToken startingToken = null;
+
+        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
+
+        boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, voiceInteraction);
+
+        mService.mOpeningApps.remove(this);
+        waitingToShow = false;
+        if (mService.mClosingApps.contains(this)) {
+            delayed = true;
+        } else if (mService.mAppTransition.isTransitionSet()) {
+            mService.mClosingApps.add(this);
+            delayed = true;
+        }
+
+        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + this + " delayed=" + delayed
+                + " animation=" + mAppAnimator.animation + " animating=" + mAppAnimator.animating);
+
+        if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
+                + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
+
+        final TaskStack stack = mTask.mStack;
+        if (delayed && !isEmpty()) {
+            // set the token aside because it has an active animation to be finished
+            if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
+                    "removeAppToken make exiting: " + this);
+            stack.mExitingAppTokens.add(this);
+            mIsExiting = true;
+        } else {
+            // Make sure there is no animation running on this token, so any windows associated
+            // with it will be removed as soon as their animations are complete
+            mAppAnimator.clearAnimation();
+            mAppAnimator.animating = false;
+            removeIfPossible();
+        }
+
+        removed = true;
+        if (startingData != null) {
+            startingToken = this;
+        }
+        stopFreezingScreen(true, true);
+        if (mService.mFocusedApp == this) {
+            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this);
+            mService.mFocusedApp = null;
+            mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
+            mService.mInputMonitor.setFocusedAppLw(null);
+        }
+
+        if (!delayed) {
+            updateReportedVisibilityLocked();
+        }
+
+        // Will only remove if startingToken non null.
+        mService.scheduleRemoveStartingWindowLocked(startingToken);
+    }
+
     void clearAnimatingFlags() {
         boolean wallpaperMightChange = false;
         for (int i = mChildren.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 1960285..ec4cdf2 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -53,6 +53,8 @@
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
@@ -62,7 +64,6 @@
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
@@ -75,6 +76,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
@@ -138,9 +140,6 @@
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
 
 /**
  * Utility class for keeping track of the WindowStates and other pertinent contents of a
@@ -155,14 +154,24 @@
     /** Unique identifier of this stack. */
     private final int mDisplayId;
 
-    // The display only has 2 child window containers. mTaskStackContainers which contains all
-    // window containers that are related to apps (Activities) and mNonAppWindowContainers which
-    // contains all window containers not related to apps (e.g. Status bar).
+    /** The containers below are the only child containers the display can have. */
+    // Contains all window containers that are related to apps (Activities)
     private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
-    private final NonAppWindowContainers mNonAppWindowContainers = new NonAppWindowContainers();
+    // Contains all non-app window containers that should be displayed above the app containers
+    // (e.g. Status bar)
+    private final NonAppWindowContainers mAboveAppWindowsContainers =
+            new NonAppWindowContainers("mAboveAppWindowsContainers");
+    // Contains all non-app window containers that should be displayed below the app containers
+    // (e.g. Wallpaper).
+    private final NonAppWindowContainers mBelowAppWindowsContainers =
+            new NonAppWindowContainers("mBelowAppWindowsContainers");
+    // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
+    // on the IME target. We mainly have this container grouping so we can keep track of all the IME
+    // window containers together and move them in-sync if/when needed.
+    private final NonAppWindowContainers mImeWindowsContainers =
+            new NonAppWindowContainers("mImeWindowsContainers");
 
-    /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
-     * from mDisplayWindows; */
+    // Z-ordered (bottom-most first) list of all Window objects.
     private final WindowList mWindows = new WindowList();
 
     // Mapping from a token IBinder to a WindowToken object on this display.
@@ -185,6 +194,7 @@
     // Accessed directly by all users.
     private boolean mLayoutNeeded;
     int pendingLayoutChanges;
+    // TODO(multi-display): remove some of the usages.
     final boolean isDefaultDisplay;
 
     /** Window tokens that are in the process of exiting, but still on screen for animations. */
@@ -267,8 +277,10 @@
         mDimLayerController = new DimLayerController(this);
 
         // These are the only direct children we should ever have and they are permanent.
+        super.addChild(mBelowAppWindowsContainers, null);
         super.addChild(mTaskStackContainers, null);
-        super.addChild(mNonAppWindowContainers, null);
+        super.addChild(mAboveAppWindowsContainers, null);
+        super.addChild(mImeWindowsContainers, null);
     }
 
     int getDisplayId() {
@@ -302,18 +314,57 @@
         if (token.asAppWindowToken() == null) {
             // Add non-app token to container hierarchy on the display. App tokens are added through
             // the parent container managing them (e.g. Tasks).
-            mNonAppWindowContainers.addChild(token, null);
+            switch (token.windowType) {
+                case TYPE_WALLPAPER:
+                    mBelowAppWindowsContainers.addChild(token);
+                    break;
+                case TYPE_INPUT_METHOD:
+                case TYPE_INPUT_METHOD_DIALOG:
+                    mImeWindowsContainers.addChild(token);
+                    break;
+                default:
+                    mAboveAppWindowsContainers.addChild(token);
+                    break;
+            }
         }
     }
 
     WindowToken removeWindowToken(IBinder binder) {
         final WindowToken token = mTokenMap.remove(binder);
         if (token != null && token.asAppWindowToken() == null) {
-            mNonAppWindowContainers.removeChild(token);
+            switch (token.windowType) {
+                case TYPE_WALLPAPER:
+                    mBelowAppWindowsContainers.removeChild(token);
+                    break;
+                case TYPE_INPUT_METHOD:
+                case TYPE_INPUT_METHOD_DIALOG:
+                    mImeWindowsContainers.removeChild(token);
+                    break;
+                default:
+                    mAboveAppWindowsContainers.removeChild(token);
+                    break;
+            }
         }
         return token;
     }
 
+    void removeAppToken(IBinder binder) {
+        final WindowToken token = removeWindowToken(binder);
+        if (token == null) {
+            Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
+            return;
+        }
+
+        final AppWindowToken appToken = token.asAppWindowToken();
+
+        if (appToken == null) {
+            Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
+            return;
+        }
+
+        appToken.onRemovedFromDisplay();
+    }
+
     Display getDisplay() {
         return mDisplay;
     }
@@ -519,9 +570,72 @@
         out.set(mContentRect);
     }
 
-    /** Refer to {@link WindowManagerService#attachStack(int, int, boolean)} */
-    void attachStack(TaskStack stack, boolean onTop) {
-        mTaskStackContainers.attachStack(stack, onTop);
+    /**
+     * Adds the stack to this display.
+     * @see WindowManagerService#addStackToDisplay(int, int, boolean)
+     */
+    Rect addStackToDisplay(int stackId, boolean onTop) {
+        boolean attachedToDisplay = false;
+        TaskStack stack = mService.mStackIdToStack.get(stackId);
+        if (stack == null) {
+            if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
+                    + mDisplayId);
+
+            stack = getStackById(stackId);
+            if (stack != null) {
+                // It's already attached to the display...clear mDeferRemoval and move stack to
+                // appropriate z-order on display as needed.
+                stack.mDeferRemoval = false;
+                moveStack(stack, onTop);
+                attachedToDisplay = true;
+            } else {
+                stack = new TaskStack(mService, stackId);
+            }
+
+            mService.mStackIdToStack.put(stackId, stack);
+            if (stackId == DOCKED_STACK_ID) {
+                mDividerControllerLocked.notifyDockedStackExistsChanged(true);
+            }
+        } else {
+            final DisplayContent currentDC = stack.getDisplayContent();
+            if (currentDC != null) {
+                throw new IllegalStateException("Trying to add stackId=" + stackId
+                        + "to displayId=" + mDisplayId + ", but it's already attached to displayId="
+                        + currentDC.getDisplayId());
+            }
+        }
+
+        if (!attachedToDisplay) {
+            mTaskStackContainers.addStackToDisplay(stack, onTop);
+        }
+
+        if (stack.getRawFullscreen()) {
+            return null;
+        }
+        final Rect bounds = new Rect();
+        stack.getRawBounds(bounds);
+        return bounds;
+    }
+
+    /** Removes the stack from the display and prepares for changing the parent. */
+    private void removeStackFromDisplay(TaskStack stack) {
+        mTaskStackContainers.removeStackFromDisplay(stack);
+    }
+
+    /** Moves the stack to this display and returns the updated bounds. */
+    Rect moveStackToDisplay(TaskStack stack) {
+        final DisplayContent currentDisplayContent = stack.getDisplayContent();
+        if (currentDisplayContent == null) {
+            throw new IllegalStateException("Trying to move stackId=" + stack.mStackId
+                    + " which is not currently attached to any display");
+        }
+        if (stack.getDisplayContent().getDisplayId() == mDisplayId) {
+            throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId
+                    + " to its current displayId=" + mDisplayId);
+        }
+
+        currentDisplayContent.removeStackFromDisplay(stack);
+        return addStackToDisplay(stack.mStackId, true /* onTop */);
     }
 
     void moveStack(TaskStack stack, boolean toTop) {
@@ -638,7 +752,7 @@
         rebuildAppWindowList();
     }
 
-    void resetAnimationBackgroundAnimator() {
+    private void resetAnimationBackgroundAnimator() {
         for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
             mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator();
         }
@@ -912,7 +1026,7 @@
                     + " mLayoutNeeded=" + mLayoutNeeded);
 
         pw.println();
-        pw.println("  Application tokens in top down Z order:");
+        pw.println(prefix + "Application tokens in top down Z order:");
         for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
             final TaskStack stack = mTaskStackContainers.get(stackNdx);
             stack.dump(prefix + "  ", pw);
@@ -931,11 +1045,11 @@
             }
         }
         pw.println();
-        mDimLayerController.dump(prefix + "  ", pw);
+        mDimLayerController.dump(prefix, pw);
         pw.println();
-        mDividerControllerLocked.dump(prefix + "  ", pw);
+        mDividerControllerLocked.dump(prefix, pw);
         pw.println();
-        mPinnedStackControllerLocked.dump(prefix + "  ", pw);
+        mPinnedStackControllerLocked.dump(prefix, pw);
 
         if (mInputMethodAnimLayerAdjustment != 0) {
             pw.println(subPrefix
@@ -2378,7 +2492,11 @@
             if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
                     pendingLayoutChanges);
 
-            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
+            // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid
+            // the wallpaper window jumping across displays.
+            // Remove check for default display when there will be support for multiple wallpaper
+            // targets (on different displays).
+            if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
                 adjustWallpaperWindows();
             }
 
@@ -3060,9 +3178,13 @@
      * Window container class that contains all containers on this display relating to Apps.
      * I.e Activities.
      */
-    private class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
+    private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
 
-        void attachStack(TaskStack stack, boolean onTop) {
+        /**
+         * Adds the stack to this container.
+         * @see WindowManagerService#addStackToDisplay(int, int, boolean)
+         */
+        void addStackToDisplay(TaskStack stack, boolean onTop) {
             if (stack.mStackId == HOME_STACK_ID) {
                 if (mHomeStack != null) {
                     throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
@@ -3073,6 +3195,21 @@
             stack.onDisplayChanged(DisplayContent.this);
         }
 
+        /** Removes the stack from its container and prepare for changing the parent. */
+        void removeStackFromDisplay(TaskStack stack) {
+            removeChild(stack);
+            stack.onRemovedFromDisplay();
+            // TODO: remove when window list will be gone.
+            // Manually remove records from window list and tap excluded windows list.
+            for (int i = mWindows.size() - 1; i >= 0; --i) {
+                final WindowState windowState = mWindows.get(i);
+                if (stack == windowState.getStack()) {
+                    mWindows.remove(i);
+                    mTapExcludedWindows.remove(windowState);
+                }
+            }
+        }
+
         void moveStack(TaskStack stack, boolean toTop) {
             if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
                 // This stack is always-on-top silly...
@@ -3142,7 +3279,28 @@
      * Window container class that contains all containers on this display that are not related to
      * Apps. E.g. status bar.
      */
-    private static class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
+    private final class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
+        /**
+         * Compares two child window tokens returns -1 if the first is lesser than the second in
+         * terms of z-order and 1 otherwise.
+         */
+        final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
+                // Tokens with higher base layer are z-ordered on-top.
+                mService.mPolicy.windowTypeToLayerLw(token1.windowType)
+                < mService.mPolicy.windowTypeToLayerLw(token2.windowType) ? -1 : 1;
 
+        private final String mName;
+        NonAppWindowContainers(String name) {
+            mName = name;
+        }
+
+        void addChild(WindowToken token) {
+            addChild(token, mWindowComparator);
+        }
+
+        @Override
+        String getName() {
+            return mName;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 743caf8..6326148 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -653,6 +653,14 @@
                 mDelayedImeWin = imeWin;
                 imeWin.mWinAnimator.startDelayingAnimationStart();
             }
+
+            // If we are already waiting for something to be drawn, clear out the old one so it
+            // still gets executed.
+            // TODO: Have a real system where we can wait on different windows to be drawn with
+            // different callbacks.
+            if (mService.mWaitingForDrawnCallback != null) {
+                mService.mWaitingForDrawnCallback.run();
+            }
             mService.mWaitingForDrawnCallback = () -> {
                 mAnimationStartDelayed = false;
                 if (mDelayedImeWin != null) {
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index a488d52..1ccf722 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -34,7 +35,7 @@
 import android.util.Size;
 import android.util.Slog;
 import android.util.TypedValue;
-import android.view.Display;
+import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.IPinnedStackController;
 import android.view.IPinnedStackListener;
@@ -68,9 +69,11 @@
     private boolean mInInteractiveMode;
     private boolean mIsImeShowing;
     private int mImeHeight;
-    private final Rect mPreImeShowingBounds = new Rect();
     private ValueAnimator mBoundsAnimator = null;
 
+    // Used to calculate stack bounds across rotations
+    private final DisplayInfo mDisplayInfo = new DisplayInfo();
+
     // The size and position information that describes where the pinned stack will go by default.
     private int mDefaultStackGravity;
     private Size mDefaultStackSize;
@@ -79,6 +82,7 @@
     // Temp vars for calculation
     private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
     private final Rect mTmpInsets = new Rect();
+    private final Rect mTmpRect = new Rect();
 
     /**
      * The callback object passed to listeners for them to notify the controller of state changes.
@@ -93,7 +97,13 @@
                     mBoundsAnimator.cancel();
                 }
                 mInInteractiveMode = inInteractiveMode;
-                mPreImeShowingBounds.setEmpty();
+            });
+        }
+
+        @Override
+        public void setSnapToEdge(final boolean snapToEdge) {
+            mHandler.post(() -> {
+                mSnapAlgorithm.setSnapToEdge(snapToEdge);
             });
         }
     }
@@ -116,6 +126,7 @@
         mDisplayContent = displayContent;
         mSnapAlgorithm = new PipSnapAlgorithm(service.mContext);
         mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
+        mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
         reloadResources();
     }
 
@@ -159,12 +170,8 @@
      * @return the default bounds to show the PIP when there is no active PIP.
      */
     Rect getDefaultBounds() {
-        final Display display = mDisplayContent.getDisplay();
         final Rect insetBounds = new Rect();
-        final Point displaySize = new Point();
-        display.getRealSize(displaySize);
-        mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mTmpInsets);
-        getInsetBounds(displaySize, mTmpInsets, insetBounds);
+        getInsetBounds(insetBounds);
 
         final Rect defaultBounds = new Rect();
         Gravity.apply(mDefaultStackGravity, mDefaultStackSize.getWidth(),
@@ -177,12 +184,16 @@
      *         controller.
      */
     Rect getMovementBounds(Rect stackBounds) {
-        final Display display = mDisplayContent.getDisplay();
+        return getMovementBounds(stackBounds, true /* adjustForIme */);
+    }
+
+    /**
+     * @return the movement bounds for the given {@param stackBounds} and the current state of the
+     *         controller.
+     */
+    Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
         final Rect movementBounds = new Rect();
-        final Point displaySize = new Point();
-        display.getRealSize(displaySize);
-        mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mTmpInsets);
-        getInsetBounds(displaySize, mTmpInsets, movementBounds);
+        getInsetBounds(movementBounds);
 
         // Adjust the right/bottom to ensure the stack bounds never goes offscreen
         movementBounds.right = Math.max(movementBounds.left, movementBounds.right -
@@ -190,30 +201,34 @@
         movementBounds.bottom = Math.max(movementBounds.top, movementBounds.bottom -
                 stackBounds.height());
 
-        // Adjust the top if the ime is open
-        if (mIsImeShowing) {
-            movementBounds.bottom -= mImeHeight;
+        // Apply the movement bounds adjustments based on the current state
+        if (adjustForIme) {
+            if (mIsImeShowing) {
+                movementBounds.bottom -= mImeHeight;
+            }
         }
-
         return movementBounds;
     }
 
     /**
-     * @return the PIP bounds given it's bounds pre-rotation, and post-rotation (with as applied
-     * by the display content, which currently transposes the dimensions but keeps each stack in
-     * the same physical space on the device).
+     * @return the repositioned PIP bounds given it's pre-change bounds, and the new display info.
      */
-    Rect getPostRotationBounds(Rect preRotationStackBounds, Rect postRotationStackBounds) {
-        // Keep the pinned stack in the same aspect ratio as in the old orientation, but
-        // move it into the position in the rotated space, and snap to the closest space
-        // in the new orientation.
-        final Rect movementBounds = getMovementBounds(preRotationStackBounds);
-        final int stackWidth = preRotationStackBounds.width();
-        final int stackHeight = preRotationStackBounds.height();
-        final int left = postRotationStackBounds.centerX() - (stackWidth / 2);
-        final int top = postRotationStackBounds.centerY() - (stackHeight / 2);
-        final Rect postRotBounds = new Rect(left, top, left + stackWidth, top + stackHeight);
-        return mSnapAlgorithm.findClosestSnapBounds(movementBounds, postRotBounds);
+    Rect onDisplayChanged(Rect preChangeStackBounds, DisplayInfo displayInfo) {
+        final Rect postChangeStackBounds = new Rect(preChangeStackBounds);
+        if (!mDisplayInfo.equals(displayInfo)) {
+            // Calculate the snap fraction of the current stack along the old movement bounds, and
+            // then update the stack bounds to the same fraction along the rotated movement bounds.
+            final Rect preChangeMovementBounds = getMovementBounds(preChangeStackBounds);
+            final float snapFraction = mSnapAlgorithm.getSnapFraction(preChangeStackBounds,
+                    preChangeMovementBounds);
+            mDisplayInfo.copyFrom(displayInfo);
+
+            final Rect postChangeMovementBounds = getMovementBounds(preChangeStackBounds,
+                    false /* adjustForIme */);
+            mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
+                    snapFraction);
+        }
+        return postChangeStackBounds;
     }
 
     /**
@@ -228,7 +243,6 @@
         final Rect stackBounds = new Rect();
         mService.getStackBounds(PINNED_STACK_ID, stackBounds);
         final Rect prevMovementBounds = getMovementBounds(stackBounds);
-        final boolean wasAdjustedForIme = mIsImeShowing;
         mIsImeShowing = adjustedForIme;
         mImeHeight = imeHeight;
         if (mInInteractiveMode) {
@@ -238,31 +252,17 @@
         } else {
             // Otherwise, we can move the PIP to a sane location to ensure that it does not block
             // the user from interacting with the IME
-            Rect toBounds;
-            if (!wasAdjustedForIme && adjustedForIme) {
-                // If we are showing the IME, then store the previous bounds
-                mPreImeShowingBounds.set(stackBounds);
-                toBounds = adjustBoundsInMovementBounds(stackBounds);
-            } else if (wasAdjustedForIme && !adjustedForIme) {
-                if (!mPreImeShowingBounds.isEmpty()) {
-                    // If we are hiding the IME and the user is not interacting with the PIP, restore
-                    // the previous bounds
-                    toBounds = mPreImeShowingBounds;
-                } else {
-                    if (stackBounds.top == prevMovementBounds.bottom) {
-                        // If the PIP is resting on top of the IME, then adjust it with the hiding
-                        // of the IME
-                        final Rect movementBounds = getMovementBounds(stackBounds);
-                        toBounds = new Rect(stackBounds);
-                        toBounds.offsetTo(toBounds.left, movementBounds.bottom);
-                    } else {
-                        // Otherwise, leave the PIP in place
-                        toBounds = stackBounds;
-                    }
-                }
+            final Rect movementBounds = getMovementBounds(stackBounds);
+            final Rect toBounds = new Rect(stackBounds);
+            if (adjustedForIme) {
+                // IME visible
+                toBounds.offset(0, Math.min(0, movementBounds.bottom - stackBounds.top));
             } else {
-                // Otherwise, the IME bounds have changed so we need to adjust the PIP bounds also
-                toBounds = adjustBoundsInMovementBounds(stackBounds);
+                // IME hidden
+                if (stackBounds.top == prevMovementBounds.bottom) {
+                    // If the PIP is resting on top of the IME, then adjust it with the hiding IME
+                    toBounds.offsetTo(toBounds.left, movementBounds.bottom);
+                }
             }
             if (!toBounds.equals(stackBounds)) {
                 if (mBoundsAnimator != null) {
@@ -275,16 +275,6 @@
     }
 
     /**
-     * @return the adjusted {@param stackBounds} such that they are in the movement bounds.
-     */
-    private Rect adjustBoundsInMovementBounds(Rect stackBounds) {
-        final Rect movementBounds = getMovementBounds(stackBounds);
-        final Rect adjustedBounds = new Rect(stackBounds);
-        adjustedBounds.offset(0, Math.min(0, movementBounds.bottom - stackBounds.top));
-        return adjustedBounds;
-    }
-
-    /**
      * Sends a broadcast that the PIP movement bounds have changed.
      */
     private void notifyBoundsChanged(boolean adjustedForIme) {
@@ -300,10 +290,12 @@
     /**
      * @return the bounds on the screen that the PIP can be visible in.
      */
-    private void getInsetBounds(Point displaySize, Rect insets, Rect outRect) {
-        outRect.set(insets.left + mScreenEdgeInsets.x, insets.top + mScreenEdgeInsets.y,
-                displaySize.x - insets.right - mScreenEdgeInsets.x,
-                displaySize.y - insets.bottom - mScreenEdgeInsets.y);
+    private void getInsetBounds(Rect outRect) {
+        mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth,
+                mDisplayInfo.logicalHeight, mTmpInsets);
+        outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y,
+                mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
+                mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
     }
 
     /**
@@ -315,6 +307,11 @@
 
     void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "PinnedStackController");
+        pw.print(prefix + "  defaultBounds="); getDefaultBounds().printShortString(pw);
+        pw.println();
+        mService.getStackBounds(PINNED_STACK_ID, mTmpRect);
+        pw.print(prefix + "  movementBounds="); getMovementBounds(mTmpRect).printShortString(pw);
+        pw.println();
         pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
         pw.println(prefix + "  mInInteractiveMode=" + mInInteractiveMode);
     }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 26f79a9..f038135 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -126,15 +126,6 @@
 
     private final ArrayList<Integer> mChangedStackList = new ArrayList();
 
-    private final ArrayList<WindowToken> mTmpTokensList = new ArrayList();
-
-    // Collection of binder tokens mapped to their window type we are allowed to create window
-    // tokens for but that are not current attached to any display. We need to track this here
-    // because a binder token can be added through {@link WindowManagerService#addWindowToken},
-    // but we don't know what display windows for the token will be added to until
-    // {@link WindowManagerService#addWindow} is called.
-    private final HashMap<IBinder, Integer> mUnattachedBinderTokens = new HashMap();
-
     // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl
     // instances will be replaced with an instance that writes a binary representation of all
     // commands to mSurfaceTraceFd.
@@ -224,49 +215,6 @@
         return dc;
     }
 
-    /** Adds the input stack id to the input display id and returns the bounds of the added stack.*/
-    Rect addStackToDisplay(int stackId, int displayId, boolean onTop) {
-        final DisplayContent dc = getDisplayContent(displayId);
-        if (dc == null) {
-            Slog.w(TAG_WM, "addStackToDisplay: Trying to add stackId=" + stackId
-                    + " to unknown displayId=" + displayId + " callers=" + Debug.getCallers(6));
-            return null;
-        }
-
-        boolean attachedToDisplay = false;
-        TaskStack stack = mService.mStackIdToStack.get(stackId);
-        if (stack == null) {
-            if (DEBUG_STACK) Slog.d(TAG_WM, "attachStack: stackId=" + stackId);
-
-            stack = dc.getStackById(stackId);
-            if (stack != null) {
-                // It's already attached to the display...clear mDeferRemoval and move stack to
-                // appropriate z-order on display as needed.
-                stack.mDeferRemoval = false;
-                dc.moveStack(stack, onTop);
-                attachedToDisplay = true;
-            } else {
-                stack = new TaskStack(mService, stackId);
-            }
-
-            mService.mStackIdToStack.put(stackId, stack);
-            if (stackId == DOCKED_STACK_ID) {
-                dc.mDividerControllerLocked.notifyDockedStackExistsChanged(true);
-            }
-        }
-
-        if (!attachedToDisplay) {
-            dc.attachStack(stack, onTop);
-        }
-
-        if (stack.getRawFullscreen()) {
-            return null;
-        }
-        final Rect bounds = new Rect();
-        stack.getRawBounds(bounds);
-        return bounds;
-    }
-
     boolean isLayoutNeeded() {
         final int numDisplays = mChildren.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
@@ -340,36 +288,6 @@
         return null;
     }
 
-    /** Return the window token associated with the input binder token on the input display */
-    WindowToken getWindowToken(IBinder binder, DisplayContent dc) {
-        final WindowToken token = dc.getWindowToken(binder);
-        if (token != null) {
-            return token;
-        }
-
-        // There is no window token mapped to the binder on the display. Create and map a window
-        // token if it is currently allowed.
-        if (!mUnattachedBinderTokens.containsKey(binder)) {
-            return null;
-        }
-
-        final int type = mUnattachedBinderTokens.get(binder);
-        return new WindowToken(mService, binder, type, true, dc);
-    }
-
-    /** Returns all window tokens mapped to the input binder. */
-    ArrayList<WindowToken> getWindowTokens(IBinder binder) {
-        mTmpTokensList.clear();
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final DisplayContent dc = mChildren.get(i);
-            final WindowToken token = dc.getWindowToken(binder);
-            if (token != null) {
-                mTmpTokensList.add(token);
-            }
-        }
-        return mTmpTokensList;
-    }
-
     /**
      * Returns the app window token for the input binder if it exist in the system.
      * NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since
@@ -403,140 +321,6 @@
         return null;
     }
 
-    void addWindowToken(IBinder binder, int type) {
-        if (mUnattachedBinderTokens.containsKey(binder)) {
-            Slog.w(TAG_WM, "addWindowToken: Attempted to add existing binder token: " + binder);
-            return;
-        }
-
-        final ArrayList<WindowToken> tokens = getWindowTokens(binder);
-
-        if (!tokens.isEmpty()) {
-            Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
-                    + " for already created window tokens: " + tokens);
-            return;
-        }
-
-        mUnattachedBinderTokens.put(binder, type);
-
-        // TODO(multi-display): By default we add this to the default display, but maybe we
-        // should provide an API for a token to be added to any display?
-        final DisplayContent dc = getDisplayContent(DEFAULT_DISPLAY);
-        final WindowToken token = new WindowToken(mService, binder, type, true, dc);
-        if (type == TYPE_WALLPAPER) {
-            dc.mWallpaperController.addWallpaperToken(token);
-        }
-    }
-
-    ArrayList<WindowToken> removeWindowToken(IBinder binder) {
-        mUnattachedBinderTokens.remove(binder);
-
-        mTmpTokensList.clear();
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final DisplayContent dc = mChildren.get(i);
-            final WindowToken token = dc.removeWindowToken(binder);
-            if (token != null) {
-                mTmpTokensList.add(token);
-            }
-        }
-        return mTmpTokensList;
-    }
-
-    /**
-     * Removed the mapping to the input binder for the system if it no longer as a window token
-     * associated with it on any display.
-     */
-    void removeWindowTokenIfPossible(IBinder binder) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final DisplayContent dc = mChildren.get(i);
-            final WindowToken token = dc.getWindowToken(binder);
-            if (token != null) {
-                return;
-            }
-        }
-
-        mUnattachedBinderTokens.remove(binder);
-    }
-
-    void removeAppToken(IBinder binder) {
-        final ArrayList<WindowToken> removedTokens = removeWindowToken(binder);
-        if (removedTokens == null || removedTokens.isEmpty()) {
-            Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
-            return;
-        }
-
-        for (int i = removedTokens.size() - 1; i >= 0; --i) {
-            WindowToken wtoken = removedTokens.get(i);
-            AppWindowToken appToken = wtoken.asAppWindowToken();
-
-            if (appToken == null) {
-                Slog.w(TAG_WM,
-                        "Attempted to remove non-App token: " + binder + " wtoken=" + wtoken);
-                continue;
-            }
-
-            AppWindowToken startingToken = null;
-
-            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + appToken);
-
-            boolean delayed = appToken.setVisibility(null, false, TRANSIT_UNSET, true,
-                    appToken.voiceInteraction);
-
-            mService.mOpeningApps.remove(appToken);
-            mService.mUnknownAppVisibilityController.appRemoved(appToken);
-            appToken.waitingToShow = false;
-            if (mService.mClosingApps.contains(appToken)) {
-                delayed = true;
-            } else if (mService.mAppTransition.isTransitionSet()) {
-                mService.mClosingApps.add(appToken);
-                delayed = true;
-            }
-
-            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app " + appToken
-                    + " delayed=" + delayed
-                    + " animation=" + appToken.mAppAnimator.animation
-                    + " animating=" + appToken.mAppAnimator.animating);
-
-            if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
-                    + appToken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
-
-            final TaskStack stack = appToken.mTask.mStack;
-            if (delayed && !appToken.isEmpty()) {
-                // set the token aside because it has an active animation to be finished
-                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
-                        "removeAppToken make exiting: " + appToken);
-                stack.mExitingAppTokens.add(appToken);
-                appToken.mIsExiting = true;
-            } else {
-                // Make sure there is no animation running on this token, so any windows associated
-                // with it will be removed as soon as their animations are complete
-                appToken.mAppAnimator.clearAnimation();
-                appToken.mAppAnimator.animating = false;
-                appToken.removeIfPossible();
-            }
-
-            appToken.removed = true;
-            if (appToken.startingData != null) {
-                startingToken = appToken;
-            }
-            appToken.stopFreezingScreen(true, true);
-            if (mService.mFocusedApp == appToken) {
-                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + appToken);
-                mService.mFocusedApp = null;
-                mService.updateFocusedWindowLocked(
-                        UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
-                mService.mInputMonitor.setFocusedAppLw(null);
-            }
-
-            if (!delayed) {
-                appToken.updateReportedVisibilityLocked();
-            }
-
-            // Will only remove if startingToken non null.
-            mService.scheduleRemoveStartingWindowLocked(startingToken);
-        }
-    }
-
     // TODO: Users would have their own window containers under the display container?
     void switchUser() {
         final int count = mChildren.size();
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index fff2981..a0270c6 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -387,8 +387,8 @@
         mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
         switch (mStackId) {
             case PINNED_STACK_ID:
-                mTmpRect2 = mDisplayContent.getPinnedStackController().getPostRotationBounds(
-                        mBounds, mTmpRect2);
+                mTmpRect2 = mDisplayContent.getPinnedStackController().onDisplayChanged(mBounds,
+                        getDisplayInfo());
                 break;
             case DOCKED_STACK_ID:
                 repositionDockedStackAfterRotation(mTmpRect2);
@@ -627,6 +627,7 @@
         mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
                 "animation background stackId=" + mStackId);
 
+        final Rect oldBounds = new Rect(mBounds);
         Rect bounds = null;
         final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
         if (mStackId == DOCKED_STACK_ID
@@ -651,6 +652,12 @@
 
         updateDisplayInfo(bounds);
 
+        // Update the pinned stack controller after the display info is updated
+        if (mStackId == PINNED_STACK_ID) {
+            mDisplayContent.getPinnedStackController().onDisplayChanged(oldBounds,
+                    getDisplayInfo());
+        }
+
         super.onDisplayChanged(dc);
     }
 
@@ -786,6 +793,14 @@
     void removeImmediately() {
         super.removeImmediately();
 
+        onRemovedFromDisplay();
+    }
+
+    /**
+     * Removes the stack it from its current parent, so it can be either destroyed completely or
+     * re-parented.
+     */
+    void onRemovedFromDisplay() {
         mDisplayContent.mDimLayerController.removeDimLayerUser(this);
         EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
 
@@ -793,15 +808,13 @@
             mAnimationBackgroundSurface.destroySurface();
             mAnimationBackgroundSurface = null;
         }
-        final DockedStackDividerController dividerController =
-                mDisplayContent.mDividerControllerLocked;
-        mDisplayContent = null;
-
-        mService.mWindowPlacerLocked.requestTraversal();
 
         if (mStackId == DOCKED_STACK_ID) {
-            dividerController.notifyDockedStackExistsChanged(false);
+            mDisplayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(false);
         }
+
+        mDisplayContent = null;
+        mService.mWindowPlacerLocked.requestTraversal();
     }
 
     void resetAnimationBackgroundAnimator() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2fef928..7723752 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1166,8 +1166,8 @@
             final boolean hasParent = parentWindow != null;
             // Use existing parent window token for child windows since they go in the same token
             // as there parent window so we can apply the same policy on them.
-            WindowToken token = mRoot.getWindowToken(
-                    hasParent ? parentWindow.mAttrs.token : attrs.token, displayContent);
+            WindowToken token = displayContent.getWindowToken(
+                    hasParent ? parentWindow.mAttrs.token : attrs.token);
             // If this is a child window, we want to apply the same type checking rules as the
             // parent window type.
             final int rootType = hasParent ? parentWindow.mAttrs.type : type;
@@ -1219,7 +1219,7 @@
                         return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                     }
                 }
-                token = new WindowToken(this, attrs.token, -1, false, displayContent);
+                token = new WindowToken(this, attrs.token, type, false, displayContent);
             } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
                 atoken = token.asAppWindowToken();
                 if (atoken == null) {
@@ -1287,7 +1287,7 @@
                 // It is not valid to use an app token with other system types; we will
                 // instead make a new token for it (as if null had been passed in for the token).
                 attrs.token = null;
-                token = new WindowToken(this, null, -1, false, displayContent);
+                token = new WindowToken(this, null, type, false, displayContent);
             }
 
             WindowState win = new WindowState(this, session, client, token, parentWindow,
@@ -2395,18 +2395,29 @@
     }
 
     @Override
-    public void addWindowToken(IBinder token, int type) {
+    public void addWindowToken(IBinder binder, int type, int displayId) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized(mWindowMap) {
-            mRoot.addWindowToken(token, type);
+            final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
+            WindowToken token = dc.getWindowToken(binder);
+            if (token != null) {
+                Slog.w(TAG_WM, "addWindowToken: Attempted to add binder token: " + binder
+                        + " for already created window token: " + token
+                        + " displayId=" + displayId);
+                return;
+            }
+            token = new WindowToken(this, binder, type, true, dc);
+            if (type == TYPE_WALLPAPER) {
+                dc.mWallpaperController.addWallpaperToken(token);
+            }
         }
     }
 
     @Override
-    public void removeWindowToken(IBinder token) {
+    public void removeWindowToken(IBinder binder, int displayId) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
@@ -2414,22 +2425,26 @@
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mWindowMap) {
-                final ArrayList<WindowToken> removedTokens = mRoot.removeWindowToken(token);
-                if (removedTokens == null || removedTokens.isEmpty()) {
-                    Slog.w(TAG_WM,
-                            "removeWindowToken: Attempted to remove non-existing token: " + token);
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
+                            + " for non-exiting displayId=" + displayId);
                     return;
                 }
 
-                for (int i = removedTokens.size() - 1; i >= 0; --i) {
-                    final WindowToken wtoken = removedTokens.get(i);
-                    wtoken.setExiting();
-                    if (wtoken.windowType == TYPE_WALLPAPER) {
-                        wtoken.getDisplayContent().mWallpaperController.removeWallpaperToken(wtoken);
-                    }
-
-                    mInputMonitor.updateInputWindowsLw(true /*force*/);
+                final WindowToken token = dc.removeWindowToken(binder);
+                if (token == null) {
+                    Slog.w(TAG_WM,
+                            "removeWindowToken: Attempted to remove non-existing token: " + binder);
+                    return;
                 }
+
+                token.setExiting();
+                if (token.windowType == TYPE_WALLPAPER) {
+                    dc.mWallpaperController.removeWallpaperToken(token);
+                }
+
+                mInputMonitor.updateInputWindowsLw(true /*force*/);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -2706,11 +2721,11 @@
     }
 
     void setFocusTaskRegionLocked() {
-        if (mFocusedApp != null) {
-            final Task task = mFocusedApp.mTask;
-            final DisplayContent displayContent = task.getDisplayContent();
+        final Task focusedTask = mFocusedApp != null ? mFocusedApp.mTask : null;
+        if (focusedTask != null) {
+            final DisplayContent displayContent = focusedTask.getDisplayContent();
             if (displayContent != null) {
-                displayContent.setTouchExcludeRegion(task);
+                displayContent.setTouchExcludeRegion(focusedTask);
             }
         }
     }
@@ -3262,7 +3277,7 @@
     }
 
     @Override
-    public void removeAppToken(IBinder token) {
+    public void removeAppToken(IBinder binder, int displayId) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeAppToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
@@ -3270,7 +3285,13 @@
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                mRoot.removeAppToken(token);
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    Slog.w(TAG_WM, "removeAppToken: Attempted to remove binder token: " + binder
+                            + " from non-existing displayId=" + displayId);
+                    return;
+                }
+                dc.removeAppToken(binder);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -3404,24 +3425,63 @@
     }
 
     /**
-     * Create a new TaskStack and place it on a DisplayContent.
+     * Place a TaskStack on a DisplayContent. Will create a new TaskStack if none is found with
+     * specified stackId.
      * @param stackId The unique identifier of the new stack.
      * @param displayId The unique identifier of the DisplayContent.
      * @param onTop If true the stack will be place at the top of the display,
-     *              else at the bottom
-     * @return The initial bounds the stack was created with. null means fullscreen.
+     *              else at the bottom.
+     * @return The bounds that the stack has after adding. null means fullscreen.
      */
-    public Rect attachStack(int stackId, int displayId, boolean onTop) {
+    public Rect addStackToDisplay(int stackId, int displayId, boolean onTop) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mWindowMap) {
-                return mRoot.addStackToDisplay(stackId, displayId, onTop);
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    throw new IllegalArgumentException("Trying to add stackId=" + stackId
+                            + " to unknown displayId=" + displayId);
+                }
+
+                return dc.addStackToDisplay(stackId, onTop);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
     }
 
+    /**
+     * Move a TaskStack from current DisplayContent to specified one.
+     * @param stackId The unique identifier of the new stack.
+     * @param displayId The unique identifier of the new display.
+     */
+    public Rect moveStackToDisplay(int stackId, int displayId) {
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            synchronized (mWindowMap) {
+                TaskStack stack = mStackIdToStack.get(stackId);
+                if (stack == null) {
+                    throw new IllegalArgumentException("Trying to move unknown stackId=" + stackId
+                            + " to displayId=" + displayId);
+                }
+
+                final DisplayContent targetDisplayContent = mRoot.getDisplayContent(displayId);
+                if (targetDisplayContent == null) {
+                    throw new IllegalArgumentException("Trying to move stackId=" + stackId
+                            + " to unknown displayId=" + displayId);
+                }
+
+                return targetDisplayContent.moveStackToDisplay(stack);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    /**
+     * Remove a TaskStack completely.
+     * @param stackId The unique identifier of the stack.
+     */
     public void removeStack(int stackId) {
         synchronized (mWindowMap) {
             final TaskStack stack = mStackIdToStack.get(stackId);
@@ -5790,33 +5850,29 @@
     private boolean mEventDispatchingEnabled;
 
     @Override
-    public void pauseKeyDispatching(IBinder _token) {
+    public void pauseKeyDispatching(IBinder binder) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "pauseKeyDispatching()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized (mWindowMap) {
-            final ArrayList<WindowToken> tokens = mRoot.getWindowTokens(_token);
-            if (tokens != null && !tokens.isEmpty()) {
-                for (int i = tokens.size() - 1; i >= 0; --i) {
-                    mInputMonitor.pauseDispatchingLw(tokens.get(i));
-                }
+            WindowToken token = mRoot.getAppWindowToken(binder);
+            if (token != null) {
+                mInputMonitor.pauseDispatchingLw(token);
             }
         }
     }
 
     @Override
-    public void resumeKeyDispatching(IBinder _token) {
+    public void resumeKeyDispatching(IBinder binder) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "resumeKeyDispatching()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized (mWindowMap) {
-            final ArrayList<WindowToken> tokens = mRoot.getWindowTokens(_token);
-            if (tokens != null && !tokens.isEmpty()) {
-                for (int i = tokens.size() - 1; i >= 0; --i) {
-                    mInputMonitor.resumeDispatchingLw(tokens.get(i));
-                }
+            WindowToken token = mRoot.getAppWindowToken(binder);
+            if (token != null) {
+                mInputMonitor.resumeDispatchingLw(token);
             }
         }
     }
@@ -8071,7 +8127,6 @@
                 pw.println("    a[animator]: animator state");
                 pw.println("    s[essions]: active sessions");
                 pw.println("    surfaces: active surfaces (debugging enabled only)");
-                pw.println("    pip: PIP state");
                 pw.println("    d[isplays]: active display contents");
                 pw.println("    t[okens]: token list");
                 pw.println("    w[indows]: window list");
@@ -8144,18 +8199,6 @@
                     pw.println(output.toString());
                 }
                 return;
-            } else if ("pip".equals(cmd)) {
-                synchronized(mWindowMap) {
-                    pw.print("defaultBounds=");
-                    getPictureInPictureDefaultBounds(DEFAULT_DISPLAY).printShortString(pw);
-                    pw.println();
-                    pw.print("movementBounds=");
-                    getPictureInPictureMovementBounds(DEFAULT_DISPLAY).printShortString(pw);
-                    pw.println();
-                    getDefaultDisplayContentLocked().getPinnedStackController().dump("", pw);
-                    pw.println();
-                }
-                return;
             } else {
                 // Dumping a single name?
                 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
@@ -8807,23 +8850,31 @@
         }
 
         @Override
-        public void addWindowToken(IBinder token, int type) {
-            WindowManagerService.this.addWindowToken(token, type);
+        public void addWindowToken(IBinder token, int type, int displayId) {
+            WindowManagerService.this.addWindowToken(token, type, displayId);
         }
 
         @Override
-        public void removeWindowToken(IBinder token, boolean removeWindows) {
+        public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) {
             synchronized(mWindowMap) {
                 if (removeWindows) {
-                    final ArrayList<WindowToken> removedTokens = mRoot.removeWindowToken(token);
-                    if (removedTokens != null && !removedTokens.isEmpty()) {
-                        for (int i = removedTokens.size() - 1; i >= 0; --i) {
-                            final WindowToken wtoken = removedTokens.get(i);
-                            wtoken.removeAllWindows();
-                        }
+                    final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                    if (dc == null) {
+                        Slog.w(TAG_WM, "removeWindowToken: Attempted to remove token: " + binder
+                                + " for non-exiting displayId=" + displayId);
+                        return;
                     }
+
+                    final WindowToken token = dc.removeWindowToken(binder);
+                    if (token == null) {
+                        Slog.w(TAG_WM, "removeWindowToken: Attempted to remove non-existing token: "
+                                + binder);
+                        return;
+                    }
+
+                    token.removeAllWindows();
                 }
-                WindowManagerService.this.removeWindowToken(token);
+                WindowManagerService.this.removeWindowToken(binder, displayId);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 534a3d2..972c359 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1353,25 +1353,6 @@
     }
 
     /**
-     * Like {@link #isVisibleLw}, but also counts a window that is currently "hidden" behind the
-     * keyguard as visible.  This allows us to apply things like window flags that impact the
-     * keyguard. XXX I am starting to think we need to have ANOTHER visibility flag for this
-     * "hidden behind keyguard" state rather than overloading mPolicyVisibility.  Ungh.
-     */
-    @Override
-    public boolean isVisibleOrBehindKeyguardLw() {
-        if (mToken.waitingToShow && mService.mAppTransition.isTransitionSet()) {
-            return false;
-        }
-        final AppWindowToken atoken = mAppToken;
-        final boolean animating = atoken != null && atoken.mAppAnimator.animation != null;
-        return mHasSurface && !mDestroying && !mAnimatingExit
-                && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
-                && ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mToken.hidden)
-                        || mWinAnimator.mAnimation != null || animating);
-    }
-
-    /**
      * Is this window visible, ignoring its app token? It is not visible if there is no surface,
      * or we are in the process of running an exit animation that will remove the surface.
      */
@@ -1418,14 +1399,6 @@
      * being visible.
      */
     boolean isOnScreen() {
-        return mPolicyVisibility && isOnScreenIgnoringKeyguard();
-    }
-
-    /**
-     * Like isOnScreen(), but ignores any force hiding of the window due
-     * to the keyguard.
-     */
-    private boolean isOnScreenIgnoringKeyguard() {
         if (!mHasSurface || mDestroying) {
             return false;
         }
@@ -1449,7 +1422,7 @@
     boolean mightAffectAllDrawn(boolean visibleOnly) {
         final boolean isViewVisible = (mAppToken == null || !mAppToken.clientHidden)
                 && (mViewVisibility == View.VISIBLE) && !mWindowRemovalAllowed;
-        return (isOnScreenIgnoringKeyguard() && (!visibleOnly || isViewVisible)
+        return (isOnScreen() && (!visibleOnly || isViewVisible)
                 || mWinAnimator.mAttrType == TYPE_BASE_APPLICATION
                 || mWinAnimator.mAttrType == TYPE_DRAWN_APPLICATION)
                 && !mAnimatingExit && !mDestroying;
@@ -1479,28 +1452,6 @@
     }
 
     /**
-     * Like isReadyForDisplay(), but ignores any force hiding of the window due
-     * to the keyguard.
-     */
-    boolean isReadyForDisplayIgnoringKeyguard() {
-        if (mToken.waitingToShow && mService.mAppTransition.isTransitionSet()) {
-            return false;
-        }
-        final AppWindowToken atoken = mAppToken;
-        if (atoken == null && !mPolicyVisibility) {
-            // If this is not an app window, and the policy has asked to force
-            // hide, then we really do want to hide.
-            return false;
-        }
-        return mHasSurface && !mDestroying
-                && ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mToken.hidden)
-                        || mWinAnimator.mAnimation != null
-                        || ((atoken != null) && (atoken.mAppAnimator.animation != null)
-                                && !mWinAnimator.isDummyAnimation())
-                        || isAnimatingWithSavedSurface());
-    }
-
-    /**
      * Like isOnScreen, but returns false if the surface hasn't yet
      * been drawn.
      */
@@ -3771,7 +3722,7 @@
 
         logPerformShow("performShow on ");
 
-        if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplayIgnoringKeyguard()) {
+        if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
             return false;
         }
 
@@ -3821,7 +3772,7 @@
                 || (DEBUG_STARTING_WINDOW && mAttrs.type == TYPE_APPLICATION_STARTING)) {
             Slog.v(TAG, prefix + this
                     + ": mDrawState=" + mWinAnimator.drawStateToString()
-                    + " readyForDisplay=" + isReadyForDisplayIgnoringKeyguard()
+                    + " readyForDisplay=" + isReadyForDisplay()
                     + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING)
                     + " during animation: policyVis=" + mPolicyVisibility
                     + " parentHidden=" + isParentWindowHidden()
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index cf1a98a..b821f09 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -469,7 +469,6 @@
     void removeImmediately() {
         if (mDisplayContent != null) {
             mDisplayContent.removeWindowToken(token);
-            mService.mRoot.removeWindowTokenIfPossible(token);
         }
         // Needs to occur after the token is removed from the display above to avoid attempt at
         // duplicate removal of this window container from it's parent.
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 2c46413..a4b5e6a 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -67,9 +67,11 @@
     libhidl \
     libhwbinder \
     libutils \
-    android.hardware.power@1.0 \
-    android.hardware.vibrator@1.0 \
-    android.hardware.light@2.0 \
-    android.hardware.vr@1.0 \
     android.hardware.audio.common@2.0 \
+    android.hardware.light@2.0 \
+    android.hardware.power@1.0 \
+    android.hardware.thermal@1.0 \
+    android.hardware.tv.cec@1.0 \
     android.hardware.tv.input@1.0 \
+    android.hardware.vibrator@1.0 \
+    android.hardware.vr@1.0 \
diff --git a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
index 14d50ce..a385704 100644
--- a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
+++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
@@ -21,7 +21,7 @@
 
 #include <stdlib.h>
 
-#include <hardware/thermal.h>
+#include <android/hardware/thermal/1.0/IThermal.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 
@@ -29,6 +29,15 @@
 
 namespace android {
 
+using hardware::hidl_vec;
+using hardware::Status;
+using hardware::thermal::V1_0::CoolingDevice;
+using hardware::thermal::V1_0::CpuUsage;
+using hardware::thermal::V1_0::IThermal;
+using hardware::thermal::V1_0::Temperature;
+using hardware::thermal::V1_0::ThermalStatus;
+using hardware::thermal::V1_0::ThermalStatusCode;
+
 // ---------------------------------------------------------------------------
 
 // These values must be kept in sync with the temperature source constants in
@@ -45,136 +54,129 @@
     jmethodID initMethod;
 } gCpuUsageInfoClassInfo;
 
-jfloat gUndefinedTemperature;
-
-static struct thermal_module* gThermalModule;
+static sp<IThermal> gThermalModule;
 
 // ----------------------------------------------------------------------------
 
 static void nativeInit(JNIEnv* env, jobject obj) {
-    status_t err = hw_get_module(THERMAL_HARDWARE_MODULE_ID, (hw_module_t const**)&gThermalModule);
-    if (err) {
-        ALOGE("Couldn't load %s module (%s)", THERMAL_HARDWARE_MODULE_ID, strerror(-err));
+    // TODO(b/31632518)
+    if (gThermalModule == nullptr) {
+        gThermalModule = IThermal::getService("thermal");
+    }
+
+    if (gThermalModule == nullptr) {
+        ALOGE("Undable to get Thermal service.");
     }
 }
 
 static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
-    if (gThermalModule && gThermalModule->getCoolingDevices) {
-        ssize_t list_size = gThermalModule->getCoolingDevices(gThermalModule, nullptr, 0);
-
-        if (list_size >= 0) {
-            cooling_device_t *list = (cooling_device_t *)
-                    malloc(list_size * sizeof(cooling_device_t));
-            ssize_t size = gThermalModule->getCoolingDevices(gThermalModule, list, list_size);
-            if (size >= 0) {
-                if (list_size > size) {
-                    list_size = size;
-                }
-                jfloat values[list_size];
-                for (ssize_t i = 0; i < list_size; ++i) {
-                    values[i] = list[i].current_value;
-                }
-
-                jfloatArray fanSpeeds = env->NewFloatArray(list_size);
-                env->SetFloatArrayRegion(fanSpeeds, 0, list_size, values);
-                free(list);
-                return fanSpeeds;
-            }
-
-            free(list);
-        }
-
-        ALOGE("Cloudn't get fan speeds because of HAL error");
+    if (gThermalModule == nullptr) {
+        ALOGE("Couldn't get fan speeds because of HAL error.");
+        return env->NewFloatArray(0);
     }
-    return env->NewFloatArray(0);
+
+    hidl_vec<CoolingDevice> list;
+    Status status = gThermalModule->getCoolingDevices(
+            [&list](ThermalStatus status, hidl_vec<CoolingDevice> devices) {
+                if (status.code == ThermalStatusCode::SUCCESS) {
+                    list = std::move(devices);
+                } else {
+                    ALOGE("Couldn't get fan speeds because of HAL error: %s",
+                          status.debugMessage.c_str());
+                }
+            }).getStatus();
+
+    if (!status.isOk()) {
+        ALOGE("getCoolingDevices failed status: %d", status.exceptionCode());
+    }
+
+    float values[list.size()];
+    for (size_t i = 0; i < list.size(); ++i) {
+        values[i] = list[i].currentValue;
+    }
+    jfloatArray fanSpeeds = env->NewFloatArray(list.size());
+    env->SetFloatArrayRegion(fanSpeeds, 0, list.size(), values);
+    return fanSpeeds;
 }
 
 static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type,
                                                int source) {
-    if (gThermalModule && gThermalModule->getTemperatures) {
-        ssize_t list_size = gThermalModule->getTemperatures(gThermalModule, nullptr, 0);
-        if (list_size >= 0) {
-            temperature_t *list = (temperature_t *) malloc(list_size * sizeof(temperature_t));
-            ssize_t size = gThermalModule->getTemperatures(gThermalModule, list, list_size);
-            if (size >= 0) {
-                if (list_size > size) {
-                    list_size = size;
-                }
-
-                jfloat values[list_size];
-                size_t length = 0;
-
-                for (ssize_t i = 0; i < list_size; ++i) {
-                    if (list[i].type == type) {
-                        switch (source) {
-                            case TEMPERATURE_CURRENT:
-                                if (list[i].current_value == UNKNOWN_TEMPERATURE) {
-                                    values[length++] = gUndefinedTemperature;
-                                } else {
-                                    values[length++] = list[i].current_value;
-                                }
-                                break;
-                            case TEMPERATURE_THROTTLING:
-                                if (list[i].throttling_threshold == UNKNOWN_TEMPERATURE) {
-                                    values[length++] = gUndefinedTemperature;
-                                } else {
-                                    values[length++] = list[i].throttling_threshold;
-                                }
-                                break;
-                            case TEMPERATURE_SHUTDOWN:
-                                if (list[i].shutdown_threshold == UNKNOWN_TEMPERATURE) {
-                                    values[length++] = gUndefinedTemperature;
-                                } else {
-                                    values[length++] = list[i].shutdown_threshold;
-                                }
-                                break;
-                            case TEMPERATURE_THROTTLING_BELOW_VR_MIN:
-                                if (list[i].vr_throttling_threshold == UNKNOWN_TEMPERATURE) {
-                                    values[length++] = gUndefinedTemperature;
-                                } else {
-                                    values[length++] = list[i].vr_throttling_threshold;
-                                }
-                                break;
-                        }
-                    }
-                }
-                jfloatArray deviceTemps = env->NewFloatArray(length);
-                env->SetFloatArrayRegion(deviceTemps, 0, length, values);
-                free(list);
-                return deviceTemps;
-            }
-            free(list);
-        }
-        ALOGE("Couldn't get device temperatures because of HAL error");
+    if (gThermalModule == nullptr) {
+        ALOGE("Couldn't get device temperatures because of HAL error.");
+        return env->NewFloatArray(0);
     }
-    return env->NewFloatArray(0);
+    hidl_vec<Temperature> list;
+    Status status = gThermalModule->getTemperatures(
+            [&list](ThermalStatus status, hidl_vec<Temperature> temperatures) {
+                if (status.code == ThermalStatusCode::SUCCESS) {
+                    list = std::move(temperatures);
+                } else {
+                    ALOGE("Couldn't get temperatures because of HAL error: %s",
+                          status.debugMessage.c_str());
+                }
+            }).getStatus();
+
+    if (!status.isOk()) {
+        ALOGE("getDeviceTemperatures failed status: %d", status.exceptionCode());
+    }
+
+    jfloat values[list.size()];
+    size_t length = 0;
+    for (size_t i = 0; i < list.size(); ++i) {
+        if (static_cast<int>(list[i].type) == type) {
+            switch (source) {
+                case TEMPERATURE_CURRENT:
+                    values[length++] = list[i].currentValue;
+                    break;
+                case TEMPERATURE_THROTTLING:
+                    values[length++] = list[i].throttlingThreshold;
+                    break;
+                case TEMPERATURE_SHUTDOWN:
+                    values[length++] = list[i].shutdownThreshold;
+                    break;
+                case TEMPERATURE_THROTTLING_BELOW_VR_MIN:
+                    values[length++] = list[i].vrThrottlingThreshold;
+                    break;
+            }
+        }
+    }
+    jfloatArray deviceTemps = env->NewFloatArray(length);
+    env->SetFloatArrayRegion(deviceTemps, 0, length, values);
+    return deviceTemps;
 }
 
 static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) {
-    if (gThermalModule && gThermalModule->getCpuUsages
-            && gCpuUsageInfoClassInfo.initMethod) {
-        ssize_t size = gThermalModule->getCpuUsages(gThermalModule, nullptr);
-        if (size >= 0) {
-            cpu_usage_t *list = (cpu_usage_t *) malloc(size * sizeof(cpu_usage_t));
-            size = gThermalModule->getCpuUsages(gThermalModule, list);
-            if (size >= 0) {
-                jobjectArray cpuUsages = env->NewObjectArray(size, gCpuUsageInfoClassInfo.clazz,
-                        nullptr);
-                for (ssize_t i = 0; i < size; ++i) {
-                    if (list[i].is_online) {
-                        jobject cpuUsage = env->NewObject(gCpuUsageInfoClassInfo.clazz,
-                                gCpuUsageInfoClassInfo.initMethod, list[i].active, list[i].total);
-                        env->SetObjectArrayElement(cpuUsages, i, cpuUsage);
-                    }
-                }
-                free(list);
-                return cpuUsages;
-            }
-            free(list);
-        }
-        ALOGE("Couldn't get CPU usages because of HAL error");
+    if (gThermalModule == nullptr || !gCpuUsageInfoClassInfo.initMethod) {
+        ALOGE("Couldn't get CPU usages because of HAL error.");
+        return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
     }
-    return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
+    hidl_vec<CpuUsage> list;
+    Status status = gThermalModule->getCpuUsages(
+            [&list](ThermalStatus status, hidl_vec<CpuUsage> cpuUsages) {
+                if (status.code == ThermalStatusCode::SUCCESS) {
+                    list = std::move(cpuUsages);
+                } else {
+                    ALOGE("Couldn't get CPU usages because of HAL error: %s",
+                          status.debugMessage.c_str());
+                }
+            }).getStatus();
+
+    if (!status.isOk()) {
+        ALOGE("getCpuUsages failed status: %d", status.exceptionCode());
+    }
+
+    jobjectArray cpuUsages = env->NewObjectArray(list.size(), gCpuUsageInfoClassInfo.clazz,
+                                                 nullptr);
+    for (size_t i = 0; i < list.size(); ++i) {
+        if (list[i].isOnline) {
+            jobject cpuUsage = env->NewObject(gCpuUsageInfoClassInfo.clazz,
+                                              gCpuUsageInfoClassInfo.initMethod,
+                                              list[i].active,
+                                              list[i].total);
+            env->SetObjectArrayElement(cpuUsages, i, cpuUsage);
+        }
+    }
+    return cpuUsages;
 }
 
 // ----------------------------------------------------------------------------
@@ -200,12 +202,6 @@
     gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
     gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz,
                                                          "<init>", "(JJ)V");
-
-    clazz = env->FindClass("android/os/HardwarePropertiesManager");
-    jfieldID undefined_temperature_field = GetStaticFieldIDOrDie(env, clazz,
-                                                                 "UNDEFINED_TEMPERATURE", "F");
-    gUndefinedTemperature = env->GetStaticFloatField(clazz, undefined_temperature_field);
-
     return res;
 }
 
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
index a23fbcb..0c5729e 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -21,16 +21,32 @@
 #include <JNIHelp.h>
 #include <ScopedPrimitiveArray.h>
 
-#include <cstring>
-
+#include <android/hardware/tv/cec/1.0/IHdmiCec.h>
+#include <android/hardware/tv/cec/1.0/IHdmiCecCallback.h>
+#include <android/hardware/tv/cec/1.0/types.h>
 #include <android_os_MessageQueue.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
-#include <hardware/hdmi_cec.h>
 #include <sys/param.h>
+#include <utils/Errors.h>
 #include <utils/Looper.h>
 #include <utils/RefBase.h>
 
+using ::android::hardware::tv::cec::V1_0::CecLogicalAddress;
+using ::android::hardware::tv::cec::V1_0::CecMessage;
+using ::android::hardware::tv::cec::V1_0::HdmiPortInfo;
+using ::android::hardware::tv::cec::V1_0::HotplugEvent;
+using ::android::hardware::tv::cec::V1_0::IHdmiCec;
+using ::android::hardware::tv::cec::V1_0::IHdmiCecCallback;
+using ::android::hardware::tv::cec::V1_0::MaxLength;
+using ::android::hardware::tv::cec::V1_0::OptionKey;
+using ::android::hardware::tv::cec::V1_0::Result;
+using ::android::hardware::tv::cec::V1_0::SendMessageResult;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+
 namespace android {
 
 static struct {
@@ -40,15 +56,13 @@
 
 class HdmiCecController {
 public:
-    HdmiCecController(hdmi_cec_device_t* device, jobject callbacksObj,
-            const sp<Looper>& looper);
-
-    void init();
+    HdmiCecController(sp<IHdmiCec> hdmiCec, jobject callbacksObj, const sp<Looper>& looper);
+    ~HdmiCecController();
 
     // Send message to other device. Note that it runs in IO thread.
-    int sendMessage(const cec_message_t& message);
+    int sendMessage(const CecMessage& message);
     // Add a logical address to device.
-    int addLogicalAddress(cec_logical_address_t address);
+    int addLogicalAddress(CecLogicalAddress address);
     // Clear all logical address registered to the device.
     void clearLogicaladdress();
     // Get physical address of device.
@@ -59,10 +73,12 @@
     uint32_t getVendorId();
     // Get Port information on all the HDMI ports.
     jobjectArray getPortInfos();
-    // Set a flag and its value.
-    void setOption(int flag, int value);
-    // Set audio return channel status.
-    void setAudioReturnChannel(int port, bool flag);
+    // Set an option to CEC HAL.
+    void setOption(OptionKey key, bool enabled);
+    // Informs CEC HAL about the current system language.
+    void setLanguage(hidl_string language);
+    // Enable audio return channel.
+    void enableAudioReturnChannel(int port, bool flag);
     // Whether to hdmi device is connected to the given port.
     bool isConnected(int port);
 
@@ -71,69 +87,48 @@
     }
 
 private:
+    class HdmiCecCallback : public IHdmiCecCallback {
+    public:
+        HdmiCecCallback(HdmiCecController* controller) : mController(controller) {};
+        Return<void> onCecMessage(const CecMessage& event)  override;
+        Return<void> onHotplugEvent(const HotplugEvent& event)  override;
+    private:
+        HdmiCecController* mController;
+    };
+
     static const int INVALID_PHYSICAL_ADDRESS = 0xFFFF;
-    static void onReceived(const hdmi_event_t* event, void* arg);
 
-    hdmi_cec_device_t* mDevice;
+    sp<IHdmiCec> mHdmiCec;
     jobject mCallbacksObj;
+    sp<IHdmiCecCallback> mHdmiCecCallback;
     sp<Looper> mLooper;
 };
 
-// RefBase wrapper for hdmi_event_t. As hdmi_event_t coming from HAL
-// may keep its own lifetime, we need to copy it in order to delegate
-// it to service thread.
-class CecEventWrapper : public LightRefBase<CecEventWrapper> {
-public:
-    explicit CecEventWrapper(const hdmi_event_t& event) {
-        // Copy message.
-        switch (event.type) {
-        case HDMI_EVENT_CEC_MESSAGE:
-            mEvent.cec.initiator = event.cec.initiator;
-            mEvent.cec.destination = event.cec.destination;
-            mEvent.cec.length = event.cec.length;
-            std::memcpy(mEvent.cec.body, event.cec.body, event.cec.length);
-            break;
-        case HDMI_EVENT_HOT_PLUG:
-            mEvent.hotplug.connected = event.hotplug.connected;
-            mEvent.hotplug.port_id = event.hotplug.port_id;
-            break;
-        default:
-            // TODO: add more type whenever new type is introduced.
-            break;
-        }
-    }
-
-    const cec_message_t& cec() const {
-        return mEvent.cec;
-    }
-
-    const hotplug_event_t& hotplug() const {
-        return mEvent.hotplug;
-    }
-
-    virtual ~CecEventWrapper() {}
-
-private:
-    hdmi_event_t mEvent;
-};
-
 // Handler class to delegate incoming message to service thread.
 class HdmiCecEventHandler : public MessageHandler {
 public:
-    HdmiCecEventHandler(HdmiCecController* controller, const sp<CecEventWrapper>& event)
-        : mController(controller),
-          mEventWrapper(event) {
-    }
+    enum EventType {
+        CEC_MESSAGE,
+        HOT_PLUG
+    };
+
+    HdmiCecEventHandler(HdmiCecController* controller, const CecMessage& cecMessage)
+            : mController(controller),
+              mCecMessage(cecMessage) {}
+
+    HdmiCecEventHandler(HdmiCecController* controller, const HotplugEvent& hotplugEvent)
+            : mController(controller),
+              mHotplugEvent(hotplugEvent) {}
 
     virtual ~HdmiCecEventHandler() {}
 
     void handleMessage(const Message& message) {
         switch (message.what) {
-        case HDMI_EVENT_CEC_MESSAGE:
-            propagateCecCommand(mEventWrapper->cec());
+        case EventType::CEC_MESSAGE:
+            propagateCecCommand(mCecMessage);
             break;
-        case HDMI_EVENT_HOT_PLUG:
-            propagateHotplugEvent(mEventWrapper->hotplug());
+        case EventType::HOT_PLUG:
+            propagateHotplugEvent(mHotplugEvent);
             break;
         default:
             // TODO: add more type whenever new type is introduced.
@@ -143,14 +138,13 @@
 
 private:
     // Propagate the message up to Java layer.
-    void propagateCecCommand(const cec_message_t& message) {
-        jint srcAddr = message.initiator;
-        jint dstAddr = message.destination;
+    void propagateCecCommand(const CecMessage& message) {
         JNIEnv* env = AndroidRuntime::getJNIEnv();
-        jbyteArray body = env->NewByteArray(message.length);
-        const jbyte* bodyPtr = reinterpret_cast<const jbyte *>(message.body);
-        env->SetByteArrayRegion(body, 0, message.length, bodyPtr);
-
+        jint srcAddr = static_cast<jint>(message.initiator);
+        jint dstAddr = static_cast<jint>(message.destination);
+        jbyteArray body = env->NewByteArray(message.body.size());
+        const jbyte* bodyPtr = reinterpret_cast<const jbyte *>(message.body.data());
+        env->SetByteArrayRegion(body, 0, message.body.size(), bodyPtr);
         env->CallVoidMethod(mController->getCallbacksObj(),
                 gHdmiCecControllerClassInfo.handleIncomingCecCommand, srcAddr,
                 dstAddr, body);
@@ -159,10 +153,10 @@
         checkAndClearExceptionFromCallback(env, __FUNCTION__);
     }
 
-    void propagateHotplugEvent(const hotplug_event_t& event) {
+    void propagateHotplugEvent(const HotplugEvent& event) {
         // Note that this method should be called in service thread.
         JNIEnv* env = AndroidRuntime::getJNIEnv();
-        jint port = event.port_id;
+        jint port = static_cast<jint>(event.portId);
         jboolean connected = (jboolean) event.connected;
         env->CallVoidMethod(mController->getCallbacksObj(),
                 gHdmiCecControllerClassInfo.handleHotplug, port, connected);
@@ -180,51 +174,83 @@
     }
 
     HdmiCecController* mController;
-    sp<CecEventWrapper> mEventWrapper;
+    CecMessage mCecMessage;
+    HotplugEvent mHotplugEvent;
 };
 
-HdmiCecController::HdmiCecController(hdmi_cec_device_t* device,
-        jobject callbacksObj, const sp<Looper>& looper) :
-    mDevice(device),
-    mCallbacksObj(callbacksObj),
-    mLooper(looper) {
+HdmiCecController::HdmiCecController(sp<IHdmiCec> hdmiCec,
+        jobject callbacksObj, const sp<Looper>& looper)
+        : mHdmiCec(hdmiCec),
+          mCallbacksObj(callbacksObj),
+          mLooper(looper) {
+    mHdmiCecCallback = new HdmiCecCallback(this);
+    Return<void> ret = mHdmiCec->setCallback(mHdmiCecCallback);
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to set a cec callback.");
+    }
 }
 
-void HdmiCecController::init() {
-    mDevice->register_event_callback(mDevice, HdmiCecController::onReceived, this);
+HdmiCecController::~HdmiCecController() {
+    Return<void> ret = mHdmiCec->setCallback(nullptr);
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to set a cec callback.");
+    }
 }
 
-int HdmiCecController::sendMessage(const cec_message_t& message) {
+int HdmiCecController::sendMessage(const CecMessage& message) {
     // TODO: propagate send_message's return value.
-    return mDevice->send_message(mDevice, &message);
+    Return<SendMessageResult> ret = mHdmiCec->sendMessage(message);
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to send CEC message.");
+        return static_cast<int>(SendMessageResult::FAIL);
+    }
+    return static_cast<int>((SendMessageResult) ret);
 }
 
-int HdmiCecController::addLogicalAddress(cec_logical_address_t address) {
-    return mDevice->add_logical_address(mDevice, address);
+int HdmiCecController::addLogicalAddress(CecLogicalAddress address) {
+    Return<Result> ret = mHdmiCec->addLogicalAddress(address);
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to add a logical address.");
+        return static_cast<int>(Result::FAILURE_UNKNOWN);
+    }
+    return static_cast<int>((Result) ret);
 }
 
 void HdmiCecController::clearLogicaladdress() {
-    mDevice->clear_logical_address(mDevice);
+    Return<void> ret = mHdmiCec->clearLogicalAddress();
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to clear logical address.");
+    }
 }
 
 int HdmiCecController::getPhysicalAddress() {
+    Result result;
     uint16_t addr;
-    if (!mDevice->get_physical_address(mDevice, &addr)) {
-        return addr;
+    Return<void> ret = mHdmiCec->getPhysicalAddress([&result, &addr](Result res, uint16_t paddr) {
+            result = res;
+            addr = paddr;
+        });
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to get physical address.");
+        return INVALID_PHYSICAL_ADDRESS;
     }
-    return INVALID_PHYSICAL_ADDRESS;
+    return result == Result::SUCCESS ? addr : INVALID_PHYSICAL_ADDRESS;
 }
 
 int HdmiCecController::getVersion() {
-    int version = 0;
-    mDevice->get_version(mDevice, &version);
-    return version;
+    Return<int32_t> ret = mHdmiCec->getCecVersion();
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to get cec version.");
+    }
+    return ret;
 }
 
 uint32_t HdmiCecController::getVendorId() {
-    uint32_t vendorId = 0;
-    mDevice->get_vendor_id(mDevice, &vendorId);
-    return vendorId;
+    Return<uint32_t> ret = mHdmiCec->getVendorId();
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to get vendor id.");
+    }
+    return ret;
 }
 
 jobjectArray HdmiCecController::getPortInfos() {
@@ -237,48 +263,69 @@
     if (ctor == NULL) {
         return NULL;
     }
-    hdmi_port_info* ports;
-    int numPorts;
-    mDevice->get_port_info(mDevice, &ports, &numPorts);
-    jobjectArray res = env->NewObjectArray(numPorts, hdmiPortInfo, NULL);
+    hidl_vec<HdmiPortInfo> ports;
+    Return<void> ret = mHdmiCec->getPortInfo([&ports](hidl_vec<HdmiPortInfo> list) {
+            ports = list;
+        });
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to get port information.");
+        return NULL;
+    }
+    jobjectArray res = env->NewObjectArray(ports.size(), hdmiPortInfo, NULL);
 
     // MHL support field will be obtained from MHL HAL. Leave it to false.
     jboolean mhlSupported = (jboolean) 0;
-    for (int i = 0; i < numPorts; ++i) {
-        hdmi_port_info* info = &ports[i];
-        jboolean cecSupported = (jboolean) info->cec_supported;
-        jboolean arcSupported = (jboolean) info->arc_supported;
-        jobject infoObj = env->NewObject(hdmiPortInfo, ctor, info->port_id, info->type,
-                info->physical_address, cecSupported, mhlSupported, arcSupported);
+    for (size_t i = 0; i < ports.size(); ++i) {
+        jboolean cecSupported = (jboolean) ports[i].cecSupported;
+        jboolean arcSupported = (jboolean) ports[i].arcSupported;
+        jobject infoObj = env->NewObject(hdmiPortInfo, ctor, ports[i].portId, ports[i].type,
+                ports[i].physicalAddress, cecSupported, mhlSupported, arcSupported);
         env->SetObjectArrayElement(res, i, infoObj);
     }
     return res;
 }
 
-void HdmiCecController::setOption(int flag, int value) {
-    mDevice->set_option(mDevice, flag, value);
+void HdmiCecController::setOption(OptionKey key, bool enabled) {
+    Return<void> ret = mHdmiCec->setOption(key, enabled);
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to set option.");
+    }
 }
 
-// Set audio return channel status.
-  void HdmiCecController::setAudioReturnChannel(int port, bool enabled) {
-    mDevice->set_audio_return_channel(mDevice, port, enabled ? 1 : 0);
+void HdmiCecController::setLanguage(hidl_string language) {
+    Return<void> ret = mHdmiCec->setLanguage(language);
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to set language.");
+    }
+}
+
+// Enable audio return channel.
+void HdmiCecController::enableAudioReturnChannel(int port, bool enabled) {
+    Return<void> ret = mHdmiCec->enableAudioReturnChannel(port, enabled);
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to enable/disable ARC.");
+    }
 }
 
 // Whether to hdmi device is connected to the given port.
 bool HdmiCecController::isConnected(int port) {
-    return mDevice->is_connected(mDevice, port) == HDMI_CONNECTED;
+    Return<bool> ret = mHdmiCec->isConnected(port);
+    if (!ret.getStatus().isOk()) {
+        ALOGE("Failed to get connection info.");
+    }
+    return ret;
 }
 
-// static
-void HdmiCecController::onReceived(const hdmi_event_t* event, void* arg) {
-    HdmiCecController* controller = static_cast<HdmiCecController*>(arg);
-    if (controller == NULL) {
-        return;
-    }
+Return<void> HdmiCecController::HdmiCecCallback::onCecMessage(const CecMessage& message) {
+    sp<HdmiCecEventHandler> handler(new HdmiCecEventHandler(mController, message));
+    mController->mLooper->sendMessage(handler, HdmiCecEventHandler::EventType::CEC_MESSAGE);
+    return Void();
+}
 
-    sp<CecEventWrapper> spEvent(new CecEventWrapper(*event));
-    sp<HdmiCecEventHandler> handler(new HdmiCecEventHandler(controller, spEvent));
-    controller->mLooper->sendMessage(handler, event->type);
+Return<void> HdmiCecController::HdmiCecCallback::onHotplugEvent(const HotplugEvent& event) {
+    sp<HdmiCecEventHandler> handler(new HdmiCecEventHandler(mController, event));
+    mController->mLooper->sendMessage(handler, HdmiCecEventHandler::EventType::HOT_PLUG);
+    return Void();
 }
 
 //------------------------------------------------------------------------------
@@ -288,30 +335,19 @@
 
 static jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj,
         jobject messageQueueObj) {
-    int err;
-    hw_module_t* module;
-    err = hw_get_module(HDMI_CEC_HARDWARE_MODULE_ID,
-            const_cast<const hw_module_t **>(&module));
-    if (err != 0) {
-        ALOGE("Error acquiring hardware module: %d", err);
+    // TODO(b/31632518)
+    sp<IHdmiCec> hdmiCec = IHdmiCec::getService("tv.cec");
+    if (hdmiCec == nullptr) {
+        ALOGE("Couldn't get tv.cec service.");
         return 0;
     }
-
-    hw_device_t* device;
-    err = module->methods->open(module, HDMI_CEC_HARDWARE_INTERFACE, &device);
-    if (err != 0) {
-        ALOGE("Error opening hardware module: %d", err);
-        return 0;
-    }
-
     sp<MessageQueue> messageQueue =
             android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
 
     HdmiCecController* controller = new HdmiCecController(
-            reinterpret_cast<hdmi_cec_device*>(device),
+            hdmiCec,
             env->NewGlobalRef(callbacksObj),
             messageQueue->getLooper());
-    controller->init();
 
     GET_METHOD_ID(gHdmiCecControllerClassInfo.handleIncomingCecCommand, clazz,
             "handleIncomingCecCommand", "(II[B)V");
@@ -323,14 +359,18 @@
 
 static jint nativeSendCecCommand(JNIEnv* env, jclass clazz, jlong controllerPtr,
         jint srcAddr, jint dstAddr, jbyteArray body) {
-    cec_message_t message;
-    message.initiator = static_cast<cec_logical_address_t>(srcAddr);
-    message.destination = static_cast<cec_logical_address_t>(dstAddr);
+    CecMessage message;
+    message.initiator = static_cast<CecLogicalAddress>(srcAddr);
+    message.destination = static_cast<CecLogicalAddress>(dstAddr);
 
     jsize len = env->GetArrayLength(body);
-    message.length = MIN(len, CEC_MESSAGE_BODY_MAX_LENGTH);
     ScopedByteArrayRO bodyPtr(env, body);
-    std::memcpy(message.body, bodyPtr.get(), message.length);
+    size_t bodyLength = MIN(static_cast<size_t>(len),
+            static_cast<size_t>(MaxLength::MESSAGE_BODY));
+    message.body.resize(bodyLength);
+    for (size_t i = 0; i < bodyLength; ++i) {
+        message.body[i] = static_cast<uint8_t>(bodyPtr[i]);
+    }
 
     HdmiCecController* controller =
             reinterpret_cast<HdmiCecController*>(controllerPtr);
@@ -340,7 +380,7 @@
 static jint nativeAddLogicalAddress(JNIEnv* env, jclass clazz, jlong controllerPtr,
         jint logicalAddress) {
     HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
-    return controller->addLogicalAddress(static_cast<cec_logical_address_t>(logicalAddress));
+    return controller->addLogicalAddress(static_cast<CecLogicalAddress>(logicalAddress));
 }
 
 static void nativeClearLogicalAddress(JNIEnv* env, jclass clazz, jlong controllerPtr) {
@@ -370,13 +410,20 @@
 
 static void nativeSetOption(JNIEnv* env, jclass clazz, jlong controllerPtr, jint flag, jint value) {
     HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
-    controller->setOption(flag, value);
+    controller->setOption(static_cast<OptionKey>(flag), value > 0 ? true : false);
 }
 
-static void nativeSetAudioReturnChannel(JNIEnv* env, jclass clazz, jlong controllerPtr,
+static void nativeSetLanguage(JNIEnv* env, jclass clazz, jlong controllerPtr, jstring language) {
+    HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
+    const char *languageStr = env->GetStringUTFChars(language, NULL);
+    controller->setLanguage(languageStr);
+    env->ReleaseStringUTFChars(language, languageStr);
+}
+
+static void nativeEnableAudioReturnChannel(JNIEnv* env, jclass clazz, jlong controllerPtr,
         jint port, jboolean enabled) {
     HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr);
-    controller->setAudioReturnChannel(port, enabled == JNI_TRUE);
+    controller->enableAudioReturnChannel(port, enabled == JNI_TRUE);
 }
 
 static jboolean nativeIsConnected(JNIEnv* env, jclass clazz, jlong controllerPtr, jint port) {
@@ -398,8 +445,9 @@
     { "nativeGetPortInfos",
       "(J)[Landroid/hardware/hdmi/HdmiPortInfo;",
       (void *) nativeGetPortInfos },
-    { "nativeSetOption", "(JII)V", (void *) nativeSetOption },
-    { "nativeSetAudioReturnChannel", "(JIZ)V", (void *) nativeSetAudioReturnChannel },
+    { "nativeSetOption", "(JIZ)V", (void *) nativeSetOption },
+    { "nativeSetLanguage", "(JLjava/lang/String;)V", (void *) nativeSetLanguage },
+    { "nativeEnableAudioReturnChannel", "(JIZ)V", (void *) nativeEnableAudioReturnChannel },
     { "nativeIsConnected", "(JI)Z", (void *) nativeIsConnected },
 };
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 42b5dc0..0ea8d4e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -51,6 +51,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.IDevicePolicyManager;
+import android.app.admin.NetworkEvent;
 import android.app.admin.PasswordMetrics;
 import android.app.admin.SecurityLog;
 import android.app.admin.SecurityLog.SecurityEvent;
@@ -6161,6 +6162,9 @@
         return hasUserSetupCompleted(UserHandle.getCallingUserId());
     }
 
+    // This checks only if the Setup Wizard has run.  Since Wear devices pair before
+    // completing Setup Wizard, and pairing involves transferring user data, calling
+    // logic may want to check mIsWatch or mPaired in addition to hasUserSetupCompleted().
     private boolean hasUserSetupCompleted(int userHandle) {
         if (!mHasFeature) {
             return true;
@@ -6409,7 +6413,7 @@
                     + "already has a device owner.");
         }
         if (isAdb()) {
-            if (hasUserSetupCompleted(userHandle)
+            if ((mIsWatch || hasUserSetupCompleted(userHandle))
                     && hasIncompatibleAccountsLocked(userHandle, owner)) {
                 throw new IllegalStateException("Not allowed to set the profile owner because "
                         + "there are already some accounts on the profile");
@@ -6417,7 +6421,7 @@
             return;
         }
         enforceCanManageProfileAndDeviceOwners();
-        if (hasUserSetupCompleted(userHandle) && !isCallerWithSystemUid()) {
+        if ((mIsWatch || hasUserSetupCompleted(userHandle)) && !isCallerWithSystemUid()) {
             throw new IllegalStateException("Cannot set the profile owner on a user which is "
                     + "already set-up");
         }
@@ -8708,6 +8712,9 @@
             if (hasUserSetupCompleted(callingUserId)) {
                 return false;
             }
+            if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
+                return false;
+            }
             return true;
         } else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE.equals(action)) {
             if (!mInjector.userManagerIsSplitSystemUser()) {
@@ -8739,7 +8746,7 @@
         }
         if (isAdb) {
             // if shell command runs after user setup completed check device status. Otherwise, OK.
-            if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
+            if (mIsWatch || hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
                 if (!mInjector.userManagerIsSplitSystemUser()) {
                     if (mUserManager.getUserCount() > 1) {
                         return CODE_NONSYSTEM_USER_EXISTS;
@@ -9106,20 +9113,19 @@
     }
 
     private synchronized void disableDeviceOwnerManagedSingleUserFeaturesIfNeeded() {
+        if (!mOwners.hasDeviceOwner()) {
+            return;
+        }
         if (!isDeviceOwnerManagedSingleUserDevice()) {
             mInjector.securityLogSetLoggingEnabledProperty(false);
-            Slog.w(LOG_TAG, "Security logging turned off as it's no longer a single user device.");
 
             getDeviceOwnerAdminLocked().isNetworkLoggingEnabled = false;
             saveSettingsLocked(mInjector.userHandleGetCallingUserId());
             setNetworkLoggingActiveInternal(false);
-            Slog.w(LOG_TAG, "Network logging turned off as it's no longer a single user"
-                    + " device.");
 
-            if (mOwners.hasDeviceOwner()) {
-                setBackupServiceEnabledInternal(false);
-                Slog.w(LOG_TAG, "Backup is off as it's a managed device that has more that one user.");
-            }
+            setBackupServiceEnabledInternal(false);
+            Slog.w(LOG_TAG, "Security logging, network logging and backup service turned off as"
+                    + " it's not a single user device.");
         }
     }
 
@@ -9558,4 +9564,23 @@
         ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
         return (deviceOwner != null) && deviceOwner.isNetworkLoggingEnabled;
     }
+
+    /*
+     * A maximum of 1200 events are returned, and the total marshalled size is in the order of
+     * 100kB, so returning a List instead of ParceledListSlice is acceptable.
+     * Ideally this would be done with ParceledList, however it only supports homogeneous types.
+     */
+    @Override
+    public synchronized List<NetworkEvent> retrieveNetworkLogs(ComponentName admin) {
+        if (!mHasFeature) {
+            return null;
+        }
+        Preconditions.checkNotNull(admin);
+        ensureDeviceOwnerManagingSingleUser(admin);
+
+        if (mNetworkLogger == null) {
+            return null;
+        }
+        return isNetworkLoggingEnabledInternal() ? mNetworkLogger.retrieveLogs() : null;
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
index db17ca2..185ccc2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
@@ -16,9 +16,16 @@
 
 package com.android.server.devicepolicy;
 
+import android.app.admin.ConnectEvent;
+import android.app.admin.DnsEvent;
+import android.app.admin.NetworkEvent;
 import android.content.pm.PackageManagerInternal;
 import android.net.IIpConnectivityMetrics;
 import android.net.INetdEventCallback;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.Slog;
@@ -40,6 +47,8 @@
     private final PackageManagerInternal mPm;
 
     private IIpConnectivityMetrics mIpConnectivityMetrics;
+    private ServiceThread mHandlerThread;
+    private NetworkLoggingHandler mNetworkLoggingHandler;
     private boolean mIsLoggingEnabled;
 
     private final INetdEventCallback mNetdEventCallback = new INetdEventCallback.Stub() {
@@ -49,7 +58,9 @@
             if (!mIsLoggingEnabled) {
                 return;
             }
-            // TODO(mkarpinski): send msg with data to Handler
+            DnsEvent dnsEvent = new DnsEvent(hostname, ipAddresses, ipAddressesCount,
+                    mPm.getNameForUid(uid), timestamp);
+            sendNetworkEvent(dnsEvent);
         }
 
         @Override
@@ -57,7 +68,18 @@
             if (!mIsLoggingEnabled) {
                 return;
             }
-            // TODO(mkarpinski): send msg with data to Handler
+            ConnectEvent connectEvent = new ConnectEvent(ipAddr, port, mPm.getNameForUid(uid),
+                    timestamp);
+            sendNetworkEvent(connectEvent);
+        }
+
+        private void sendNetworkEvent(NetworkEvent event) {
+            Message msg = mNetworkLoggingHandler.obtainMessage(
+                    NetworkLoggingHandler.LOG_NETWORK_EVENT_MSG);
+            Bundle bundle = new Bundle();
+            bundle.putParcelable(NetworkLoggingHandler.NETWORK_EVENT_KEY, event);
+            msg.setData(bundle);
+            mNetworkLoggingHandler.sendMessage(msg);
         }
     };
 
@@ -87,7 +109,13 @@
         }
         try {
            if (mIpConnectivityMetrics.registerNetdEventCallback(mNetdEventCallback)) {
-                // TODO(mkarpinski): start a new ServiceThread, instantiate a Handler etc.
+                mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
+                        /* allowIo */ false);
+                mHandlerThread.start();
+                mNetworkLoggingHandler = new NetworkLoggingHandler(mHandlerThread.getLooper(),
+                        mDpm);
+                mNetworkLoggingHandler.scheduleBatchFinalization(
+                        NetworkLoggingHandler.BATCH_FINALIZATION_TIMEOUT_MS);
                 mIsLoggingEnabled = true;
                 return true;
             } else {
@@ -101,7 +129,7 @@
 
     boolean stopNetworkLogging() {
         Log.d(TAG, "Stopping network logging");
-        // stop the logging regardless of whether we failed to unregister listener
+        // stop the logging regardless of whether we fail to unregister listener
         mIsLoggingEnabled = false;
         try {
             if (!checkIpConnectivityMetricsService()) {
@@ -114,8 +142,12 @@
         } catch (RemoteException re) {
             Slog.wtf(TAG, "Failed to make remote calls to unregister the callback", re);
         } finally {
-            // TODO(mkarpinski): quitSafely() the Handler
+            mHandlerThread.quitSafely();
             return true;
         }
     }
+
+    List<NetworkEvent> retrieveLogs() {
+        return mNetworkLoggingHandler.retrieveFullLogBatch();
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
new file mode 100644
index 0000000..96884e6
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
@@ -0,0 +1,113 @@
+/*
+ * 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.devicepolicy;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.ConnectEvent;
+import android.app.admin.DnsEvent;
+import android.app.admin.NetworkEvent;
+import android.net.IIpConnectivityMetrics;
+import android.net.INetdEventCallback;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A Handler class for managing network logging on a background thread.
+ */
+final class NetworkLoggingHandler extends Handler {
+
+    private static final String TAG = NetworkLoggingHandler.class.getSimpleName();
+
+    static final String NETWORK_EVENT_KEY = "network_event";
+
+    // est. ~128kB of memory usage per full batch TODO(mkarpinski): fine tune based on testing data
+    // If this value changes, update DevicePolicyManager#retrieveNetworkLogs() javadoc
+    private static final int MAX_EVENTS_PER_BATCH = 1200;
+    static final long BATCH_FINALIZATION_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(90);
+
+    static final int LOG_NETWORK_EVENT_MSG = 1;
+    static final int FINALIZE_BATCH_MSG = 2;
+
+    private final DevicePolicyManagerService mDpm;
+
+    // threadsafe as it's Handler's thread confined
+    private ArrayList<NetworkEvent> mNetworkEvents = new ArrayList<NetworkEvent>();
+
+    @GuardedBy("this")
+    private ArrayList<NetworkEvent> mFullBatch;
+
+    NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm) {
+        super(looper);
+        mDpm = dpm;
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        switch (msg.what) {
+            case LOG_NETWORK_EVENT_MSG: {
+                NetworkEvent networkEvent = msg.getData().getParcelable(NETWORK_EVENT_KEY);
+                if (networkEvent != null) {
+                    mNetworkEvents.add(networkEvent);
+                    if (mNetworkEvents.size() >= MAX_EVENTS_PER_BATCH) {
+                        finalizeBatchAndNotifyDeviceOwner();
+                    }
+                }
+                break;
+            }
+            case FINALIZE_BATCH_MSG: {
+                finalizeBatchAndNotifyDeviceOwner();
+                break;
+            }
+        }
+    }
+
+    void scheduleBatchFinalization(long delay) {
+        removeMessages(FINALIZE_BATCH_MSG);
+        sendMessageDelayed(obtainMessage(FINALIZE_BATCH_MSG), delay);
+    }
+
+    private synchronized void finalizeBatchAndNotifyDeviceOwner() {
+        mFullBatch = mNetworkEvents;
+        // start a new batch from scratch
+        mNetworkEvents = new ArrayList<NetworkEvent>();
+        scheduleBatchFinalization(BATCH_FINALIZATION_TIMEOUT_MS);
+        // notify DO that there's a new non-empty batch waiting
+        if (mFullBatch.size() > 0) {
+            mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE,
+                    /* extras */ null);
+        } else {
+            mFullBatch = null;
+        }
+    }
+
+    synchronized List<NetworkEvent> retrieveFullLogBatch() {
+        List<NetworkEvent> ret = mFullBatch;
+        mFullBatch = null;
+        return ret;
+    }
+}
+
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 62947eb..cc96f56 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -156,8 +156,8 @@
             "com.android.server.midi.MidiService$Lifecycle";
     private static final String WIFI_SERVICE_CLASS =
             "com.android.server.wifi.WifiService";
-    private static final String WIFI_NAN_SERVICE_CLASS =
-            "com.android.server.wifi.nan.WifiNanService";
+    private static final String WIFI_AWARE_SERVICE_CLASS =
+            "com.android.server.wifi.aware.WifiAwareService";
     private static final String WIFI_P2P_SERVICE_CLASS =
             "com.android.server.wifi.p2p.WifiP2pService";
     private static final String ETHERNET_SERVICE_CLASS =
@@ -910,12 +910,13 @@
                 }
                 traceEnd();
 
-                if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_NAN)) {
-                    traceBeginAndSlog("StartWifiNan");
-                    mSystemServiceManager.startService(WIFI_NAN_SERVICE_CLASS);
+                if (context.getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_WIFI_AWARE)) {
+                    traceBeginAndSlog("StartWifiAware");
+                    mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS);
                     traceEnd();
                 } else {
-                    Slog.i(TAG, "No Wi-Fi NAN Service (NAN support Not Present)");
+                    Slog.i(TAG, "No Wi-Fi Aware Service (Aware support Not Present)");
                 }
 
                 if (context.getPackageManager().hasSystemFeature(
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index ad432d1..629146f 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -18,6 +18,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+
 import com.android.internal.util.FastXmlSerializer;
 
 import org.mockito.Mock;
@@ -52,6 +53,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.when;
 
 @SmallTest
@@ -74,6 +76,8 @@
     private RankingHelper mHelper;
     private final String pkg = "com.android.server.notification";
     private final int uid = 0;
+    private final String pkg2 = "pkg2";
+    private final int uid2 = 1111111;
 
     private Context getContext() {
         return InstrumentationRegistry.getTargetContext();
@@ -134,8 +138,11 @@
 
         final ApplicationInfo legacy = new ApplicationInfo();
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+        final ApplicationInfo upgrade = new ApplicationInfo();
+        upgrade.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
         try {
-            when(mPm.getApplicationInfo(anyString(), anyInt())).thenReturn(legacy);
+            when(mPm.getApplicationInfoAsUser(eq(pkg), anyInt(), anyInt())).thenReturn(legacy);
+            when(mPm.getApplicationInfoAsUser(eq(pkg2), anyInt(), anyInt())).thenReturn(upgrade);
         } catch (PackageManager.NameNotFoundException e) {}
     }
 
@@ -270,16 +277,16 @@
     }
 
     @Test
-    public void testChannelXml_defaultChannelUpdatedApp() throws Exception {
-        final ApplicationInfo updated = new ApplicationInfo();
-        updated.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
-        when(mPm.getApplicationInfo(anyString(), anyInt())).thenReturn(updated);
-
-        NotificationChannel channel1 =
+    public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception {
+         NotificationChannel channel1 =
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_MIN);
-
         mHelper.createNotificationChannel(pkg, uid, channel1);
 
+        final NotificationChannel defaultChannel =
+                mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+        defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mHelper.updateNotificationChannel(pkg, uid, defaultChannel);
+
         ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(),
                 NotificationChannel.DEFAULT_CHANNEL_ID);
 
@@ -293,60 +300,156 @@
                 pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID).getImportance());
     }
 
-    // TODO: test with hardcoded N xml.
     @Test
     public void testChannelXml_upgradeCreateDefaultChannel() throws Exception {
-        mHelper.setImportance(pkg, uid, NotificationManager.IMPORTANCE_HIGH);
-        mHelper.setPriority(pkg, uid, Notification.PRIORITY_MAX);
-        mHelper.setVisibilityOverride(pkg, uid, Notification.VISIBILITY_SECRET);
-        // pre-O xml won't have channels.
-        mHelper.deleteNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
-
-        ByteArrayOutputStream baos =
-                writeXmlAndPurge(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
-
+        final String preupgradeXml = "<ranking version=\"1\">\n"
+             + "<package name=\"" + pkg + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH
+            + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\""
+            + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + uid + "\" />\n"
+            + "<package name=\"" + pkg2 + "\" uid=\"" + uid2 + "\" visibility=\""
+            + Notification.VISIBILITY_PRIVATE + "\" />\n"
+            + "</ranking>";
         XmlPullParser parser = Xml.newPullParser();
-        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
-                null);
+        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
+            null);
         parser.nextTag();
         mHelper.readXml(parser, false);
 
-        final NotificationChannel updated =
-                mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
-        assertEquals(NotificationManager.IMPORTANCE_HIGH, updated.getImportance());
-        assertTrue(updated.canBypassDnd());
-        assertEquals(Notification.VISIBILITY_SECRET, updated.getLockscreenVisibility());
+        final NotificationChannel updated1 =
+            mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+        assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance());
+        assertTrue(updated1.canBypassDnd());
+        assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility());
         assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE
-                | NotificationChannel.USER_LOCKED_PRIORITY
-                | NotificationChannel.USER_LOCKED_VISIBILITY, updated.getUserLockedFields());
+            | NotificationChannel.USER_LOCKED_PRIORITY
+            | NotificationChannel.USER_LOCKED_VISIBILITY, updated1.getUserLockedFields());
+
+        final NotificationChannel updated2 =
+            mHelper.getNotificationChannel(pkg2, uid2, NotificationChannel.DEFAULT_CHANNEL_ID);
+        // clamped
+        assertEquals(NotificationManager.IMPORTANCE_LOW, updated2.getImportance());
+        assertFalse(updated2.canBypassDnd());
+        assertEquals(Notification.VISIBILITY_PRIVATE, updated2.getLockscreenVisibility());
+        assertEquals(NotificationChannel.USER_LOCKED_VISIBILITY, updated2.getUserLockedFields());
     }
 
-    // TODO: test lock individually.
     @Test
-    public void testUpdate_userLockedChannelFields() throws Exception {
+    public void testUpdate_userLockedImportance() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setRingtone(new Uri.Builder().scheme("test").build());
-        channel.setLights(true);
-        channel.setBypassDnd(true);
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+
+        mHelper.createNotificationChannel(pkg, uid, channel);
+
+        // same id, try to update
+        final NotificationChannel channel2 =
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+
+        mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+
+        // no fields should be changed
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+    }
+
+    @Test
+    public void testUpdate_userLockedVisibility() throws Exception {
+        // all fields locked by user
+        final NotificationChannel channel =
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
-        channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE
-                | NotificationChannel.USER_LOCKED_VISIBILITY
-                | NotificationChannel.USER_LOCKED_VIBRATION
-                | NotificationChannel.USER_LOCKED_LIGHTS
-                | NotificationChannel.USER_LOCKED_PRIORITY
-                | NotificationChannel.USER_LOCKED_RINGTONE);
+        channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
+
+        mHelper.createNotificationChannel(pkg, uid, channel);
+
+        // same id, try to update
+        final NotificationChannel channel2 =
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
+
+        mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+
+        // no fields should be changed
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+    }
+
+    @Test
+    public void testUpdate_userLockedVibration() throws Exception {
+        // all fields locked by user
+        final NotificationChannel channel =
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setLights(false);
+        channel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
+
+        mHelper.createNotificationChannel(pkg, uid, channel);
+
+        // same id, try to update
+        final NotificationChannel channel2 =
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setVibration(true);
+
+        mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+
+        // no fields should be changed
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+    }
+
+    @Test
+    public void testUpdate_userLockedLights() throws Exception {
+        // all fields locked by user
+        final NotificationChannel channel =
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setLights(false);
+        channel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
+
+        mHelper.createNotificationChannel(pkg, uid, channel);
+
+        // same id, try to update
+        final NotificationChannel channel2 =
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setLights(true);
+
+        mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+
+        // no fields should be changed
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+    }
+
+    @Test
+    public void testUpdate_userLockedPriority() throws Exception {
+        // all fields locked by user
+        final NotificationChannel channel =
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setBypassDnd(true);
+        channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
 
         mHelper.createNotificationChannel(pkg, uid, channel);
 
         // same id, try to update all fields
         final NotificationChannel channel2 =
-                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
-        channel2.setRingtone(new Uri.Builder().scheme("test2").build());
-        channel2.setLights(false);
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
         channel2.setBypassDnd(false);
-        channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
+
+        mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+
+        // no fields should be changed
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+    }
+
+    @Test
+    public void testUpdate_userLockedRingtone() throws Exception {
+        // all fields locked by user
+        final NotificationChannel channel =
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setRingtone(new Uri.Builder().scheme("test").build());
+        channel.lockFields(NotificationChannel.USER_LOCKED_RINGTONE);
+
+        mHelper.createNotificationChannel(pkg, uid, channel);
+
+        // same id, try to update all fields
+        final NotificationChannel channel2 =
+            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setRingtone(new Uri.Builder().scheme("test2").build());
 
         mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
 
diff --git a/services/tests/runtests.py b/services/tests/runtests.py
index 35fec90f..7980dc2 100755
--- a/services/tests/runtests.py
+++ b/services/tests/runtests.py
@@ -61,8 +61,8 @@
 
     print 'Running tests...'
     if len(sys.argv) != 1:
-        run('adb shell am instrument -w "%s" %s' %
-            (INSTRUMENTED_PACKAGE_RUNNER, ' '.join(sys.argv[1:])))
+        run('adb shell am instrument -w %s "%s"' %
+            (' '.join(sys.argv[1:]), INSTRUMENTED_PACKAGE_RUNNER))
         return 0
 
     # It would be nice if the activity manager accepted a list of packages, but
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 25a421e..42d9412 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -246,7 +246,7 @@
                 Log.d(TAG, "set mUidObserver to " + mUidObserver);
                 return null;
             }
-        }).when(mActivityManager).registerUidObserver(any(), anyInt());
+        }).when(mActivityManager).registerUidObserver(any(), anyInt(), null);
 
         mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
                 mNetworkManager, mIpm, mTime, mPolicyDir, true);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
new file mode 100644
index 0000000..cb5e8bb
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
@@ -0,0 +1,827 @@
+/*
+ * 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.accessibility;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.animation.ValueAnimator;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.MagnificationSpec;
+import android.view.WindowManagerInternal;
+import android.view.WindowManagerInternal.MagnificationCallbacks;
+
+import com.android.internal.R;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.Locale;
+
+@RunWith(AndroidJUnit4.class)
+public class MagnificationControllerTest {
+    static final Rect INITIAL_MAGNIFICATION_BOUNDS = new Rect(0, 0, 100, 200);
+    static final PointF INITIAL_MAGNIFICATION_BOUNDS_CENTER = new PointF(
+            INITIAL_MAGNIFICATION_BOUNDS.centerX(), INITIAL_MAGNIFICATION_BOUNDS.centerY());
+    static final PointF INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER = new PointF(25, 50);
+    static final PointF INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER = new PointF(75, 150);
+    static final Rect OTHER_MAGNIFICATION_BOUNDS = new Rect(100, 200, 500, 600);
+    static final PointF OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER = new PointF(400, 500);
+    static final Region INITIAL_MAGNIFICATION_REGION = new Region(INITIAL_MAGNIFICATION_BOUNDS);
+    static final Region OTHER_REGION = new Region(OTHER_MAGNIFICATION_BOUNDS);
+    static final int SERVICE_ID_1 = 1;
+    static final int SERVICE_ID_2 = 2;
+
+    final Context mMockContext = mock(Context.class);
+    final AccessibilityManagerService mMockAms = mock(AccessibilityManagerService.class);
+    final WindowManagerInternal mMockWindowManager = mock(WindowManagerInternal.class);
+    final MessageCapturingHandler mMessageCapturingHandler =
+            new MessageCapturingHandler(new Handler.Callback() {
+        @Override
+        public boolean handleMessage(Message msg) {
+            return mMagnificationController.handleMessage(msg);
+        }
+    });
+    final ArgumentCaptor<MagnificationSpec> mMagnificationSpecCaptor =
+            ArgumentCaptor.forClass(MagnificationSpec.class);
+    final ValueAnimator mMockValueAnimator = mock(ValueAnimator.class);
+    MagnificationController.SettingsBridge mMockSettingsBridge;
+
+
+    MagnificationController mMagnificationController;
+    ValueAnimator.AnimatorUpdateListener mTargetAnimationListener;
+
+    @BeforeClass
+    public static void oneTimeInitialization() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+    }
+
+    @Before
+    public void setUp() {
+        when(mMockContext.getMainLooper()).thenReturn(Looper.myLooper());
+        Resources mockResources = mock(Resources.class);
+        when(mMockContext.getResources()).thenReturn(mockResources);
+        when(mockResources.getInteger(R.integer.config_longAnimTime))
+                .thenReturn(1000);
+        mMockSettingsBridge = mock(MagnificationController.SettingsBridge.class);
+        mMagnificationController = new MagnificationController(mMockContext, mMockAms, new Object(),
+                mMessageCapturingHandler, mMockWindowManager, mMockValueAnimator,
+                mMockSettingsBridge);
+
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
+                Object[] args = invocationOnMock.getArguments();
+                Region regionArg = (Region) args[0];
+                regionArg.set(INITIAL_MAGNIFICATION_REGION);
+                return null;
+            }
+        }).when(mMockWindowManager).getMagnificationRegion((Region) anyObject());
+
+        ArgumentCaptor<ValueAnimator.AnimatorUpdateListener> listenerArgumentCaptor =
+                ArgumentCaptor.forClass(ValueAnimator.AnimatorUpdateListener.class);
+        verify(mMockValueAnimator).addUpdateListener(listenerArgumentCaptor.capture());
+        mTargetAnimationListener = listenerArgumentCaptor.getValue();
+        Mockito.reset(mMockValueAnimator); // Ignore other initialization
+    }
+
+    @Test
+    public void testRegister_WindowManagerAndContextRegisterListeners() {
+        mMagnificationController.register();
+        verify(mMockContext).registerReceiver(
+                (BroadcastReceiver) anyObject(), (IntentFilter) anyObject());
+        verify(mMockWindowManager).setMagnificationCallbacks((MagnificationCallbacks) anyObject());
+        assertTrue(mMagnificationController.isRegisteredLocked());
+    }
+
+    @Test
+    public void testRegister_WindowManagerAndContextUnregisterListeners() {
+        mMagnificationController.register();
+        mMagnificationController.unregister();
+
+        verify(mMockContext).unregisterReceiver((BroadcastReceiver) anyObject());
+        verify(mMockWindowManager).setMagnificationCallbacks(null);
+        assertFalse(mMagnificationController.isRegisteredLocked());
+    }
+
+    @Test
+    public void testInitialState_noMagnificationAndMagnificationRegionReadFromWindowManager() {
+        mMagnificationController.register();
+        MagnificationSpec expectedInitialSpec = getMagnificationSpec(1.0f, 0.0f, 0.0f);
+        Region initialMagRegion = new Region();
+        Rect initialBounds = new Rect();
+
+        assertEquals(expectedInitialSpec, getCurrentMagnificationSpec());
+        mMagnificationController.getMagnificationRegion(initialMagRegion);
+        mMagnificationController.getMagnificationBounds(initialBounds);
+        assertEquals(INITIAL_MAGNIFICATION_REGION, initialMagRegion);
+        assertEquals(INITIAL_MAGNIFICATION_BOUNDS, initialBounds);
+        assertEquals(INITIAL_MAGNIFICATION_BOUNDS.centerX(),
+                mMagnificationController.getCenterX(), 0.0f);
+        assertEquals(INITIAL_MAGNIFICATION_BOUNDS.centerY(),
+                mMagnificationController.getCenterY(), 0.0f);
+    }
+
+    @Test
+    public void testNotRegistered_publicMethodsShouldBeBenign() {
+        assertFalse(mMagnificationController.isMagnifying());
+        assertFalse(mMagnificationController.magnificationRegionContains(100, 100));
+        assertFalse(mMagnificationController.reset(true));
+        assertFalse(mMagnificationController.setScale(2, 100, 100, true, 0));
+        assertFalse(mMagnificationController.setCenter(100, 100, false, 1));
+        assertFalse(mMagnificationController.setScaleAndCenter(1.5f, 100, 100, false, 2));
+        assertTrue(mMagnificationController.getIdOfLastServiceToMagnify() < 0);
+
+        mMagnificationController.getMagnificationRegion(new Region());
+        mMagnificationController.getMagnificationBounds(new Rect());
+        mMagnificationController.getScale();
+        mMagnificationController.getOffsetX();
+        mMagnificationController.getOffsetY();
+        mMagnificationController.getCenterX();
+        mMagnificationController.getCenterY();
+        mMagnificationController.offsetMagnifiedRegion(50, 50, 1);
+        mMagnificationController.unregister();
+    }
+
+    @Test
+    public void testSetScale_noAnimation_shouldGoStraightToWindowManagerAndUpdateState() {
+        mMagnificationController.register();
+        final float scale = 2.0f;
+        final PointF center = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
+        final PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, center, scale);
+        assertTrue(mMagnificationController
+                .setScale(scale, center.x, center.y, false, SERVICE_ID_1));
+
+        final MagnificationSpec expectedSpec = getMagnificationSpec(scale, offsets);
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedSpec)));
+        assertThat(getCurrentMagnificationSpec(), closeTo(expectedSpec));
+        assertEquals(center.x, mMagnificationController.getCenterX(), 0.0);
+        assertEquals(center.y, mMagnificationController.getCenterY(), 0.0);
+        verify(mMockValueAnimator, times(0)).start();
+    }
+
+    @Test
+    public void testSetScale_withPivotAndAnimation_stateChangesAndAnimationHappens() {
+        mMagnificationController.register();
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        float scale = 2.0f;
+        PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        assertTrue(mMagnificationController
+                .setScale(scale, pivotPoint.x, pivotPoint.y, true, SERVICE_ID_1));
+
+        // New center should be halfway between original center and pivot
+        PointF newCenter = new PointF((pivotPoint.x + INITIAL_MAGNIFICATION_BOUNDS.centerX()) / 2,
+                (pivotPoint.y + INITIAL_MAGNIFICATION_BOUNDS.centerY()) / 2);
+        PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
+        MagnificationSpec endSpec = getMagnificationSpec(scale, offsets);
+
+        assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
+        assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
+        assertThat(getCurrentMagnificationSpec(), closeTo(endSpec));
+        verify(mMockValueAnimator).start();
+
+        // Initial value
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(0.0f);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        verify(mMockWindowManager).setMagnificationSpec(startSpec);
+
+        // Intermediate point
+        Mockito.reset(mMockWindowManager);
+        float fraction = 0.5f;
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        verify(mMockWindowManager).setMagnificationSpec(
+                argThat(closeTo(getInterpolatedMagSpec(startSpec, endSpec, fraction))));
+
+        // Final value
+        Mockito.reset(mMockWindowManager);
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(1.0f);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(endSpec)));
+    }
+
+    @Test
+    public void testSetCenter_whileMagnifying_noAnimation_centerMoves() {
+        mMagnificationController.register();
+        // First zoom in
+        float scale = 2.0f;
+        assertTrue(mMagnificationController.setScale(scale,
+                INITIAL_MAGNIFICATION_BOUNDS.centerX(), INITIAL_MAGNIFICATION_BOUNDS.centerY(),
+                false, SERVICE_ID_1));
+        Mockito.reset(mMockWindowManager);
+
+        PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        assertTrue(mMagnificationController
+                .setCenter(newCenter.x, newCenter.y, false, SERVICE_ID_1));
+        PointF expectedOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
+        MagnificationSpec expectedSpec = getMagnificationSpec(scale, expectedOffsets);
+
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedSpec)));
+        assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.0);
+        assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.0);
+        verify(mMockValueAnimator, times(0)).start();
+    }
+
+    @Test
+    public void testSetScaleAndCenter_animated_stateChangesAndAnimationHappens() {
+        mMagnificationController.register();
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        float scale = 2.5f;
+        PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
+        MagnificationSpec endSpec = getMagnificationSpec(scale, offsets);
+
+        assertTrue(mMagnificationController.setScaleAndCenter(scale, newCenter.x, newCenter.y,
+                true, SERVICE_ID_1));
+
+        assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
+        assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
+        assertThat(getCurrentMagnificationSpec(), closeTo(endSpec));
+        verify(mMockAms).notifyMagnificationChanged(
+                INITIAL_MAGNIFICATION_REGION, scale, newCenter.x, newCenter.y);
+        verify(mMockValueAnimator).start();
+
+        // Initial value
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(0.0f);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        verify(mMockWindowManager).setMagnificationSpec(startSpec);
+
+        // Intermediate point
+        Mockito.reset(mMockWindowManager);
+        float fraction = 0.33f;
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        verify(mMockWindowManager).setMagnificationSpec(
+                argThat(closeTo(getInterpolatedMagSpec(startSpec, endSpec, fraction))));
+
+        // Final value
+        Mockito.reset(mMockWindowManager);
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(1.0f);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(endSpec)));
+    }
+
+    @Test
+    public void testSetScaleAndCenter_scaleOutOfBounds_cappedAtLimits() {
+        mMagnificationController.register();
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter,
+                MagnificationController.MAX_SCALE);
+        MagnificationSpec endSpec = getMagnificationSpec(
+                MagnificationController.MAX_SCALE, offsets);
+
+        assertTrue(mMagnificationController.setScaleAndCenter(
+                MagnificationController.MAX_SCALE + 1.0f,
+                newCenter.x, newCenter.y, false, SERVICE_ID_1));
+
+        assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
+        assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(endSpec)));
+        Mockito.reset(mMockWindowManager);
+
+        // Verify that we can't zoom below 1x
+        assertTrue(mMagnificationController.setScaleAndCenter(0.5f,
+                INITIAL_MAGNIFICATION_BOUNDS_CENTER.x, INITIAL_MAGNIFICATION_BOUNDS_CENTER.y,
+                false, SERVICE_ID_1));
+
+        assertEquals(INITIAL_MAGNIFICATION_BOUNDS_CENTER.x,
+                mMagnificationController.getCenterX(), 0.5);
+        assertEquals(INITIAL_MAGNIFICATION_BOUNDS_CENTER.y,
+                mMagnificationController.getCenterY(), 0.5);
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(startSpec)));
+    }
+
+    @Test
+    public void testSetScaleAndCenter_centerOutOfBounds_cappedAtLimits() {
+        mMagnificationController.register();
+        float scale = 2.0f;
+
+        // Off the edge to the top and left
+        assertTrue(mMagnificationController.setScaleAndCenter(
+                scale, -100f, -200f, false, SERVICE_ID_1));
+
+        PointF newCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
+        PointF newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
+        assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
+        assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
+        verify(mMockWindowManager).setMagnificationSpec(
+                argThat(closeTo(getMagnificationSpec(scale, newOffsets))));
+        Mockito.reset(mMockWindowManager);
+
+        // Off the edge to the bottom and right
+        assertTrue(mMagnificationController.setScaleAndCenter(scale,
+                INITIAL_MAGNIFICATION_BOUNDS.right + 1, INITIAL_MAGNIFICATION_BOUNDS.bottom + 1,
+                false, SERVICE_ID_1));
+        newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
+        assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.5);
+        assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.5);
+        verify(mMockWindowManager).setMagnificationSpec(
+                argThat(closeTo(getMagnificationSpec(scale, newOffsets))));
+    }
+
+    @Test
+    public void testMagnificationRegionChanged_serviceNotified() {
+        mMagnificationController.register();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        callbacks.onMagnificationRegionChanged(OTHER_REGION);
+        mMessageCapturingHandler.sendAllMessages();
+        verify(mMockAms).notifyMagnificationChanged(OTHER_REGION, 1.0f,
+                OTHER_MAGNIFICATION_BOUNDS.centerX(), OTHER_MAGNIFICATION_BOUNDS.centerY());
+    }
+
+    @Test
+    public void testOffsetMagnifiedRegion_whileMagnifying_offsetsMove() {
+        mMagnificationController.register();
+        PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
+        float scale = 2.0f;
+        PointF startOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, startCenter, scale);
+        // First zoom in
+        assertTrue(mMagnificationController
+                .setScaleAndCenter(scale, startCenter.x, startCenter.y, false, SERVICE_ID_1));
+        Mockito.reset(mMockWindowManager);
+
+        PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        PointF newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
+        mMagnificationController.offsetMagnifiedRegion(
+                startOffsets.x - newOffsets.x, startOffsets.y - newOffsets.y, SERVICE_ID_1);
+
+        MagnificationSpec expectedSpec = getMagnificationSpec(scale, newOffsets);
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedSpec)));
+        assertEquals(newCenter.x, mMagnificationController.getCenterX(), 0.0);
+        assertEquals(newCenter.y, mMagnificationController.getCenterY(), 0.0);
+        verify(mMockValueAnimator, times(0)).start();
+    }
+
+    @Test
+    public void testOffsetMagnifiedRegion_whileNotMagnifying_hasNoEffect() {
+        mMagnificationController.register();
+        Mockito.reset(mMockWindowManager);
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        mMagnificationController.offsetMagnifiedRegion(10, 10, SERVICE_ID_1);
+        assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+        mMagnificationController.offsetMagnifiedRegion(-10, -10, SERVICE_ID_1);
+        assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+        verifyNoMoreInteractions(mMockWindowManager);
+    }
+
+    @Test
+    public void testOffsetMagnifiedRegion_whileMagnifyingButAtEdge_hasNoEffect() {
+        mMagnificationController.register();
+        float scale = 2.0f;
+
+        // Upper left edges
+        PointF ulCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
+        assertTrue(mMagnificationController
+                .setScaleAndCenter(scale, ulCenter.x, ulCenter.y, false, SERVICE_ID_1));
+        Mockito.reset(mMockWindowManager);
+        MagnificationSpec ulSpec = getCurrentMagnificationSpec();
+        mMagnificationController.offsetMagnifiedRegion(-10, -10, SERVICE_ID_1);
+        assertThat(getCurrentMagnificationSpec(), closeTo(ulSpec));
+        verifyNoMoreInteractions(mMockWindowManager);
+
+        // Lower right edges
+        PointF lrCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        assertTrue(mMagnificationController
+                .setScaleAndCenter(scale, lrCenter.x, lrCenter.y, false, SERVICE_ID_1));
+        Mockito.reset(mMockWindowManager);
+        MagnificationSpec lrSpec = getCurrentMagnificationSpec();
+        mMagnificationController.offsetMagnifiedRegion(10, 10, SERVICE_ID_1);
+        assertThat(getCurrentMagnificationSpec(), closeTo(lrSpec));
+        verifyNoMoreInteractions(mMockWindowManager);
+    }
+
+    @Test
+    public void testGetIdOfLastServiceToChange_returnsCorrectValue() {
+        mMagnificationController.register();
+        PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
+        assertTrue(mMagnificationController
+                .setScale(2.0f, startCenter.x, startCenter.y, false, SERVICE_ID_1));
+        assertEquals(SERVICE_ID_1, mMagnificationController.getIdOfLastServiceToMagnify());
+        assertTrue(mMagnificationController
+                .setScale(1.5f, startCenter.x, startCenter.y, false, SERVICE_ID_2));
+        assertEquals(SERVICE_ID_2, mMagnificationController.getIdOfLastServiceToMagnify());
+    }
+
+    @Test
+    public void testSetUserId_resetsOnlyIfIdChanges() {
+        final int userId1 = 1;
+        final int userId2 = 2;
+
+        mMagnificationController.register();
+        mMagnificationController.setUserId(userId1);
+        PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
+        float scale = 2.0f;
+        mMagnificationController.setScale(scale, startCenter.x, startCenter.y, false, SERVICE_ID_1);
+
+        mMagnificationController.setUserId(userId1);
+        assertTrue(mMagnificationController.isMagnifying());
+        mMagnificationController.setUserId(userId2);
+        assertFalse(mMagnificationController.isMagnifying());
+    }
+
+    @Test
+    public void testResetIfNeeded_doesWhatItSays() {
+        mMagnificationController.register();
+        zoomIn2xToMiddle();
+        assertTrue(mMagnificationController.resetIfNeeded(false));
+        verify(mMockAms).notifyMagnificationChanged(
+                eq(INITIAL_MAGNIFICATION_REGION), eq(1.0f), anyInt(), anyInt());
+        assertFalse(mMagnificationController.isMagnifying());
+        assertFalse(mMagnificationController.resetIfNeeded(false));
+    }
+
+    @Test
+    public void testTurnScreenOff_resetsMagnification() {
+        mMagnificationController.register();
+        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mMockContext).registerReceiver(
+                broadcastReceiverCaptor.capture(), (IntentFilter) anyObject());
+        BroadcastReceiver br = broadcastReceiverCaptor.getValue();
+        zoomIn2xToMiddle();
+        br.onReceive(mMockContext, null);
+        mMessageCapturingHandler.sendAllMessages();
+        assertFalse(mMagnificationController.isMagnifying());
+    }
+
+    @Test
+    public void testUserContextChange_resetsMagnification() {
+        mMagnificationController.register();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        zoomIn2xToMiddle();
+        callbacks.onUserContextChanged();
+        mMessageCapturingHandler.sendAllMessages();
+        assertFalse(mMagnificationController.isMagnifying());
+    }
+
+    @Test
+    public void testRotation_resetsMagnification() {
+        mMagnificationController.register();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        zoomIn2xToMiddle();
+        mMessageCapturingHandler.sendAllMessages();
+        assertTrue(mMagnificationController.isMagnifying());
+        callbacks.onRotationChanged(0);
+        mMessageCapturingHandler.sendAllMessages();
+        assertFalse(mMagnificationController.isMagnifying());
+    }
+
+    @Test
+    public void testBoundsChange_whileMagnifyingWithCompatibleSpec_noSpecChange() {
+        // Going from a small region to a large one leads to no issues
+        mMagnificationController.register();
+        zoomIn2xToMiddle();
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        Mockito.reset(mMockWindowManager);
+        callbacks.onMagnificationRegionChanged(OTHER_REGION);
+        mMessageCapturingHandler.sendAllMessages();
+        assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+        verifyNoMoreInteractions(mMockWindowManager);
+    }
+
+    @Test
+    public void testBoundsChange_whileZoomingWithCompatibleSpec_noSpecChange() {
+        mMagnificationController.register();
+        PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
+        float scale = 2.0f;
+        mMagnificationController.setScale(scale, startCenter.x, startCenter.y, true, SERVICE_ID_1);
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        Mockito.reset(mMockWindowManager);
+        callbacks.onMagnificationRegionChanged(OTHER_REGION);
+        mMessageCapturingHandler.sendAllMessages();
+        assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+        verifyNoMoreInteractions(mMockWindowManager);
+    }
+
+    @Test
+    public void testBoundsChange_whileMagnifyingWithIncompatibleSpec_offsetsConstrained() {
+        // In a large region, pan to the farthest point possible
+        mMagnificationController.register();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        callbacks.onMagnificationRegionChanged(OTHER_REGION);
+        mMessageCapturingHandler.sendAllMessages();
+        PointF startCenter = OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        float scale = 2.0f;
+        mMagnificationController.setScale(scale, startCenter.x, startCenter.y, false, SERVICE_ID_1);
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(startSpec)));
+        Mockito.reset(mMockWindowManager);
+
+        callbacks.onMagnificationRegionChanged(INITIAL_MAGNIFICATION_REGION);
+        mMessageCapturingHandler.sendAllMessages();
+
+        MagnificationSpec endSpec = getCurrentMagnificationSpec();
+        assertThat(endSpec, CoreMatchers.not(closeTo(startSpec)));
+        PointF expectedOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS,
+                INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER, scale);
+        assertThat(endSpec, closeTo(getMagnificationSpec(scale, expectedOffsets)));
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(endSpec)));
+    }
+
+    @Test
+    public void testBoundsChange_whileZoomingWithIncompatibleSpec_jumpsToCompatibleSpec() {
+        mMagnificationController.register();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        callbacks.onMagnificationRegionChanged(OTHER_REGION);
+        mMessageCapturingHandler.sendAllMessages();
+        PointF startCenter = OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        float scale = 2.0f;
+        mMagnificationController.setScale(scale, startCenter.x, startCenter.y, true, SERVICE_ID_1);
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        when (mMockValueAnimator.isRunning()).thenReturn(true);
+
+        callbacks.onMagnificationRegionChanged(INITIAL_MAGNIFICATION_REGION);
+        mMessageCapturingHandler.sendAllMessages();
+        verify(mMockValueAnimator).cancel();
+
+        MagnificationSpec endSpec = getCurrentMagnificationSpec();
+        assertThat(endSpec, CoreMatchers.not(closeTo(startSpec)));
+        PointF expectedOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS,
+                INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER, scale);
+        assertThat(endSpec, closeTo(getMagnificationSpec(scale, expectedOffsets)));
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(endSpec)));
+    }
+
+    @Test
+    public void testRequestRectOnScreen_rectAlreadyOnScreen_doesNothing() {
+        mMagnificationController.register();
+        zoomIn2xToMiddle();
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        Mockito.reset(mMockWindowManager);
+        int centerX = (int) INITIAL_MAGNIFICATION_BOUNDS_CENTER.x;
+        int centerY = (int) INITIAL_MAGNIFICATION_BOUNDS_CENTER.y;
+        callbacks.onRectangleOnScreenRequested(centerX - 1, centerY - 1, centerX + 1, centerY - 1);
+        mMessageCapturingHandler.sendAllMessages();
+        assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+        verifyNoMoreInteractions(mMockWindowManager);
+    }
+
+    @Test
+    public void testRequestRectOnScreen_rectCanFitOnScreen_pansToGetRectOnScreen() {
+        mMagnificationController.register();
+        zoomIn2xToMiddle();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        Mockito.reset(mMockWindowManager);
+        callbacks.onRectangleOnScreenRequested(0, 0, 1, 1);
+        mMessageCapturingHandler.sendAllMessages();
+        MagnificationSpec expectedEndSpec = getMagnificationSpec(2.0f, 0, 0);
+        assertThat(getCurrentMagnificationSpec(), closeTo(expectedEndSpec));
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedEndSpec)));
+    }
+
+    @Test
+    public void testRequestRectOnScreen_garbageInput_doesNothing() {
+        mMagnificationController.register();
+        zoomIn2xToMiddle();
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        Mockito.reset(mMockWindowManager);
+        callbacks.onRectangleOnScreenRequested(0, 0, -50, -50);
+        mMessageCapturingHandler.sendAllMessages();
+        assertThat(getCurrentMagnificationSpec(), closeTo(startSpec));
+        verifyNoMoreInteractions(mMockWindowManager);
+    }
+
+
+    @Test
+    public void testRequestRectOnScreen_rectTooWide_pansToGetStartOnScreenBasedOnLocale() {
+        Locale.setDefault(new Locale("en", "us"));
+        mMagnificationController.register();
+        zoomIn2xToMiddle();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        Mockito.reset(mMockWindowManager);
+        Rect wideRect = new Rect(0, 50, 100, 51);
+        callbacks.onRectangleOnScreenRequested(
+                wideRect.left, wideRect.top, wideRect.right, wideRect.bottom);
+        mMessageCapturingHandler.sendAllMessages();
+        MagnificationSpec expectedEndSpec = getMagnificationSpec(2.0f, 0, startSpec.offsetY);
+        assertThat(getCurrentMagnificationSpec(), closeTo(expectedEndSpec));
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedEndSpec)));
+        Mockito.reset(mMockWindowManager);
+
+        // Repeat with RTL
+        Locale.setDefault(new Locale("he", "il"));
+        callbacks.onRectangleOnScreenRequested(
+                wideRect.left, wideRect.top, wideRect.right, wideRect.bottom);
+        mMessageCapturingHandler.sendAllMessages();
+        expectedEndSpec = getMagnificationSpec(2.0f, -100, startSpec.offsetY);
+        assertThat(getCurrentMagnificationSpec(), closeTo(expectedEndSpec));
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedEndSpec)));
+    }
+
+    @Test
+    public void testRequestRectOnScreen_rectTooTall_pansMinimumToGetTopOnScreen() {
+        mMagnificationController.register();
+        zoomIn2xToMiddle();
+        MagnificationCallbacks callbacks = getMagnificationCallbacks();
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        Mockito.reset(mMockWindowManager);
+        Rect tallRect = new Rect(50, 0, 51, 100);
+        callbacks.onRectangleOnScreenRequested(
+                tallRect.left, tallRect.top, tallRect.right, tallRect.bottom);
+        mMessageCapturingHandler.sendAllMessages();
+        MagnificationSpec expectedEndSpec = getMagnificationSpec(2.0f, startSpec.offsetX, 0);
+        assertThat(getCurrentMagnificationSpec(), closeTo(expectedEndSpec));
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(expectedEndSpec)));
+    }
+
+    @Test
+    public void testChangeMagnification_duringAnimation_animatesToNewValue() {
+        mMagnificationController.register();
+        MagnificationSpec startSpec = getCurrentMagnificationSpec();
+        float scale = 2.5f;
+        PointF firstCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        MagnificationSpec firstEndSpec = getMagnificationSpec(
+                scale, computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, firstCenter, scale));
+
+        assertTrue(mMagnificationController.setScaleAndCenter(scale, firstCenter.x, firstCenter.y,
+                true, SERVICE_ID_1));
+
+        assertEquals(firstCenter.x, mMagnificationController.getCenterX(), 0.5);
+        assertEquals(firstCenter.y, mMagnificationController.getCenterY(), 0.5);
+        assertThat(getCurrentMagnificationSpec(), closeTo(firstEndSpec));
+        verify(mMockValueAnimator, times(1)).start();
+
+        // Initial value
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(0.0f);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        verify(mMockWindowManager).setMagnificationSpec(startSpec);
+        verify(mMockAms).notifyMagnificationChanged(
+                INITIAL_MAGNIFICATION_REGION, scale, firstCenter.x, firstCenter.y);
+        Mockito.reset(mMockWindowManager);
+
+        // Intermediate point
+        float fraction = 0.33f;
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        MagnificationSpec intermediateSpec1 =
+                getInterpolatedMagSpec(startSpec, firstEndSpec, fraction);
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(intermediateSpec1)));
+        Mockito.reset(mMockWindowManager);
+
+        PointF newCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
+        MagnificationSpec newEndSpec = getMagnificationSpec(
+                scale, computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale));
+        assertTrue(mMagnificationController.setCenter(
+                newCenter.x, newCenter.y, true, SERVICE_ID_1));
+
+        // Animation should have been restarted
+        verify(mMockValueAnimator, times(2)).start();
+        verify(mMockAms).notifyMagnificationChanged(
+                INITIAL_MAGNIFICATION_REGION, scale, newCenter.x, newCenter.y);
+
+        // New starting point should be where we left off
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(0.0f);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(intermediateSpec1)));
+        Mockito.reset(mMockWindowManager);
+
+        // Second intermediate point
+        fraction = 0.5f;
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        verify(mMockWindowManager).setMagnificationSpec(
+                argThat(closeTo(getInterpolatedMagSpec(intermediateSpec1, newEndSpec, fraction))));
+        Mockito.reset(mMockWindowManager);
+
+        // Final value should be the new center
+        Mockito.reset(mMockWindowManager);
+        when(mMockValueAnimator.getAnimatedFraction()).thenReturn(1.0f);
+        mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+        verify(mMockWindowManager).setMagnificationSpec(argThat(closeTo(newEndSpec)));
+    }
+
+    private void zoomIn2xToMiddle() {
+        PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
+        float scale = 2.0f;
+        mMagnificationController.setScale(scale, startCenter.x, startCenter.y, false, SERVICE_ID_1);
+        assertTrue(mMagnificationController.isMagnifying());
+    }
+
+    private MagnificationCallbacks getMagnificationCallbacks() {
+        ArgumentCaptor<MagnificationCallbacks> magnificationCallbacksCaptor =
+                ArgumentCaptor.forClass(MagnificationCallbacks.class);
+        verify(mMockWindowManager)
+                .setMagnificationCallbacks(magnificationCallbacksCaptor.capture());
+        return magnificationCallbacksCaptor.getValue();
+    }
+
+    private PointF computeOffsets(Rect magnifiedBounds, PointF center, float scale) {
+        return new PointF(
+                magnifiedBounds.centerX() - scale * center.x,
+                magnifiedBounds.centerY() - scale * center.y);
+    }
+
+    private MagnificationSpec getInterpolatedMagSpec(MagnificationSpec start, MagnificationSpec end,
+            float fraction) {
+        MagnificationSpec interpolatedSpec = MagnificationSpec.obtain();
+        interpolatedSpec.scale = start.scale + fraction * (end.scale - start.scale);
+        interpolatedSpec.offsetX = start.offsetX + fraction * (end.offsetX - start.offsetX);
+        interpolatedSpec.offsetY = start.offsetY + fraction * (end.offsetY - start.offsetY);
+        return interpolatedSpec;
+    }
+
+    private MagnificationSpec getMagnificationSpec(float scale, PointF offsets) {
+        return getMagnificationSpec(scale, offsets.x, offsets.y);
+    }
+
+    private MagnificationSpec getMagnificationSpec(float scale, float offsetX, float offsetY) {
+        MagnificationSpec spec = MagnificationSpec.obtain();
+        spec.scale = scale;
+        spec.offsetX = offsetX;
+        spec.offsetY = offsetY;
+        return spec;
+    }
+
+    private MagnificationSpec getCurrentMagnificationSpec() {
+        return getMagnificationSpec(mMagnificationController.getScale(),
+                mMagnificationController.getOffsetX(), mMagnificationController.getOffsetY());
+    }
+
+    private MagSpecMatcher closeTo(MagnificationSpec spec) {
+        return new MagSpecMatcher(spec, 0.01f, 0.5f);
+    }
+
+    private class MagSpecMatcher extends TypeSafeMatcher<MagnificationSpec> {
+        final MagnificationSpec mMagSpec;
+        final float mScaleTolerance;
+        final float mOffsetTolerance;
+
+        MagSpecMatcher(MagnificationSpec spec, float scaleTolerance, float offsetTolerance) {
+            mMagSpec = spec;
+            mScaleTolerance = scaleTolerance;
+            mOffsetTolerance = offsetTolerance;
+        }
+
+        @Override
+        protected boolean matchesSafely(MagnificationSpec magnificationSpec) {
+            if (Math.abs(mMagSpec.scale - magnificationSpec.scale) > mScaleTolerance) {
+                return false;
+            }
+            if (Math.abs(mMagSpec.offsetX - magnificationSpec.offsetX) > mOffsetTolerance) {
+                return false;
+            }
+            if (Math.abs(mMagSpec.offsetY - magnificationSpec.offsetY) > mOffsetTolerance) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("Match spec: " + mMagSpec);
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java b/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java
new file mode 100644
index 0000000..003f7ab
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java
@@ -0,0 +1,78 @@
+/*
+ * 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.accessibility;
+
+import android.os.Handler;
+import android.os.Message;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility class to capture messages dispatched through a handler and control when they arrive
+ * at their target.
+ */
+public class MessageCapturingHandler extends Handler {
+    List<Pair<Message, Long>> timedMessages = new ArrayList<>();
+
+    Handler.Callback mCallback;
+
+    public MessageCapturingHandler(Handler.Callback callback) {
+        mCallback = callback;
+    }
+
+    @Override
+    public boolean sendMessageAtTime(Message message, long uptimeMillis) {
+        timedMessages.add(new Pair<>(Message.obtain(message), uptimeMillis));
+        return super.sendMessageAtTime(message, uptimeMillis);
+    }
+
+    public void sendOneMessage() {
+        Message message = timedMessages.remove(0).first;
+        removeMessages(message.what, message.obj);
+        mCallback.handleMessage(message);
+        removeStaleMessages();
+    }
+
+    public void sendAllMessages() {
+        while (!timedMessages.isEmpty()) {
+            sendOneMessage();
+        }
+    }
+
+    public void sendLastMessage() {
+        Message message = timedMessages.remove(timedMessages.size() - 1).first;
+        removeMessages(message.what, message.obj);
+        mCallback.handleMessage(message);
+        removeStaleMessages();
+    }
+
+    public boolean hasMessages() {
+        removeStaleMessages();
+        return !timedMessages.isEmpty();
+    }
+
+    private void removeStaleMessages() {
+        for (int i = 0; i < timedMessages.size(); i++) {
+            Message message = timedMessages.get(i).first;
+            if (!hasMessages(message.what, message.obj)) {
+                timedMessages.remove(i--);
+            }
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
index 5920fef..d5305d9 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
@@ -92,7 +92,12 @@
 
     @Before
     public void setUp() {
-        mMessageCapturingHandler = new MessageCapturingHandler();
+        mMessageCapturingHandler = new MessageCapturingHandler(new Handler.Callback() {
+            @Override
+            public boolean handleMessage(Message msg) {
+                return mMotionEventInjector.handleMessage(msg);
+            }
+        });
         mMotionEventInjector = new MotionEventInjector(mMessageCapturingHandler);
         mClickList.add(
                 MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, CLICK_X, CLICK_Y_START, 0));
@@ -501,48 +506,4 @@
             return false;
         }
     }
-
-    private class MessageCapturingHandler extends Handler {
-        List<Pair<Message, Long>> timedMessages = new ArrayList<>();
-
-        @Override
-        public boolean sendMessageAtTime(Message message, long uptimeMillis) {
-            timedMessages.add(new Pair<>(Message.obtain(message), uptimeMillis));
-            return super.sendMessageAtTime(message, uptimeMillis);
-        }
-
-        void sendOneMessage() {
-            Message message = timedMessages.remove(0).first;
-            removeMessages(message.what, message.obj);
-            mMotionEventInjector.handleMessage(message);
-            removeStaleMessages();
-        }
-
-        void sendAllMessages() {
-            while (!timedMessages.isEmpty()) {
-                sendOneMessage();
-            }
-        }
-
-        void sendLastMessage() {
-            Message message = timedMessages.remove(timedMessages.size() - 1).first;
-            removeMessages(message.what, message.obj);
-            mMotionEventInjector.handleMessage(message);
-            removeStaleMessages();
-        }
-
-        boolean hasMessages() {
-            removeStaleMessages();
-            return !timedMessages.isEmpty();
-        }
-
-        private void removeStaleMessages() {
-            for (int i = 0; i < timedMessages.size(); i++) {
-                Message message = timedMessages.get(i).first;
-                if (!hasMessages(message.what, message.obj)) {
-                    timedMessages.remove(i--);
-                }
-            }
-        }
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
new file mode 100644
index 0000000..315d37c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.devicepolicy;
+
+import android.app.admin.ConnectEvent;
+import android.app.admin.DnsEvent;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import static junit.framework.Assert.assertEquals;
+
+@SmallTest
+public class NetworkEventTest extends DpmTestBase {
+
+    /**
+     * Test parceling and unparceling of a ConnectEvent.
+     */
+    public void testConnectEventParceling() {
+        ConnectEvent event = new ConnectEvent("127.0.0.1", 80, "com.android.whateverdude", 100000);
+        Parcel p = Parcel.obtain();
+        p.writeParcelable(event, 0);
+        p.setDataPosition(0);
+        ConnectEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
+        p.recycle();
+        assertEquals(event.getIpAddress(), unparceledEvent.getIpAddress());
+        assertEquals(event.getPort(), unparceledEvent.getPort());
+        assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
+        assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
+    }
+
+    /**
+     * Test parceling and unparceling of a DnsEvent.
+     */
+    public void testDnsEventParceling() {
+        DnsEvent event = new DnsEvent("d.android.com", new String[]{"192.168.0.1", "127.0.0.1"}, 2,
+                "com.android.whateverdude", 100000);
+        Parcel p = Parcel.obtain();
+        p.writeParcelable(event, 0);
+        p.setDataPosition(0);
+        DnsEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
+        p.recycle();
+        assertEquals(event.getHostname(), unparceledEvent.getHostname());
+        assertEquals(event.getIpAddresses()[0], unparceledEvent.getIpAddresses()[0]);
+        assertEquals(event.getIpAddresses()[1], unparceledEvent.getIpAddresses()[1]);
+        assertEquals(event.getIpAddressesCount(), unparceledEvent.getIpAddressesCount());
+        assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
+        assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
index 21560ac..5eee7b9 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.when;
 
 import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.METERED_NO;
 import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
@@ -336,7 +337,7 @@
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                         BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -344,7 +345,7 @@
 
         // Delta
         uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                         BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -374,7 +375,7 @@
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                         BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -382,7 +383,7 @@
 
         // Delta
         uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                         BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -412,7 +413,7 @@
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                         BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -420,7 +421,7 @@
 
         // Delta
         uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
                         BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -450,16 +451,17 @@
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_NO,
-                        BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
+                .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
+                        ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
 
         // Delta
         uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_NO,
-                        BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
+                .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
+                        ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES,
+                        2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java
index f2cf90c..728eb73 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java
@@ -22,6 +22,9 @@
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
 import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.METERED_ALL;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.METERED_YES;
 import static android.net.NetworkStats.ROAMING_ALL;
 import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.ROAMING_YES;
@@ -305,9 +308,10 @@
         // verify service recorded history
         assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0);
         assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_NO, 512L, 4L, 256L, 2L, 4);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L,
-                6);
+        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, METERED_NO, ROAMING_NO, 512L, 4L, 256L,
+                2L, 4);
+        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, METERED_NO, ROAMING_NO, 512L, 4L,
+                256L, 2L, 6);
         assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0);
 
 
@@ -329,9 +333,10 @@
         // after systemReady(), we should have historical stats loaded again
         assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0);
         assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_NO, 512L, 4L, 256L, 2L, 4);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L,
-                6);
+        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, METERED_NO, ROAMING_NO, 512L, 4L, 256L,
+                2L, 4);
+        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, METERED_NO, ROAMING_NO, 512L, 4L,
+                256L, 2L, 6);
         assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0);
 
     }
@@ -638,20 +643,20 @@
         NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(3, stats.size());
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 50L, 5L,
-                50L, 5L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 10L, 1L, 10L,
-                1L, 1);
-        assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2048L, 16L,
-                1024L, 8L, 0);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 50L,
+                5L, 50L, 5L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 10L,
+                1L, 10L, 1L, 1);
+        assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                2048L, 16L, 1024L, 8L, 0);
 
         // now verify that recent history only contains one uid
         final long currentTime = currentTimeMillis();
         stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true);
         assertEquals(1, stats.size());
-        assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
-                512L, 4L, 0);
+        assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                1024L, 8L, 512L, 4L, 0);
     }
 
     @Test
@@ -705,14 +710,56 @@
         final NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(4, stats.size());
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L,
-                128L, 2L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L,
-                1L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 2L,
-                32L, 2L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, ROAMING_NO, 1L, 1L, 1L,
-                1L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L,
+                2L, 128L, 2L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L,
+                1L, 64L, 1L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                32L, 2L, 32L, 2L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, METERED_NO, ROAMING_NO, 1L,
+                1L, 1L, 1L, 1);
+    }
+
+    @Test
+    public void testMetered() throws Exception {
+        // pretend that network comes online
+        expectCurrentTime();
+        expectDefaultSettings();
+        expectNetworkState(buildWifiState(true /* isMetered */));
+        expectNetworkStatsSummary(buildEmptyStats());
+        expectNetworkStatsUidDetail(buildEmptyStats());
+        expectBandwidthControlCheck();
+
+        mService.forceUpdateIfaces();
+
+
+        // create some initial traffic
+        incrementCurrentTime(HOUR_IN_MILLIS);
+        expectCurrentTime();
+        expectDefaultSettings();
+        expectNetworkStatsSummary(buildEmptyStats());
+        // Note that all traffic from NetworkManagementService is tagged as METERED_NO and
+        // ROAMING_NO, because metered and roaming isn't tracked at that layer. We layer it
+        // on top by inspecting the iface properties.
+        expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L,
+                        2L, 128L, 2L, 0L)
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L,
+                        1L, 64L, 1L, 0L));
+        mService.incrementOperationCount(UID_RED, 0xF00D, 1);
+
+        forcePollAndWaitForIdle();
+
+        // verify service recorded history
+        assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1);
+        // verify entire history present
+        final NetworkStats stats = mSession.getSummaryForAllUid(
+                sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
+        assertEquals(2, stats.size());
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                128L, 2L, 128L, 2L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, 64L,
+                1L, 64L, 1L, 1);
     }
 
     @Test
@@ -733,14 +780,14 @@
         expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
-        // Note that all traffic from NetworkManagementService is tagged as ROAMING_NO, because
-        // roaming isn't tracked at that layer. We layer it on top by inspecting the iface
-        // properties.
+        // Note that all traffic from NetworkManagementService is tagged as METERED_NO and
+        // ROAMING_NO, because metered and roaming isn't tracked at that layer. We layer it
+        // on top by inspecting the iface properties.
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L,
-                        128L, 2L, 0L)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L,
-                        1L, 0L));
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO,
+                        128L, 2L, 128L, 2L, 0L)
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO, 64L,
+                        1L, 64L, 1L, 0L));
         forcePollAndWaitForIdle();
 
         // verify service recorded history
@@ -750,10 +797,10 @@
         final NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(2, stats.size());
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 2L,
-                128L, 2L, 0);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L,
-                1L, 0);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_YES,
+                128L, 2L, 128L, 2L, 0);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_YES, 64L,
+                1L, 64L, 1L, 0);
     }
 
     @Test
@@ -780,7 +827,8 @@
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L);
         final String[] tetherIfacePairs = new String[] { TEST_IFACE, "wlan0" };
         final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1)
-                .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, 0L);
+                .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L,
+                        0L);
 
         expectNetworkStatsUidDetail(uidStats, tetherIfacePairs, tetherStats);
         forcePollAndWaitForIdle();
@@ -923,18 +971,18 @@
 
         // verify summary API
         final NetworkStats stats = mSession.getSummaryForNetwork(template, start, end);
-        assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, rxBytes,
-                rxPackets, txBytes, txPackets, operations);
+        assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO,
+                rxBytes, rxPackets, txBytes, txPackets, operations);
     }
 
     private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets,
             long txBytes, long txPackets, int operations) throws Exception {
-        assertUidTotal(template, uid, SET_ALL, ROAMING_ALL, rxBytes, rxPackets, txBytes, txPackets,
-                operations);
+        assertUidTotal(template, uid, SET_ALL, METERED_ALL, ROAMING_ALL, rxBytes, rxPackets,
+                txBytes, txPackets, operations);
     }
 
-    private void assertUidTotal(NetworkTemplate template, int uid, int set, int roaming,
-            long rxBytes, long rxPackets, long txBytes, long txPackets, int operations)
+    private void assertUidTotal(NetworkTemplate template, int uid, int set, int metered,
+            int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations)
             throws Exception {
         // verify history API
         final NetworkStatsHistory history = mSession.getHistoryForUid(
@@ -945,8 +993,8 @@
         // verify summary API
         final NetworkStats stats = mSession.getSummaryForAllUid(
                 template, Long.MIN_VALUE, Long.MAX_VALUE, false);
-        assertValues(stats, IFACE_ALL, uid, set, TAG_NONE, roaming, rxBytes, rxPackets, txBytes,
-                txPackets, operations);
+        assertValues(stats, IFACE_ALL, uid, set, TAG_NONE, metered, roaming, rxBytes, rxPackets,
+                txBytes, txPackets, operations);
     }
 
     private void expectSystemReady() throws Exception {
@@ -1034,8 +1082,8 @@
     }
 
     private static void assertValues(NetworkStats stats, String iface, int uid, int set,
-            int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets,
-            int operations) {
+            int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes,
+            long txPackets, int operations) {
         final NetworkStats.Entry entry = new NetworkStats.Entry();
         List<Integer> sets = new ArrayList<>();
         if (set == SET_DEFAULT || set == SET_ALL) {
@@ -1053,11 +1101,21 @@
             roamings.add(ROAMING_YES);
         }
 
+        List<Integer> meterings = new ArrayList<>();
+        if (metered == METERED_NO || metered == METERED_ALL) {
+            meterings.add(METERED_NO);
+        }
+        if (metered == METERED_YES || metered == METERED_ALL) {
+            meterings.add(METERED_YES);
+        }
+
         for (int s : sets) {
             for (int r : roamings) {
-                final int i = stats.findIndex(iface, uid, s, tag, r);
-                if (i != -1) {
-                    entry.add(stats.getValues(i, null));
+                for (int m : meterings) {
+                    final int i = stats.findIndex(iface, uid, s, tag, m, r);
+                    if (i != -1) {
+                        entry.add(stats.getValues(i, null));
+                    }
                 }
             }
         }
@@ -1080,11 +1138,18 @@
     }
 
     private static NetworkState buildWifiState() {
+        return buildWifiState(false);
+    }
+
+    private static NetworkState buildWifiState(boolean isMetered) {
         final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
         info.setDetailedState(DetailedState.CONNECTED, null, null);
         final LinkProperties prop = new LinkProperties();
         prop.setInterfaceName(TEST_IFACE);
         final NetworkCapabilities capabilities = new NetworkCapabilities();
+        if (!isMetered) {
+            capabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+        }
         return new NetworkState(info, prop, capabilities, null, null, TEST_SSID);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 1f0422b..40d8ac0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -37,6 +37,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /** Test {@link UserManager} functionality. */
 public class UserManagerTest extends AndroidTestCase {
@@ -441,6 +445,33 @@
         switchUser(startUser);
     }
 
+    @MediumTest
+    public void testConcurrentUserCreate() throws Exception {
+        int userCount = mUserManager.getUserCount();
+        int maxSupportedUsers = UserManager.getMaxSupportedUsers();
+        int canBeCreatedCount = maxSupportedUsers - userCount;
+        // Test exceeding the limit while running in parallel
+        int createUsersCount = canBeCreatedCount + 5;
+        ExecutorService es = Executors.newCachedThreadPool();
+        AtomicInteger created = new AtomicInteger();
+        for (int i = 0; i < createUsersCount; i++) {
+            final String userName = "testConcUser" + i;
+            es.submit(() -> {
+                UserInfo user = mUserManager.createUser(userName, 0);
+                if (user != null) {
+                    created.incrementAndGet();
+                    synchronized (mUserRemoveLock) {
+                        usersToRemove.add(user.id);
+                    }
+                }
+            });
+        }
+        es.shutdown();
+        es.awaitTermination(20, TimeUnit.SECONDS);
+        assertEquals(maxSupportedUsers, mUserManager.getUserCount());
+        assertEquals(canBeCreatedCount, created.get());
+    }
+
     private boolean isPackageInstalledForUser(String packageName, int userId) {
         try {
             return mPackageManager.getPackageInfoAsUser(packageName, 0, userId) != null;
@@ -523,4 +554,5 @@
         }
         return profile;
     }
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java b/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java
index 763c50b..d2512ac 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.ContentObserver;
 import android.webkit.WebViewProviderInfo;
 
 import java.util.HashMap;
@@ -120,5 +121,8 @@
     }
 
     @Override
-    public void setMultiprocessEnabled(boolean enabled) {}
+    public void setMultiProcessEnabledFromContext(Context context) {}
+
+    @Override
+    public void registerContentObserver(Context context, ContentObserver contentObserver) {}
 }
diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
index 0f898e5..0519448 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
@@ -16,27 +16,33 @@
 
 package com.android.server.webkit;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.Signature;
 import android.os.Bundle;
-import android.util.Base64;
-import android.test.AndroidTestCase;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.MediumTest;
-
+import android.util.Base64;
 import android.webkit.WebViewFactory;
 import android.webkit.WebViewProviderInfo;
 import android.webkit.WebViewProviderResponse;
 
-import java.util.concurrent.CountDownLatch;
-
 import org.hamcrest.Description;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import org.mockito.Mockito;
 import org.mockito.Matchers;
 import org.mockito.ArgumentMatcher;
 
+import java.util.concurrent.CountDownLatch;
+
 
 /**
  * Tests for WebViewUpdateService
@@ -45,8 +51,9 @@
  */
 // Use MediumTest instead of SmallTest as the implementation of WebViewUpdateService
 // is intended to work on several threads and uses at least one sleep/wait-statement.
+@RunWith(AndroidJUnit4.class)
 @MediumTest
-public class WebViewUpdateServiceTest extends AndroidTestCase {
+public class WebViewUpdateServiceTest {
     private final static String TAG = WebViewUpdateServiceTest.class.getSimpleName();
 
     private WebViewUpdateServiceImpl mWebViewUpdateServiceImpl;
@@ -54,11 +61,6 @@
 
     private static final String WEBVIEW_LIBRARY_FLAG = "com.android.webview.WebViewLibrary";
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
-
     /**
      * Creates a new instance.
      */
@@ -108,7 +110,7 @@
         // Add (enabled and valid) package infos for each provider
         setEnabledAndValidPackageInfos(webviewPackages);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
                 Mockito.argThat(new IsPackageInfoWithName(expectedProviderName)));
@@ -205,12 +207,27 @@
         assertEquals(expectedPackage, response.packageInfo.packageName);
     }
 
+    /**
+     * The WebView preparation boot phase is run on the main thread (especially on a thread with a
+     * looper) so to avoid bugs where our tests fail because a looper hasn't been attached to the
+     * thread running prepareWebViewInSystemServer we run it on the main thread.
+     */
+    private void runWebViewBootPreparationOnMainSync() {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+            }
+        });
+    }
+
 
     // ****************
     // Tests
     // ****************
 
 
+    @Test
     public void testWithSinglePackage() {
         String testPackageName = "test.package.name";
         checkCertainPackageUsedAfterWebViewBootPreparation(testPackageName,
@@ -219,6 +236,7 @@
                             true /*default available*/, false /* fallback */, null)});
     }
 
+    @Test
     public void testDefaultPackageUsedOverNonDefault() {
         String defaultPackage = "defaultPackage";
         String nonDefaultPackage = "nonDefaultPackage";
@@ -228,6 +246,7 @@
         checkCertainPackageUsedAfterWebViewBootPreparation(defaultPackage, packages);
     }
 
+    @Test
     public void testSeveralRelros() {
         String singlePackage = "singlePackage";
         checkCertainPackageUsedAfterWebViewBootPreparation(
@@ -239,6 +258,7 @@
 
     // Ensure that package with valid signatures is chosen rather than package with invalid
     // signatures.
+    @Test
     public void testWithSignatures() {
         String validPackage = "valid package";
         String invalidPackage = "invalid package";
@@ -264,7 +284,7 @@
                     true /* valid */, true /* installed */, new Signature[]{validSignature}
                     , 0 /* updateTime */));
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
 
         checkPreparationPhasesForPackage(validPackage, 1 /* first preparation for this package */);
@@ -274,13 +294,14 @@
         assertEquals(validPackage, validPackages[0].packageName);
     }
 
+    @Test
     public void testFailWaitingForRelro() {
         WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
             new WebViewProviderInfo("packagename", "", true, true, null)};
         setupWithPackages(packages);
         setEnabledAndValidPackageInfos(packages);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
                 Mockito.argThat(new IsPackageInfoWithName(packages[0].packageName)));
@@ -291,12 +312,13 @@
         assertEquals(WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO, response.status);
     }
 
+    @Test
     public void testFailListingEmptyWebviewPackages() {
         WebViewProviderInfo[] packages = new WebViewProviderInfo[0];
         setupWithPackages(packages);
         setEnabledAndValidPackageInfos(packages);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged(
                 Matchers.anyObject());
@@ -330,6 +352,7 @@
         assertEquals(null, mWebViewUpdateServiceImpl.getCurrentWebViewPackage());
     }
 
+    @Test
     public void testFailListingInvalidWebviewPackage() {
         WebViewProviderInfo wpi = new WebViewProviderInfo("package", "", true, true, null);
         WebViewProviderInfo[] packages = new WebViewProviderInfo[] {wpi};
@@ -338,7 +361,7 @@
                 createPackageInfo(wpi.packageName, true /* enabled */, false /* valid */,
                     true /* installed */));
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged(
                 Matchers.anyObject());
@@ -357,6 +380,7 @@
     }
 
     // Test that switching provider using changeProviderAndSetting works.
+    @Test
     public void testSwitchingProvider() {
         String firstPackage = "first";
         String secondPackage = "second";
@@ -366,6 +390,7 @@
         checkSwitchingProvider(packages, firstPackage, secondPackage);
     }
 
+    @Test
     public void testSwitchingProviderToNonDefault() {
         String defaultPackage = "defaultPackage";
         String nonDefaultPackage = "nonDefaultPackage";
@@ -386,11 +411,13 @@
     }
 
     // Change provider during relro creation by using changeProviderAndSetting
+    @Test
     public void testSwitchingProviderDuringRelroCreation() {
         checkChangingProviderDuringRelroCreation(true);
     }
 
     // Change provider during relro creation by enabling a provider
+    @Test
     public void testChangingProviderThroughEnablingDuringRelroCreation() {
         checkChangingProviderDuringRelroCreation(false);
     }
@@ -415,7 +442,7 @@
 
         CountDownLatch countdown = new CountDownLatch(1);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
                 Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
@@ -463,10 +490,12 @@
         }
     }
 
+    @Test
     public void testRunFallbackLogicIfEnabled() {
         checkFallbackLogicBeingRun(true);
     }
 
+    @Test
     public void testDontRunFallbackLogicIfDisabled() {
         checkFallbackLogicBeingRun(false);
     }
@@ -482,7 +511,7 @@
         setupWithPackages(packages, fallbackLogicEnabled);
         setEnabledAndValidPackageInfos(packages);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
         // Verify that we disable the fallback package if fallback logic enabled, and don't disable
         // the fallback package if that logic is disabled
         if (fallbackLogicEnabled) {
@@ -518,6 +547,7 @@
      * 2. Install non-fallback
      * 3. Fallback should be disabled
      */
+    @Test
     public void testInstallingNonFallbackPackage() {
         String primaryPackage = "primary";
         String fallbackPackage = "fallback";
@@ -531,7 +561,7 @@
                 createPackageInfo(fallbackPackage, true /* enabled */ , true /* valid */,
                     true /* installed */));
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
         Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
                 Matchers.anyObject(), Matchers.anyObject());
 
@@ -552,6 +582,7 @@
         Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(fallbackPackage));
     }
 
+    @Test
     public void testFallbackChangesEnabledState() {
         String primaryPackage = "primary";
         String fallbackPackage = "fallback";
@@ -563,7 +594,7 @@
         setupWithPackages(packages, true /* fallbackLogicEnabled */);
         setEnabledAndValidPackageInfos(packages);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         // Verify fallback disabled at boot when primary package enabled
         Mockito.verify(mTestSystemImpl).enablePackageForUser(
@@ -601,10 +632,12 @@
         checkPreparationPhasesForPackage(primaryPackage, 2);
     }
 
+    @Test
     public void testAddUserWhenFallbackLogicEnabled() {
         checkAddingNewUser(true);
     }
 
+    @Test
     public void testAddUserWhenFallbackLogicDisabled() {
         checkAddingNewUser(false);
     }
@@ -638,6 +671,7 @@
      * Timing dependent test where we verify that the list of valid webview packages becoming empty
      * at a certain point doesn't crash us or break our state.
      */
+    @Test
     public void testNotifyRelroDoesntCrashIfNoPackages() {
         String firstPackage = "first";
         String secondPackage = "second";
@@ -650,7 +684,7 @@
         // Add (enabled and valid) package infos for each provider
         setEnabledAndValidPackageInfos(packages);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
                 Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
@@ -689,6 +723,7 @@
      * Verify that even if a user-chosen package is removed temporarily we start using it again when
      * it is added back.
      */
+    @Test
     public void testTempRemovePackageDoesntSwitchProviderPermanently() {
         String firstPackage = "first";
         String secondPackage = "second";
@@ -722,6 +757,7 @@
      * Ensure that we update the user-chosen setting across boots if the chosen package is no
      * longer installed and valid.
      */
+    @Test
     public void testProviderSettingChangedDuringBootIfProviderNotAvailable() {
         String chosenPackage = "chosenPackage";
         String nonChosenPackage = "non-chosenPackage";
@@ -739,7 +775,7 @@
         // Set user-chosen package
         mTestSystemImpl.updateUserSetting(null, chosenPackage);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         // Verify that we switch the setting to point to the current package
         Mockito.verify(mTestSystemImpl).updateUserSetting(
@@ -749,10 +785,12 @@
         checkPreparationPhasesForPackage(nonChosenPackage, 1);
     }
 
+    @Test
     public void testRecoverFailedListingWebViewPackagesSettingsChange() {
         checkRecoverAfterFailListingWebviewPackages(true);
     }
 
+    @Test
     public void testRecoverFailedListingWebViewPackagesAddedPackage() {
         checkRecoverAfterFailListingWebviewPackages(false);
     }
@@ -799,10 +837,12 @@
         checkPreparationPhasesForPackage(secondPackage, 1);
     }
 
+    @Test
     public void testDontKillIfPackageReplaced() {
         checkDontKillIfPackageRemoved(true);
     }
 
+    @Test
     public void testDontKillIfPackageRemoved() {
         checkDontKillIfPackageRemoved(false);
     }
@@ -836,6 +876,7 @@
                 Mockito.anyObject());
     }
 
+    @Test
     public void testKillIfSettingChanged() {
         String firstPackage = "first";
         String secondPackage = "second";
@@ -857,6 +898,7 @@
      * Test that we kill apps using an old provider when we change the provider setting, even if the
      * new provider is not the one we intended to change to.
      */
+    @Test
     public void testKillIfChangeProviderIncorrectly() {
         String firstPackage = "first";
         String secondPackage = "second";
@@ -874,7 +916,7 @@
         // Start with the setting pointing to the third package
         mTestSystemImpl.updateUserSetting(null, thirdPackage);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
         checkPreparationPhasesForPackage(thirdPackage, 1);
 
         mTestSystemImpl.setPackageInfo(
@@ -890,52 +932,62 @@
         Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(thirdPackage));
     }
 
+    @Test
     public void testLowerPackageVersionNotValid() {
         checkPackageVersions(new int[]{200000} /* system version */, 100000/* candidate version */,
                 false /* expected validity */);
     }
 
+    @Test
     public void testEqualPackageVersionValid() {
         checkPackageVersions(new int[]{100000} /* system version */, 100000 /* candidate version */,
                 true /* expected validity */);
     }
 
+    @Test
     public void testGreaterPackageVersionValid() {
         checkPackageVersions(new int[]{100000} /* system versions */, 200000 /* candidate version */,
                 true /* expected validity */);
     }
 
+    @Test
     public void testLastFiveDigitsIgnored() {
         checkPackageVersions(new int[]{654321} /* system version */, 612345 /* candidate version */,
                 true /* expected validity */);
     }
 
+    @Test
     public void testMinimumSystemVersionUsedTwoDefaultsCandidateValid() {
         checkPackageVersions(new int[]{300000, 100000} /* system versions */,
                 200000 /* candidate version */, true /* expected validity */);
     }
 
+    @Test
     public void testMinimumSystemVersionUsedTwoDefaultsCandidateInvalid() {
         checkPackageVersions(new int[]{300000, 200000} /* system versions */,
                  100000 /* candidate version */, false /* expected validity */);
     }
 
+    @Test
     public void testMinimumSystemVersionUsedSeveralDefaultsCandidateValid() {
         checkPackageVersions(new int[]{100000, 200000, 300000, 400000, 500000} /* system versions */,
                 100000 /* candidate version */, true /* expected validity */);
     }
 
+    @Test
     public void testMinimumSystemVersionUsedSeveralDefaultsCandidateInvalid() {
         checkPackageVersions(new int[]{200000, 300000, 400000, 500000, 600000} /* system versions */,
                 100000 /* candidate version */, false /* expected validity */);
     }
 
+    @Test
     public void testMinimumSystemVersionUsedFallbackIgnored() {
         checkPackageVersions(new int[]{300000, 400000, 500000, 600000, 700000} /* system versions */,
                 200000 /* candidate version */, false /* expected validity */, true /* add fallback */,
                 100000 /* fallback version */, false /* expected validity of fallback */);
     }
 
+    @Test
     public void testFallbackValid() {
         checkPackageVersions(new int[]{300000, 400000, 500000, 600000, 700000} /* system versions */,
                 200000/* candidate version */, false /* expected validity */, true /* add fallback */,
@@ -1030,7 +1082,7 @@
 
         assertEquals(expectedNumValidPackages, validPackages.length);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         // The non-system package is not available by default so it shouldn't be used here
         checkPreparationPhasesForPackage(systemPackage + "1", 1);
@@ -1048,6 +1100,7 @@
 
     // Ensure that the update service uses an uninstalled package if that is the only package
     // available.
+    @Test
     public void testWithSingleUninstalledPackage() {
         String testPackageName = "test.package.name";
         WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
@@ -1057,15 +1110,17 @@
         mTestSystemImpl.setPackageInfo(createPackageInfo(testPackageName, true /* enabled */,
                     true /* valid */, false /* installed */));
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         checkPreparationPhasesForPackage(testPackageName, 1 /* first preparation phase */);
     }
 
+    @Test
     public void testNonhiddenPackageUserOverHidden() {
         checkVisiblePackageUserOverNonVisible(false /* true == uninstalled, false == hidden */);
     }
 
+    @Test
     public void testInstalledPackageUsedOverUninstalled() {
         checkVisiblePackageUserOverNonVisible(true /* true == uninstalled, false == hidden */);
     }
@@ -1088,16 +1143,18 @@
                     true /* valid */, (testUninstalled ? false : true) /* installed */,
                     null /* signatures */, 0 /* updateTime */, (testHidden ? true : false)));
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
     }
 
+    @Test
     public void testCantSwitchToHiddenPackage () {
         checkCantSwitchToNonVisiblePackage(false /* true == uninstalled, false == hidden */);
     }
 
 
+    @Test
     public void testCantSwitchToUninstalledPackage () {
         checkCantSwitchToNonVisiblePackage(true /* true == uninstalled, false == hidden */);
     }
@@ -1126,7 +1183,7 @@
                     null /* signatures */, 0 /* updateTime */,
                     (testHidden ? true : false) /* hidden */));
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
 
@@ -1146,11 +1203,13 @@
                 Mockito.argThat(new IsPackageInfoWithName(installedPackage)));
     }
 
+    @Test
     public void testHiddenPackageNotPrioritizedEvenIfChosen() {
         checkNonvisiblePackageNotPrioritizedEvenIfChosen(
                 false /* true == uninstalled, false == hidden */);
     }
 
+    @Test
     public void testUninstalledPackageNotPrioritizedEvenIfChosen() {
         checkNonvisiblePackageNotPrioritizedEvenIfChosen(
                 true /* true == uninstalled, false == hidden */);
@@ -1178,7 +1237,7 @@
         // Start with the setting pointing to the uninstalled package
         mTestSystemImpl.updateUserSetting(null, uninstalledPackage);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
     }
@@ -1187,6 +1246,7 @@
      * Ensures that fallback becomes enabled if the primary package is uninstalled for the current
      * user.
      */
+    @Test
     public void testFallbackEnabledIfPrimaryUninstalled() {
         String primaryPackage = "primary";
         String fallbackPackage = "fallback";
@@ -1201,7 +1261,7 @@
         mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
                     true /* valid */, true /* installed */));
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
         // Verify that we enable the fallback package
         Mockito.verify(mTestSystemImpl).enablePackageForAllUsers(
                 Mockito.anyObject(), Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */);
@@ -1209,6 +1269,7 @@
         checkPreparationPhasesForPackage(fallbackPackage, 1 /* first preparation phase */);
     }
 
+    @Test
     public void testPreparationRunsIffNewPackage() {
         String primaryPackage = "primary";
         String fallbackPackage = "fallback";
@@ -1224,7 +1285,7 @@
         mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
                     true /* valid */, true /* installed */));
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */);
         Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser(
@@ -1270,6 +1331,7 @@
         checkPreparationPhasesForPackage(primaryPackage, 3 /* third preparation phase */);
     }
 
+    @Test
     public void testGetCurrentWebViewPackage() {
         PackageInfo firstPackage = createPackageInfo("first", true /* enabled */,
                         true /* valid */, true /* installed */);
@@ -1280,7 +1342,7 @@
         setupWithPackages(packages, true);
         mTestSystemImpl.setPackageInfo(firstPackage);
 
-        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        runWebViewBootPreparationOnMainSync();
 
         Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
                 Mockito.argThat(new IsPackageInfoWithName(firstPackage.packageName)));
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 3e7d272..38a98b2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -61,6 +61,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
 import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
+import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
@@ -151,6 +152,7 @@
             return 2;
         }
         switch (type) {
+            case TYPE_PRESENTATION:
             case TYPE_PRIVATE_PRESENTATION:
                 return 2;
             case TYPE_WALLPAPER:
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 19b4186..fd1c91a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -66,6 +66,8 @@
 
     class TaskWithBounds extends Task {
         final Rect mBounds;
+        final Rect mInsetBounds = new Rect();
+        boolean mFullscreenForTest = true;
         TaskWithBounds(Rect bounds) {
             super(0, mStubStack, 0, sWm, null, null, false);
             mBounds = bounds;
@@ -76,11 +78,11 @@
         }
         @Override
         void getTempInsetBounds(Rect outBounds) {
-            outBounds.setEmpty();
+            outBounds.set(mInsetBounds);
         }
         @Override
         boolean isFullscreen() {
-            return true;
+            return mFullscreenForTest;
         }
     }
 
@@ -237,6 +239,41 @@
         assertRect(w.mFrame, 600, 600, 900, 900);
     }
 
+    @Test
+    public void testLayoutNonfullscreenTask() {
+        final Rect taskBounds = new Rect(300, 300, 700, 700);
+        TaskWithBounds task = new TaskWithBounds(taskBounds);
+        task.mFullscreenForTest = false;
+        WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
+        w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
+
+        final Rect pf = new Rect(0, 0, 1000, 1000);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, null);
+        // For non fullscreen tasks the containing frame is based off the
+        // task bounds not the parent frame.
+        assertRect(w.mFrame, 300, 300, 700, 700);
+        assertRect(w.getContentFrameLw(), 300, 300, 700, 700);
+        assertRect(w.mContentInsets, 0, 0, 0, 0);
+
+        pf.set(0, 0, 1000, 1000);
+        // We still produce insets against the containing frame the same way.
+        final Rect cf = new Rect(0, 0, 500, 500);
+        w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null);
+        assertRect(w.mFrame, 300, 300, 700, 700);
+        assertRect(w.getContentFrameLw(), 300, 300, 500, 500);
+        assertRect(w.mContentInsets, 0, 0, 200, 200);
+
+        pf.set(0, 0, 1000, 1000);
+        // However if we set temp inset bounds, the insets will be computed
+        // as if our window was laid out there,  but it will be laid out according to
+        // the task bounds.
+        task.mInsetBounds.set(200, 200, 600, 600);
+        w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null);
+        assertRect(w.mFrame, 300, 300, 700, 700);
+        assertRect(w.getContentFrameLw(), 300, 300, 600, 600);
+        assertRect(w.mContentInsets, 0, 0, 100, 100);
+    }
+
     private WindowState createWindow(Task task, int width, int height) {
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
         attrs.width = width;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 8268b40..7dacf16 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -59,6 +59,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+
 final class VoiceInteractionSessionConnection implements ServiceConnection {
 
     final static String TAG = "VoiceInteractionServiceManager";
@@ -198,8 +201,7 @@
                         | Context.BIND_ALLOW_OOM_MANAGEMENT, new UserHandle(mUser));
         if (mBound) {
             try {
-                mIWindowManager.addWindowToken(mToken,
-                        WindowManager.LayoutParams.TYPE_VOICE_INTERACTION);
+                mIWindowManager.addWindowToken(mToken, TYPE_VOICE_INTERACTION, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Failed adding window token", e);
             }
@@ -501,7 +503,7 @@
             }
             mContext.unbindService(this);
             try {
-                mIWindowManager.removeWindowToken(mToken);
+                mIWindowManager.removeWindowToken(mToken, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Failed removing window token", e);
             }
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index df7d539..f3fada9 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -93,7 +93,8 @@
             ParcelableConnection connection) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.handleCreateConnectionComplete(id, request, connection);
+                adapter.handleCreateConnectionComplete(id, request, connection,
+                        Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -108,7 +109,7 @@
     void setActive(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setActive(callId);
+                adapter.setActive(callId, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -122,7 +123,7 @@
     void setRinging(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setRinging(callId);
+                adapter.setRinging(callId, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -136,7 +137,7 @@
     void setDialing(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setDialing(callId);
+                adapter.setDialing(callId, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -151,7 +152,7 @@
     void setPulling(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setPulling(callId);
+                adapter.setPulling(callId, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -167,7 +168,7 @@
     void setDisconnected(String callId, DisconnectCause disconnectCause) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setDisconnected(callId, disconnectCause);
+                adapter.setDisconnected(callId, disconnectCause, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -181,7 +182,7 @@
     void setOnHold(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setOnHold(callId);
+                adapter.setOnHold(callId, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -196,7 +197,7 @@
     void setRingbackRequested(String callId, boolean ringback) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setRingbackRequested(callId, ringback);
+                adapter.setRingbackRequested(callId, ringback, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -205,7 +206,7 @@
     void setConnectionCapabilities(String callId, int capabilities) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setConnectionCapabilities(callId, capabilities);
+                adapter.setConnectionCapabilities(callId, capabilities, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -214,7 +215,7 @@
     void setConnectionProperties(String callId, int properties) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setConnectionProperties(callId, properties);
+                adapter.setConnectionProperties(callId, properties, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -232,7 +233,7 @@
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
                 Log.d(this, "sending connection %s with conference %s", callId, conferenceCallId);
-                adapter.setIsConferenced(callId, conferenceCallId);
+                adapter.setIsConferenced(callId, conferenceCallId, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -247,7 +248,7 @@
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
                 Log.d(this, "merge failed for call %s", callId);
-                adapter.setConferenceMergeFailed(callId);
+                adapter.setConferenceMergeFailed(callId, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -262,7 +263,7 @@
     void removeCall(String callId) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.removeCall(callId);
+                adapter.removeCall(callId, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -271,7 +272,7 @@
     void onPostDialWait(String callId, String remaining) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.onPostDialWait(callId, remaining);
+                adapter.onPostDialWait(callId, remaining, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -280,7 +281,7 @@
     void onPostDialChar(String callId, char nextChar) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.onPostDialChar(callId, nextChar);
+                adapter.onPostDialChar(callId, nextChar, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -294,7 +295,7 @@
     void addConferenceCall(String callId, ParcelableConference parcelableConference) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.addConferenceCall(callId, parcelableConference);
+                adapter.addConferenceCall(callId, parcelableConference, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -307,7 +308,8 @@
         // Only supported when there is only one adapter.
         if (mAdapters.size() == 1) {
             try {
-                mAdapters.iterator().next().queryRemoteConnectionServices(callback);
+                mAdapters.iterator().next().queryRemoteConnectionServices(callback,
+                        Log.getExternalSession());
             } catch (RemoteException e) {
                 Log.e(this, e, "Exception trying to query for remote CSs");
             }
@@ -326,7 +328,8 @@
             try {
                 adapter.setVideoProvider(
                         callId,
-                        videoProvider == null ? null : videoProvider.getInterface());
+                        videoProvider == null ? null : videoProvider.getInterface(),
+                        Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -341,7 +344,7 @@
     void setIsVoipAudioMode(String callId, boolean isVoip) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setIsVoipAudioMode(callId, isVoip);
+                adapter.setIsVoipAudioMode(callId, isVoip, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -350,7 +353,7 @@
     void setStatusHints(String callId, StatusHints statusHints) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setStatusHints(callId, statusHints);
+                adapter.setStatusHints(callId, statusHints, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -359,7 +362,7 @@
     void setAddress(String callId, Uri address, int presentation) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setAddress(callId, address, presentation);
+                adapter.setAddress(callId, address, presentation, Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -368,7 +371,8 @@
     void setCallerDisplayName(String callId, String callerDisplayName, int presentation) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setCallerDisplayName(callId, callerDisplayName, presentation);
+                adapter.setCallerDisplayName(callId, callerDisplayName, presentation,
+                        Log.getExternalSession());
             } catch (RemoteException e) {
             }
         }
@@ -389,7 +393,7 @@
         Log.v(this, "setVideoState: %d", videoState);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setVideoState(callId, videoState);
+                adapter.setVideoState(callId, videoState, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -399,7 +403,8 @@
         Log.v(this, "setConferenceableConnections: %s, %s", callId, conferenceableCallIds);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setConferenceableConnections(callId, conferenceableCallIds);
+                adapter.setConferenceableConnections(callId, conferenceableCallIds,
+                        Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -415,7 +420,7 @@
         Log.v(this, "addExistingConnection: %s", callId);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.addExistingConnection(callId, connection);
+                adapter.addExistingConnection(callId, connection, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -431,7 +436,7 @@
         Log.v(this, "putExtras: %s", callId);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.putExtras(callId, extras);
+                adapter.putExtras(callId, extras, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -450,7 +455,7 @@
             try {
                 Bundle bundle = new Bundle();
                 bundle.putBoolean(key, value);
-                adapter.putExtras(callId, bundle);
+                adapter.putExtras(callId, bundle, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -469,7 +474,7 @@
             try {
                 Bundle bundle = new Bundle();
                 bundle.putInt(key, value);
-                adapter.putExtras(callId, bundle);
+                adapter.putExtras(callId, bundle, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -488,7 +493,7 @@
             try {
                 Bundle bundle = new Bundle();
                 bundle.putString(key, value);
-                adapter.putExtras(callId, bundle);
+                adapter.putExtras(callId, bundle, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -503,7 +508,7 @@
         Log.v(this, "removeExtras: %s %s", callId, keys);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.removeExtras(callId, keys);
+                adapter.removeExtras(callId, keys, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
@@ -520,7 +525,7 @@
         Log.v(this, "onConnectionEvent: %s", event);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.onConnectionEvent(callId, event, extras);
+                adapter.onConnectionEvent(callId, event, extras, Log.getExternalSession());
             } catch (RemoteException ignored) {
             }
         }
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 486f9d5..afe5e33 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -21,6 +21,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
+import android.telecom.Logging.Session;
 
 import com.android.internal.os.SomeArgs;
 import com.android.internal.telecom.IConnectionServiceAdapter;
@@ -87,49 +88,55 @@
                         mDelegate.handleCreateConnectionComplete(
                                 (String) args.arg1,
                                 (ConnectionRequest) args.arg2,
-                                (ParcelableConnection) args.arg3);
+                                (ParcelableConnection) args.arg3,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_SET_ACTIVE:
-                    mDelegate.setActive((String) msg.obj);
+                    mDelegate.setActive((String) msg.obj, null /*Session.Info*/);
                     break;
                 case MSG_SET_RINGING:
-                    mDelegate.setRinging((String) msg.obj);
+                    mDelegate.setRinging((String) msg.obj, null /*Session.Info*/);
                     break;
                 case MSG_SET_DIALING:
-                    mDelegate.setDialing((String) msg.obj);
+                    mDelegate.setDialing((String) msg.obj, null /*Session.Info*/);
                     break;
                 case MSG_SET_PULLING:
-                    mDelegate.setPulling((String) msg.obj);
+                    mDelegate.setPulling((String) msg.obj, null /*Session.Info*/);
                     break;
                 case MSG_SET_DISCONNECTED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setDisconnected((String) args.arg1, (DisconnectCause) args.arg2);
+                        mDelegate.setDisconnected((String) args.arg1, (DisconnectCause) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_SET_ON_HOLD:
-                    mDelegate.setOnHold((String) msg.obj);
+                    mDelegate.setOnHold((String) msg.obj, null /*Session.Info*/);
                     break;
                 case MSG_SET_RINGBACK_REQUESTED:
-                    mDelegate.setRingbackRequested((String) msg.obj, msg.arg1 == 1);
+                    mDelegate.setRingbackRequested((String) msg.obj, msg.arg1 == 1,
+                            null /*Session.Info*/);
                     break;
                 case MSG_SET_CONNECTION_CAPABILITIES:
-                    mDelegate.setConnectionCapabilities((String) msg.obj, msg.arg1);
+                    mDelegate.setConnectionCapabilities((String) msg.obj, msg.arg1,
+                            null /*Session.Info*/);
                     break;
                 case MSG_SET_CONNECTION_PROPERTIES:
-                    mDelegate.setConnectionProperties((String) msg.obj, msg.arg1);
+                    mDelegate.setConnectionProperties((String) msg.obj, msg.arg1,
+                            null /*Session.Info*/);
                     break;
                 case MSG_SET_IS_CONFERENCED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setIsConferenced((String) args.arg1, (String) args.arg2);
+                        mDelegate.setIsConferenced((String) args.arg1, (String) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -139,19 +146,22 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         mDelegate.addConferenceCall(
-                                (String) args.arg1, (ParcelableConference) args.arg2);
+                                (String) args.arg1, (ParcelableConference) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_REMOVE_CALL:
-                    mDelegate.removeCall((String) msg.obj);
+                    mDelegate.removeCall((String) msg.obj,
+                            null /*Session.Info*/);
                     break;
                 case MSG_ON_POST_DIAL_WAIT: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.onPostDialWait((String) args.arg1, (String) args.arg2);
+                        mDelegate.onPostDialWait((String) args.arg1, (String) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -160,35 +170,39 @@
                 case MSG_ON_POST_DIAL_CHAR: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.onPostDialChar((String) args.arg1, (char) args.argi1);
+                        mDelegate.onPostDialChar((String) args.arg1, (char) args.argi1,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_QUERY_REMOTE_CALL_SERVICES:
-                    mDelegate.queryRemoteConnectionServices((RemoteServiceCallback) msg.obj);
+                    mDelegate.queryRemoteConnectionServices((RemoteServiceCallback) msg.obj,
+                            null /*Session.Info*/);
                     break;
                 case MSG_SET_VIDEO_STATE:
-                    mDelegate.setVideoState((String) msg.obj, msg.arg1);
+                    mDelegate.setVideoState((String) msg.obj, msg.arg1, null /*Session.Info*/);
                     break;
                 case MSG_SET_VIDEO_CALL_PROVIDER: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         mDelegate.setVideoProvider((String) args.arg1,
-                                (IVideoProvider) args.arg2);
+                                (IVideoProvider) args.arg2, null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_SET_IS_VOIP_AUDIO_MODE:
-                    mDelegate.setIsVoipAudioMode((String) msg.obj, msg.arg1 == 1);
+                    mDelegate.setIsVoipAudioMode((String) msg.obj, msg.arg1 == 1,
+                            null /*Session.Info*/);
                     break;
                 case MSG_SET_STATUS_HINTS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setStatusHints((String) args.arg1, (StatusHints) args.arg2);
+                        mDelegate.setStatusHints((String) args.arg1, (StatusHints) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -197,7 +211,8 @@
                 case MSG_SET_ADDRESS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setAddress((String) args.arg1, (Uri) args.arg2, args.argi1);
+                        mDelegate.setAddress((String) args.arg1, (Uri) args.arg2, args.argi1,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -207,7 +222,8 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         mDelegate.setCallerDisplayName(
-                                (String) args.arg1, (String) args.arg2, args.argi1);
+                                (String) args.arg1, (String) args.arg2, args.argi1,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -216,8 +232,8 @@
                 case MSG_SET_CONFERENCEABLE_CONNECTIONS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setConferenceableConnections(
-                                (String) args.arg1, (List<String>) args.arg2);
+                        mDelegate.setConferenceableConnections((String) args.arg1,
+                                (List<String>) args.arg2, null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -226,8 +242,8 @@
                 case MSG_ADD_EXISTING_CONNECTION: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.addExistingConnection(
-                                (String) args.arg1, (ParcelableConnection) args.arg2);
+                        mDelegate.addExistingConnection((String) args.arg1,
+                                (ParcelableConnection) args.arg2, null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -236,7 +252,8 @@
                 case MSG_SET_CONFERENCE_MERGE_FAILED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setConferenceMergeFailed((String) args.arg1);
+                        mDelegate.setConferenceMergeFailed((String) args.arg1,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -245,7 +262,8 @@
                 case MSG_PUT_EXTRAS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.putExtras((String) args.arg1, (Bundle) args.arg2);
+                        mDelegate.putExtras((String) args.arg1, (Bundle) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -254,7 +272,8 @@
                 case MSG_REMOVE_EXTRAS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.removeExtras((String) args.arg1, (List<String>) args.arg2);
+                        mDelegate.removeExtras((String) args.arg1, (List<String>) args.arg2,
+                                null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -264,7 +283,7 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2,
-                                (Bundle) args.arg3);
+                                (Bundle) args.arg3, null /*Session.Info*/);
                     } finally {
                         args.recycle();
                     }
@@ -279,7 +298,8 @@
         public void handleCreateConnectionComplete(
                 String id,
                 ConnectionRequest request,
-                ParcelableConnection connection) {
+                ParcelableConnection connection,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = id;
             args.arg2 = request;
@@ -288,28 +308,28 @@
         }
 
         @Override
-        public void setActive(String connectionId) {
+        public void setActive(String connectionId, Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_ACTIVE, connectionId).sendToTarget();
         }
 
         @Override
-        public void setRinging(String connectionId) {
+        public void setRinging(String connectionId, Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_RINGING, connectionId).sendToTarget();
         }
 
         @Override
-        public void setDialing(String connectionId) {
+        public void setDialing(String connectionId, Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_DIALING, connectionId).sendToTarget();
         }
 
         @Override
-        public void setPulling(String connectionId) {
+        public void setPulling(String connectionId, Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_PULLING, connectionId).sendToTarget();
         }
 
         @Override
-        public void setDisconnected(
-                String connectionId, DisconnectCause disconnectCause) {
+        public void setDisconnected(String connectionId, DisconnectCause disconnectCause,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = disconnectCause;
@@ -317,39 +337,43 @@
         }
 
         @Override
-        public void setOnHold(String connectionId) {
+        public void setOnHold(String connectionId, Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_ON_HOLD, connectionId).sendToTarget();
         }
 
         @Override
-        public void setRingbackRequested(String connectionId, boolean ringback) {
+        public void setRingbackRequested(String connectionId, boolean ringback,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_RINGBACK_REQUESTED, ringback ? 1 : 0, 0, connectionId)
                     .sendToTarget();
         }
 
         @Override
-        public void setConnectionCapabilities(String connectionId, int connectionCapabilities) {
+        public void setConnectionCapabilities(String connectionId, int connectionCapabilities,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(
                     MSG_SET_CONNECTION_CAPABILITIES, connectionCapabilities, 0, connectionId)
                     .sendToTarget();
         }
 
         @Override
-        public void setConnectionProperties(String connectionId, int connectionProperties) {
+        public void setConnectionProperties(String connectionId, int connectionProperties,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(
                     MSG_SET_CONNECTION_PROPERTIES, connectionProperties, 0, connectionId)
                     .sendToTarget();
         }
 
         @Override
-        public void setConferenceMergeFailed(String callId) {
+        public void setConferenceMergeFailed(String callId, Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
             mHandler.obtainMessage(MSG_SET_CONFERENCE_MERGE_FAILED, args).sendToTarget();
         }
 
         @Override
-        public void setIsConferenced(String callId, String conferenceCallId) {
+        public void setIsConferenced(String callId, String conferenceCallId,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
             args.arg2 = conferenceCallId;
@@ -357,7 +381,8 @@
         }
 
         @Override
-        public void addConferenceCall(String callId, ParcelableConference parcelableConference) {
+        public void addConferenceCall(String callId, ParcelableConference parcelableConference,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
             args.arg2 = parcelableConference;
@@ -365,12 +390,14 @@
         }
 
         @Override
-        public void removeCall(String connectionId) {
+        public void removeCall(String connectionId,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_REMOVE_CALL, connectionId).sendToTarget();
         }
 
         @Override
-        public void onPostDialWait(String connectionId, String remainingDigits) {
+        public void onPostDialWait(String connectionId, String remainingDigits,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = remainingDigits;
@@ -378,7 +405,8 @@
         }
 
         @Override
-        public void onPostDialChar(String connectionId, char nextChar) {
+        public void onPostDialChar(String connectionId, char nextChar,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.argi1 = nextChar;
@@ -386,17 +414,20 @@
         }
 
         @Override
-        public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
+        public void queryRemoteConnectionServices(RemoteServiceCallback callback,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_QUERY_REMOTE_CALL_SERVICES, callback).sendToTarget();
         }
 
         @Override
-        public void setVideoState(String connectionId, int videoState) {
+        public void setVideoState(String connectionId, int videoState,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_VIDEO_STATE, videoState, 0, connectionId).sendToTarget();
         }
 
         @Override
-        public void setVideoProvider(String connectionId, IVideoProvider videoProvider) {
+        public void setVideoProvider(String connectionId, IVideoProvider videoProvider,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = videoProvider;
@@ -404,13 +435,15 @@
         }
 
         @Override
-        public final void setIsVoipAudioMode(String connectionId, boolean isVoip) {
+        public final void setIsVoipAudioMode(String connectionId, boolean isVoip,
+                Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_SET_IS_VOIP_AUDIO_MODE, isVoip ? 1 : 0, 0,
                     connectionId).sendToTarget();
         }
 
         @Override
-        public final void setStatusHints(String connectionId, StatusHints statusHints) {
+        public final void setStatusHints(String connectionId, StatusHints statusHints,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = statusHints;
@@ -418,7 +451,8 @@
         }
 
         @Override
-        public final void setAddress(String connectionId, Uri address, int presentation) {
+        public final void setAddress(String connectionId, Uri address, int presentation,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = address;
@@ -428,7 +462,8 @@
 
         @Override
         public final void setCallerDisplayName(
-                String connectionId, String callerDisplayName, int presentation) {
+                String connectionId, String callerDisplayName, int presentation,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = callerDisplayName;
@@ -437,8 +472,8 @@
         }
 
         @Override
-        public final void setConferenceableConnections(
-                String connectionId, List<String> conferenceableConnectionIds) {
+        public final void setConferenceableConnections(String connectionId,
+                List<String> conferenceableConnectionIds, Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = conferenceableConnectionIds;
@@ -446,8 +481,8 @@
         }
 
         @Override
-        public final void addExistingConnection(
-                String connectionId, ParcelableConnection connection) {
+        public final void addExistingConnection(String connectionId,
+                ParcelableConnection connection, Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = connection;
@@ -455,7 +490,7 @@
         }
 
         @Override
-        public final void putExtras(String connectionId, Bundle extras) {
+        public final void putExtras(String connectionId, Bundle extras, Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = extras;
@@ -463,7 +498,8 @@
         }
 
         @Override
-        public final void removeExtras(String connectionId, List<String> keys) {
+        public final void removeExtras(String connectionId, List<String> keys,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = keys;
@@ -471,7 +507,8 @@
         }
 
         @Override
-        public final void onConnectionEvent(String connectionId, String event, Bundle extras) {
+        public final void onConnectionEvent(String connectionId, String event, Bundle extras,
+                Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = event;
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 3927d81..0a8470a 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -21,6 +21,7 @@
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
 import android.os.RemoteException;
+import android.telecom.Logging.Session;
 
 import com.android.internal.telecom.IConnectionService;
 import com.android.internal.telecom.IConnectionServiceAdapter;
@@ -54,7 +55,8 @@
         public void handleCreateConnectionComplete(
                 String id,
                 ConnectionRequest request,
-                ParcelableConnection parcel) {
+                ParcelableConnection parcel,
+                Session.Info info) {
             RemoteConnection connection =
                     findConnectionForAction(id, "handleCreateConnectionSuccessful");
             if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
@@ -95,7 +97,7 @@
         }
 
         @Override
-        public void setActive(String callId) {
+        public void setActive(String callId, Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "setActive")
                         .setState(Connection.STATE_ACTIVE);
@@ -106,25 +108,26 @@
         }
 
         @Override
-        public void setRinging(String callId) {
+        public void setRinging(String callId, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setRinging")
                     .setState(Connection.STATE_RINGING);
         }
 
         @Override
-        public void setDialing(String callId) {
+        public void setDialing(String callId, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setDialing")
                     .setState(Connection.STATE_DIALING);
         }
 
         @Override
-        public void setPulling(String callId) {
+        public void setPulling(String callId, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setPulling")
                     .setState(Connection.STATE_PULLING_CALL);
         }
 
         @Override
-        public void setDisconnected(String callId, DisconnectCause disconnectCause) {
+        public void setDisconnected(String callId, DisconnectCause disconnectCause,
+                Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "setDisconnected")
                         .setDisconnected(disconnectCause);
@@ -135,7 +138,7 @@
         }
 
         @Override
-        public void setOnHold(String callId) {
+        public void setOnHold(String callId, Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "setOnHold")
                         .setState(Connection.STATE_HOLDING);
@@ -146,13 +149,14 @@
         }
 
         @Override
-        public void setRingbackRequested(String callId, boolean ringing) {
+        public void setRingbackRequested(String callId, boolean ringing, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setRingbackRequested")
                     .setRingbackRequested(ringing);
         }
 
         @Override
-        public void setConnectionCapabilities(String callId, int connectionCapabilities) {
+        public void setConnectionCapabilities(String callId, int connectionCapabilities,
+                Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "setConnectionCapabilities")
                         .setConnectionCapabilities(connectionCapabilities);
@@ -163,7 +167,8 @@
         }
 
         @Override
-        public void setConnectionProperties(String callId, int connectionProperties) {
+        public void setConnectionProperties(String callId, int connectionProperties,
+                Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "setConnectionProperties")
                         .setConnectionProperties(connectionProperties);
@@ -174,7 +179,8 @@
         }
 
         @Override
-        public void setIsConferenced(String callId, String conferenceCallId) {
+        public void setIsConferenced(String callId, String conferenceCallId,
+                Session.Info sessionInfo) {
             // Note: callId should not be null; conferenceCallId may be null
             RemoteConnection connection =
                     findConnectionForAction(callId, "setIsConferenced");
@@ -195,7 +201,7 @@
         }
 
         @Override
-        public void setConferenceMergeFailed(String callId) {
+        public void setConferenceMergeFailed(String callId, Session.Info sessionInfo) {
             // Nothing to do here.
             // The event has already been handled and there is no state to update
             // in the underlying connection or conference objects
@@ -203,8 +209,7 @@
 
         @Override
         public void addConferenceCall(
-                final String callId,
-                ParcelableConference parcel) {
+                final String callId, ParcelableConference parcel, Session.Info sessionInfo) {
             RemoteConference conference = new RemoteConference(callId,
                     mOutgoingConnectionServiceRpc);
 
@@ -247,7 +252,7 @@
         }
 
         @Override
-        public void removeCall(String callId) {
+        public void removeCall(String callId, Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "removeCall")
                         .setDestroyed();
@@ -258,24 +263,26 @@
         }
 
         @Override
-        public void onPostDialWait(String callId, String remaining) {
+        public void onPostDialWait(String callId, String remaining, Session.Info sessionInfo) {
             findConnectionForAction(callId, "onPostDialWait")
                     .setPostDialWait(remaining);
         }
 
         @Override
-        public void onPostDialChar(String callId, char nextChar) {
+        public void onPostDialChar(String callId, char nextChar, Session.Info sessionInfo) {
             findConnectionForAction(callId, "onPostDialChar")
                     .onPostDialChar(nextChar);
         }
 
         @Override
-        public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
+        public void queryRemoteConnectionServices(RemoteServiceCallback callback,
+                Session.Info sessionInfo) {
             // Not supported from remote connection service.
         }
 
         @Override
-        public void setVideoProvider(String callId, IVideoProvider videoProvider) {
+        public void setVideoProvider(String callId, IVideoProvider videoProvider,
+                Session.Info sessionInfo) {
             RemoteConnection.VideoProvider remoteVideoProvider = null;
             if (videoProvider != null) {
                 remoteVideoProvider = new RemoteConnection.VideoProvider(videoProvider);
@@ -285,32 +292,34 @@
         }
 
         @Override
-        public void setVideoState(String callId, int videoState) {
+        public void setVideoState(String callId, int videoState, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setVideoState")
                     .setVideoState(videoState);
         }
 
         @Override
-        public void setIsVoipAudioMode(String callId, boolean isVoip) {
+        public void setIsVoipAudioMode(String callId, boolean isVoip, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setIsVoipAudioMode")
                     .setIsVoipAudioMode(isVoip);
         }
 
         @Override
-        public void setStatusHints(String callId, StatusHints statusHints) {
+        public void setStatusHints(String callId, StatusHints statusHints,
+                Session.Info sessionInfo) {
             findConnectionForAction(callId, "setStatusHints")
                     .setStatusHints(statusHints);
         }
 
         @Override
-        public void setAddress(String callId, Uri address, int presentation) {
+        public void setAddress(String callId, Uri address, int presentation,
+                Session.Info sessionInfo) {
             findConnectionForAction(callId, "setAddress")
                     .setAddress(address, presentation);
         }
 
         @Override
         public void setCallerDisplayName(String callId, String callerDisplayName,
-                int presentation) {
+                int presentation, Session.Info sessionInfo) {
             findConnectionForAction(callId, "setCallerDisplayName")
                     .setCallerDisplayName(callerDisplayName, presentation);
         }
@@ -321,8 +330,8 @@
         }
 
         @Override
-        public final void setConferenceableConnections(
-                String callId, List<String> conferenceableConnectionIds) {
+        public final void setConferenceableConnections(String callId,
+                List<String> conferenceableConnectionIds, Session.Info sessionInfo) {
             List<RemoteConnection> conferenceable = new ArrayList<>();
             for (String id : conferenceableConnectionIds) {
                 if (mConnectionById.containsKey(id)) {
@@ -340,7 +349,8 @@
         }
 
         @Override
-        public void addExistingConnection(final String callId, ParcelableConnection connection) {
+        public void addExistingConnection(String callId, ParcelableConnection connection,
+                Session.Info sessionInfo) {
             RemoteConnection remoteConnection = new RemoteConnection(callId,
                     mOutgoingConnectionServiceRpc, connection);
             mConnectionById.put(callId, remoteConnection);
@@ -355,7 +365,7 @@
         }
 
         @Override
-        public void putExtras(String callId, Bundle extras) {
+        public void putExtras(String callId, Bundle extras, Session.Info sessionInfo) {
             if (hasConnection(callId)) {
                 findConnectionForAction(callId, "putExtras").putExtras(extras);
             } else {
@@ -364,7 +374,7 @@
         }
 
         @Override
-        public void removeExtras(String callId, List<String> keys) {
+        public void removeExtras(String callId, List<String> keys, Session.Info sessionInfo) {
             if (hasConnection(callId)) {
                 findConnectionForAction(callId, "removeExtra").removeExtras(keys);
             } else {
@@ -373,7 +383,8 @@
         }
 
         @Override
-        public void onConnectionEvent(String callId, String event, Bundle extras) {
+        public void onConnectionEvent(String callId, String event, Bundle extras,
+                Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
                 findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event,
                         extras);
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 3bf83ae..002c3bb 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.telecom.ConnectionRequest;
 import android.telecom.DisconnectCause;
+import android.telecom.Logging.Session;
 import android.telecom.ParcelableConnection;
 import android.telecom.ParcelableConference;
 import android.telecom.StatusHints;
@@ -39,59 +40,68 @@
     void handleCreateConnectionComplete(
             String callId,
             in ConnectionRequest request,
-            in ParcelableConnection connection);
+            in ParcelableConnection connection,
+            in Session.Info sessionInfo);
 
-    void setActive(String callId);
+    void setActive(String callId, in Session.Info sessionInfo);
 
-    void setRinging(String callId);
+    void setRinging(String callId, in Session.Info sessionInfo);
 
-    void setDialing(String callId);
+    void setDialing(String callId, in Session.Info sessionInfo);
 
-    void setPulling(String callId);
+    void setPulling(String callId, in Session.Info sessionInfo);
 
-    void setDisconnected(String callId, in DisconnectCause disconnectCause);
+    void setDisconnected(String callId, in DisconnectCause disconnectCause,
+    in Session.Info sessionInfo);
 
-    void setOnHold(String callId);
+    void setOnHold(String callId, in Session.Info sessionInfo);
 
-    void setRingbackRequested(String callId, boolean ringing);
+    void setRingbackRequested(String callId, boolean ringing, in Session.Info sessionInfo);
 
-    void setConnectionCapabilities(String callId, int connectionCapabilities);
+    void setConnectionCapabilities(String callId, int connectionCapabilities,
+    in Session.Info sessionInfo);
 
-    void setConnectionProperties(String callId, int connectionProperties);
+    void setConnectionProperties(String callId, int connectionProperties,
+    in Session.Info sessionInfo);
 
-    void setIsConferenced(String callId, String conferenceCallId);
+    void setIsConferenced(String callId, String conferenceCallId, in Session.Info sessionInfo);
 
-    void setConferenceMergeFailed(String callId);
+    void setConferenceMergeFailed(String callId, in Session.Info sessionInfo);
 
-    void addConferenceCall(String callId, in ParcelableConference conference);
+    void addConferenceCall(String callId, in ParcelableConference conference,
+    in Session.Info sessionInfo);
 
-    void removeCall(String callId);
+    void removeCall(String callId, in Session.Info sessionInfo);
 
-    void onPostDialWait(String callId, String remaining);
+    void onPostDialWait(String callId, String remaining, in Session.Info sessionInfo);
 
-    void onPostDialChar(String callId, char nextChar);
+    void onPostDialChar(String callId, char nextChar, in Session.Info sessionInfo);
 
-    void queryRemoteConnectionServices(RemoteServiceCallback callback);
+    void queryRemoteConnectionServices(RemoteServiceCallback callback, in Session.Info sessionInfo);
 
-    void setVideoProvider(String callId, IVideoProvider videoProvider);
+    void setVideoProvider(String callId, IVideoProvider videoProvider, in Session.Info sessionInfo);
 
-    void setVideoState(String callId, int videoState);
+    void setVideoState(String callId, int videoState, in Session.Info sessionInfo);
 
-    void setIsVoipAudioMode(String callId, boolean isVoip);
+    void setIsVoipAudioMode(String callId, boolean isVoip, in Session.Info sessionInfo);
 
-    void setStatusHints(String callId, in StatusHints statusHints);
+    void setStatusHints(String callId, in StatusHints statusHints, in Session.Info sessionInfo);
 
-    void setAddress(String callId, in Uri address, int presentation);
+    void setAddress(String callId, in Uri address, int presentation, in Session.Info sessionInfo);
 
-    void setCallerDisplayName(String callId, String callerDisplayName, int presentation);
+    void setCallerDisplayName(String callId, String callerDisplayName, int presentation,
+    in Session.Info sessionInfo);
 
-    void setConferenceableConnections(String callId, in List<String> conferenceableCallIds);
+    void setConferenceableConnections(String callId, in List<String> conferenceableCallIds,
+    in Session.Info sessionInfo);
 
-    void addExistingConnection(String callId, in ParcelableConnection connection);
+    void addExistingConnection(String callId, in ParcelableConnection connection,
+    in Session.Info sessionInfo);
 
-    void putExtras(String callId, in Bundle extras);
+    void putExtras(String callId, in Bundle extras, in Session.Info sessionInfo);
 
-    void removeExtras(String callId, in List<String> keys);
+    void removeExtras(String callId, in List<String> keys, in Session.Info sessionInfo);
 
-    void onConnectionEvent(String callId, String event, in Bundle extras);
+    void onConnectionEvent(String callId, String event, in Bundle extras,
+    in Session.Info sessionInfo);
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7506b10..60a27bd 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -498,6 +498,13 @@
             "disable_severe_when_extreme_disabled_bool";
 
     /**
+     * The message expiration time in milliseconds for duplicate detection purposes.
+     * @hide
+     */
+    public static final String KEY_MESSAGE_EXPIRATION_TIME_LONG =
+            "message_expiration_time_long";
+
+    /**
      * The data call retry configuration for different types of APN.
      * @hide
      */
@@ -1165,6 +1172,7 @@
         sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
         sDefaults.putBoolean(KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL, true);
+        sDefaults.putLong(KEY_MESSAGE_EXPIRATION_TIME_LONG, 86400000L);
         sDefaults.putStringArray(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS, new String[]{
                 "default:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,"
                         + "320000:5000,640000:5000,1280000:5000,1800000:5000",
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a5b7304..dcf2f06 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1193,7 +1193,7 @@
     private int getPhoneTypeFromProperty(int phoneId) {
         String type = getTelephonyProperty(phoneId,
                 TelephonyProperties.CURRENT_ACTIVE_PHONE, null);
-        if (type == null || type.equals("")) {
+        if (type == null || type.isEmpty()) {
             return getPhoneTypeFromNetworkType(phoneId);
         }
         return Integer.parseInt(type);
@@ -1209,7 +1209,7 @@
         // use the system property for default network type.
         // This is a fail safe, and can only happen at first boot.
         String mode = getTelephonyProperty(phoneId, "ro.telephony.default_network", null);
-        if (mode != null) {
+        if (mode != null && !mode.isEmpty()) {
             return TelephonyManager.getPhoneType(Integer.parseInt(mode));
         }
         return TelephonyManager.PHONE_TYPE_NONE;
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 16a0def..f5f7ea3 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -32,7 +32,6 @@
 import android.os.UserHandle;
 import android.app.UiAutomation;
 import android.app.IActivityManager;
-import android.app.IActivityManager.WaitResult;
 import android.support.test.rule.logging.AtraceLogger;
 import android.test.InstrumentationTestCase;
 import android.test.InstrumentationTestRunner;
diff --git a/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java b/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java
index 6d42cce..f896030 100644
--- a/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java
+++ b/tests/net/java/android/net/ConnectivityMetricsLoggerTest.java
@@ -18,6 +18,7 @@
 
 import android.os.Bundle;
 import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
 import java.util.List;
 import junit.framework.TestCase;
 import org.mockito.ArgumentCaptor;
@@ -49,6 +50,7 @@
         mLog = new ConnectivityMetricsLogger(mService);
     }
 
+    @SmallTest
     public void testLogEvents() throws Exception {
         mLog.logEvent(1, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
         mLog.logEvent(2, FAKE_COMPONENT, FAKE_EVENT, FAKE_EV);
@@ -60,6 +62,7 @@
         assertEventsEqual(expectedEvent(3), gotEvents.get(2));
     }
 
+    @SmallTest
     public void testLogEventTriggerThrottling() throws Exception {
         when(mService.logEvent(any())).thenReturn(1234L);
 
@@ -70,6 +73,7 @@
         assertEventsEqual(expectedEvent(1), gotEvents.get(0));
     }
 
+    @SmallTest
     public void testLogEventFails() throws Exception {
         when(mService.logEvent(any())).thenReturn(-1L); // Error.
 
@@ -80,6 +84,7 @@
         assertEventsEqual(expectedEvent(1), gotEvents.get(0));
     }
 
+    @SmallTest
     public void testLogEventWhenThrottling() throws Exception {
         when(mService.logEvent(any())).thenReturn(Long.MAX_VALUE); // Throttled
 
@@ -92,6 +97,7 @@
         assertEventsEqual(expectedEvent(1), gotEvents.get(0));
     }
 
+    @SmallTest
     public void testLogEventRecoverFromThrottling() throws Exception {
         final long throttleTimeout = System.currentTimeMillis() + 10;
         when(mService.logEvent(any())).thenReturn(throttleTimeout, 0L);
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 81f66a5..51adfe7 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -33,7 +33,6 @@
 import android.system.Os;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import static android.system.OsConstants.*;
 
 import com.android.frameworks.tests.net.R;
@@ -155,7 +154,7 @@
      * generating bytecode for that program and running it through the
      * interpreter to verify it functions correctly.
      */
-    @MediumTest
+    @SmallTest
     public void testApfInstructions() throws IllegalInstructionException {
         // Empty program should pass because having the program counter reach the
         // location immediately after the program indicates the packet should be
@@ -563,7 +562,7 @@
      * Generate some BPF programs, translate them to APF, then run APF and BPF programs
      * over packet traces and verify both programs filter out the same packets.
      */
-    @MediumTest
+    @SmallTest
     public void testApfAgainstBpf() throws Exception {
         String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
                 "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
@@ -721,7 +720,7 @@
     private static final byte[] ANOTHER_IPV4_ADDR        = {10, 0, 0, 2};
     private static final byte[] IPV4_ANY_HOST_ADDR       = {0, 0, 0, 0};
 
-    @MediumTest
+    @SmallTest
     public void testApfFilterIPv4() throws Exception {
         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
@@ -776,7 +775,7 @@
         apfFilter.shutdown();
     }
 
-    @MediumTest
+    @SmallTest
     public void testApfFilterIPv6() throws Exception {
         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
         ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
@@ -802,7 +801,7 @@
         apfFilter.shutdown();
     }
 
-    @MediumTest
+    @SmallTest
     public void testApfFilterMulticast() throws Exception {
         final byte[] unicastIpv4Addr   = {(byte)192,0,2,63};
         final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
@@ -912,7 +911,7 @@
         assertDrop(program, garpReply());
     }
 
-    @MediumTest
+    @SmallTest
     public void testApfFilterArp() throws Exception {
         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
         ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
@@ -1031,7 +1030,7 @@
         ipManagerCallback.assertNoProgramUpdate();
     }
 
-    @MediumTest
+    @SmallTest
     public void testApfFilterRa() throws Exception {
         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
         TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
diff --git a/tests/net/java/android/net/dhcp/DhcpPacketTest.java b/tests/net/java/android/net/dhcp/DhcpPacketTest.java
index bc8baa1..d79c312 100644
--- a/tests/net/java/android/net/dhcp/DhcpPacketTest.java
+++ b/tests/net/java/android/net/dhcp/DhcpPacketTest.java
@@ -473,6 +473,7 @@
         assertEquals(Integer.toHexString(expected), Integer.toHexString(got));
     }
 
+    @SmallTest
     public void testTruncatedOfferPackets() throws Exception {
         final byte[] packet = HexDump.hexStringToByteArray(
             // IP header.
@@ -506,6 +507,7 @@
         }
     }
 
+    @SmallTest
     public void testRandomPackets() throws Exception {
         final int maxRandomPacketSize = 512;
         final Random r = new Random();
diff --git a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
index e677475..5deba27 100644
--- a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
+++ b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
@@ -24,6 +24,7 @@
 import android.net.netlink.NetlinkErrorMessage;
 import android.net.netlink.NetlinkMessage;
 import android.net.netlink.StructNlMsgErr;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -53,6 +54,7 @@
     public static final byte[] NLM_ERROR_OK =
             HexEncoding.decode(NLM_ERROR_OK_HEX.toCharArray(), false);
 
+    @SmallTest
     public void testParseNlmErrorOk() {
         final ByteBuffer byteBuffer = ByteBuffer.wrap(NLM_ERROR_OK);
         byteBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.
diff --git a/tests/net/java/android/net/netlink/NetlinkSocketTest.java b/tests/net/java/android/net/netlink/NetlinkSocketTest.java
index c599fe3..78b3b70 100644
--- a/tests/net/java/android/net/netlink/NetlinkSocketTest.java
+++ b/tests/net/java/android/net/netlink/NetlinkSocketTest.java
@@ -20,6 +20,7 @@
 import android.net.netlink.RtNetlinkNeighborMessage;
 import android.net.netlink.StructNdMsg;
 import android.net.netlink.StructNlMsgHdr;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.system.ErrnoException;
 import android.system.NetlinkSocketAddress;
 import android.system.OsConstants;
@@ -33,6 +34,7 @@
 public class NetlinkSocketTest extends TestCase {
     private final String TAG = "NetlinkSocketTest";
 
+    @SmallTest
     public void testBasicWorkingGetNeighborsQuery() throws Exception {
         NetlinkSocket s = new NetlinkSocket(OsConstants.NETLINK_ROUTE);
         assertNotNull(s);
@@ -91,6 +93,7 @@
         s.close();
     }
 
+    @SmallTest
     public void testRepeatedCloseCallsAreQuiet() throws Exception {
         // Create a working NetlinkSocket.
         NetlinkSocket s = new NetlinkSocket(OsConstants.NETLINK_ROUTE);
diff --git a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
index 19ee000..029758e 100644
--- a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
+++ b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
@@ -21,12 +21,13 @@
 import android.net.netlink.RtNetlinkNeighborMessage;
 import android.net.netlink.StructNdMsg;
 import android.net.netlink.StructNlMsgHdr;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.system.OsConstants;
 import android.util.Log;
 import libcore.util.HexEncoding;
 
-import java.net.InetAddress;
 import java.net.Inet4Address;
+import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -135,6 +136,7 @@
     public static final byte[] RTM_GETNEIGH_RESPONSE =
             HexEncoding.decode(RTM_GETNEIGH_RESPONSE_HEX.replaceAll(" ", "").toCharArray(), false);
 
+    @SmallTest
     public void testParseRtmDelNeigh() {
         final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_DELNEIGH);
         byteBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.
@@ -161,6 +163,7 @@
         assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination);
     }
 
+    @SmallTest
     public void testParseRtmNewNeigh() {
         final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_NEWNEIGH);
         byteBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.
@@ -187,6 +190,7 @@
         assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination);
     }
 
+    @SmallTest
     public void testParseRtmGetNeighResponse() {
         final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_GETNEIGH_RESPONSE);
         byteBuffer.order(ByteOrder.LITTLE_ENDIAN);  // For testing.
@@ -211,6 +215,7 @@
         assertEquals(14, messageCount);
     }
 
+    @SmallTest
     public void testCreateRtmNewNeighMessage() {
         final int seqNo = 2635;
         final int ifIndex = 14;
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 885e8a7..4a6fb13 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -70,7 +70,6 @@
 import android.test.AndroidTestCase;
 import android.test.FlakyTest;
 import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 import android.util.LogPrinter;
@@ -195,6 +194,7 @@
     }
 
     // Tests that IdleableHandlerThread works as expected.
+    @SmallTest
     public void testIdleableHandlerThread() {
         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
 
@@ -219,6 +219,7 @@
         }
     }
 
+    @SmallTest
     @FlakyTest(tolerance = 3)
     public void testNotWaitingForIdleCausesRaceConditions() {
         // Bring up a network that we can use to send messages to ConnectivityService.
@@ -842,7 +843,7 @@
         return cv;
     }
 
-    @LargeTest
+    @SmallTest
     public void testLingering() throws Exception {
         verifyNoNetwork();
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -882,7 +883,7 @@
         verifyNoNetwork();
     }
 
-    @LargeTest
+    @SmallTest
     public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
         // Test bringing up unvalidated WiFi
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -917,7 +918,7 @@
         verifyNoNetwork();
     }
 
-    @LargeTest
+    @SmallTest
     public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
         // Test bringing up unvalidated cellular.
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -943,7 +944,7 @@
         verifyNoNetwork();
     }
 
-    @LargeTest
+    @SmallTest
     public void testUnlingeringDoesNotValidate() throws Exception {
         // Test bringing up unvalidated WiFi.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -971,7 +972,7 @@
                 NET_CAPABILITY_VALIDATED));
     }
 
-    @LargeTest
+    @SmallTest
     public void testCellularOutscoresWeakWifi() throws Exception {
         // Test bringing up validated cellular.
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -997,7 +998,7 @@
         verifyActiveNetwork(TRANSPORT_WIFI);
     }
 
-    @LargeTest
+    @SmallTest
     public void testReapingNetwork() throws Exception {
         // Test bringing up WiFi without NET_CAPABILITY_INTERNET.
         // Expect it to be torn down immediately because it satisfies no requests.
@@ -1030,7 +1031,7 @@
         waitFor(cv);
     }
 
-    @LargeTest
+    @SmallTest
     public void testCellularFallback() throws Exception {
         // Test bringing up validated cellular.
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -1068,7 +1069,7 @@
         verifyActiveNetwork(TRANSPORT_WIFI);
     }
 
-    @LargeTest
+    @SmallTest
     public void testWiFiFallback() throws Exception {
         // Test bringing up unvalidated WiFi.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -1195,7 +1196,7 @@
         }
     }
 
-    @LargeTest
+    @SmallTest
     public void testStateChangeNetworkCallbacks() throws Exception {
         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
@@ -1578,7 +1579,7 @@
         handlerThread.quit();
     }
 
-    @LargeTest
+    @SmallTest
     public void testNetworkFactoryRequests() throws Exception {
         tryNetworkFactoryRequests(NET_CAPABILITY_MMS);
         tryNetworkFactoryRequests(NET_CAPABILITY_SUPL);
@@ -1598,7 +1599,7 @@
         // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
     }
 
-    @LargeTest
+    @SmallTest
     public void testNoMutableNetworkRequests() throws Exception {
         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
         NetworkRequest.Builder builder = new NetworkRequest.Builder();
@@ -1623,7 +1624,7 @@
         } catch (IllegalArgumentException expected) {}
     }
 
-    @LargeTest
+    @SmallTest
     public void testMMSonWiFi() throws Exception {
         // Test bringing up cellular without MMS NetworkRequest gets reaped
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -1658,7 +1659,7 @@
         verifyActiveNetwork(TRANSPORT_WIFI);
     }
 
-    @LargeTest
+    @SmallTest
     public void testMMSonCell() throws Exception {
         // Test bringing up cellular without MMS
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -1684,7 +1685,7 @@
         verifyActiveNetwork(TRANSPORT_CELLULAR);
     }
 
-    @LargeTest
+    @SmallTest
     public void testCaptivePortal() {
         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
@@ -1733,7 +1734,7 @@
         validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
     }
 
-    @LargeTest
+    @SmallTest
     public void testAvoidOrIgnoreCaptivePortals() {
         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
@@ -1804,7 +1805,7 @@
                 execptionCalled);
     }
 
-    @LargeTest
+    @SmallTest
     public void testRegisterDefaultNetworkCallback() throws Exception {
         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
@@ -1865,7 +1866,7 @@
         }
     }
 
-    @LargeTest
+    @SmallTest
     public void testRequestCallbackUpdates() throws Exception {
         // File a network request for mobile.
         final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
@@ -2458,6 +2459,7 @@
         return mWiFiNetworkAgent.getNetwork();
     }
 
+    @SmallTest
     public void testPacketKeepalives() throws Exception {
         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index bce5787e..77956be 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -24,6 +24,7 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkMisc;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.text.format.DateUtils;
 import com.android.internal.R;
 import com.android.server.ConnectivityService;
@@ -70,6 +71,7 @@
         mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT);
     }
 
+    @SmallTest
     public void testTransitions() {
         setNotificationSwitch(transition(WIFI, CELLULAR));
         NetworkAgentInfo nai1 = wifiNai(100);
@@ -79,6 +81,7 @@
         assertFalse(mMonitor.isNotificationEnabled(nai2, nai1));
     }
 
+    @SmallTest
     public void testNotificationOnLinger() {
         setNotificationSwitch(transition(WIFI, CELLULAR));
         setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
@@ -89,6 +92,7 @@
         verifyNotification(from, to);
     }
 
+    @SmallTest
     public void testToastOnLinger() {
         setNotificationSwitch(transition(WIFI, CELLULAR));
         setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
@@ -99,6 +103,7 @@
         verifyToast(from, to);
     }
 
+    @SmallTest
     public void testNotificationClearedAfterDisconnect() {
         setNotificationSwitch(transition(WIFI, CELLULAR));
         setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
@@ -112,6 +117,7 @@
         verify(mNotifier, times(1)).clearNotification(100);
     }
 
+    @SmallTest
     public void testNotificationClearedAfterSwitchingBack() {
         setNotificationSwitch(transition(WIFI, CELLULAR));
         setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
@@ -125,6 +131,7 @@
         verify(mNotifier, times(1)).clearNotification(100);
     }
 
+    @SmallTest
     public void testUniqueToast() {
         setNotificationSwitch(transition(WIFI, CELLULAR));
         setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
@@ -142,6 +149,7 @@
         verifyNoNotifications();
     }
 
+    @SmallTest
     public void testMultipleNotifications() {
         setNotificationSwitch(transition(WIFI, CELLULAR));
         setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
@@ -160,6 +168,7 @@
         verifyNotification(wifi2, cell);
     }
 
+    @SmallTest
     public void testRateLimiting() throws InterruptedException {
         mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, LOW_RATE_LIMIT);
 
@@ -185,6 +194,7 @@
         verifyNoNotifications();
     }
 
+    @SmallTest
     public void testDailyLimiting() throws InterruptedException {
         mMonitor = new TestableLingerMonitor(mCtx, mNotifier, LOW_DAILY_LIMIT, HIGH_RATE_LIMIT);
 
@@ -211,6 +221,7 @@
         verifyNoNotifications();
     }
 
+    @SmallTest
     public void testUniqueNotification() {
         setNotificationSwitch(transition(WIFI, CELLULAR));
         setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
@@ -227,6 +238,7 @@
         verifyNotification(from, to);
     }
 
+    @SmallTest
     public void testIgnoreNeverValidatedNetworks() {
         setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
         setNotificationSwitch(transition(WIFI, CELLULAR));
@@ -238,6 +250,7 @@
         verifyNoNotifications();
     }
 
+    @SmallTest
     public void testIgnoreCurrentlyValidatedNetworks() {
         setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
         setNotificationSwitch(transition(WIFI, CELLULAR));
@@ -249,6 +262,7 @@
         verifyNoNotifications();
     }
 
+    @SmallTest
     public void testNoNotificationType() {
         setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
         setNotificationSwitch();
@@ -259,6 +273,7 @@
         verifyNoNotifications();
     }
 
+    @SmallTest
     public void testNoTransitionToNotify() {
         setNotificationType(LingerMonitor.NOTIFY_TYPE_NONE);
         setNotificationSwitch(transition(WIFI, CELLULAR));
@@ -269,6 +284,7 @@
         verifyNoNotifications();
     }
 
+    @SmallTest
     public void testDifferentTransitionToNotify() {
         setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
         setNotificationSwitch(transition(CELLULAR, WIFI));
diff --git a/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java b/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java
index 5f84ea1..5981f48 100644
--- a/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/MetricsLoggerServiceTest.java
@@ -20,6 +20,7 @@
 import android.net.ConnectivityMetricsEvent;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.test.suitebuilder.annotation.SmallTest;
 import static android.net.ConnectivityMetricsEvent.Reference;
 
 import junit.framework.TestCase;
@@ -67,12 +68,14 @@
         mService.onStart();
     }
 
+    @SmallTest
     public void testGetNoEvents() throws Exception {
         Reference r = new Reference(0);
         assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r));
         assertEquals(0, r.getValue());
     }
 
+    @SmallTest
     public void testLogAndGetEvents() throws Exception {
         mService.mBinder.logEvents(EVENTS);
 
@@ -85,6 +88,7 @@
         assertEquals(N_EVENTS, r.getValue());
     }
 
+    @SmallTest
     public void testLogOneByOne() throws Exception {
         for (ConnectivityMetricsEvent ev : EVENTS) {
             mService.mBinder.logEvent(ev);
@@ -99,6 +103,7 @@
         assertEquals(N_EVENTS, r.getValue());
     }
 
+    @SmallTest
     public void testInterleavedLogAndGet() throws Exception {
         mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 0, 3));
 
@@ -117,6 +122,7 @@
         assertEquals(N_EVENTS, r.getValue());
     }
 
+    @SmallTest
     public void testMultipleGetAll() throws Exception {
         mService.mBinder.logEvents(Arrays.copyOf(EVENTS, 3));
 
@@ -131,6 +137,7 @@
         assertEquals(N_EVENTS, r2.getValue());
     }
 
+    @SmallTest
     public void testLogAndDumpConcurrently() throws Exception {
         for (int i = 0; i < 50; i++) {
             mContext = null;
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index af4a374..2bb62bb 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -23,6 +23,7 @@
 import android.net.metrics.INetdEventListener;
 import android.net.metrics.IpConnectivityLog;
 import android.os.RemoteException;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import junit.framework.TestCase;
 import org.junit.Before;
@@ -83,6 +84,7 @@
         verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture());
     }
 
+    @SmallTest
     public void testOneBatch() throws Exception {
         log(105, LATENCIES);
         log(106, Arrays.copyOf(LATENCIES, BATCH_SIZE - 1)); // one lookup short of a batch event
@@ -97,6 +99,7 @@
             new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES));
     }
 
+    @SmallTest
     public void testSeveralBatches() throws Exception {
         log(105, LATENCIES);
         log(106, LATENCIES);
@@ -110,6 +113,7 @@
             new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES));
     }
 
+    @SmallTest
     public void testBatchAndNetworkLost() throws Exception {
         byte[] eventTypes = Arrays.copyOf(EVENT_TYPES, 20);
         byte[] returnCodes = Arrays.copyOf(RETURN_CODES, 20);
@@ -126,6 +130,7 @@
             new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES));
     }
 
+    @SmallTest
     public void testConcurrentBatchesAndDumps() throws Exception {
         final long stop = System.currentTimeMillis() + 100;
         final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null"));
@@ -147,6 +152,7 @@
             new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES));
     }
 
+    @SmallTest
     public void testConcurrentBatchesAndNetworkLoss() throws Exception {
         logAsync(105, LATENCIES);
         Thread.sleep(10L);
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index f737b24..7d6f32b 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -73,7 +73,7 @@
         }
 
         try {
-            mWm.addWindowToken(null, 0);
+            mWm.addWindowToken(null, 0, DEFAULT_DISPLAY);
             fail("IWindowManager.addWindowToken did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
@@ -83,7 +83,7 @@
         }
 
         try {
-            mWm.removeWindowToken(null);
+            mWm.removeWindowToken(null, DEFAULT_DISPLAY);
             fail("IWindowManager.removeWindowToken did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
@@ -126,7 +126,7 @@
 
         try {
             mWm.setAppOrientation(null, 0);
-            mWm.addWindowToken(null, 0);
+            mWm.addWindowToken(null, 0, DEFAULT_DISPLAY);
             fail("IWindowManager.setAppOrientation did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
@@ -206,7 +206,7 @@
         }
 
         try {
-            mWm.removeAppToken(null);
+            mWm.removeAppToken(null, DEFAULT_DISPLAY);
             fail("IWindowManager.removeAppToken did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 9b62e14..2e34197 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -803,7 +803,7 @@
             ResXMLTree tree(dynamicRefTable);
             asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
             if (asset == NULL) {
-                fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
+                fprintf(stderr, "ERROR: dump failed because resource %s not found\n", resname);
                 goto bail;
             }
 
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 197884dc..1efd2ed 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -194,14 +194,14 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libaapt2_jni
 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_MODULE_HOST_OS := darwin linux
+LOCAL_MODULE_HOST_OS := darwin linux windows
 LOCAL_CFLAGS := $(cFlags)
 LOCAL_CFLAGS_darwin := $(cFlags_darwin)
 LOCAL_CFLAGS_windows := $(cFlags_windows)
 LOCAL_CPPFLAGS := $(cppFlags)
 LOCAL_C_INCLUDES := $(protoIncludes)
 LOCAL_SRC_FILES := $(toolSources) $(sourcesJni)
-LOCAL_STATIC_LIBRARIES := libaapt2 libnativehelper $(hostStaticLibs)
+LOCAL_STATIC_LIBRARIES := libaapt2 $(hostStaticLibs)
 LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
 LOCAL_LDLIBS := $(hostLdLibs)
 LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin)
diff --git a/tools/aapt2/jni/Aapt2.java b/tools/aapt2/jni/Aapt2.java
deleted file mode 100644
index aed23de..0000000
--- a/tools/aapt2/jni/Aapt2.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.android.tools.aapt2;
-
-import java.util.List;
-
-/**
- * {@code aapt2} JNI interface. To use the {@code aapt2} native interface, the
- * shared library must first be loaded and then a new instance of this class can
- * be used to access the library.
- */
-public class Aapt2 {
-
-  /**
-   * Invokes {@code aapt2} to perform resource compilation.
-   *
-   * @param arguments arguments for compilation (see {@code Compile.cpp})
-   */
-  public static void compile(List<String> arguments) {
-    nativeCompile(arguments);
-  }
-
-  /**
-   * Invokes {@code aapt2} to perform linking.
-   *
-   * @param arguments arguments for linking (see {@code Link.cpp})
-   */
-  public static void link(List<String> arguments) {
-    nativeLink(arguments);
-  }
-
-  /**
-   * JNI call.
-   *
-   * @param arguments arguments for compilation (see {@code Compile.cpp})
-   */
-  private static native void nativeCompile(List<String> arguments);
-
-  /**
-   * JNI call.
-   *
-   * @param arguments arguments for linking (see {@code Link.cpp})
-   */
-  private static native void nativeLink(List<String> arguments);
-}
-
diff --git a/tools/aapt2/jni/Makefile b/tools/aapt2/jni/Makefile
deleted file mode 100644
index a9e628f..0000000
--- a/tools/aapt2/jni/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# This Makefile will generate the JNI headers for the Aapt2 class.
-#
-
-AAPT2_PKG=com.android.tools.aapt2
-AAPT2_DIR=$(shell echo -n com/android/tools/aapt2 | tr . /)
-OUT=out
-OUT_CLASSES=$(OUT)/classes
-OUT_HEADERS=.
-
-AAPT2_JAVA=Aapt2.java
-AAPT2_CLASSES=$(OUT_CLASSES)/$(AAPT2_DIR)/Aapt2.class
-
-AAPT2_HEADERS=$(OUT_HEADERS)/Aapt2.h
-
-all: $(AAPT2_HEADERS)
-
-$(AAPT2_HEADERS): $(AAPT2_JAVA) $(AAPT2_CLASSES)
-	mkdir -p $(OUT_HEADERS)
-	$(JAVA_HOME)/bin/javah -d $(OUT_HEADERS) -cp $(OUT_CLASSES) $(AAPT2_PKG).Aapt2
-
-$(AAPT2_CLASSES): $(AAPT2_JAVA)
-	mkdir -p $(OUT_CLASSES)
-	javac -d $(OUT_CLASSES) $(AAPT2_JAVA)
-
diff --git a/tools/aapt2/jni/ScopedUtfChars.h b/tools/aapt2/jni/ScopedUtfChars.h
new file mode 100644
index 0000000..a8c4b13
--- /dev/null
+++ b/tools/aapt2/jni/ScopedUtfChars.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef SCOPED_UTF_CHARS_H_included
+#define SCOPED_UTF_CHARS_H_included
+
+#include <string.h>
+#include <jni.h>
+
+#include "android-base/logging.h"
+
+// This file was copied with some minor modifications from libnativehelper.
+// As soon as libnativehelper can be compiled for Windows, this file should be
+// replaced with libnativehelper's implementation.
+class ScopedUtfChars {
+ public:
+  ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
+    CHECK(s != nullptr);
+    utf_chars_ = env->GetStringUTFChars(s, nullptr);
+  }
+
+  ScopedUtfChars(ScopedUtfChars&& rhs) :
+      env_(rhs.env_), string_(rhs.string_), utf_chars_(rhs.utf_chars_) {
+    rhs.env_ = nullptr;
+    rhs.string_ = nullptr;
+    rhs.utf_chars_ = nullptr;
+  }
+
+  ~ScopedUtfChars() {
+    if (utf_chars_) {
+      env_->ReleaseStringUTFChars(string_, utf_chars_);
+    }
+  }
+
+  ScopedUtfChars& operator=(ScopedUtfChars&& rhs) {
+    if (this != &rhs) {
+      // Delete the currently owned UTF chars.
+      this->~ScopedUtfChars();
+
+      // Move the rhs ScopedUtfChars and zero it out.
+      env_ = rhs.env_;
+      string_ = rhs.string_;
+      utf_chars_ = rhs.utf_chars_;
+      rhs.env_ = nullptr;
+      rhs.string_ = nullptr;
+      rhs.utf_chars_ = nullptr;
+    }
+    return *this;
+  }
+
+  const char* c_str() const {
+    return utf_chars_;
+  }
+
+  size_t size() const {
+    return strlen(utf_chars_);
+  }
+
+  const char& operator[](size_t n) const {
+    return utf_chars_[n];
+  }
+
+ private:
+  JNIEnv* env_;
+  jstring string_;
+  const char* utf_chars_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars);
+};
+
+#endif  // SCOPED_UTF_CHARS_H_included
diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp
index 211ada8..5518fe2 100644
--- a/tools/aapt2/jni/aapt2_jni.cpp
+++ b/tools/aapt2/jni/aapt2_jni.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "com_android_tools_aapt2_Aapt2.h"
+#include "com_android_tools_aapt2_Aapt2Jni.h"
 
 #include <algorithm>
 #include <memory>
@@ -22,7 +22,7 @@
 #include <vector>
 
 #include "android-base/logging.h"
-#include "nativehelper/ScopedUtfChars.h"
+#include "ScopedUtfChars.h"
 
 #include "util/Util.h"
 
@@ -46,8 +46,8 @@
 
   // Now, iterate all strings in the list
   // (note: generic erasure means get() return an Object)
-  jmethodID get_method_id =
-      env->GetMethodID(list_cls, "get", "()Ljava/lang/Object;");
+  jmethodID get_method_id = env->GetMethodID(list_cls, "get", "(I)Ljava/lang/Object;");
+  CHECK(get_method_id != 0);
   for (jint i = 0; i < size; i++) {
     // Call get(i) to get the string in the ith position.
     jobject string_obj_uncast = env->CallObjectMethod(obj, get_method_id, i);
@@ -76,7 +76,7 @@
   return pieces;
 }
 
-JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2_nativeCompile(
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile(
     JNIEnv *env, jclass aapt_obj, jobject arguments_obj) {
   std::vector<ScopedUtfChars> compile_args_jni =
       list_to_utfchars(env, arguments_obj);
@@ -85,10 +85,15 @@
   aapt::Compile(compile_args);
 }
 
-JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2_nativeLink(
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(
     JNIEnv *env, jclass aapt_obj, jobject arguments_obj) {
   std::vector<ScopedUtfChars> link_args_jni =
       list_to_utfchars(env, arguments_obj);
   std::vector<aapt::StringPiece> link_args = extract_pieces(link_args_jni);
   aapt::Link(link_args);
 }
+
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping(
+        JNIEnv *env, jclass aapt_obj) {
+  // This is just a dummy method to see if the library has been loaded.
+}
diff --git a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2.h b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2.h
deleted file mode 100644
index 443b98f..0000000
--- a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class com_android_tools_aapt2_Aapt2 */
-
-#ifndef _Included_com_android_tools_aapt2_Aapt2
-#define _Included_com_android_tools_aapt2_Aapt2
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class:     com_android_tools_aapt2_Aapt2
- * Method:    nativeCompile
- * Signature: (Ljava/util/List;)V
- */
-JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2_nativeCompile
-  (JNIEnv *, jclass, jobject);
-
-/*
- * Class:     com_android_tools_aapt2_Aapt2
- * Method:    nativeLink
- * Signature: (Ljava/util/List;)V
- */
-JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2_nativeLink
-  (JNIEnv *, jclass, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h
new file mode 100644
index 0000000..56c3c18
--- /dev/null
+++ b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h
@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_android_tools_aapt2_Aapt2Jni */
+
+#ifndef _Included_com_android_tools_aapt2_Aapt2Jni
+#define _Included_com_android_tools_aapt2_Aapt2Jni
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     com_android_tools_aapt2_Aapt2Jni
+ * Method:    ping
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     com_android_tools_aapt2_Aapt2Jni
+ * Method:    nativeCompile
+ * Signature: (Ljava/util/List;)V
+ */
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     com_android_tools_aapt2_Aapt2Jni
+ * Method:    nativeLink
+ * Signature: (Ljava/util/List;)V
+ */
+JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink
+  (JNIEnv *, jclass, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index c86f5c3..4596210 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -86,7 +86,7 @@
     }
 
     @Override
-    public void addWindowToken(IBinder arg0, int arg1) throws RemoteException {
+    public void addWindowToken(IBinder arg0, int arg1, int arg2) throws RemoteException {
         // TODO Auto-generated method stub
 
     }
@@ -277,13 +277,13 @@
     }
 
     @Override
-    public void removeAppToken(IBinder arg0) throws RemoteException {
+    public void removeAppToken(IBinder arg0, int arg1) throws RemoteException {
         // TODO Auto-generated method stub
 
     }
 
     @Override
-    public void removeWindowToken(IBinder arg0) throws RemoteException {
+    public void removeWindowToken(IBinder arg0, int arg1) throws RemoteException {
         // TODO Auto-generated method stub
 
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index a0b2977..1b3b563 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -374,7 +374,9 @@
             return true;
         }
 
-        return false;
+        // If the value is not a valid reference, fallback to pass the value as a string.
+        outValue.string = value.getValue();
+        return true;
     }
 
 
diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk
index 199fafa..4a1511e 100644
--- a/tools/split-select/Android.mk
+++ b/tools/split-select/Android.mk
@@ -73,7 +73,7 @@
 LOCAL_MODULE_HOST_OS := darwin linux windows
 
 LOCAL_SRC_FILES := $(sources)
-
+LOCAL_STATIC_LIBRARIES := $(hostStaticLibs)
 LOCAL_C_INCLUDES := $(cIncludes)
 LOCAL_CFLAGS := $(cFlags) -D_DARWIN_UNLIMITED_STREAMS
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 8d819b9..18a580e 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1066,7 +1066,7 @@
     /** @hide */
     public static final int WIFI_FEATURE_SCANNER          = 0x0020;  // WifiScanner APIs
     /** @hide */
-    public static final int WIFI_FEATURE_NAN              = 0x0040;  // Neighbor Awareness Networking
+    public static final int WIFI_FEATURE_AWARE              = 0x0040;  // Wi-Fi AWare networking
     /** @hide */
     public static final int WIFI_FEATURE_D2D_RTT          = 0x0080;  // Device-to-device RTT
     /** @hide */
@@ -1147,8 +1147,8 @@
      * @return true if this adapter supports Neighbour Awareness Network APIs
      * @hide
      */
-    public boolean isNanSupported() {
-        return isFeatureSupported(WIFI_FEATURE_NAN);
+    public boolean isWifiAwareSupported() {
+        return isFeatureSupported(WIFI_FEATURE_AWARE);
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/nan/ConfigRequest.aidl b/wifi/java/android/net/wifi/aware/ConfigRequest.aidl
similarity index 95%
rename from wifi/java/android/net/wifi/nan/ConfigRequest.aidl
rename to wifi/java/android/net/wifi/aware/ConfigRequest.aidl
index 38dddc2..68a7c85 100644
--- a/wifi/java/android/net/wifi/nan/ConfigRequest.aidl
+++ b/wifi/java/android/net/wifi/aware/ConfigRequest.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 parcelable ConfigRequest;
diff --git a/wifi/java/android/net/wifi/nan/ConfigRequest.java b/wifi/java/android/net/wifi/aware/ConfigRequest.java
similarity index 96%
rename from wifi/java/android/net/wifi/nan/ConfigRequest.java
rename to wifi/java/android/net/wifi/aware/ConfigRequest.java
index bcd7932..4aacbae 100644
--- a/wifi/java/android/net/wifi/nan/ConfigRequest.java
+++ b/wifi/java/android/net/wifi/aware/ConfigRequest.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.os.Parcel;
 import android.os.Parcelable;
 
 /**
- * Defines a request object to configure a Wi-Fi NAN network. Built using
+ * Defines a request object to configure a Wi-Fi Aware network. Built using
  * {@link ConfigRequest.Builder}. Configuration is requested using
- * {@link WifiNanManager#attach(android.os.Handler, WifiNanAttachCallback)}.
+ * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)}.
  * Note that the actual achieved configuration may be different from the
  * requested configuration - since different applications may request different
  * configurations.
@@ -221,7 +221,7 @@
         }
 
         /**
-         * The Cluster ID is generated randomly for new NAN networks. Specify
+         * The Cluster ID is generated randomly for new Aware networks. Specify
          * the lower range of the cluster ID. The upper range is specified using
          * the {@link ConfigRequest.Builder#setClusterHigh(int)}. The permitted
          * range is 0 (the default) to the value specified by
@@ -246,7 +246,7 @@
         }
 
         /**
-         * The Cluster ID is generated randomly for new NAN networks. Specify
+         * The Cluster ID is generated randomly for new Aware networks. Specify
          * the lower upper of the cluster ID. The lower range is specified using
          * the {@link ConfigRequest.Builder#setClusterLow(int)}. The permitted
          * range is the value specified by
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanDiscoverySessionCallback.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
similarity index 88%
rename from wifi/java/android/net/wifi/nan/IWifiNanDiscoverySessionCallback.aidl
rename to wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
index f2e371d..8ff3842 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanDiscoverySessionCallback.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 /**
- * Callback interface that WifiNanManager implements
+ * Callback interface that WifiAwareManager implements
  *
  * {@hide}
  */
-oneway interface IWifiNanDiscoverySessionCallback
+oneway interface IWifiAwareDiscoverySessionCallback
 {
     void onSessionStarted(int discoverySessionId);
     void onSessionConfigSuccess();
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl
similarity index 85%
rename from wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl
rename to wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl
index 9ac7bf2..30dd64d 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
-import android.net.wifi.nan.ConfigRequest;
+import android.net.wifi.aware.ConfigRequest;
 import android.net.wifi.RttManager;
 
 /**
- * Callback interface that WifiNanManager implements
+ * Callback interface that WifiAwareManager implements
  *
  * {@hide}
  */
-oneway interface IWifiNanEventCallback
+oneway interface IWifiAwareEventCallback
 {
     void onConnectSuccess(int clientId);
     void onConnectFail(int reason);
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
similarity index 71%
rename from wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
rename to wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
index 5485824..9c92807 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
@@ -14,40 +14,40 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.app.PendingIntent;
 
-import android.net.wifi.nan.ConfigRequest;
-import android.net.wifi.nan.IWifiNanDiscoverySessionCallback;
-import android.net.wifi.nan.IWifiNanEventCallback;
-import android.net.wifi.nan.PublishConfig;
-import android.net.wifi.nan.SubscribeConfig;
-import android.net.wifi.nan.WifiNanCharacteristics;
+import android.net.wifi.aware.ConfigRequest;
+import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback;
+import android.net.wifi.aware.IWifiAwareEventCallback;
+import android.net.wifi.aware.PublishConfig;
+import android.net.wifi.aware.SubscribeConfig;
+import android.net.wifi.aware.WifiAwareCharacteristics;
 import android.net.wifi.RttManager;
 
 /**
- * Interface that WifiNanService implements
+ * Interface that WifiAwareService implements
  *
  * {@hide}
  */
-interface IWifiNanManager
+interface IWifiAwareManager
 {
-    // NAN API
+    // Aware API
     void enableUsage();
     void disableUsage();
     boolean isUsageEnabled();
-    WifiNanCharacteristics getCharacteristics();
+    WifiAwareCharacteristics getCharacteristics();
 
     // client API
-    void connect(in IBinder binder, in String callingPackage, in IWifiNanEventCallback callback,
+    void connect(in IBinder binder, in String callingPackage, in IWifiAwareEventCallback callback,
             in ConfigRequest configRequest, boolean notifyOnIdentityChanged);
     void disconnect(int clientId, in IBinder binder);
 
     void publish(int clientId, in PublishConfig publishConfig,
-            in IWifiNanDiscoverySessionCallback callback);
+            in IWifiAwareDiscoverySessionCallback callback);
     void subscribe(int clientId, in SubscribeConfig subscribeConfig,
-            in IWifiNanDiscoverySessionCallback callback);
+            in IWifiAwareDiscoverySessionCallback callback);
 
     // session API
     void updatePublish(int clientId, int discoverySessionId, in PublishConfig publishConfig);
diff --git a/wifi/java/android/net/wifi/nan/LvBufferUtils.java b/wifi/java/android/net/wifi/aware/LvBufferUtils.java
similarity index 99%
rename from wifi/java/android/net/wifi/nan/LvBufferUtils.java
rename to wifi/java/android/net/wifi/aware/LvBufferUtils.java
index eb56070..3265243 100644
--- a/wifi/java/android/net/wifi/nan/LvBufferUtils.java
+++ b/wifi/java/android/net/wifi/aware/LvBufferUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.annotation.Nullable;
 
@@ -28,7 +28,7 @@
  * Length/Value format. The utilities accept a configuration of the size of
  * the Length field.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
 public class LvBufferUtils {
     private LvBufferUtils() {
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/wifi/java/android/net/wifi/aware/PublishConfig.aidl
similarity index 95%
rename from wifi/java/android/net/wifi/nan/PublishConfig.aidl
rename to wifi/java/android/net/wifi/aware/PublishConfig.aidl
index 5f66d16..2e6dd00 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/wifi/java/android/net/wifi/aware/PublishConfig.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 parcelable PublishConfig;
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java
similarity index 92%
rename from wifi/java/android/net/wifi/nan/PublishConfig.java
rename to wifi/java/android/net/wifi/aware/PublishConfig.java
index 30c5bc0..5d3ad058 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.java
+++ b/wifi/java/android/net/wifi/aware/PublishConfig.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -30,13 +30,14 @@
 import java.util.Arrays;
 
 /**
- * Defines the configuration of a NAN publish session. Built using
+ * Defines the configuration of a Aware publish session. Built using
  * {@link PublishConfig.Builder}. A publish session is created using
- * {@link WifiNanSession#publish(android.os.Handler, PublishConfig, WifiNanDiscoverySessionCallback)}
+ * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
+ * WifiAwareDiscoverySessionCallback)}
  * or updated using
- * {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)}.
+ * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
 public final class PublishConfig implements Parcelable {
     /** @hide */
@@ -182,8 +183,9 @@
      *
      * @hide
      */
-    public void assertValid(WifiNanCharacteristics characteristics) throws IllegalArgumentException {
-        WifiNanUtils.validateServiceName(mServiceName);
+    public void assertValid(WifiAwareCharacteristics characteristics)
+            throws IllegalArgumentException {
+        WifiAwareUtils.validateServiceName(mServiceName);
 
         if (!LvBufferUtils.isValid(mMatchFilter, 1)) {
             throw new IllegalArgumentException(
@@ -320,12 +322,12 @@
          * Sets the number of times an unsolicited (configured using
          * {@link PublishConfig.Builder#setPublishType(int)}) publish session
          * will be broadcast. When the count is reached an event will be
-         * generated for {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)}
-         * with {@link WifiNanDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless
+         * generated for {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}
+         * with {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless
          * {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
          * <p>
          *     Optional. 0 by default - indicating the session doesn't terminate on its own.
-         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#destroy()} is
+         *     Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
          *     called.
          *
          * @param publishCount Number of publish packets to broadcast.
@@ -346,12 +348,12 @@
          * {@link PublishConfig.Builder#setPublishType(int)}) publish session
          * will be alive - broadcasting a packet. When the TTL is reached
          * an event will be generated for
-         * {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)} with
-         * {@link WifiNanDiscoverySessionCallback#TERMINATE_REASON_DONE}  [unless
+         * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} with
+         * {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}  [unless
          * {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
          * <p>
          *     Optional. 0 by default - indicating the session doesn't terminate on its own.
-         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#destroy()} is
+         *     Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
          *     called.
          *
          * @param ttlSec Lifetime of a publish session in seconds.
@@ -369,7 +371,7 @@
 
         /**
          * Configure whether a publish terminate notification
-         * {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)} is reported
+         * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} is reported
          * back to the callback.
          *
          * @param enable If true the terminate callback will be called when the
diff --git a/wifi/java/android/net/wifi/nan/SubscribeConfig.aidl b/wifi/java/android/net/wifi/aware/SubscribeConfig.aidl
similarity index 95%
rename from wifi/java/android/net/wifi/nan/SubscribeConfig.aidl
rename to wifi/java/android/net/wifi/aware/SubscribeConfig.aidl
index 92344a4..bd73d5e 100644
--- a/wifi/java/android/net/wifi/nan/SubscribeConfig.aidl
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 parcelable SubscribeConfig;
diff --git a/wifi/java/android/net/wifi/nan/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
similarity index 93%
rename from wifi/java/android/net/wifi/nan/SubscribeConfig.java
rename to wifi/java/android/net/wifi/aware/SubscribeConfig.java
index ea7b8e4..2a6cc93 100644
--- a/wifi/java/android/net/wifi/nan/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -30,13 +30,14 @@
 import java.util.Arrays;
 
 /**
- * Defines the configuration of a NAN subscribe session. Built using
+ * Defines the configuration of a Aware subscribe session. Built using
  * {@link SubscribeConfig.Builder}. Subscribe is done using
- * {@link WifiNanSession#subscribe(android.os.Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)}
+ * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
+ * WifiAwareDiscoverySessionCallback)}
  * or
- * {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+ * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
 public final class SubscribeConfig implements Parcelable {
     /** @hide */
@@ -209,8 +210,9 @@
      *
      * @hide
      */
-    public void assertValid(WifiNanCharacteristics characteristics) throws IllegalArgumentException {
-        WifiNanUtils.validateServiceName(mServiceName);
+    public void assertValid(WifiAwareCharacteristics characteristics)
+            throws IllegalArgumentException {
+        WifiAwareUtils.validateServiceName(mServiceName);
 
         if (!LvBufferUtils.isValid(mMatchFilter, 1)) {
             throw new IllegalArgumentException(
@@ -352,11 +354,11 @@
          * Sets the number of times an active (
          * {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session
          * will broadcast. When the count is reached an event will be
-         * generated for {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)}
-         * with {@link WifiNanDiscoverySessionCallback#TERMINATE_REASON_DONE}.
+         * generated for {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}
+         * with {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}.
          * <p>
          *     Optional. 0 by default - indicating the session doesn't terminate on its own.
-         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#destroy()} is
+         *     Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
          *     called.
          *
          * @param subscribeCount Number of subscribe packets to broadcast.
@@ -377,11 +379,11 @@
          * {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session
          * will be alive - i.e. broadcasting a packet. When the TTL is reached
          * an event will be generated for
-         * {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)} with
-         * {@link WifiNanDiscoverySessionCallback#TERMINATE_REASON_DONE}.
+         * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} with
+         * {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}.
          * <p>
          *     Optional. 0 by default - indicating the session doesn't terminate on its own.
-         *     Session will be terminated when {@link WifiNanDiscoveryBaseSession#destroy()} is
+         *     Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
          *     called.
          *
          * @param ttlSec Lifetime of a subscribe session in seconds.
@@ -401,7 +403,7 @@
          * Sets the match style of the subscription - how are matches from a
          * single match session (corresponding to the same publish action on the
          * peer) reported to the host (using the
-         * {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
+         * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
          * ). The options are: only report the first match and ignore the rest
          * {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single
          * match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default).
@@ -421,7 +423,7 @@
 
         /**
          * Configure whether a subscribe terminate notification
-         * {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)} is reported
+         * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} is reported
          * back to the callback.
          *
          * @param enable If true the terminate callback will be called when the
diff --git a/wifi/java/android/net/wifi/nan/TlvBufferUtils.java b/wifi/java/android/net/wifi/aware/TlvBufferUtils.java
similarity index 99%
rename from wifi/java/android/net/wifi/nan/TlvBufferUtils.java
rename to wifi/java/android/net/wifi/aware/TlvBufferUtils.java
index 2c5aab4..56c9069 100644
--- a/wifi/java/android/net/wifi/nan/TlvBufferUtils.java
+++ b/wifi/java/android/net/wifi/aware/TlvBufferUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.annotation.Nullable;
 
@@ -32,7 +32,7 @@
  * the Type field and the Length field. A Type field size of 0 is allowed -
  * allowing usage for LV (no T) array formats.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
 public class TlvBufferUtils {
     private TlvBufferUtils() {
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java b/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
new file mode 100644
index 0000000..2cace61
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
@@ -0,0 +1,47 @@
+/*
+ * 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.net.wifi.aware;
+
+/**
+ * Base class for Aware attach callbacks. Should be extended by applications and set when calling
+ * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)}. These are callbacks
+ * applying to the Aware connection as a whole - not to specific publish or subscribe sessions -
+ * for that see {@link WifiAwareDiscoverySessionCallback}.
+ *
+ * @hide PROPOSED_AWARE_API
+ */
+public class WifiAwareAttachCallback {
+    /**
+     * Called when Aware attach operation
+     * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)}
+     * is completed and that we can now start discovery sessions or connections.
+     *
+     * @param session The Aware object on which we can execute further Aware operations - e.g.
+     *                discovery, connections.
+     */
+    public void onAttached(WifiAwareSession session) {
+        /* empty */
+    }
+
+    /**
+     * Called when Aware attach operation
+     * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)} failed.
+     */
+    public void onAttachFailed() {
+        /* empty */
+    }
+}
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.aidl b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
similarity index 89%
copy from wifi/java/android/net/wifi/nan/PublishConfig.aidl
copy to wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
index 5f66d16..a35e71d 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.aidl
+++ b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
-parcelable PublishConfig;
+parcelable WifiAwareCharacteristics;
diff --git a/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.java b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
similarity index 73%
rename from wifi/java/android/net/wifi/nan/WifiNanCharacteristics.java
rename to wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
index f43ed4d..6232c14 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 /**
- * The characteristics of the Wi-Fi NAN implementation.
+ * The characteristics of the Wi-Fi Aware implementation.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
-public class WifiNanCharacteristics implements Parcelable {
+public class WifiAwareCharacteristics implements Parcelable {
     /** @hide */
     public static final String KEY_MAX_SERVICE_NAME_LENGTH = "key_max_service_name_length";
     /** @hide */
@@ -37,41 +37,41 @@
     private Bundle mCharacteristics = new Bundle();
 
     /** @hide : should not be created by apps */
-    public WifiNanCharacteristics(Bundle characteristics) {
+    public WifiAwareCharacteristics(Bundle characteristics) {
         mCharacteristics = characteristics;
     }
 
     /**
-     * Returns the maximum string length that can be used to specify a NAN service name. Restricts
+     * Returns the maximum string length that can be used to specify a Aware service name. Restricts
      * the parameters of the {@link PublishConfig.Builder#setServiceName(String)} and
      * {@link SubscribeConfig.Builder#setServiceName(String)}.
      *
-     * @return A positive integer, maximum string length of NAN service name.
+     * @return A positive integer, maximum string length of Aware service name.
      */
     public int getMaxServiceNameLength() {
         return mCharacteristics.getInt(KEY_MAX_SERVICE_NAME_LENGTH);
     }
 
     /**
-     * Returns the maximum length of byte array that can be used to specify a NAN service specific
-     * information field: the arbitrary load used in discovery or the message length of NAN
+     * Returns the maximum length of byte array that can be used to specify a Aware service specific
+     * information field: the arbitrary load used in discovery or the message length of Aware
      * message exchange. Restricts the parameters of the
      * {@link PublishConfig.Builder#setServiceSpecificInfo(byte[])},
      * {@link SubscribeConfig.Builder#setServiceSpecificInfo(byte[])}, and
-     * {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[])} variants.
+     * {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])} variants.
      *
-     * @return A positive integer, maximum length of byte array for NAN messaging.
+     * @return A positive integer, maximum length of byte array for Aware messaging.
      */
     public int getMaxServiceSpecificInfoLength() {
         return mCharacteristics.getInt(KEY_MAX_SERVICE_SPECIFIC_INFO_LENGTH);
     }
 
     /**
-     * Returns the maximum length of byte array that can be used to specify a NAN match filter.
+     * Returns the maximum length of byte array that can be used to specify a Aware match filter.
      * Restricts the parameters of the {@link PublishConfig.Builder#setMatchFilter(byte[])} and
      * {@link SubscribeConfig.Builder#setMatchFilter(byte[])}.
      *
-     * @return A positive integer, maximum legngth of byte array for NAN discovery match filter.
+     * @return A positive integer, maximum legngth of byte array for Aware discovery match filter.
      */
     public int getMaxMatchFilterLength() {
         return mCharacteristics.getInt(KEY_MAX_MATCH_FILTER_LENGTH);
@@ -87,17 +87,17 @@
         return 0;
     }
 
-    public static final Creator<WifiNanCharacteristics> CREATOR =
-            new Creator<WifiNanCharacteristics>() {
+    public static final Creator<WifiAwareCharacteristics> CREATOR =
+            new Creator<WifiAwareCharacteristics>() {
                 @Override
-                public WifiNanCharacteristics createFromParcel(Parcel in) {
-                    WifiNanCharacteristics c = new WifiNanCharacteristics(in.readBundle());
+                public WifiAwareCharacteristics createFromParcel(Parcel in) {
+                    WifiAwareCharacteristics c = new WifiAwareCharacteristics(in.readBundle());
                     return c;
                 }
 
                 @Override
-                public WifiNanCharacteristics[] newArray(int size) {
-                    return new WifiNanCharacteristics[size];
+                public WifiAwareCharacteristics[] newArray(int size) {
+                    return new WifiAwareCharacteristics[size];
                 }
             };
 }
diff --git a/wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java b/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
similarity index 70%
rename from wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java
rename to wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
index 17e974b..07f7523 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanDiscoveryBaseSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -27,30 +27,30 @@
 import java.lang.ref.WeakReference;
 
 /**
- * A class representing a single publish or subscribe NAN session. This object
+ * A class representing a single publish or subscribe Aware session. This object
  * will not be created directly - only its child classes are available:
- * {@link WifiNanPublishDiscoverySession} and {@link WifiNanSubscribeDiscoverySession}. This
+ * {@link WifiAwarePublishDiscoverySession} and {@link WifiAwareSubscribeDiscoverySession}. This
  * class provides functionality common to both publish and subscribe discovery sessions:
  * <ul>
  *     <li>Sending messages: {@link #sendMessage(Object, int, byte[])} or
  *     {@link #sendMessage(Object, int, byte[], int)} methods.
- *     <li>Creating a network-specifier when requesting a NAN connection:
+ *     <li>Creating a network-specifier when requesting a Aware connection:
  *     {@link #createNetworkSpecifier(int, Object, byte[])}.
  * </ul>
  * The {@link #destroy()} method must be called to destroy discovery sessions once they are
  * no longer needed.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
-public class WifiNanDiscoveryBaseSession {
-    private static final String TAG = "WifiNanDiscoveryBaseSsn";
+public class WifiAwareDiscoveryBaseSession {
+    private static final String TAG = "WifiAwareDiscBaseSsn";
     private static final boolean DBG = false;
     private static final boolean VDBG = false; // STOPSHIP if true
 
     private static final int MAX_SEND_RETRY_COUNT = 5;
 
     /** @hide */
-    protected WeakReference<WifiNanManager> mMgr;
+    protected WeakReference<WifiAwareManager> mMgr;
     /** @hide */
     protected final int mClientId;
     /** @hide */
@@ -71,7 +71,7 @@
     }
 
     /** @hide */
-    public WifiNanDiscoveryBaseSession(WifiNanManager manager, int clientId, int sessionId) {
+    public WifiAwareDiscoveryBaseSession(WifiAwareManager manager, int clientId, int sessionId) {
         if (VDBG) {
             Log.v(TAG, "New discovery session created: manager=" + manager + ", clientId="
                     + clientId + ", sessionId=" + sessionId);
@@ -93,12 +93,12 @@
      *     This operation must be done on a session which is no longer needed. Otherwise system
      *     resources will continue to be utilized until the application exits. The only
      *     exception is a session for which we received a termination callback,
-     *     {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)}.
+     *     {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}.
      */
     public void destroy() {
-        WifiNanManager mgr = mMgr.get();
+        WifiAwareManager mgr = mMgr.get();
         if (mgr == null) {
-            Log.w(TAG, "destroy: called post GC on WifiNanManager");
+            Log.w(TAG, "destroy: called post GC on WifiAwareManager");
             return;
         }
         mgr.terminateSession(mClientId, mSessionId);
@@ -137,26 +137,26 @@
     }
 
     /**
-     * Sends a message to the specified destination. NAN messages are transmitted in the context
+     * Sends a message to the specified destination. Aware messages are transmitted in the context
      * of a discovery session - executed subsequent to a publish/subscribe
-     * {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} event.
+     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} event.
      * <p>
-     *     NAN messages are not guaranteed delivery. Callbacks on
-     *     {@link WifiNanDiscoverySessionCallback} indicate message was transmitted successfully,
-     *     {@link WifiNanDiscoverySessionCallback#onMessageSent(int)}, or transmission failed
+     *     Aware messages are not guaranteed delivery. Callbacks on
+     *     {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
+     *     {@link WifiAwareDiscoverySessionCallback#onMessageSent(int)}, or transmission failed
      *     (possibly after several retries) -
-     *     {@link WifiNanDiscoverySessionCallback#onMessageSendFailed(int)}.
+     *     {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}.
      * <p>
      *     The peer will get a callback indicating a message was received using
-     *     {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])}.
+     *     {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])}.
      *
      * @param peerHandle The peer's handle for the message. Must be a result of an
-     *        {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
+     *        {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
      *        or
-     *        {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])} events.
+     *        {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])} events.
      * @param messageId An arbitrary integer used by the caller to identify the message. The same
      *            integer ID will be returned in the callbacks indicating message send success or
-     *            failure. The {@code messageId} is not used internally by the NAN service - it
+     *            failure. The {@code messageId} is not used internally by the Aware service - it
      *                  can be arbitrary and non-unique.
      * @param message The message to be transmitted.
      * @param retryCount An integer specifying how many additional service-level (as opposed to PHY
@@ -170,9 +170,9 @@
             Log.w(TAG, "sendMessage: called on terminated session");
             return;
         } else {
-            WifiNanManager mgr = mMgr.get();
+            WifiAwareManager mgr = mMgr.get();
             if (mgr == null) {
-                Log.w(TAG, "sendMessage: called post GC on WifiNanManager");
+                Log.w(TAG, "sendMessage: called post GC on WifiAwareManager");
                 return;
             }
 
@@ -181,28 +181,28 @@
     }
 
     /**
-     * Sends a message to the specified destination. NAN messages are transmitted in the context
+     * Sends a message to the specified destination. Aware messages are transmitted in the context
      * of a discovery session - executed subsequent to a publish/subscribe
-     * {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} event.
+     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} event.
      * <p>
-     *     NAN messages are not guaranteed delivery. Callbacks on
-     *     {@link WifiNanDiscoverySessionCallback} indicate message was transmitted successfully,
-     *     {@link WifiNanDiscoverySessionCallback#onMessageSent(int)}, or transmission failed
+     *     Aware messages are not guaranteed delivery. Callbacks on
+     *     {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
+     *     {@link WifiAwareDiscoverySessionCallback#onMessageSent(int)}, or transmission failed
      *     (possibly after several retries) -
-     *     {@link WifiNanDiscoverySessionCallback#onMessageSendFailed(int)}.
+     *     {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}.
      * <p>
      *     The peer will get a callback indicating a message was received using
-     *     {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])}.
+     *     {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])}.
      * Equivalent to {@link #sendMessage(Object, int, byte[], int)} with a {@code retryCount} of
      * 0.
      *
      * @param peerHandle The peer's handle for the message. Must be a result of an
-     *        {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
+     *        {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
      *        or
-     *        {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])} events.
+     *        {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])} events.
      * @param messageId An arbitrary integer used by the caller to identify the message. The same
      *            integer ID will be returned in the callbacks indicating message send success or
-     *            failure. The {@code messageId} is not used internally by the NAN service - it
+     *            failure. The {@code messageId} is not used internally by the Aware service - it
      *                  can be arbitrary and non-unique.
      * @param message The message to be transmitted.
      */
@@ -212,8 +212,8 @@
 
     /**
      * Start a ranging operation with the specified peers. The peer IDs are obtained from an
-     * {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} or
-     * {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])} operation - can
+     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} or
+     * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])} operation - can
      * only range devices which are part of an ongoing discovery session.
      *
      * @param params   RTT parameters - each corresponding to a specific peer ID (the array sizes
@@ -221,16 +221,17 @@
      *                 {@link android.net.wifi.RttManager.RttParams#bssid} member must be set to
      *                 a peer ID - not to a MAC address.
      * @param listener The listener to receive the results of the ranging session.
-     * @hide PROPOSED_NAN_SYSTEM_API [TODO: b/28847998 - track RTT API & visilibity]
+     * @hide PROPOSED_AWARE_SYSTEM_API
+     * [TODO: b/28847998 - track RTT API & visilibity]
      */
     public void startRanging(RttManager.RttParams[] params, RttManager.RttListener listener) {
         if (mTerminated) {
             Log.w(TAG, "startRanging: called on terminated session");
             return;
         } else {
-            WifiNanManager mgr = mMgr.get();
+            WifiAwareManager mgr = mMgr.get();
             if (mgr == null) {
-                Log.w(TAG, "startRanging: called post GC on WifiNanManager");
+                Log.w(TAG, "startRanging: called post GC on WifiAwareManager");
                 return;
             }
 
@@ -240,23 +241,23 @@
 
     /**
      * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for a
-     * WiFi NAN connection to the specified peer. The
+     * WiFi Aware connection to the specified peer. The
      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
-     * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_NAN}.
+     * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
      * <p>
-     * This method should be used when setting up a connection with a peer discovered through NAN
+     * This method should be used when setting up a connection with a peer discovered through Aware
      * discovery or communication (in such scenarios the MAC address of the peer is shielded by
-     * an opaque peer ID handle). If a NAN connection is needed to a peer discovered using other
+     * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other
      * OOB (out-of-band) mechanism then use the alternative
-     * {@link WifiNanSession#createNetworkSpecifier(int, byte[], byte[])} method - which uses the
+     * {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])} method - which uses the
      * peer's MAC address.
      *
      * @param role The role of this device:
-     * {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_INITIATOR} or
-     * {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_RESPONDER}
+     * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
+     * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
      * @param peerHandle The peer's handle obtained through
-     * {@link WifiNanDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} or
-     * {@link WifiNanDiscoverySessionCallback#onMessageReceived(Object, byte[])}. On a RESPONDER
+     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} or
+     * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])}. On a RESPONDER
      *               this value is used to gate the acceptance of a connection request from only
      *               that peer. A RESPONDER may specified a null - indicating that it will accept
      *               connection requests from any device.
@@ -268,18 +269,19 @@
      *
      * @return A string to be used to construct
      * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
-     * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,android.net.ConnectivityManager.NetworkCallback)}
+     * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
+     * android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
      */
-    public String createNetworkSpecifier(@WifiNanManager.DataPathRole int role,
+    public String createNetworkSpecifier(@WifiAwareManager.DataPathRole int role,
             @Nullable Object peerHandle, @Nullable byte[] token) {
         if (mTerminated) {
             Log.w(TAG, "createNetworkSpecifier: called on terminated session");
             return null;
         } else {
-            WifiNanManager mgr = mMgr.get();
+            WifiAwareManager mgr = mMgr.get();
             if (mgr == null) {
-                Log.w(TAG, "createNetworkSpecifier: called post GC on WifiNanManager");
+                Log.w(TAG, "createNetworkSpecifier: called post GC on WifiAwareManager");
                 return null;
             }
 
diff --git a/wifi/java/android/net/wifi/nan/WifiNanDiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
similarity index 66%
rename from wifi/java/android/net/wifi/nan/WifiNanDiscoverySessionCallback.java
rename to wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
index 271f420..9dfa24f 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanDiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -23,18 +23,20 @@
 import java.lang.annotation.RetentionPolicy;
 
 /**
- * Base class for NAN session events callbacks. Should be extended by
+ * Base class for Aware session events callbacks. Should be extended by
  * applications wanting notifications. The callbacks are set when a
  * publish or subscribe session is created using
- * {@link WifiNanSession#publish(android.os.Handler, PublishConfig, WifiNanDiscoverySessionCallback)}
+ * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
+ * WifiAwareDiscoverySessionCallback)}
  * or
- * {@link WifiNanSession#subscribe(android.os.Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)} .
+ * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
+ * WifiAwareDiscoverySessionCallback)} .
  * <p>
  * A single callback is set at session creation - it cannot be replaced.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
-public class WifiNanDiscoverySessionCallback {
+public class WifiAwareDiscoverySessionCallback {
     /** @hide */
     @IntDef({
             TERMINATE_REASON_DONE, TERMINATE_REASON_FAIL })
@@ -46,7 +48,7 @@
      * Indicates that publish or subscribe session is done - all the
      * requested operations (per {@link PublishConfig} or
      * {@link SubscribeConfig}) have been executed. Failure reason flag for
-     * {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)} callback.
+     * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} callback.
      */
     public static final int TERMINATE_REASON_DONE = 100;
 
@@ -54,39 +56,41 @@
      * Indicates that publish or subscribe session is terminated due to a
      * failure.
      * Failure reason flag for
-     * {@link WifiNanDiscoverySessionCallback#onSessionTerminated(int)} callback.
+     * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} callback.
      */
     public static final int TERMINATE_REASON_FAIL = 101;
 
     /**
      * Called when a publish operation is started successfully in response to a
-     * {@link WifiNanSession#publish(android.os.Handler, PublishConfig, WifiNanDiscoverySessionCallback)}
+     * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
+     * WifiAwareDiscoverySessionCallback)}
      * operation.
      *
-     * @param session The {@link WifiNanPublishDiscoverySession} used to control the
+     * @param session The {@link WifiAwarePublishDiscoverySession} used to control the
      *            discovery session.
      */
-    public void onPublishStarted(@NonNull WifiNanPublishDiscoverySession session) {
+    public void onPublishStarted(@NonNull WifiAwarePublishDiscoverySession session) {
         /* empty */
     }
 
     /**
      * Called when a subscribe operation is started successfully in response to a
-     * {@link WifiNanSession#subscribe(android.os.Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)}
+     * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
+     * WifiAwareDiscoverySessionCallback)}
      * operation.
      *
-     * @param session The {@link WifiNanSubscribeDiscoverySession} used to control the
+     * @param session The {@link WifiAwareSubscribeDiscoverySession} used to control the
      *            discovery session.
      */
-    public void onSubscribeStarted(@NonNull WifiNanSubscribeDiscoverySession session) {
+    public void onSubscribeStarted(@NonNull WifiAwareSubscribeDiscoverySession session) {
         /* empty */
     }
 
     /**
      * Called when a publish or subscribe discovery session configuration update request
      * succeeds. Called in response to
-     * {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)} or
-     * {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+     * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or
+     * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
      */
     public void onSessionConfigUpdated() {
         /* empty */
@@ -94,12 +98,14 @@
 
     /**
      * Called when a publish or subscribe discovery session cannot be created:
-     * {@link WifiNanSession#publish(android.os.Handler, PublishConfig, WifiNanDiscoverySessionCallback)}
+     * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
+     * WifiAwareDiscoverySessionCallback)}
      * or
-     * {@link WifiNanSession#subscribe(android.os.Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)},
+     * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
+     * WifiAwareDiscoverySessionCallback)},
      * or when a configuration update fails:
-     * {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)} or
-     * {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+     * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or
+     * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
      * <p>
      *     For discovery session updates failure leaves the session running with its previous
      *     configuration - the discovery session is not terminated.
@@ -110,12 +116,12 @@
 
     /**
      * Called when a discovery session (publish or subscribe) terminates. Termination may be due
-     * to user-request (either directly through {@link WifiNanDiscoveryBaseSession#destroy()} or
+     * to user-request (either directly through {@link WifiAwareDiscoveryBaseSession#destroy()} or
      * application-specified expiration, e.g. {@link PublishConfig.Builder#setPublishCount(int)}
      * or {@link SubscribeConfig.Builder#setTtlSec(int)}) or due to a failure.
      *
      * @param reason The termination reason using
-     *            {@code WifiNanDiscoverySessionCallback.TERMINATE_*} codes.
+     *            {@code WifiAwareDiscoverySessionCallback.TERMINATE_*} codes.
      */
     public void onSessionTerminated(@SessionTerminateCodes int reason) {
         /* empty */
@@ -138,12 +144,12 @@
     }
 
     /**
-     * Called in response to {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[])}
+     * Called in response to {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])}
      * when a message is transmitted successfully - i.e. when it was received successfully by the
      * peer (corresponds to an ACK being received).
      * <p>
      * Note that either this callback or
-     * {@link WifiNanDiscoverySessionCallback#onMessageSendFailed(int)} will be
+     * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)} will be
      * received - never both.
      *
      * @param messageId The arbitrary message ID specified when sending the message.
@@ -154,12 +160,12 @@
 
     /**
      * Called when message transmission fails - when no ACK is received from the peer.
-     * Retries when ACKs are not received are done by hardware, MAC, and in the NAN stack (using
-     * the {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[], int)} method) - this
-     * event is received after all retries are exhausted.
+     * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
+     * the {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[], int)} method) -
+     * this event is received after all retries are exhausted.
      * <p>
      * Note that either this callback or
-     * {@link WifiNanDiscoverySessionCallback#onMessageSent(int)} will be received
+     * {@link WifiAwareDiscoverySessionCallback#onMessageSent(int)} will be received
      * - never both.
      *
      * @param messageId The arbitrary message ID specified when sending the message.
@@ -170,8 +176,8 @@
 
     /**
      * Called when a message is received from a discovery session peer - in response to the
-     * peer's {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[])} or
-     * {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[], int)}.
+     * peer's {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])} or
+     * {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[], int)}.
      *
      * @param peerHandle An opaque handle to the peer matching our discovery operation.
      * @param message A byte array containing the message.
diff --git a/wifi/java/android/net/wifi/nan/WifiNanIdentityChangedListener.java b/wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java
similarity index 75%
rename from wifi/java/android/net/wifi/nan/WifiNanIdentityChangedListener.java
rename to wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java
index 7cb928f..e8f52cd4 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanIdentityChangedListener.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java
@@ -14,23 +14,23 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 /**
- * Base class for a listener which is called with the MAC address of the NAN interface whenever
+ * Base class for a listener which is called with the MAC address of the Aware interface whenever
  * it is changed. Change may be due to device joining a cluster, starting a cluster, or discovery
  * interface change (addresses are randomized at regular intervals). The implication is that
  * peers you've been communicating with may no longer recognize you and you need to re-establish
  * your identity - e.g. by starting a discovery session. This actual MAC address of the
- * interface may also be useful if the application uses alternative (non-NAN) discovery but needs
- * to set up a NAN connection. The provided NAN discovery interface MAC address can then be used
- * in {@link WifiNanSession#createNetworkSpecifier(int, byte[], byte[])}.
+ * interface may also be useful if the application uses alternative (non-Aware) discovery but needs
+ * to set up a Aware connection. The provided Aware discovery interface MAC address can then be used
+ * in {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
-public class WifiNanIdentityChangedListener {
+public class WifiAwareIdentityChangedListener {
     /**
-     * @param mac The MAC address of the NAN discovery interface. The application must have the
+     * @param mac The MAC address of the Aware discovery interface. The application must have the
      * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to get the actual MAC address,
      *            otherwise all 0's will be provided.
      */
diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
similarity index 76%
rename from wifi/java/android/net/wifi/nan/WifiNanManager.java
rename to wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 002b953..10b70ab 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -48,80 +48,86 @@
 import java.util.Arrays;
 
 /**
- * This class provides the primary API for managing Wi-Fi NAN operations:
+ * This class provides the primary API for managing Wi-Fi Aware operations:
  * discovery and peer-to-peer data connections. Get an instance of this class by calling
  * {@link android.content.Context#getSystemService(String)
- * Context.getSystemService(Context.WIFI_NAN_SERVICE)}.
+ * Context.getSystemService(Context.WIFI_AWARE_SERVICE)}.
  * <p>
  * The class provides access to:
  * <ul>
- * <li>Initialize a NAN cluster (peer-to-peer synchronization). Refer to
- * {@link #attach(Handler, WifiNanAttachCallback)}.
+ * <li>Initialize a Aware cluster (peer-to-peer synchronization). Refer to
+ * {@link #attach(Handler, WifiAwareAttachCallback)}.
  * <li>Create discovery sessions (publish or subscribe sessions). Refer to
- * {@link WifiNanSession#publish(Handler, PublishConfig, WifiNanDiscoverySessionCallback)} and
- * {@link WifiNanSession#subscribe(Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)}.
- * <li>Create a NAN network specifier to be used with
+ * {@link WifiAwareSession#publish(Handler, PublishConfig, WifiAwareDiscoverySessionCallback)} and
+ * {@link WifiAwareSession#subscribe(Handler, SubscribeConfig, WifiAwareDiscoverySessionCallback)}.
+ * <li>Create a Aware network specifier to be used with
  * {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}
- * to set-up a NAN connection with a peer. Refer to
- * {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])} and
- * {@link WifiNanSession#createNetworkSpecifier(int, byte[], byte[])}.
+ * to set-up a Aware connection with a peer. Refer to
+ * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])} and
+ * {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}.
  * </ul>
  * <p>
- *     NAN may not be usable when Wi-Fi is disabled (and other conditions). To validate that
+ *     Aware may not be usable when Wi-Fi is disabled (and other conditions). To validate that
  *     the functionality is available use the {@link #isAvailable()} function. To track
- *     changes in NAN usability register for the {@link #ACTION_WIFI_NAN_STATE_CHANGED} broadcast.
- *     Note that this broadcast is not sticky - you should register for it and then check the
- *     above API to avoid a race condition.
+ *     changes in Aware usability register for the {@link #ACTION_WIFI_AWARE_STATE_CHANGED}
+ *     broadcast. Note that this broadcast is not sticky - you should register for it and then
+ *     check the above API to avoid a race condition.
  * <p>
- *     An application must use {@link #attach(Handler, WifiNanAttachCallback)} to initialize a NAN
- *     cluster - before making any other NAN operation. NAN cluster membership is a device-wide
- *     operation - the API guarantees that the device is in a cluster or joins a NAN cluster (or
- *     starts one if none can be found). Information about attach success (or failure) are
- *     returned in callbacks of {@link WifiNanAttachCallback}. Proceed with NAN discovery or
- *     connection setup only after receiving confirmation that NAN attach succeeded -
- *     {@link WifiNanAttachCallback#onAttached(WifiNanSession)}. When an application is
- *     finished using NAN it <b>must</b> use the {@link WifiNanSession#destroy()} API
- *     to indicate to the NAN service that the device may detach from the NAN cluster. The
- *     device will actually disable NAN once the last application detaches.
+ *     An application must use {@link #attach(Handler, WifiAwareAttachCallback)} to initialize a
+ *     Aware cluster - before making any other Aware operation. Aware cluster membership is a
+ *     device-wide operation - the API guarantees that the device is in a cluster or joins a
+ *     Aware cluster (or starts one if none can be found). Information about attach success (or
+ *     failure) are returned in callbacks of {@link WifiAwareAttachCallback}. Proceed with Aware
+ *     discovery or connection setup only after receiving confirmation that Aware attach
+ *     succeeded - {@link WifiAwareAttachCallback#onAttached(WifiAwareSession)}. When an
+ *     application is finished using Aware it <b>must</b> use the
+ *     {@link WifiAwareSession#destroy()} API to indicate to the Aware service that the device
+ *     may detach from the Aware cluster. The device will actually disable Aware once the last
+ *     application detaches.
  * <p>
- *     Once a NAN attach is confirmed use the
- *     {@link WifiNanSession#publish(Handler, PublishConfig, WifiNanDiscoverySessionCallback)} or
- *     {@link WifiNanSession#subscribe(Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)}
- *     to create publish or subscribe NAN discovery sessions. Events are called on the provided
- *     callback object {@link WifiNanDiscoverySessionCallback}. Specifically, the
- *     {@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)}
+ *     Once a Aware attach is confirmed use the
+ *     {@link WifiAwareSession#publish(Handler, PublishConfig, WifiAwareDiscoverySessionCallback)}
+ *     or
+ *     {@link WifiAwareSession#subscribe(Handler, SubscribeConfig,
+ *     WifiAwareDiscoverySessionCallback)}
+ *     to create publish or subscribe Aware discovery sessions. Events are called on the provided
+ *     callback object {@link WifiAwareDiscoverySessionCallback}. Specifically, the
+ *     {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}
  *     and
- *     {@link WifiNanDiscoverySessionCallback#onSubscribeStarted(WifiNanSubscribeDiscoverySession)}
- *     return {@link WifiNanPublishDiscoverySession} and {@link WifiNanSubscribeDiscoverySession}
+ *     {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(
+ *     WifiAwareSubscribeDiscoverySession)}
+ *     return {@link WifiAwarePublishDiscoverySession} and
+ *     {@link WifiAwareSubscribeDiscoverySession}
  *     objects respectively on which additional session operations can be performed, e.g. updating
- *     the session {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)} and
- *     {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can also
- *     be used to send messages using the
- *     {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[])} APIs. When an
+ *     the session {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} and
+ *     {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can
+ *     also be used to send messages using the
+ *     {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])} APIs. When an
  *     application is finished with a discovery session it <b>must</b> terminate it using the
- *     {@link WifiNanDiscoveryBaseSession#destroy()} API.
+ *     {@link WifiAwareDiscoveryBaseSession#destroy()} API.
  * <p>
- *    Creating connections between NAN devices is managed by the standard
- *    {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}.
+ *    Creating connections between Aware devices is managed by the standard
+ *    {@link ConnectivityManager#requestNetwork(NetworkRequest,
+ *    ConnectivityManager.NetworkCallback)}.
  *    The {@link NetworkRequest} object should be constructed with:
  *    <ul>
  *        <li>{@link NetworkRequest.Builder#addTransportType(int)} of
- *        {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_NAN}.
+ *        {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
  *        <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using
- *        {@link WifiNanSession#createNetworkSpecifier(int, byte[], byte[])} or
- *        {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])}.
+ *        {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])} or
+ *        {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])}.
  *    </ul>
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
-public class WifiNanManager {
-    private static final String TAG = "WifiNanManager";
+public class WifiAwareManager {
+    private static final String TAG = "WifiAwareManager";
     private static final boolean DBG = false;
     private static final boolean VDBG = false; // STOPSHIP if true
 
     /**
-     * Keys used to generate a Network Specifier for the NAN network request. The network specifier
-     * is formatted as a JSON string.
+     * Keys used to generate a Network Specifier for the Aware network request. The network
+     * specifier is formatted as a JSON string.
      */
 
     /**
@@ -197,44 +203,44 @@
     public static final String NETWORK_SPECIFIER_KEY_TOKEN = "token";
 
     /**
-     * Broadcast intent action to indicate that the state of Wi-Fi NAN availability has changed.
+     * Broadcast intent action to indicate that the state of Wi-Fi Aware availability has changed.
      * Use the {@link #isAvailable()} to query the current status.
      * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering
-     * the broadcast to check the current state of Wi-Fi NAN.
+     * the broadcast to check the current state of Wi-Fi Aware.
      * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
      * components will be launched.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_WIFI_NAN_STATE_CHANGED =
-            "android.net.wifi.nan.action.WIFI_NAN_STATE_CHANGED";
+    public static final String ACTION_WIFI_AWARE_STATE_CHANGED =
+            "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
 
     /** @hide */
     @IntDef({
-            WIFI_NAN_DATA_PATH_ROLE_INITIATOR, WIFI_NAN_DATA_PATH_ROLE_RESPONDER})
+            WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, WIFI_AWARE_DATA_PATH_ROLE_RESPONDER})
     @Retention(RetentionPolicy.SOURCE)
     public @interface DataPathRole {
     }
 
     /**
      * Connection creation role is that of INITIATOR. Used to create a network specifier string
-     * when requesting a NAN network.
+     * when requesting a Aware network.
      *
-     * @see WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])
-     * @see WifiNanSession#createNetworkSpecifier(int, byte[], byte[])
+     * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])
+     * @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
      */
-    public static final int WIFI_NAN_DATA_PATH_ROLE_INITIATOR = 0;
+    public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0;
 
     /**
      * Connection creation role is that of RESPONDER. Used to create a network specifier string
-     * when requesting a NAN network.
+     * when requesting a Aware network.
      *
-     * @see WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])
-     * @see WifiNanSession#createNetworkSpecifier(int, byte[], byte[])
+     * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])
+     * @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
      */
-    public static final int WIFI_NAN_DATA_PATH_ROLE_RESPONDER = 1;
+    public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1;
 
     private final Context mContext;
-    private final IWifiNanManager mService;
+    private final IWifiAwareManager mService;
 
     private final Object mLock = new Object(); // lock access to the following vars
 
@@ -242,14 +248,14 @@
     private SparseArray<RttManager.RttListener> mRangingListeners = new SparseArray<>();
 
     /** @hide */
-    public WifiNanManager(Context context, IWifiNanManager service) {
+    public WifiAwareManager(Context context, IWifiAwareManager service) {
         mContext = context;
         mService = service;
     }
 
     /**
-     * Enable the usage of the NAN API. Doesn't actually turn on NAN cluster formation - that
-     * only happens when an attach is attempted. {@link #ACTION_WIFI_NAN_STATE_CHANGED} broadcast
+     * Enable the usage of the Aware API. Doesn't actually turn on Aware cluster formation - that
+     * only happens when an attach is attempted. {@link #ACTION_WIFI_AWARE_STATE_CHANGED} broadcast
      * will be triggered.
      *
      * @hide
@@ -263,9 +269,9 @@
     }
 
     /**
-     * Disable the usage of the NAN API. All attempts to attach() will be rejected. All open
-     * connections and sessions will be terminated. {@link #ACTION_WIFI_NAN_STATE_CHANGED} broadcast
-     * will be triggered.
+     * Disable the usage of the Aware API. All attempts to attach() will be rejected. All open
+     * connections and sessions will be terminated. {@link #ACTION_WIFI_AWARE_STATE_CHANGED}
+     * broadcast will be triggered.
      *
      * @hide
      */
@@ -278,10 +284,11 @@
     }
 
     /**
-     * Returns the current status of NAN API: whether or not NAN is available. To track changes
-     * in the state of NAN API register for the {@link #ACTION_WIFI_NAN_STATE_CHANGED} broadcast.
+     * Returns the current status of Aware API: whether or not Aware is available. To track
+     * changes in the state of Aware API register for the
+     * {@link #ACTION_WIFI_AWARE_STATE_CHANGED} broadcast.
      *
-     * @return A boolean indicating whether the app can use the NAN API at this time (true) or
+     * @return A boolean indicating whether the app can use the Aware API at this time (true) or
      * not (false).
      */
     public boolean isAvailable() {
@@ -293,12 +300,13 @@
     }
 
     /**
-     * Returns the characteristics of the Wi-Fi NAN interface: a set of parameters which specify
+     * Returns the characteristics of the Wi-Fi Aware interface: a set of parameters which specify
      * limitations on configurations, e.g. the maximum service name length.
      *
-     * @return An object specifying configuration limitations of NAN.
+     * @return An object specifying configuration limitations of Aware.
+     * @hide PROPOSED_AWARE_API
      */
-    public WifiNanCharacteristics getCharacteristics() {
+    public WifiAwareCharacteristics getCharacteristics() {
         try {
             return mService.getCharacteristics();
         } catch (RemoteException e) {
@@ -307,14 +315,14 @@
     }
 
     /**
-     * Attach to the Wi-Fi NAN service - enabling the application to create discovery sessions or
+     * Attach to the Wi-Fi Aware service - enabling the application to create discovery sessions or
      * create connections to peers. The device will attach to an existing cluster if it can find
-     * one or create a new cluster (if it is the first to enable NAN in its vicinity). Results
+     * one or create a new cluster (if it is the first to enable Aware in its vicinity). Results
      * (e.g. successful attach to a cluster) are provided to the {@code attachCallback} object.
-     * An application <b>must</b> call {@link WifiNanSession#destroy()} when done with the
-     * Wi-Fi NAN object.
+     * An application <b>must</b> call {@link WifiAwareSession#destroy()} when done with the
+     * Wi-Fi Aware object.
      * <p>
-     * Note: a NAN cluster is a shared resource - if the device is already attached to a cluster
+     * Note: a Aware cluster is a shared resource - if the device is already attached to a cluster
      * then this function will simply indicate success immediately using the same {@code
      * attachCallback}.
      *
@@ -322,29 +330,29 @@
      * attachCallback} object. If a null is provided then the application's main thread will be
      *                used.
      * @param attachCallback A callback for attach events, extended from
-     * {@link WifiNanAttachCallback}.
+     * {@link WifiAwareAttachCallback}.
      */
-    public void attach(@Nullable Handler handler, @NonNull WifiNanAttachCallback attachCallback) {
+    public void attach(@Nullable Handler handler, @NonNull WifiAwareAttachCallback attachCallback) {
         attach(handler, null, attachCallback, null);
     }
 
     /**
-     * Attach to the Wi-Fi NAN service - enabling the application to create discovery sessions or
+     * Attach to the Wi-Fi Aware service - enabling the application to create discovery sessions or
      * create connections to peers. The device will attach to an existing cluster if it can find
-     * one or create a new cluster (if it is the first to enable NAN in its vicinity). Results
+     * one or create a new cluster (if it is the first to enable Aware in its vicinity). Results
      * (e.g. successful attach to a cluster) are provided to the {@code attachCallback} object.
-     * An application <b>must</b> call {@link WifiNanSession#destroy()} when done with the
-     * Wi-Fi NAN object.
+     * An application <b>must</b> call {@link WifiAwareSession#destroy()} when done with the
+     * Wi-Fi Aware object.
      * <p>
-     * Note: a NAN cluster is a shared resource - if the device is already attached to a cluster
+     * Note: a Aware cluster is a shared resource - if the device is already attached to a cluster
      * then this function will simply indicate success immediately using the same {@code
      * attachCallback}.
      * <p>
-     * This version of the API attaches a listener to receive the MAC address of the NAN interface
+     * This version of the API attaches a listener to receive the MAC address of the Aware interface
      * on startup and whenever it is updated (it is randomized at regular intervals for privacy).
      * The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
      * permission to execute this attach request. Otherwise, use the
-     * {@link #attach(Handler, WifiNanAttachCallback)} version. Note that aside from permission
+     * {@link #attach(Handler, WifiAwareAttachCallback)} version. Note that aside from permission
      * requirements this listener will wake up the host at regular intervals causing higher power
      * consumption, do not use it unless the information is necessary (e.g. for OOB discovery).
      *
@@ -352,19 +360,19 @@
      * attachCallback} and {@code identityChangedListener} objects. If a null is provided then the
      *                application's main thread will be used.
      * @param attachCallback A callback for attach events, extended from
-     * {@link WifiNanAttachCallback}.
+     * {@link WifiAwareAttachCallback}.
      * @param identityChangedListener A listener for changed identity, extended from
-     * {@link WifiNanIdentityChangedListener}.
+     * {@link WifiAwareIdentityChangedListener}.
      */
-    public void attach(@Nullable Handler handler, @NonNull WifiNanAttachCallback attachCallback,
-            @NonNull WifiNanIdentityChangedListener identityChangedListener) {
+    public void attach(@Nullable Handler handler, @NonNull WifiAwareAttachCallback attachCallback,
+            @NonNull WifiAwareIdentityChangedListener identityChangedListener) {
         attach(handler, null, attachCallback, identityChangedListener);
     }
 
     /** @hide */
     public void attach(Handler handler, ConfigRequest configRequest,
-            WifiNanAttachCallback attachCallback,
-            WifiNanIdentityChangedListener identityChangedListener) {
+            WifiAwareAttachCallback attachCallback,
+            WifiAwareIdentityChangedListener identityChangedListener) {
         if (VDBG) {
             Log.v(TAG, "attach(): handler=" + handler + ", callback=" + attachCallback
                     + ", configRequest=" + configRequest + ", identityChangedListener="
@@ -377,7 +385,7 @@
             try {
                 Binder binder = new Binder();
                 mService.connect(binder, mContext.getOpPackageName(),
-                        new WifiNanEventCallbackProxy(this, looper, binder, attachCallback,
+                        new WifiAwareEventCallbackProxy(this, looper, binder, attachCallback,
                                 identityChangedListener), configRequest,
                         identityChangedListener != null);
             } catch (RemoteException e) {
@@ -399,12 +407,12 @@
 
     /** @hide */
     public void publish(int clientId, Looper looper, PublishConfig publishConfig,
-            WifiNanDiscoverySessionCallback callback) {
+            WifiAwareDiscoverySessionCallback callback) {
         if (VDBG) Log.v(TAG, "publish(): clientId=" + clientId + ", config=" + publishConfig);
 
         try {
             mService.publish(clientId, publishConfig,
-                    new WifiNanDiscoverySessionCallbackProxy(this, looper, true, callback,
+                    new WifiAwareDiscoverySessionCallbackProxy(this, looper, true, callback,
                             clientId));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -427,7 +435,7 @@
 
     /** @hide */
     public void subscribe(int clientId, Looper looper, SubscribeConfig subscribeConfig,
-            WifiNanDiscoverySessionCallback callback) {
+            WifiAwareDiscoverySessionCallback callback) {
         if (VDBG) {
             if (VDBG) {
                 Log.v(TAG,
@@ -437,7 +445,7 @@
 
         try {
             mService.subscribe(clientId, subscribeConfig,
-                    new WifiNanDiscoverySessionCallbackProxy(this, looper, false, callback,
+                    new WifiAwareDiscoverySessionCallbackProxy(this, looper, false, callback,
                             clientId));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -535,13 +543,13 @@
             type = NETWORK_SPECIFIER_TYPE_1D;
         }
 
-        if (role != WIFI_NAN_DATA_PATH_ROLE_INITIATOR
-                && role != WIFI_NAN_DATA_PATH_ROLE_RESPONDER) {
+        if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
+                && role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
             throw new IllegalArgumentException(
                     "createNetworkSpecifier: Invalid 'role' argument when creating a network "
                             + "specifier");
         }
-        if (role == WIFI_NAN_DATA_PATH_ROLE_INITIATOR) {
+        if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
             if (token == null) {
                 throw new IllegalArgumentException(
                         "createNetworkSpecifier: Invalid null token - not permitted on INITIATOR");
@@ -592,13 +600,13 @@
             type = NETWORK_SPECIFIER_TYPE_2D;
         }
 
-        if (role != WIFI_NAN_DATA_PATH_ROLE_INITIATOR
-                && role != WIFI_NAN_DATA_PATH_ROLE_RESPONDER) {
+        if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
+                && role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
             throw new IllegalArgumentException(
                     "createNetworkSpecifier: Invalid 'role' argument when creating a network "
                             + "specifier");
         }
-        if (role == WIFI_NAN_DATA_PATH_ROLE_INITIATOR) {
+        if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
             if (peer == null || peer.length != 6) {
                 throw new IllegalArgumentException(
                         "createNetworkSpecifier: Invalid peer MAC address");
@@ -634,7 +642,7 @@
         return json.toString();
     }
 
-    private static class WifiNanEventCallbackProxy extends IWifiNanEventCallback.Stub {
+    private static class WifiAwareEventCallbackProxy extends IWifiAwareEventCallback.Stub {
         private static final int CALLBACK_CONNECT_SUCCESS = 0;
         private static final int CALLBACK_CONNECT_FAIL = 1;
         private static final int CALLBACK_IDENTITY_CHANGED = 2;
@@ -643,12 +651,12 @@
         private static final int CALLBACK_RANGING_ABORTED = 5;
 
         private final Handler mHandler;
-        private final WeakReference<WifiNanManager> mNanManager;
+        private final WeakReference<WifiAwareManager> mAwareManager;
         private final Binder mBinder;
         private final Looper mLooper;
 
         RttManager.RttListener getAndRemoveRangingListener(int rangingId) {
-            WifiNanManager mgr = mNanManager.get();
+            WifiAwareManager mgr = mAwareManager.get();
             if (mgr == null) {
                 Log.w(TAG, "getAndRemoveRangingListener: called post GC");
                 return null;
@@ -662,39 +670,40 @@
         }
 
         /**
-         * Constructs a {@link WifiNanAttachCallback} using the specified looper.
+         * Constructs a {@link WifiAwareAttachCallback} using the specified looper.
          * All callbacks will delivered on the thread of the specified looper.
          *
          * @param looper The looper on which to execute the callbacks.
          */
-        WifiNanEventCallbackProxy(WifiNanManager mgr, Looper looper, Binder binder,
-                final WifiNanAttachCallback attachCallback,
-                final WifiNanIdentityChangedListener identityChangedListener) {
-            mNanManager = new WeakReference<>(mgr);
+        WifiAwareEventCallbackProxy(WifiAwareManager mgr, Looper looper, Binder binder,
+                final WifiAwareAttachCallback attachCallback,
+                final WifiAwareIdentityChangedListener identityChangedListener) {
+            mAwareManager = new WeakReference<>(mgr);
             mLooper = looper;
             mBinder = binder;
 
-            if (VDBG) Log.v(TAG, "WifiNanEventCallbackProxy ctor: looper=" + looper);
+            if (VDBG) Log.v(TAG, "WifiAwareEventCallbackProxy ctor: looper=" + looper);
             mHandler = new Handler(looper) {
                 @Override
                 public void handleMessage(Message msg) {
                     if (DBG) {
-                        Log.d(TAG, "WifiNanEventCallbackProxy: What=" + msg.what + ", msg=" + msg);
+                        Log.d(TAG, "WifiAwareEventCallbackProxy: What=" + msg.what + ", msg="
+                                + msg);
                     }
 
-                    WifiNanManager mgr = mNanManager.get();
+                    WifiAwareManager mgr = mAwareManager.get();
                     if (mgr == null) {
-                        Log.w(TAG, "WifiNanEventCallbackProxy: handleMessage post GC");
+                        Log.w(TAG, "WifiAwareEventCallbackProxy: handleMessage post GC");
                         return;
                     }
 
                     switch (msg.what) {
                         case CALLBACK_CONNECT_SUCCESS:
                             attachCallback.onAttached(
-                                    new WifiNanSession(mgr, mBinder, msg.arg1));
+                                    new WifiAwareSession(mgr, mBinder, msg.arg1));
                             break;
                         case CALLBACK_CONNECT_FAIL:
-                            mNanManager.clear();
+                            mAwareManager.clear();
                             attachCallback.onAttachFailed();
                             break;
                         case CALLBACK_IDENTITY_CHANGED:
@@ -801,8 +810,8 @@
         }
     }
 
-    private static class WifiNanDiscoverySessionCallbackProxy extends
-            IWifiNanDiscoverySessionCallback.Stub {
+    private static class WifiAwareDiscoverySessionCallbackProxy extends
+            IWifiAwareDiscoverySessionCallback.Stub {
         private static final int CALLBACK_SESSION_STARTED = 0;
         private static final int CALLBACK_SESSION_CONFIG_SUCCESS = 1;
         private static final int CALLBACK_SESSION_CONFIG_FAIL = 2;
@@ -815,23 +824,24 @@
         private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
         private static final String MESSAGE_BUNDLE_KEY_MESSAGE2 = "message2";
 
-        private final WeakReference<WifiNanManager> mNanManager;
+        private final WeakReference<WifiAwareManager> mAwareManager;
         private final boolean mIsPublish;
-        private final WifiNanDiscoverySessionCallback mOriginalCallback;
+        private final WifiAwareDiscoverySessionCallback mOriginalCallback;
         private final int mClientId;
 
         private final Handler mHandler;
-        private WifiNanDiscoveryBaseSession mSession;
+        private WifiAwareDiscoveryBaseSession mSession;
 
-        WifiNanDiscoverySessionCallbackProxy(WifiNanManager mgr, Looper looper, boolean isPublish,
-                WifiNanDiscoverySessionCallback originalCallback, int clientId) {
-            mNanManager = new WeakReference<>(mgr);
+        WifiAwareDiscoverySessionCallbackProxy(WifiAwareManager mgr, Looper looper,
+                boolean isPublish, WifiAwareDiscoverySessionCallback originalCallback,
+                int clientId) {
+            mAwareManager = new WeakReference<>(mgr);
             mIsPublish = isPublish;
             mOriginalCallback = originalCallback;
             mClientId = clientId;
 
             if (VDBG) {
-                Log.v(TAG, "WifiNanDiscoverySessionCallbackProxy ctor: isPublish=" + isPublish);
+                Log.v(TAG, "WifiAwareDiscoverySessionCallbackProxy ctor: isPublish=" + isPublish);
             }
 
             mHandler = new Handler(looper) {
@@ -839,8 +849,8 @@
                 public void handleMessage(Message msg) {
                     if (DBG) Log.d(TAG, "What=" + msg.what + ", msg=" + msg);
 
-                    if (mNanManager.get() == null) {
-                        Log.w(TAG, "WifiNanDiscoverySessionCallbackProxy: handleMessage post GC");
+                    if (mAwareManager.get() == null) {
+                        Log.w(TAG, "WifiAwareDiscoverySessionCallbackProxy: handleMessage post GC");
                         return;
                     }
 
@@ -858,7 +868,7 @@
                                  * creation failed (as opposed to update
                                  * failing)
                                  */
-                                mNanManager.clear();
+                                mAwareManager.clear();
                             }
                             break;
                         case CALLBACK_SESSION_TERMINATED:
@@ -977,20 +987,20 @@
                         "onSessionStarted: sessionId=" + sessionId + ": session already created!?");
             }
 
-            WifiNanManager mgr = mNanManager.get();
+            WifiAwareManager mgr = mAwareManager.get();
             if (mgr == null) {
                 Log.w(TAG, "onProxySessionStarted: mgr GC'd");
                 return;
             }
 
             if (mIsPublish) {
-                WifiNanPublishDiscoverySession session = new WifiNanPublishDiscoverySession(mgr,
+                WifiAwarePublishDiscoverySession session = new WifiAwarePublishDiscoverySession(mgr,
                         mClientId, sessionId);
                 mSession = session;
                 mOriginalCallback.onPublishStarted(session);
             } else {
-                WifiNanSubscribeDiscoverySession
-                        session = new WifiNanSubscribeDiscoverySession(mgr, mClientId, sessionId);
+                WifiAwareSubscribeDiscoverySession
+                        session = new WifiAwareSubscribeDiscoverySession(mgr, mClientId, sessionId);
                 mSession = session;
                 mOriginalCallback.onSubscribeStarted(session);
             }
@@ -1004,7 +1014,7 @@
             } else {
                 Log.w(TAG, "Proxy: onSessionTerminated called but mSession is null!?");
             }
-            mNanManager.clear();
+            mAwareManager.clear();
             mOriginalCallback.onSessionTerminated(reason);
         }
     }
diff --git a/wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java b/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
similarity index 65%
rename from wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java
rename to wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
index 75c6cb7..610a92c 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanPublishDiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
@@ -14,39 +14,40 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.annotation.NonNull;
 import android.util.Log;
 
 /**
- * A class representing a NAN publish session. Created when
- * {@link WifiNanSession#publish(android.os.Handler, PublishConfig, WifiNanDiscoverySessionCallback)}
+ * A class representing a Aware publish session. Created when
+ * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
+ * WifiAwareDiscoverySessionCallback)}
  * is called and a discovery session is created and returned in
- * {@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)}. See
- * baseline functionality of all discovery sessions in {@link WifiNanDiscoveryBaseSession}. This
+ * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}. See
+ * baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}. This
  * object allows updating an existing/running publish discovery session using
  * {@link #updatePublish(PublishConfig)}.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
-public class WifiNanPublishDiscoverySession extends WifiNanDiscoveryBaseSession {
-    private static final String TAG = "WifiNanPublishDiscSsn";
+public class WifiAwarePublishDiscoverySession extends WifiAwareDiscoveryBaseSession {
+    private static final String TAG = "WifiAwarePublishDiscSsn";
 
     /** @hide */
-    public WifiNanPublishDiscoverySession(WifiNanManager manager, int clientId, int sessionId) {
+    public WifiAwarePublishDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) {
         super(manager, clientId, sessionId);
     }
 
     /**
      * Re-configure the currently active publish session. The
-     * {@link WifiNanDiscoverySessionCallback} is not replaced - the same listener used
+     * {@link WifiAwareDiscoverySessionCallback} is not replaced - the same listener used
      * at creation is still used. The results of the configuration are returned using
-     * {@link WifiNanDiscoverySessionCallback}:
+     * {@link WifiAwareDiscoverySessionCallback}:
      * <ul>
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigUpdated()}: configuration
+     *     <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigUpdated()}: configuration
      *     update succeeded.
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFailed()}: configuration
+     *     <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()}: configuration
      *     update failed. The publish discovery session is still running using its previous
      *     configuration (i.e. update failure does not terminate the session).
      * </ul>
@@ -58,9 +59,9 @@
             Log.w(TAG, "updatePublish: called on terminated session");
             return;
         } else {
-            WifiNanManager mgr = mMgr.get();
+            WifiAwareManager mgr = mMgr.get();
             if (mgr == null) {
-                Log.w(TAG, "updatePublish: called post GC on WifiNanManager");
+                Log.w(TAG, "updatePublish: called post GC on WifiAwareManager");
                 return;
             }
 
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
similarity index 66%
rename from wifi/java/android/net/wifi/nan/WifiNanSession.java
rename to wifi/java/android/net/wifi/aware/WifiAwareSession.java
index df5e3c1..357bd43 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.net.NetworkRequest;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.Looper;
@@ -29,17 +28,17 @@
 import java.lang.ref.WeakReference;
 
 /**
- * This class represents a Wi-Fi NAN session - an attachment to the Wi-Fi NAN service through
+ * This class represents a Wi-Fi Aware session - an attachment to the Wi-Fi Aware service through
  * which the app can execute discovery operations.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
-public class WifiNanSession {
-    private static final String TAG = "WifiNanSession";
+public class WifiAwareSession {
+    private static final String TAG = "WifiAwareSession";
     private static final boolean DBG = false;
     private static final boolean VDBG = false; // STOPSHIP if true
 
-    private final WeakReference<WifiNanManager> mMgr;
+    private final WeakReference<WifiAwareManager> mMgr;
     private final Binder mBinder;
     private final int mClientId;
 
@@ -47,7 +46,7 @@
     private final CloseGuard mCloseGuard = CloseGuard.get();
 
     /** @hide */
-    public WifiNanSession(WifiNanManager manager, Binder binder, int clientId) {
+    public WifiAwareSession(WifiAwareManager manager, Binder binder, int clientId) {
         if (VDBG) Log.v(TAG, "New session created: manager=" + manager + ", clientId=" + clientId);
 
         mMgr = new WeakReference<>(manager);
@@ -59,19 +58,19 @@
     }
 
     /**
-     * Destroy the Wi-Fi NAN service session and, if no other applications are attached to NAN,
-     * also disable NAN. This method destroys all outstanding operations - i.e. all publish and
+     * Destroy the Wi-Fi Aware service session and, if no other applications are attached to Aware,
+     * also disable Aware. This method destroys all outstanding operations - i.e. all publish and
      * subscribes are terminated, and any outstanding data-links are shut-down. However, it is
      * good practice to destroy these discovery sessions and connections explicitly before a
      * session-wide destroy.
      * <p>
      * An application may re-attach after a destroy using
-     * {@link WifiNanManager#attach(Handler, WifiNanAttachCallback)} .
+     * {@link WifiAwareManager#attach(Handler, WifiAwareAttachCallback)} .
      */
     public void destroy() {
-        WifiNanManager mgr = mMgr.get();
+        WifiAwareManager mgr = mMgr.get();
         if (mgr == null) {
-            Log.w(TAG, "destroy: called post GC on WifiNanManager");
+            Log.w(TAG, "destroy: called post GC on WifiAwareManager");
             return;
         }
         mgr.disconnect(mClientId, mBinder);
@@ -94,23 +93,24 @@
     }
 
     /**
-     * Issue a request to the NAN service to create a new NAN publish discovery session, using
+     * Issue a request to the Aware service to create a new Aware publish discovery session, using
      * the specified {@code publishConfig} configuration. The results of the publish operation
-     * are routed to the callbacks of {@link WifiNanDiscoverySessionCallback}:
+     * are routed to the callbacks of {@link WifiAwareDiscoverySessionCallback}:
      * <ul>
      *     <li>
-     *     {@link WifiNanDiscoverySessionCallback#onPublishStarted(WifiNanPublishDiscoverySession)}
+     *     {@link WifiAwareDiscoverySessionCallback#onPublishStarted(
+     *     WifiAwarePublishDiscoverySession)}
      *     is called when the publish session is created and provides a handle to the session.
      *     Further operations on the publish session can be executed on that object.
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFailed()} is called if the
+     *     <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()} is called if the
      *     publish operation failed.
      * </ul>
      * <p>
      * Other results of the publish session operations will also be routed to callbacks
      * on the {@code callback} object. The resulting publish session can be modified using
-     * {@link WifiNanPublishDiscoverySession#updatePublish(PublishConfig)}.
+     * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}.
      * <p>
-     *      An application must use the {@link WifiNanDiscoveryBaseSession#destroy()} to
+     *      An application must use the {@link WifiAwareDiscoveryBaseSession#destroy()} to
      *      terminate the publish discovery session once it isn't needed. This will free
      *      resources as well terminate any on-air transmissions.
      * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
@@ -120,14 +120,14 @@
      * callback} object. If a null is provided then the application's main thread will be used.
      * @param publishConfig The {@link PublishConfig} specifying the
      *            configuration of the requested publish session.
-     * @param callback A {@link WifiNanDiscoverySessionCallback} derived object to be used for
+     * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for
      *                 session event callbacks.
      */
     public void publish(@Nullable Handler handler, @NonNull PublishConfig publishConfig,
-            @NonNull WifiNanDiscoverySessionCallback callback) {
-        WifiNanManager mgr = mMgr.get();
+            @NonNull WifiAwareDiscoverySessionCallback callback) {
+        WifiAwareManager mgr = mMgr.get();
         if (mgr == null) {
-            Log.e(TAG, "publish: called post GC on WifiNanManager");
+            Log.e(TAG, "publish: called post GC on WifiAwareManager");
             return;
         }
         if (mTerminated) {
@@ -139,23 +139,24 @@
     }
 
     /**
-     * Issue a request to the NAN service to create a new NAN subscribe discovery session, using
+     * Issue a request to the Aware service to create a new Aware subscribe discovery session, using
      * the specified {@code subscribeConfig} configuration. The results of the subscribe
-     * operation are routed to the callbacks of {@link WifiNanDiscoverySessionCallback}:
+     * operation are routed to the callbacks of {@link WifiAwareDiscoverySessionCallback}:
      * <ul>
      *     <li>
-     *  {@link WifiNanDiscoverySessionCallback#onSubscribeStarted(WifiNanSubscribeDiscoverySession)}
+     *  {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(
+     *  WifiAwareSubscribeDiscoverySession)}
      *     is called when the subscribe session is created and provides a handle to the session.
      *     Further operations on the subscribe session can be executed on that object.
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFailed()} is called if the
+     *     <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()} is called if the
      *     subscribe operation failed.
      * </ul>
      * <p>
      * Other results of the subscribe session operations will also be routed to callbacks
      * on the {@code callback} object. The resulting subscribe session can be modified using
-     * {@link WifiNanSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+     * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
      * <p>
-     *      An application must use the {@link WifiNanDiscoveryBaseSession#destroy()} to
+     *      An application must use the {@link WifiAwareDiscoveryBaseSession#destroy()} to
      *      terminate the subscribe discovery session once it isn't needed. This will free
      *      resources as well terminate any on-air transmissions.
      * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
@@ -165,14 +166,14 @@
      * callback} object. If a null is provided then the application's main thread will be used.
      * @param subscribeConfig The {@link SubscribeConfig} specifying the
      *            configuration of the requested subscribe session.
-     * @param callback A {@link WifiNanDiscoverySessionCallback} derived object to be used for
+     * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for
      *                 session event callbacks.
      */
     public void subscribe(@Nullable Handler handler, @NonNull SubscribeConfig subscribeConfig,
-            @NonNull WifiNanDiscoverySessionCallback callback) {
-        WifiNanManager mgr = mMgr.get();
+            @NonNull WifiAwareDiscoverySessionCallback callback) {
+        WifiAwareManager mgr = mMgr.get();
         if (mgr == null) {
-            Log.e(TAG, "publish: called post GC on WifiNanManager");
+            Log.e(TAG, "publish: called post GC on WifiAwareManager");
             return;
         }
         if (mTerminated) {
@@ -184,20 +185,20 @@
     }
 
     /**
-     * Create a {@link NetworkRequest.Builder#setNetworkSpecifier(String)} for a
-     * WiFi NAN connection to the specified peer. The
-     * {@link NetworkRequest.Builder#addTransportType(int)} should be set to
-     * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_NAN}.
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for a
+     * WiFi Aware connection to the specified peer. The
+     * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
+     * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
      * <p>
      *     This API is targeted for applications which can obtain the peer MAC address using OOB
-     *     (out-of-band) discovery. NAN discovery does not provide the MAC address of the peer -
-     *     when using NAN discovery use the alternative network specifier method -
-     *     {@link WifiNanDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])}.
+     *     (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
+     *     when using Aware discovery use the alternative network specifier method -
+     *     {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])}.
      *
      * @param role  The role of this device:
-     *              {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_INITIATOR} or
-     *              {@link WifiNanManager#WIFI_NAN_DATA_PATH_ROLE_RESPONDER}
-     * @param peer  The MAC address of the peer's NAN discovery interface. On a RESPONDER this
+     *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
+     *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
+     * @param peer  The MAC address of the peer's Aware discovery interface. On a RESPONDER this
      *              value is used to gate the acceptance of a connection request from only that
      *              peer. A RESPONDER may specified a null - indicating that it will accept
      *              connection requests from any device.
@@ -209,14 +210,15 @@
      *
      * @return A string to be used to construct
      * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
-     * {@link android.net.ConnectivityManager#requestNetwork(NetworkRequest, android.net.ConnectivityManager.NetworkCallback)}
+     * {@link android.net.ConnectivityManager#requestNetwork(NetworkRequest,
+     * android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
      */
-    public String createNetworkSpecifier(@WifiNanManager.DataPathRole int role, @Nullable byte[] peer,
-            @Nullable byte[] token) {
-        WifiNanManager mgr = mMgr.get();
+    public String createNetworkSpecifier(@WifiAwareManager.DataPathRole int role,
+            @Nullable byte[] peer, @Nullable byte[] token) {
+        WifiAwareManager mgr = mMgr.get();
         if (mgr == null) {
-            Log.e(TAG, "createNetworkSpecifier: called post GC on WifiNanManager");
+            Log.e(TAG, "createNetworkSpecifier: called post GC on WifiAwareManager");
             return "";
         }
         if (mTerminated) {
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java b/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
similarity index 65%
rename from wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java
rename to wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
index f5b4c0c..7c48f54 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSubscribeDiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
@@ -14,41 +14,43 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 import android.annotation.NonNull;
 import android.util.Log;
 
 /**
- * A class representing a NAN subscribe session. Created when
- * {@link WifiNanSession#subscribe(android.os.Handler, SubscribeConfig, WifiNanDiscoverySessionCallback)}
+ * A class representing a Aware subscribe session. Created when
+ * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
+ * WifiAwareDiscoverySessionCallback)}
  * is called and a discovery session is created and returned in
- * {@link WifiNanDiscoverySessionCallback#onSubscribeStarted(WifiNanSubscribeDiscoverySession)}.
- * See baseline functionality of all discovery sessions in {@link WifiNanDiscoveryBaseSession}.
+ * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(WifiAwareSubscribeDiscoverySession)}.
+ * See baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}.
  * This object allows updating an existing/running subscribe discovery session using
  * {@link #updateSubscribe(SubscribeConfig)}.
  *
- * @hide PROPOSED_NAN_API
+ * @hide PROPOSED_AWARE_API
  */
-public class WifiNanSubscribeDiscoverySession extends WifiNanDiscoveryBaseSession {
-    private static final String TAG = "WifiNanSubscribeDiscSsn";
+public class WifiAwareSubscribeDiscoverySession extends WifiAwareDiscoveryBaseSession {
+    private static final String TAG = "WifiAwareSubsDiscSsn";
 
     /**
      * {@hide}
      */
-    public WifiNanSubscribeDiscoverySession(WifiNanManager manager, int clientId, int sessionId) {
+    public WifiAwareSubscribeDiscoverySession(WifiAwareManager manager, int clientId,
+            int sessionId) {
         super(manager, clientId, sessionId);
     }
 
     /**
      * Re-configure the currently active subscribe session. The
-     * {@link WifiNanDiscoverySessionCallback} is not replaced - the same listener used
+     * {@link WifiAwareDiscoverySessionCallback} is not replaced - the same listener used
      * at creation is still used. The results of the configuration are returned using
-     * {@link WifiNanDiscoverySessionCallback}:
+     * {@link WifiAwareDiscoverySessionCallback}:
      * <ul>
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigUpdated()}: configuration
+     *     <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigUpdated()}: configuration
      *     update succeeded.
-     *     <li>{@link WifiNanDiscoverySessionCallback#onSessionConfigFailed()}: configuration
+     *     <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()}: configuration
      *     update failed. The subscribe discovery session is still running using its previous
      *     configuration (i.e. update failure does not terminate the session).
      * </ul>
@@ -61,9 +63,9 @@
             Log.w(TAG, "updateSubscribe: called on terminated session");
             return;
         } else {
-            WifiNanManager mgr = mMgr.get();
+            WifiAwareManager mgr = mMgr.get();
             if (mgr == null) {
-                Log.w(TAG, "updateSubscribe: called post GC on WifiNanManager");
+                Log.w(TAG, "updateSubscribe: called post GC on WifiAwareManager");
                 return;
             }
 
diff --git a/wifi/java/android/net/wifi/nan/WifiNanUtils.java b/wifi/java/android/net/wifi/aware/WifiAwareUtils.java
similarity index 93%
rename from wifi/java/android/net/wifi/nan/WifiNanUtils.java
rename to wifi/java/android/net/wifi/aware/WifiAwareUtils.java
index c0f36b4..4083388 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanUtils.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareUtils.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package android.net.wifi.nan;
+package android.net.wifi.aware;
 
 /**
- * Provides utilities for the Wifi NAN manager/service.
+ * Provides utilities for the Wifi Aware manager/service.
  *
  * @hide
  */
-public class WifiNanUtils {
+public class WifiAwareUtils {
     /**
      * Per spec: The Service Name is a UTF-8 encoded string from 1 to 255 bytes in length. The
      * only acceptable single-byte UTF-8 symbols for a Service Name are alphanumeric values (A-Z,
diff --git a/wifi/java/android/net/wifi/aware/package.html b/wifi/java/android/net/wifi/aware/package.html
new file mode 100644
index 0000000..1a990d8
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/package.html
@@ -0,0 +1,43 @@
+<HTML>
+<BODY>
+<p>Provides classes which allow applications to use Wi-Fi Aware to discover peers and create
+    connections to them.</p>
+<p>Using the Wi-Fi Aware APIs, applications can advertise services, discover peers which are
+    advertising services, and connect to them.
+    Wi-Fi Aware is independent of Wi-Fi infrastructure (i.e. a device may or may
+    not be associated with an AP concurrent to using Wi-Fi Aware). </p>
+<p>The primary entry point to Wi-Fi Aware capabilities is the
+    {@link android.net.wifi.aware.WifiAwareManager} class, which is acquired by calling
+    {@link android.content.Context#getSystemService(String)
+    Context.getSystemService(Context.WIFI_AWARE_SERVICE)}</p>
+
+<p>Some APIs may require the following user permissions:</p>
+<ul>
+    <li>{@link android.Manifest.permission#ACCESS_WIFI_STATE}</li>
+    <li>{@link android.Manifest.permission#CHANGE_WIFI_STATE}</li>
+    <li>{@link android.Manifest.permission#ACCESS_COARSE_LOCATION}</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Not all Android-powered devices support Wi-Fi Aware
+    functionality.
+    If your application only works with Wi-Fi Aware (i.e. it should only be installed on devices which
+    support Wi-Fi Aware), declare so with a <a
+            href="{@docRoot}guide/topics/manifest/uses-feature-element.html">
+        {@code &lt;uses-feature&gt;}</a>
+    element in the manifest file:</p>
+<pre>
+&lt;manifest ...>
+    &lt;uses-feature android:name="android.hardware.wifi.aware" />
+    ...
+&lt;/manifest>
+</pre>
+<p>Alternatively, if you application does not require Wi-Fi Aware but can take advantage of it if
+    available, you can perform
+    the check at run-time in your code using {@link
+    android.content.pm.PackageManager#hasSystemFeature(String)} with {@link
+    android.content.pm.PackageManager#FEATURE_WIFI_AWARE}:</p>
+<pre>
+    getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
+</pre>
+</BODY>
+</HTML>
diff --git a/wifi/java/android/net/wifi/nan/WifiNanAttachCallback.java b/wifi/java/android/net/wifi/nan/WifiNanAttachCallback.java
deleted file mode 100644
index d8c310b..0000000
--- a/wifi/java/android/net/wifi/nan/WifiNanAttachCallback.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.net.wifi.nan;
-
-/**
- * Base class for NAN attach callbacks. Should be extended by applications and set when calling
- * {@link WifiNanManager#attach(android.os.Handler, WifiNanAttachCallback)}. These are callbacks
- * applying to the NAN connection as a whole - not to specific publish or subscribe sessions -
- * for that see {@link WifiNanDiscoverySessionCallback}.
- *
- * @hide PROPOSED_NAN_API
- */
-public class WifiNanAttachCallback {
-    /**
-     * Called when NAN attach operation
-     * {@link WifiNanManager#attach(android.os.Handler, WifiNanAttachCallback)}
-     * is completed and that we can now start discovery sessions or connections.
-     *
-     * @param session The NAN object on which we can execute further NAN operations - e.g.
-     *                discovery, connections.
-     */
-    public void onAttached(WifiNanSession session) {
-        /* empty */
-    }
-
-    /**
-     * Called when NAN attach operation
-     * {@link WifiNanManager#attach(android.os.Handler, WifiNanAttachCallback)} failed.
-     */
-    public void onAttachFailed() {
-        /* empty */
-    }
-}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.aidl b/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.aidl
deleted file mode 100644
index e562a00..0000000
--- a/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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.net.wifi.nan;
-
-parcelable WifiNanCharacteristics;
diff --git a/wifi/java/android/net/wifi/nan/package.html b/wifi/java/android/net/wifi/nan/package.html
deleted file mode 100644
index ae3cf6c..0000000
--- a/wifi/java/android/net/wifi/nan/package.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<HTML>
-<BODY>
-<p>Provides classes which allow applications to use Wi-Fi NAN to discover peers and create
-    connections to them.</p>
-<p>Using the Wi-Fi NAN APIs, applications can advertise services, discover peers which are
-    advertising services, and connect to them.
-    Wi-Fi NAN is independent of Wi-Fi infrastructure (i.e. a device may or may
-    not be associated with an AP concurrent to using Wi-Fi NAN). </p>
-<p>The primary entry point to Wi-Fi NAN capabilities is the
-    {@link android.net.wifi.nan.WifiNanManager} class, which is acquired by calling
-    {@link android.content.Context#getSystemService(String)
-    Context.getSystemService(Context.WIFI_NAN_SERVICE)}</p>
-
-<p>Some APIs may require the following user permissions:</p>
-<ul>
-    <li>{@link android.Manifest.permission#ACCESS_WIFI_STATE}</li>
-    <li>{@link android.Manifest.permission#CHANGE_WIFI_STATE}</li>
-    <li>{@link android.Manifest.permission#ACCESS_COARSE_LOCATION}</li>
-</ul>
-
-<p class="note"><strong>Note:</strong> Not all Android-powered devices support Wi-Fi NAN
-    functionality.
-    If your application only works with Wi-Fi NAN (i.e. it should only be installed on devices which
-    support Wi-Fi NAN), declare so with a <a
-            href="{@docRoot}guide/topics/manifest/uses-feature-element.html">
-        {@code &lt;uses-feature&gt;}</a>
-    element in the manifest file:</p>
-<pre>
-&lt;manifest ...>
-    &lt;uses-feature android:name="android.hardware.wifi.nan" />
-    ...
-&lt;/manifest>
-</pre>
-<p>Alternatively, if you application does not require Wi-Fi NAN but can take advantage of it if
-    available, you can perform
-    the check at run-time in your code using {@link
-    android.content.pm.PackageManager#hasSystemFeature(String)} with {@link
-    android.content.pm.PackageManager#FEATURE_WIFI_NAN}:</p>
-<pre>
-    getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_NAN)
-</pre>
-</BODY>
-</HTML>
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 8d5cf63..398308d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -283,6 +283,13 @@
     public static final String EXTRA_HANDOVER_MESSAGE =
             "android.net.wifi.p2p.EXTRA_HANDOVER_MESSAGE";
 
+    /**
+     * The lookup key for a calling package returned by the WifiP2pService.
+     * @hide
+     */
+    public static final String CALLING_PACKAGE =
+            "android.net.wifi.p2p.CALLING_PACKAGE";
+
     IWifiP2pManager mService;
 
     private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
@@ -1271,7 +1278,10 @@
      */
     public void requestPeers(Channel c, PeerListListener listener) {
         checkChannel(c);
-        c.mAsyncChannel.sendMessage(REQUEST_PEERS, 0, c.putListener(listener));
+        Bundle callingPackage = new Bundle();
+        callingPackage.putString(CALLING_PACKAGE, c.mContext.getOpPackageName());
+        c.mAsyncChannel.sendMessage(REQUEST_PEERS, 0, c.putListener(listener),
+                callingPackage);
     }
 
     /**