Merge "Add key for sms_convert_destination_number"
diff --git a/Android.mk b/Android.mk
index e352bc7..4fea0d4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -288,7 +288,6 @@
 	core/java/android/view/accessibility/IAccessibilityManagerClient.aidl \
 	core/java/android/view/IApplicationToken.aidl \
 	core/java/android/view/IAppTransitionAnimationSpecsFuture.aidl \
-	core/java/android/view/IAssetAtlas.aidl \
 	core/java/android/view/IDockedStackListener.aidl \
 	core/java/android/view/IGraphicsStats.aidl \
 	core/java/android/view/IInputFilter.aidl \
@@ -860,6 +859,7 @@
     -since $(SRC_API_DIR)/22.txt 22 \
     -since $(SRC_API_DIR)/23.txt 23 \
     -since $(SRC_API_DIR)/24.txt 24 \
+    -since $(SRC_API_DIR)/25.txt 25 \
 		-werror -hide 111 -hide 113 \
 		-overview $(LOCAL_PATH)/core/java/overview.html
 
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..f5bd945
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,7 @@
+[Hook Scripts]
+checkstyle_hook = ../../development/tools/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
+                  -fw core/java/android/animation/
+                      core/java/android/text/
+                      core/java/android/view/
+                      core/java/android/transition/
+                      core/java/android/widget/
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java
new file mode 100644
index 0000000..519d1f4
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.graphics.perftests;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Bitmap.Config;
+import android.graphics.Paint;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.view.DisplayListCanvas;
+import android.view.RenderNode;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@LargeTest
+public class CanvasPerfTest {
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void testBasicViewGroupDraw() {
+        // This test is a clone of BM_DisplayListCanvas_basicViewGroupDraw
+
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        RenderNode node = RenderNode.create("benchmark", null);
+        RenderNode child = RenderNode.create("child", null);
+        child.setLeftTopRightBottom(50, 50, 100, 100);
+
+        DisplayListCanvas canvas = node.start(100, 100);
+        node.end(canvas);
+        canvas = child.start(50, 50);
+        canvas.drawColor(Color.WHITE);
+        child.end(canvas);
+
+        while (state.keepRunning()) {
+            canvas = node.start(200, 200);
+            canvas.setHighContrastText(false);
+            int save = canvas.save();
+            canvas.clipRect(1, 1, 199, 199);
+            canvas.insertReorderBarrier();
+            for (int i = 0; i < 5; i++) {
+                canvas.drawRenderNode(child);
+            }
+            canvas.insertInorderBarrier();
+            canvas.restoreToCount(save);
+            node.end(canvas);
+        }
+    }
+
+    @Test
+    public void testRecordSimpleBitmapView() {
+        // This test is a clone of BM_DisplayListCanvas_record_simpleBitmapView
+
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        RenderNode node = RenderNode.create("benchmark", null);
+
+        DisplayListCanvas canvas = node.start(100, 100);
+        node.end(canvas);
+        Bitmap bitmap = Bitmap.createBitmap(80, 80, Config.ARGB_8888);
+        Paint paint = new Paint();
+        paint.setColor(Color.BLACK);
+
+        while (state.keepRunning()) {
+            canvas = node.start(100, 100);
+            {
+                canvas.save();
+                canvas.drawRect(0, 0, 100, 100, paint);
+                canvas.restore();
+            }
+            {
+                canvas.save();
+                canvas.translate(10, 10);
+                canvas.drawBitmap(bitmap, 0, 0, null);
+                canvas.restore();
+            }
+            node.end(canvas);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/os/ParcelArrayPerfTest.java b/apct-tests/perftests/core/src/android/os/ParcelArrayPerfTest.java
new file mode 100644
index 0000000..a67aeca
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/ParcelArrayPerfTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.os;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class ParcelArrayPerfTest {
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Parameters(name = "size={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] { {1}, {10}, {100}, {1000} });
+    }
+
+    private final int mSize;
+
+    private Parcel mWriteParcel;
+
+    private byte[] mByteArray;
+    private int[] mIntArray;
+    private long[] mLongArray;
+
+    private Parcel mByteParcel;
+    private Parcel mIntParcel;
+    private Parcel mLongParcel;
+
+    public ParcelArrayPerfTest(int size) {
+        mSize = size;
+    }
+
+    @Before
+    public void setUp() {
+        mWriteParcel = Parcel.obtain();
+
+        mByteArray = new byte[mSize];
+        mIntArray = new int[mSize];
+        mLongArray = new long[mSize];
+
+        mByteParcel = Parcel.obtain();
+        mByteParcel.writeByteArray(mByteArray);
+        mIntParcel = Parcel.obtain();
+        mIntParcel.writeIntArray(mIntArray);
+        mLongParcel = Parcel.obtain();
+        mLongParcel.writeLongArray(mLongArray);
+    }
+
+    @After
+    public void tearDown() {
+        mWriteParcel.recycle();
+        mWriteParcel = null;
+    }
+
+    @Test
+    public void timeWriteByteArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mWriteParcel.setDataPosition(0);
+            mWriteParcel.writeByteArray(mByteArray);
+        }
+    }
+
+    @Test
+    public void timeCreateByteArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mByteParcel.setDataPosition(0);
+            mByteParcel.createByteArray();
+        }
+    }
+
+    @Test
+    public void timeReadByteArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mByteParcel.setDataPosition(0);
+            mByteParcel.readByteArray(mByteArray);
+        }
+    }
+
+    @Test
+    public void timeWriteIntArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mWriteParcel.setDataPosition(0);
+            mWriteParcel.writeIntArray(mIntArray);
+        }
+    }
+
+    @Test
+    public void timeCreateIntArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mIntParcel.setDataPosition(0);
+            mIntParcel.createIntArray();
+        }
+    }
+
+    @Test
+    public void timeReadIntArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mIntParcel.setDataPosition(0);
+            mIntParcel.readIntArray(mIntArray);
+        }
+    }
+
+    @Test
+    public void timeWriteLongArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mWriteParcel.setDataPosition(0);
+            mWriteParcel.writeLongArray(mLongArray);
+        }
+    }
+
+    @Test
+    public void timeCreateLongArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mLongParcel.setDataPosition(0);
+            mLongParcel.createLongArray();
+        }
+    }
+
+    @Test
+    public void timeReadLongArray() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mLongParcel.setDataPosition(0);
+            mLongParcel.readLongArray(mLongArray);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/os/ParcelPerfTest.java b/apct-tests/perftests/core/src/android/os/ParcelPerfTest.java
new file mode 100644
index 0000000..8cd45f7
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/ParcelPerfTest.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 android.os;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ParcelPerfTest {
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private Parcel mParcel;
+
+    @Before
+    public void setUp() {
+        mParcel = Parcel.obtain();
+        mParcel.setDataPosition(0);
+        mParcel.setDataCapacity(8);
+    }
+
+    @After
+    public void tearDown() {
+        mParcel.recycle();
+        mParcel = null;
+    }
+
+    @Test
+    public void timeSetDataPosition() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mParcel.setDataPosition(0);
+        }
+    }
+
+    @Test
+    public void timeWriteByte() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final byte val = 0xF;
+        while (state.keepRunning()) {
+            mParcel.setDataPosition(0);
+            mParcel.writeByte(val);
+        }
+    }
+
+    @Test
+    public void timeReadByte() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mParcel.setDataPosition(0);
+            mParcel.readByte();
+        }
+    }
+
+    @Test
+    public void timeWriteInt() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final int val = 0xF;
+        while (state.keepRunning()) {
+            mParcel.setDataPosition(0);
+            mParcel.writeInt(val);
+        }
+    }
+
+    @Test
+    public void timeReadInt() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mParcel.setDataPosition(0);
+            mParcel.readInt();
+        }
+    }
+
+    @Test
+    public void timeWriteLong() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final long val = 0xF;
+        while (state.keepRunning()) {
+            mParcel.setDataPosition(0);
+            mParcel.writeLong(val);
+        }
+    }
+
+    @Test
+    public void timeReadLong() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mParcel.setDataPosition(0);
+            mParcel.readLong();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/java/lang/perftests/SystemPerfTest.java b/apct-tests/perftests/core/src/java/lang/perftests/SystemPerfTest.java
index 6a49c03..1e9c49c 100644
--- a/apct-tests/perftests/core/src/java/lang/perftests/SystemPerfTest.java
+++ b/apct-tests/perftests/core/src/java/lang/perftests/SystemPerfTest.java
@@ -24,6 +24,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.TimeUnit;
+
 @RunWith(AndroidJUnit4.class)
 @LargeTest
 public class SystemPerfTest {
@@ -37,4 +39,25 @@
             System.nanoTime();
         }
     }
+
+    @Test
+    public void testBenchmarkOverhead() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {}
+    }
+
+    void spinBlock(long durationNs) {
+        long start = System.nanoTime();
+        while (System.nanoTime() - start < durationNs) {}
+    }
+
+    @Test
+    public void testBenchmarkPauseResumeOverhead() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            spinBlock(TimeUnit.MICROSECONDS.toNanos(5));
+            state.resumeTiming();
+        }
+    }
 }
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java
index cdbca63..88cb8e6 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTest.java
@@ -57,8 +57,6 @@
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 public class UserLifecycleTest {
-    private final int MIN_REPEAT_TIMES = 4;
-
     private final int TIMEOUT_REMOVE_USER_MS = 4 * 1000; // 4 sec
     private final int CHECK_USER_REMOVED_INTERVAL_MS = 200; // 0.2 sec
 
@@ -90,7 +88,6 @@
         mAm = context.getSystemService(ActivityManager.class);
         mIam = ActivityManagerNative.getDefault();
         mState = mPerfStatusReporter.getBenchmarkState();
-        mState.setMinRepeatTimes(MIN_REPEAT_TIMES);
         mUsersToRemove = new ArrayList<>();
     }
 
@@ -300,4 +297,4 @@
             mUsersToRemove.add(userId);
         }
     }
-}
\ No newline at end of file
+}
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 b27d71b..519d524 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
@@ -23,6 +23,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Provides a benchmark framework.
@@ -41,39 +42,48 @@
  *     System.out.println(state.summaryLine());
  * }
  */
-public class BenchmarkState {
+public final class BenchmarkState {
+
     private static final String TAG = "BenchmarkState";
 
-    private static final int NOT_STARTED = 1;  // The benchmark has not started yet.
+    private static final int NOT_STARTED = 0;  // The benchmark has not started yet.
+    private static final int WARMUP = 1; // The benchmark is warming up.
     private static final int RUNNING = 2;  // The benchmark is running.
-    private static final int RUNNING_PAUSED = 3;  // The benchmark is temporary paused.
-    private static final int FINISHED = 4;  // The benchmark has stopped.
+    private static final int FINISHED = 3;  // The benchmark has stopped.
 
     private int mState = NOT_STARTED;  // Current benchmark state.
 
-    private long mNanoPreviousTime = 0;  // Previously captured System.nanoTime().
-    private long mNanoFinishTime = 0;  // Finish if System.nanoTime() returns after than this value.
-    private long mNanoPausedTime = 0; // The System.nanoTime() when the pauseTiming() is called.
-    private long mNanoPausedDuration = 0;  // The duration of paused state in nano sec.
-    private long mNanoTimeLimit = 1 * 1000 * 1000 * 1000;  // 1 sec. Default time limit.
+    private static final long WARMUP_DURATION_NS = ms2ns(250); // warm-up for at least 250ms
+    private static final int WARMUP_MIN_ITERATIONS = 16; // minimum iterations to warm-up for
+
+    // TODO: Tune these values.
+    private static final long TARGET_TEST_DURATION_NS = ms2ns(500); // target testing for 500 ms
+    private static final int MAX_TEST_ITERATIONS = 1000000;
+    private static final int MIN_TEST_ITERATIONS = 100;
+    private static final int REPEAT_COUNT = 5;
+
+    private long mStartTimeNs = 0;  // Previously captured System.nanoTime().
+    private boolean mPaused;
+    private long mPausedTimeNs = 0; // The System.nanoTime() when the pauseTiming() is called.
+    private long mPausedDurationNs = 0;  // The duration of paused state in nano sec.
+
+    private int mIteration = 0;
+    private int mMaxIterations = 0;
+
+    private int mRepeatCount = 0;
 
     // Statistics. These values will be filled when the benchmark has finished.
     // The computation needs double precision, but long int is fine for final reporting.
     private long mMedian = 0;
     private double mMean = 0.0;
     private double mStandardDeviation = 0.0;
-
-    // Number of iterations needed for calculating the stats.
-    private int mMinRepeatTimes = 16;
+    private long mMin = 0;
 
     // Individual duration in nano seconds.
     private ArrayList<Long> mResults = new ArrayList<>();
 
-    /**
-     * Sets the number of iterations needed for calculating the stats. Default is 16.
-     */
-    public void setMinRepeatTimes(int minRepeatTimes) {
-        mMinRepeatTimes = minRepeatTimes;
+    private static final long ms2ns(long ms) {
+        return TimeUnit.MILLISECONDS.toNanos(ms);
     }
 
     /**
@@ -89,8 +99,13 @@
         mMedian = size % 2 == 0 ? (mResults.get(size / 2) + mResults.get(size / 2 + 1)) / 2 :
                 mResults.get(size / 2);
 
+        mMin = mResults.get(0);
         for (int i = 0; i < size; ++i) {
-            mMean += mResults.get(i);
+            long result = mResults.get(i);
+            mMean += result;
+            if (result < mMin) {
+                mMin = result;
+            }
         }
         mMean /= (double) size;
 
@@ -104,24 +119,56 @@
     // Stops the benchmark timer.
     // This method can be called only when the timer is running.
     public void pauseTiming() {
-        if (mState == RUNNING_PAUSED) {
+        if (mPaused) {
             throw new IllegalStateException(
                     "Unable to pause the benchmark. The benchmark has already paused.");
         }
-        mNanoPausedTime = System.nanoTime();
-        mState = RUNNING_PAUSED;
+        mPausedTimeNs = System.nanoTime();
+        mPaused = true;
     }
 
     // Starts the benchmark timer.
     // This method can be called only when the timer is stopped.
     public void resumeTiming() {
-        if (mState == RUNNING) {
+        if (!mPaused) {
             throw new IllegalStateException(
                     "Unable to resume the benchmark. The benchmark is already running.");
         }
-        mNanoPausedDuration += System.nanoTime() - mNanoPausedTime;
-        mNanoPausedTime = 0;
+        mPausedDurationNs += System.nanoTime() - mPausedTimeNs;
+        mPausedTimeNs = 0;
+        mPaused = false;
+    }
+
+    private void beginWarmup() {
+        mStartTimeNs = System.nanoTime();
+        mIteration = 0;
+        mState = WARMUP;
+    }
+
+    private void beginBenchmark(long warmupDuration, int iterations) {
+        mMaxIterations = (int) (TARGET_TEST_DURATION_NS / (warmupDuration / iterations));
+        mMaxIterations = Math.min(MAX_TEST_ITERATIONS,
+                Math.max(mMaxIterations, MIN_TEST_ITERATIONS));
+        mPausedDurationNs = 0;
+        mIteration = 0;
+        mRepeatCount = 0;
         mState = RUNNING;
+        mStartTimeNs = System.nanoTime();
+    }
+
+    private boolean startNextTestRun() {
+        final long currentTime = System.nanoTime();
+        mResults.add((currentTime - mStartTimeNs - mPausedDurationNs) / mMaxIterations);
+        mRepeatCount++;
+        if (mRepeatCount >= REPEAT_COUNT) {
+            calculateSatistics();
+            mState = FINISHED;
+            return false;
+        }
+        mPausedDurationNs = 0;
+        mIteration = 0;
+        mStartTimeNs = System.nanoTime();
+        return true;
     }
 
     /**
@@ -132,28 +179,28 @@
     public boolean keepRunning() {
         switch (mState) {
             case NOT_STARTED:
-                mNanoPreviousTime = System.nanoTime();
-                mNanoFinishTime = mNanoPreviousTime + mNanoTimeLimit;
-                mState = RUNNING;
+                beginWarmup();
+                return true;
+            case WARMUP:
+                mIteration++;
+                // Only check nanoTime on every iteration in WARMUP since we
+                // don't yet have a target iteration count.
+                final long duration = System.nanoTime() - mStartTimeNs;
+                if (mIteration >= WARMUP_MIN_ITERATIONS && duration >= WARMUP_DURATION_NS) {
+                    beginBenchmark(duration, mIteration);
+                }
                 return true;
             case RUNNING:
-                final long currentTime = System.nanoTime();
-                mResults.add(currentTime - mNanoPreviousTime - mNanoPausedDuration);
-                mNanoPausedDuration = 0;
-
-                // To calculate statistics, needs two or more samples.
-                if (mResults.size() > mMinRepeatTimes && currentTime > mNanoFinishTime) {
-                    calculateSatistics();
-                    mState = FINISHED;
-                    return false;
+                mIteration++;
+                if (mIteration >= mMaxIterations) {
+                    return startNextTestRun();
                 }
-
-                mNanoPreviousTime = currentTime;
+                if (mPaused) {
+                    throw new IllegalStateException(
+                            "Benchmark step finished with paused state. " +
+                            "Resume the benchmark before finishing each step.");
+                }
                 return true;
-            case RUNNING_PAUSED:
-                throw new IllegalStateException(
-                        "Benchmark step finished with paused state. " +
-                        "Resume the benchmark before finishing each step.");
             case FINISHED:
                 throw new IllegalStateException("The benchmark has finished.");
             default:
@@ -161,21 +208,28 @@
         }
     }
 
-    public long mean() {
+    private long mean() {
         if (mState != FINISHED) {
             throw new IllegalStateException("The benchmark hasn't finished");
         }
         return (long) mMean;
     }
 
-    public long median() {
+    private long median() {
         if (mState != FINISHED) {
             throw new IllegalStateException("The benchmark hasn't finished");
         }
         return mMedian;
     }
 
-    public long standardDeviation() {
+    private long min() {
+        if (mState != FINISHED) {
+            throw new IllegalStateException("The benchmark hasn't finished");
+        }
+        return mMin;
+    }
+
+    private long standardDeviation() {
         if (mState != FINISHED) {
             throw new IllegalStateException("The benchmark hasn't finished");
         }
@@ -187,10 +241,11 @@
         sb.append("Summary: ");
         sb.append("median=").append(median()).append("ns, ");
         sb.append("mean=").append(mean()).append("ns, ");
+        sb.append("min=").append(min()).append("ns, ");
         sb.append("sigma=").append(standardDeviation()).append(", ");
         sb.append("iteration=").append(mResults.size()).append(", ");
         // print out the first few iterations' number for double checking.
-        int sampleNumber = Math.min(mResults.size(), mMinRepeatTimes);
+        int sampleNumber = Math.min(mResults.size(), 16);
         for (int i = 0; i < sampleNumber; i++) {
             sb.append("No ").append(i).append(" result is ").append(mResults.get(i)).append(", ");
         }
@@ -202,6 +257,7 @@
         Bundle status = new Bundle();
         status.putLong(key + "_median", median());
         status.putLong(key + "_mean", mean());
+        status.putLong(key + "_min", min());
         status.putLong(key + "_standardDeviation", standardDeviation());
         instrumentation.sendStatus(Activity.RESULT_OK, status);
     }
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/PerfStatusReporter.java b/apct-tests/perftests/utils/src/android/perftests/utils/PerfStatusReporter.java
index 3933b57..64b0bf5 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/PerfStatusReporter.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/PerfStatusReporter.java
@@ -18,8 +18,9 @@
 
 import android.support.test.InstrumentationRegistry;
 
-import org.junit.rules.TestWatcher;
+import org.junit.rules.TestRule;
 import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
 
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
@@ -47,7 +48,7 @@
  * name when using parameterization.
  */
 
-public class PerfStatusReporter extends TestWatcher {
+public class PerfStatusReporter implements TestRule {
     private final BenchmarkState mState = new BenchmarkState();
 
     public BenchmarkState getBenchmarkState() {
@@ -55,33 +56,39 @@
     }
 
     @Override
-    protected void succeeded(Description description) {
-        String invokeMethodName = description.getMethodName();
-        // validate and simplify the function name.
-        // First, remove the "test" prefix which normally comes from CTS test.
-        // Then make sure the [subTestName] is valid, not just numbers like [0].
-        if (invokeMethodName.startsWith("test")) {
-            assertTrue("The test name " + invokeMethodName + " is too short",
-                    invokeMethodName.length() > 5);
-            invokeMethodName = invokeMethodName.substring(4, 5).toLowerCase()
-                    + invokeMethodName.substring(5);
-        }
-
-        int index = invokeMethodName.lastIndexOf('[');
-        if (index > 0) {
-            boolean allDigits = true;
-            for (int i = index + 1; i < invokeMethodName.length() - 1; i++) {
-                if (!Character.isDigit(invokeMethodName.charAt(i))) {
-                    allDigits = false;
-                    break;
+    public Statement apply(Statement base, Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                String invokeMethodName = description.getMethodName();
+                // validate and simplify the function name.
+                // First, remove the "test" prefix which normally comes from CTS test.
+                // Then make sure the [subTestName] is valid, not just numbers like [0].
+                if (invokeMethodName.startsWith("test")) {
+                    assertTrue("The test name " + invokeMethodName + " is too short",
+                            invokeMethodName.length() > 5);
+                    invokeMethodName = invokeMethodName.substring(4, 5).toLowerCase()
+                            + invokeMethodName.substring(5);
                 }
+
+                int index = invokeMethodName.lastIndexOf('[');
+                if (index > 0) {
+                    boolean allDigits = true;
+                    for (int i = index + 1; i < invokeMethodName.length() - 1; i++) {
+                        if (!Character.isDigit(invokeMethodName.charAt(i))) {
+                            allDigits = false;
+                            break;
+                        }
+                    }
+                    assertFalse("The name in [] can't contain only digits for " + invokeMethodName,
+                            allDigits);
+                }
+
+                base.evaluate();
+
+                mState.sendFullStatusReport(InstrumentationRegistry.getInstrumentation(),
+                        invokeMethodName);
             }
-            assertFalse("The name in [] can't contain only digits for " + invokeMethodName,
-                    allDigits);
-        }
-
-        mState.sendFullStatusReport(InstrumentationRegistry.getInstrumentation(),
-                invokeMethodName);
+        };
     }
-
 }
diff --git a/api/current.txt b/api/current.txt
index 56f0bb0..2beea12 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -855,6 +855,7 @@
     field public static final int mediaRouteTypes = 16843694; // 0x10103ae
     field public static final int menuCategory = 16843230; // 0x10101de
     field public static final int mimeType = 16842790; // 0x1010026
+    field public static final int min = 16843367; // 0x1010267
     field public static final int minDate = 16843583; // 0x101033f
     field public static final int minEms = 16843098; // 0x101015a
     field public static final int minHeight = 16843072; // 0x1010140
@@ -3265,6 +3266,7 @@
   public class ValueAnimator extends android.animation.Animator {
     ctor public ValueAnimator();
     method public void addUpdateListener(android.animation.ValueAnimator.AnimatorUpdateListener);
+    method public static boolean areAnimatorsEnabled();
     method public float getAnimatedFraction();
     method public java.lang.Object getAnimatedValue();
     method public java.lang.Object getAnimatedValue(java.lang.String);
@@ -30307,6 +30309,8 @@
 
   public final class PrintJobInfo implements android.os.Parcelable {
     method public int describeContents();
+    method public int getAdvancedIntOption(java.lang.String);
+    method public java.lang.String getAdvancedStringOption(java.lang.String);
     method public android.print.PrintAttributes getAttributes();
     method public int getCopies();
     method public long getCreationTime();
@@ -30315,6 +30319,7 @@
     method public android.print.PageRange[] getPages();
     method public android.print.PrinterId getPrinterId();
     method public int getState();
+    method public boolean hasAdvancedOption(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.print.PrintJobInfo> CREATOR;
     field public static final int STATE_BLOCKED = 4; // 0x4
@@ -30458,9 +30463,11 @@
     method protected void onDisconnected();
     method protected abstract void onPrintJobQueued(android.printservice.PrintJob);
     method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob);
+    field public static final java.lang.String EXTRA_CAN_SELECT_PRINTER = "android.printservice.extra.CAN_SELECT_PRINTER";
     field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO";
     field public static final java.lang.String EXTRA_PRINT_DOCUMENT_INFO = "android.printservice.extra.PRINT_DOCUMENT_INFO";
     field public static final java.lang.String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO";
+    field public static final java.lang.String EXTRA_SELECT_PRINTER = "android.printservice.extra.SELECT_PRINTER";
     field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService";
     field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
   }
@@ -31678,6 +31685,7 @@
     method public static void notifyDirectoryChange(android.content.ContentResolver);
     field public static final java.lang.String ACCOUNT_NAME = "accountName";
     field public static final java.lang.String ACCOUNT_TYPE = "accountType";
+    field public static final java.lang.String CALLER_PACKAGE_PARAM_KEY = "callerPackage";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_directory";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/contact_directories";
     field public static final android.net.Uri CONTENT_URI;
@@ -32572,7 +32580,7 @@
     field public static final java.lang.String RADIO_CELL = "cell";
     field public static final java.lang.String RADIO_NFC = "nfc";
     field public static final java.lang.String RADIO_WIFI = "wifi";
-    field public static final java.lang.String SHOW_PROCESSES = "show_processes";
+    field public static final deprecated java.lang.String SHOW_PROCESSES = "show_processes";
     field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
     field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
     field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
@@ -34848,6 +34856,7 @@
     method public static void requestRebind(android.content.ComponentName);
     method public final void requestUnbind();
     method public final void setNotificationsShown(java.lang.String[]);
+    method public final void snoozeNotification(java.lang.String, long);
     field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
     field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
@@ -36894,6 +36903,7 @@
     field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
     field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
+    field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
     field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
@@ -36961,6 +36971,7 @@
     field public static final java.lang.String KEY_MMS_UA_PROF_TAG_NAME_STRING = "uaProfTagName";
     field public static final java.lang.String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
     field public static final java.lang.String KEY_MMS_USER_AGENT_STRING = "userAgent";
+    field public static final java.lang.String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
     field public static final java.lang.String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
     field public static final java.lang.String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
     field public static final java.lang.String KEY_RCS_CONFIG_SERVER_URL_STRING = "rcs_config_server_url_string";
@@ -45838,6 +45849,7 @@
     method public deprecated void freeMemory();
     method public android.net.http.SslCertificate getCertificate();
     method public int getContentHeight();
+    method public static android.content.pm.PackageInfo getCurrentWebViewPackage();
     method public android.graphics.Bitmap getFavicon();
     method public android.webkit.WebView.HitTestResult getHitTestResult();
     method public deprecated java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
@@ -47471,6 +47483,7 @@
     method public android.graphics.PorterDuff.Mode getIndeterminateTintMode();
     method public android.view.animation.Interpolator getInterpolator();
     method public synchronized int getMax();
+    method public synchronized int getMin();
     method public synchronized int getProgress();
     method public android.content.res.ColorStateList getProgressBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getProgressBackgroundTintMode();
@@ -47493,6 +47506,7 @@
     method public void setInterpolator(android.content.Context, int);
     method public void setInterpolator(android.view.animation.Interpolator);
     method public synchronized void setMax(int);
+    method public synchronized void setMin(int);
     method public synchronized void setProgress(int);
     method public void setProgress(int, boolean);
     method public void setProgressBackgroundTintList(android.content.res.ColorStateList);
diff --git a/api/system-current.txt b/api/system-current.txt
index 7617caf..db8a501 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -962,6 +962,7 @@
     field public static final int mediaRouteTypes = 16843694; // 0x10103ae
     field public static final int menuCategory = 16843230; // 0x10101de
     field public static final int mimeType = 16842790; // 0x1010026
+    field public static final int min = 16843367; // 0x1010267
     field public static final int minDate = 16843583; // 0x101033f
     field public static final int minEms = 16843098; // 0x101015a
     field public static final int minHeight = 16843072; // 0x1010140
@@ -3380,6 +3381,7 @@
   public class ValueAnimator extends android.animation.Animator {
     ctor public ValueAnimator();
     method public void addUpdateListener(android.animation.ValueAnimator.AnimatorUpdateListener);
+    method public static boolean areAnimatorsEnabled();
     method public float getAnimatedFraction();
     method public java.lang.Object getAnimatedValue();
     method public java.lang.Object getAnimatedValue(java.lang.String);
@@ -32907,6 +32909,8 @@
 
   public final class PrintJobInfo implements android.os.Parcelable {
     method public int describeContents();
+    method public int getAdvancedIntOption(java.lang.String);
+    method public java.lang.String getAdvancedStringOption(java.lang.String);
     method public android.print.PrintAttributes getAttributes();
     method public int getCopies();
     method public long getCreationTime();
@@ -32915,6 +32919,7 @@
     method public android.print.PageRange[] getPages();
     method public android.print.PrinterId getPrinterId();
     method public int getState();
+    method public boolean hasAdvancedOption(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.print.PrintJobInfo> CREATOR;
     field public static final int STATE_BLOCKED = 4; // 0x4
@@ -33058,9 +33063,11 @@
     method protected void onDisconnected();
     method protected abstract void onPrintJobQueued(android.printservice.PrintJob);
     method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob);
+    field public static final java.lang.String EXTRA_CAN_SELECT_PRINTER = "android.printservice.extra.CAN_SELECT_PRINTER";
     field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO";
     field public static final java.lang.String EXTRA_PRINT_DOCUMENT_INFO = "android.printservice.extra.PRINT_DOCUMENT_INFO";
     field public static final java.lang.String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO";
+    field public static final java.lang.String EXTRA_SELECT_PRINTER = "android.printservice.extra.SELECT_PRINTER";
     field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService";
     field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
   }
@@ -34302,6 +34309,7 @@
     method public static void notifyDirectoryChange(android.content.ContentResolver);
     field public static final java.lang.String ACCOUNT_NAME = "accountName";
     field public static final java.lang.String ACCOUNT_TYPE = "accountType";
+    field public static final java.lang.String CALLER_PACKAGE_PARAM_KEY = "callerPackage";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_directory";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/contact_directories";
     field public static final android.net.Uri CONTENT_URI;
@@ -35329,7 +35337,7 @@
     field public static final java.lang.String RADIO_CELL = "cell";
     field public static final java.lang.String RADIO_NFC = "nfc";
     field public static final java.lang.String RADIO_WIFI = "wifi";
-    field public static final java.lang.String SHOW_PROCESSES = "show_processes";
+    field public static final deprecated java.lang.String SHOW_PROCESSES = "show_processes";
     field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
     field public static final java.lang.String THEATER_MODE_ON = "theater_mode_on";
     field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
@@ -37628,6 +37636,7 @@
     method public final void requestUnbind();
     method public final void setNotificationsShown(java.lang.String[]);
     method public final void setOnNotificationPostedTrim(int);
+    method public final void snoozeNotification(java.lang.String, long);
     method public void unregisterAsSystemService() throws android.os.RemoteException;
     field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
@@ -37689,6 +37698,7 @@
     field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
     field public static final int REASON_PACKAGE_SUSPENDED = 14; // 0xe
     field public static final int REASON_PROFILE_TURNED_OFF = 15; // 0xf
+    field public static final int REASON_SNOOZED = 18; // 0x12
     field public static final int REASON_UNAUTOBUNDLED = 16; // 0x10
     field public static final int REASON_USER_STOPPED = 6; // 0x6
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationRankerService";
@@ -39985,6 +39995,7 @@
     field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
     field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
+    field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
     field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
@@ -40052,6 +40063,7 @@
     field public static final java.lang.String KEY_MMS_UA_PROF_TAG_NAME_STRING = "uaProfTagName";
     field public static final java.lang.String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
     field public static final java.lang.String KEY_MMS_USER_AGENT_STRING = "userAgent";
+    field public static final java.lang.String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
     field public static final java.lang.String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
     field public static final java.lang.String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
     field public static final java.lang.String KEY_RCS_CONFIG_SERVER_URL_STRING = "rcs_config_server_url_string";
@@ -49114,6 +49126,7 @@
     method public deprecated void freeMemory();
     method public android.net.http.SslCertificate getCertificate();
     method public int getContentHeight();
+    method public static android.content.pm.PackageInfo getCurrentWebViewPackage();
     method public android.graphics.Bitmap getFavicon();
     method public android.webkit.WebView.HitTestResult getHitTestResult();
     method public deprecated java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
@@ -51010,6 +51023,7 @@
     method public android.graphics.PorterDuff.Mode getIndeterminateTintMode();
     method public android.view.animation.Interpolator getInterpolator();
     method public synchronized int getMax();
+    method public synchronized int getMin();
     method public synchronized int getProgress();
     method public android.content.res.ColorStateList getProgressBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getProgressBackgroundTintMode();
@@ -51032,6 +51046,7 @@
     method public void setInterpolator(android.content.Context, int);
     method public void setInterpolator(android.view.animation.Interpolator);
     method public synchronized void setMax(int);
+    method public synchronized void setMin(int);
     method public synchronized void setProgress(int);
     method public void setProgress(int, boolean);
     method public void setProgressBackgroundTintList(android.content.res.ColorStateList);
diff --git a/api/test-current.txt b/api/test-current.txt
index 9a21d46..e9f2f0e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -855,6 +855,7 @@
     field public static final int mediaRouteTypes = 16843694; // 0x10103ae
     field public static final int menuCategory = 16843230; // 0x10101de
     field public static final int mimeType = 16842790; // 0x1010026
+    field public static final int min = 16843367; // 0x1010267
     field public static final int minDate = 16843583; // 0x101033f
     field public static final int minEms = 16843098; // 0x101015a
     field public static final int minHeight = 16843072; // 0x1010140
@@ -3265,6 +3266,7 @@
   public class ValueAnimator extends android.animation.Animator {
     ctor public ValueAnimator();
     method public void addUpdateListener(android.animation.ValueAnimator.AnimatorUpdateListener);
+    method public static boolean areAnimatorsEnabled();
     method public float getAnimatedFraction();
     method public java.lang.Object getAnimatedValue();
     method public java.lang.Object getAnimatedValue(java.lang.String);
@@ -30382,6 +30384,8 @@
 
   public final class PrintJobInfo implements android.os.Parcelable {
     method public int describeContents();
+    method public int getAdvancedIntOption(java.lang.String);
+    method public java.lang.String getAdvancedStringOption(java.lang.String);
     method public android.print.PrintAttributes getAttributes();
     method public int getCopies();
     method public long getCreationTime();
@@ -30392,6 +30396,7 @@
     method public float getProgress();
     method public int getState();
     method public java.lang.CharSequence getStatus(android.content.pm.PackageManager);
+    method public boolean hasAdvancedOption(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.print.PrintJobInfo> CREATOR;
     field public static final int STATE_BLOCKED = 4; // 0x4
@@ -30536,9 +30541,11 @@
     method protected void onDisconnected();
     method protected abstract void onPrintJobQueued(android.printservice.PrintJob);
     method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob);
+    field public static final java.lang.String EXTRA_CAN_SELECT_PRINTER = "android.printservice.extra.CAN_SELECT_PRINTER";
     field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO";
     field public static final java.lang.String EXTRA_PRINT_DOCUMENT_INFO = "android.printservice.extra.PRINT_DOCUMENT_INFO";
     field public static final java.lang.String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO";
+    field public static final java.lang.String EXTRA_SELECT_PRINTER = "android.printservice.extra.SELECT_PRINTER";
     field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService";
     field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
   }
@@ -31756,6 +31763,7 @@
     method public static void notifyDirectoryChange(android.content.ContentResolver);
     field public static final java.lang.String ACCOUNT_NAME = "accountName";
     field public static final java.lang.String ACCOUNT_TYPE = "accountType";
+    field public static final java.lang.String CALLER_PACKAGE_PARAM_KEY = "callerPackage";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_directory";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/contact_directories";
     field public static final android.net.Uri CONTENT_URI;
@@ -32650,7 +32658,7 @@
     field public static final java.lang.String RADIO_CELL = "cell";
     field public static final java.lang.String RADIO_NFC = "nfc";
     field public static final java.lang.String RADIO_WIFI = "wifi";
-    field public static final java.lang.String SHOW_PROCESSES = "show_processes";
+    field public static final deprecated java.lang.String SHOW_PROCESSES = "show_processes";
     field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
     field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
     field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
@@ -34929,6 +34937,7 @@
     method public static void requestRebind(android.content.ComponentName);
     method public final void requestUnbind();
     method public final void setNotificationsShown(java.lang.String[]);
+    method public final void snoozeNotification(java.lang.String, long);
     field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
     field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
@@ -36975,6 +36984,7 @@
     field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
     field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
+    field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
     field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
@@ -37042,6 +37052,7 @@
     field public static final java.lang.String KEY_MMS_UA_PROF_TAG_NAME_STRING = "uaProfTagName";
     field public static final java.lang.String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
     field public static final java.lang.String KEY_MMS_USER_AGENT_STRING = "userAgent";
+    field public static final java.lang.String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
     field public static final java.lang.String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
     field public static final java.lang.String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
     field public static final java.lang.String KEY_RCS_CONFIG_SERVER_URL_STRING = "rcs_config_server_url_string";
@@ -41020,6 +41031,156 @@
 
 }
 
+package android.util.proto {
+
+  public final class EncodedBuffer {
+    ctor public EncodedBuffer();
+    ctor public EncodedBuffer(int);
+    method public void dumpBuffers(java.lang.String);
+    method public static void dumpByteString(java.lang.String, java.lang.String, byte[]);
+    method public void editRawFixed32(int, int);
+    method public byte[] getBytes(int);
+    method public int getChunkCount();
+    method public java.lang.String getDebugString();
+    method public int getRawFixed32At(int);
+    method public static int getRawVarint32Size(int);
+    method public static int getRawVarint64Size(long);
+    method public static int getRawZigZag32Size(int);
+    method public static int getRawZigZag64Size(long);
+    method public int getReadPos();
+    method public int getReadableSize();
+    method public int getWriteBufIndex();
+    method public int getWriteIndex();
+    method public int getWritePos();
+    method public byte readRawByte();
+    method public int readRawFixed32();
+    method public long readRawUnsigned();
+    method public void rewindRead();
+    method public void rewindWriteTo(int);
+    method public void skipRead(int);
+    method public void startEditing();
+    method public void writeFromThisBuffer(int, int);
+    method public void writeRawBuffer(byte[]);
+    method public void writeRawBuffer(byte[], int, int);
+    method public void writeRawByte(byte);
+    method public void writeRawFixed32(int);
+    method public void writeRawFixed64(long);
+    method public void writeRawVarint32(int);
+    method public void writeRawVarint64(long);
+    method public void writeRawZigZag32(int);
+    method public void writeRawZigZag64(long);
+  }
+
+  public final class ProtoOutputStream {
+    ctor public ProtoOutputStream();
+    ctor public ProtoOutputStream(int);
+    method public static int checkFieldId(long, long);
+    method public static int convertObjectIdToOrdinal(int);
+    method public void dump(java.lang.String);
+    method public void endObject(long);
+    method public void endRepeatedObject(long);
+    method public byte[] getBytes();
+    method public static int getDepthFromToken(long);
+    method public static int getObjectIdFromToken(long);
+    method public static boolean getRepeatedFromToken(long);
+    method public static int getSizePosFromToken(long);
+    method public static int getTagSizeFromToken(long);
+    method public static long makeFieldId(int, long);
+    method public static long makeToken(int, boolean, int, int, int);
+    method public long startObject(long);
+    method public long startRepeatedObject(long);
+    method public static java.lang.String token2String(long);
+    method public void writeBool(long, boolean);
+    method public void writeBytes(long, byte[]);
+    method public void writeDouble(long, double);
+    method public void writeEnum(long, int);
+    method public void writeFixed32(long, int);
+    method public void writeFixed64(long, long);
+    method public void writeFloat(long, float);
+    method public void writeInt32(long, int);
+    method public void writeInt64(long, long);
+    method public void writePackedBool(long, boolean[]);
+    method public void writePackedDouble(long, double[]);
+    method public void writePackedEnum(long, int[]);
+    method public void writePackedFixed32(long, int[]);
+    method public void writePackedFixed64(long, long[]);
+    method public void writePackedFloat(long, float[]);
+    method public void writePackedInt32(long, int[]);
+    method public void writePackedInt64(long, long[]);
+    method public void writePackedSFixed32(long, int[]);
+    method public void writePackedSFixed64(long, long[]);
+    method public void writePackedSInt32(long, int[]);
+    method public void writePackedSInt64(long, long[]);
+    method public void writePackedUInt32(long, int[]);
+    method public void writePackedUInt64(long, long[]);
+    method public void writeRepeatedBool(long, boolean);
+    method public void writeRepeatedBytes(long, byte[]);
+    method public void writeRepeatedDouble(long, double);
+    method public void writeRepeatedEnum(long, int);
+    method public void writeRepeatedFixed32(long, int);
+    method public void writeRepeatedFixed64(long, long);
+    method public void writeRepeatedFloat(long, float);
+    method public void writeRepeatedInt32(long, int);
+    method public void writeRepeatedInt64(long, long);
+    method public void writeRepeatedSFixed32(long, int);
+    method public void writeRepeatedSFixed64(long, long);
+    method public void writeRepeatedSInt32(long, int);
+    method public void writeRepeatedSInt64(long, long);
+    method public void writeRepeatedString(long, java.lang.String);
+    method public void writeRepeatedUInt32(long, int);
+    method public void writeRepeatedUInt64(long, long);
+    method public void writeSFixed32(long, int);
+    method public void writeSFixed64(long, long);
+    method public void writeSInt32(long, int);
+    method public void writeSInt64(long, long);
+    method public void writeString(long, java.lang.String);
+    method public void writeTag(int, int);
+    method public void writeUInt32(long, int);
+    method public void writeUInt64(long, long);
+    field public static final long FIELD_COUNT_MASK = 16492674416640L; // 0xf0000000000L
+    field public static final long FIELD_COUNT_PACKED = 5497558138880L; // 0x50000000000L
+    field public static final long FIELD_COUNT_REPEATED = 2199023255552L; // 0x20000000000L
+    field public static final int FIELD_COUNT_SHIFT = 40; // 0x28
+    field public static final long FIELD_COUNT_SINGLE = 1099511627776L; // 0x10000000000L
+    field public static final long FIELD_COUNT_UNKNOWN = 0L; // 0x0L
+    field public static final int FIELD_ID_MASK = -8; // 0xfffffff8
+    field public static final int FIELD_ID_SHIFT = 3; // 0x3
+    field public static final long FIELD_TYPE_BOOL = 55834574848L; // 0xd00000000L
+    field public static final long FIELD_TYPE_BYTES = 64424509440L; // 0xf00000000L
+    field public static final long FIELD_TYPE_DOUBLE = 4294967296L; // 0x100000000L
+    field public static final long FIELD_TYPE_ENUM = 68719476736L; // 0x1000000000L
+    field public static final long FIELD_TYPE_FIXED32 = 38654705664L; // 0x900000000L
+    field public static final long FIELD_TYPE_FIXED64 = 42949672960L; // 0xa00000000L
+    field public static final long FIELD_TYPE_FLOAT = 8589934592L; // 0x200000000L
+    field public static final long FIELD_TYPE_INT32 = 12884901888L; // 0x300000000L
+    field public static final long FIELD_TYPE_INT64 = 17179869184L; // 0x400000000L
+    field public static final long FIELD_TYPE_MASK = 1095216660480L; // 0xff00000000L
+    field public static final long FIELD_TYPE_OBJECT = 73014444032L; // 0x1100000000L
+    field public static final long FIELD_TYPE_SFIXED32 = 47244640256L; // 0xb00000000L
+    field public static final long FIELD_TYPE_SFIXED64 = 51539607552L; // 0xc00000000L
+    field public static final int FIELD_TYPE_SHIFT = 32; // 0x20
+    field public static final long FIELD_TYPE_SINT32 = 30064771072L; // 0x700000000L
+    field public static final long FIELD_TYPE_SINT64 = 34359738368L; // 0x800000000L
+    field public static final long FIELD_TYPE_STRING = 60129542144L; // 0xe00000000L
+    field public static final long FIELD_TYPE_UINT32 = 21474836480L; // 0x500000000L
+    field public static final long FIELD_TYPE_UINT64 = 25769803776L; // 0x600000000L
+    field public static final long FIELD_TYPE_UNKNOWN = 0L; // 0x0L
+    field public static final java.lang.String TAG = "ProtoOutputStream";
+    field public static final int WIRE_TYPE_END_GROUP = 4; // 0x4
+    field public static final int WIRE_TYPE_FIXED32 = 5; // 0x5
+    field public static final int WIRE_TYPE_FIXED64 = 1; // 0x1
+    field public static final int WIRE_TYPE_LENGTH_DELIMITED = 2; // 0x2
+    field public static final int WIRE_TYPE_MASK = 7; // 0x7
+    field public static final int WIRE_TYPE_START_GROUP = 3; // 0x3
+    field public static final int WIRE_TYPE_VARINT = 0; // 0x0
+  }
+
+  public class ProtoParseException extends java.lang.RuntimeException {
+    ctor public ProtoParseException(java.lang.String);
+  }
+
+}
+
 package android.view {
 
   public abstract class AbsSavedState implements android.os.Parcelable {
@@ -45926,6 +46087,7 @@
     method public deprecated void freeMemory();
     method public android.net.http.SslCertificate getCertificate();
     method public int getContentHeight();
+    method public static android.content.pm.PackageInfo getCurrentWebViewPackage();
     method public android.graphics.Bitmap getFavicon();
     method public android.webkit.WebView.HitTestResult getHitTestResult();
     method public deprecated java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
@@ -47564,6 +47726,7 @@
     method public android.graphics.PorterDuff.Mode getIndeterminateTintMode();
     method public android.view.animation.Interpolator getInterpolator();
     method public synchronized int getMax();
+    method public synchronized int getMin();
     method public synchronized int getProgress();
     method public android.content.res.ColorStateList getProgressBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getProgressBackgroundTintMode();
@@ -47586,6 +47749,7 @@
     method public void setInterpolator(android.content.Context, int);
     method public void setInterpolator(android.view.animation.Interpolator);
     method public synchronized void setMax(int);
+    method public synchronized void setMin(int);
     method public synchronized void setProgress(int);
     method public void setProgress(int, boolean);
     method public void setProgressBackgroundTintList(android.content.res.ColorStateList);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 3759de2..e197bfc 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -63,6 +63,7 @@
 import android.text.TextUtils;
 import android.util.AndroidException;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.view.IWindowManager;
 
 import com.android.internal.os.BaseCommand;
@@ -385,78 +386,12 @@
 
         String op = nextArgRequired();
 
-        if (op.equals("start")) {
-            runAmCmd(getRawArgs());
-        } else if (op.equals("startservice")) {
-            runStartService();
-        } else if (op.equals("stopservice")) {
-            runStopService();
-        } else if (op.equals("force-stop") || op.equals("kill") || op.equals("kill-all")) {
-            runAmCmd(getRawArgs());
+        if (op.equals("broadcast")) {
+            sendBroadcast();
         } else if (op.equals("instrument")) {
             runInstrument();
-        } else if (op.equals("trace-ipc")) {
-            runTraceIpc();
-        } else if (op.equals("broadcast")) {
-            sendBroadcast();
-        } else if (op.equals("profile")) {
-            runProfile();
-        } else if (op.equals("dumpheap")) {
-            runDumpHeap();
-        } else if (op.equals("set-debug-app")) {
-            runSetDebugApp();
-        } else if (op.equals("clear-debug-app")) {
-            runClearDebugApp();
-        } else if (op.equals("set-watch-heap")) {
-            runSetWatchHeap();
-        } else if (op.equals("clear-watch-heap")) {
-            runClearWatchHeap();
-        } else if (op.equals("bug-report")) {
-            runBugReport();
-        } else if (op.equals("monitor")) {
-            runMonitor();
-        } else if (op.equals("hang")) {
-            runHang();
-        } else if (op.equals("restart")) {
-            runRestart();
-        } else if (op.equals("idle-maintenance")) {
-            runIdleMaintenance();
-        } else if (op.equals("screen-compat")) {
-            runScreenCompat();
-        } else if (op.equals("package-importance")) {
-            runPackageImportance();
-        } else if (op.equals("to-uri")) {
-            runToUri(0);
-        } else if (op.equals("to-intent-uri")) {
-            runToUri(Intent.URI_INTENT_SCHEME);
-        } else if (op.equals("to-app-uri")) {
-            runToUri(Intent.URI_ANDROID_APP_SCHEME);
-        } else if (op.equals("switch-user")) {
-            runSwitchUser();
-        } else if (op.equals("start-user")) {
-            runStartUserInBackground();
-        } else if (op.equals("unlock-user")) {
-            runUnlockUser();
-        } else if (op.equals("stop-user")) {
-            runStopUser();
-        } else if (op.equals("stack")) {
-            runStack();
-        } else if (op.equals("task")) {
-            runTask();
-        } else if (op.equals("get-config")) {
-            runGetConfig();
-        } else if (op.equals("suppress-resize-config-changes")) {
-            runSuppressResizeConfigChanges();
-        } else if (op.equals("set-inactive")) {
-            runSetInactive();
-        } else if (op.equals("get-inactive")) {
-            runGetInactive();
-        } else if (op.equals("send-trim-memory")) {
-            runSendTrimMemory();
-        } else if (op.equals("get-current-user")) {
-            runGetCurrentUser();
         } else {
-            showError("Error: unknown command '" + op + "'");
+            runAmCmd(getRawArgs());
         }
     }
 
@@ -473,7 +408,13 @@
     }
 
     static final class MyShellCallback extends ShellCallback {
+        boolean mActive = true;
+
         @Override public ParcelFileDescriptor onOpenOutputFile(String path, String seLinuxContext) {
+            if (!mActive) {
+                System.err.println("Open attempt after active for: " + path);
+                return null;
+            }
             File file = new File(path);
             //System.err.println("Opening file: " + file.getAbsolutePath());
             //Log.i("Am", "Opening file: " + file.getAbsolutePath());
@@ -506,12 +447,15 @@
     }
 
     void runAmCmd(String[] args) throws AndroidException {
+        final MyShellCallback cb = new MyShellCallback();
         try {
             mAm.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
-                    args, new MyShellCallback(), new ResultReceiver(null) { });
+                    args, cb, new ResultReceiver(null) { });
         } catch (RemoteException e) {
             System.err.println(NO_SYSTEM_ERROR_CODE);
             throw new AndroidException("Can't call activity manager; is the system running?");
+        } finally {
+            cb.mActive = false;
         }
     }
 
@@ -550,7 +494,7 @@
                 } else if (opt.equals("--track-allocation")) {
                     mStartFlags |= ActivityManager.START_FLAG_TRACK_ALLOCATION;
                 } else if (opt.equals("--user")) {
-                    mUserId = parseUserArg(nextArgRequired());
+                    mUserId = UserHandle.parseUserArg(nextArgRequired());
                 } else if (opt.equals("--receiver-permission")) {
                     mReceiverPermission = nextArgRequired();
                 } else if (opt.equals("--stack")) {
@@ -563,38 +507,28 @@
         });
     }
 
-    private void runStartService() throws Exception {
-        Intent intent = makeIntent(UserHandle.USER_CURRENT);
-        if (mUserId == UserHandle.USER_ALL) {
-            System.err.println("Error: Can't start activity with user 'all'");
-            return;
-        }
-        System.out.println("Starting service: " + intent);
-        ComponentName cn = mAm.startService(null, intent, intent.getType(),
-                SHELL_PACKAGE_NAME, mUserId);
-        if (cn == null) {
-            System.err.println("Error: Not found; no service started.");
-        } else if (cn.getPackageName().equals("!")) {
-            System.err.println("Error: Requires permission " + cn.getClassName());
-        } else if (cn.getPackageName().equals("!!")) {
-            System.err.println("Error: " + cn.getClassName());
-        }
-    }
+    private class IntentReceiver extends IIntentReceiver.Stub {
+        private boolean mFinished = false;
 
-    private void runStopService() throws Exception {
-        Intent intent = makeIntent(UserHandle.USER_CURRENT);
-        if (mUserId == UserHandle.USER_ALL) {
-            System.err.println("Error: Can't stop activity with user 'all'");
-            return;
+        @Override
+        public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
+                boolean ordered, boolean sticky, int sendingUser) {
+            String line = "Broadcast completed: result=" + resultCode;
+            if (data != null) line = line + ", data=\"" + data + "\"";
+            if (extras != null) line = line + ", extras: " + extras;
+            System.out.println(line);
+            synchronized (this) {
+                mFinished = true;
+                notifyAll();
+            }
         }
-        System.out.println("Stopping service: " + intent);
-        int result = mAm.stopService(null, intent, intent.getType(), mUserId);
-        if (result == 0) {
-            System.err.println("Service not stopped: was not running.");
-        } else if (result == 1) {
-            System.err.println("Service stopped");
-        } else if (result == -1) {
-            System.err.println("Error stopping service");
+
+        public synchronized void waitForFinish() {
+            try {
+                while (!mFinished) wait();
+            } catch (InterruptedException e) {
+                throw new IllegalStateException(e);
+            }
         }
     }
 
@@ -736,773 +670,6 @@
         }
     }
 
-    private void runTraceIpc() throws Exception {
-        String op = nextArgRequired();
-        if (op.equals("start")) {
-            runTraceIpcStart();
-        } else if (op.equals("stop")) {
-            runTraceIpcStop();
-        } else {
-            showError("Error: unknown command '" + op + "'");
-            return;
-        }
-    }
-
-    private void runTraceIpcStart() throws Exception {
-        System.out.println("Starting IPC tracing.");
-        mAm.startBinderTracking();
-    }
-
-    private void runTraceIpcStop() throws Exception {
-        String opt;
-        String filename = null;
-        while ((opt=nextOption()) != null) {
-            if (opt.equals("--dump-file")) {
-                filename = nextArgRequired();
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-        if (filename == null) {
-            System.err.println("Error: Specify filename to dump logs to.");
-            return;
-        }
-
-        ParcelFileDescriptor fd = null;
-
-        try {
-            File file = new File(filename);
-            file.delete();
-            fd = openForSystemServer(file,
-                    ParcelFileDescriptor.MODE_CREATE |
-                            ParcelFileDescriptor.MODE_TRUNCATE |
-                            ParcelFileDescriptor.MODE_WRITE_ONLY);
-        } catch (FileNotFoundException e) {
-            System.err.println("Error: Unable to open file: " + filename);
-            System.err.println("Consider using a file under /data/local/tmp/");
-            return;
-        }
-
-        ;
-        if (!mAm.stopBinderTrackingAndDump(fd)) {
-            throw new AndroidException("STOP TRACE FAILED.");
-        }
-
-        System.out.println("Stopped IPC tracing. Dumping logs to: " + filename);
-    }
-
-    static void removeWallOption() {
-        String props = SystemProperties.get("dalvik.vm.extra-opts");
-        if (props != null && props.contains("-Xprofile:wallclock")) {
-            props = props.replace("-Xprofile:wallclock", "");
-            props = props.trim();
-            SystemProperties.set("dalvik.vm.extra-opts", props);
-        }
-    }
-
-    private void runProfile() throws Exception {
-        String profileFile = null;
-        boolean start = false;
-        boolean wall = false;
-        int userId = UserHandle.USER_CURRENT;
-        int profileType = 0;
-        mSamplingInterval = 0;
-
-        String process = null;
-
-        String cmd = nextArgRequired();
-
-        if ("start".equals(cmd)) {
-            start = true;
-            String opt;
-            while ((opt=nextOption()) != null) {
-                if (opt.equals("--user")) {
-                    userId = parseUserArg(nextArgRequired());
-                } else if (opt.equals("--wall")) {
-                    wall = true;
-                } else if (opt.equals("--sampling")) {
-                    mSamplingInterval = Integer.parseInt(nextArgRequired());
-                } else {
-                    System.err.println("Error: Unknown option: " + opt);
-                    return;
-                }
-            }
-            process = nextArgRequired();
-        } else if ("stop".equals(cmd)) {
-            String opt;
-            while ((opt=nextOption()) != null) {
-                if (opt.equals("--user")) {
-                    userId = parseUserArg(nextArgRequired());
-                } else {
-                    System.err.println("Error: Unknown option: " + opt);
-                    return;
-                }
-            }
-            process = nextArg();
-        } else {
-            // Compatibility with old syntax: process is specified first.
-            process = cmd;
-            cmd = nextArgRequired();
-            if ("start".equals(cmd)) {
-                start = true;
-            } else if (!"stop".equals(cmd)) {
-                throw new IllegalArgumentException("Profile command " + process + " not valid");
-            }
-        }
-
-        if (userId == UserHandle.USER_ALL) {
-            System.err.println("Error: Can't profile with user 'all'");
-            return;
-        }
-
-        ParcelFileDescriptor fd = null;
-        ProfilerInfo profilerInfo = null;
-
-        if (start) {
-            profileFile = nextArgRequired();
-            try {
-                fd = openForSystemServer(
-                        new File(profileFile),
-                        ParcelFileDescriptor.MODE_CREATE |
-                        ParcelFileDescriptor.MODE_TRUNCATE |
-                        ParcelFileDescriptor.MODE_WRITE_ONLY);
-            } catch (FileNotFoundException e) {
-                System.err.println("Error: Unable to open file: " + profileFile);
-                System.err.println("Consider using a file under /data/local/tmp/");
-                return;
-            }
-            profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false);
-        }
-
-        try {
-            if (wall) {
-                // XXX doesn't work -- this needs to be set before booting.
-                String props = SystemProperties.get("dalvik.vm.extra-opts");
-                if (props == null || !props.contains("-Xprofile:wallclock")) {
-                    props = props + " -Xprofile:wallclock";
-                    //SystemProperties.set("dalvik.vm.extra-opts", props);
-                }
-            } else if (start) {
-                //removeWallOption();
-            }
-            if (!mAm.profileControl(process, userId, start, profilerInfo, profileType)) {
-                wall = false;
-                throw new AndroidException("PROFILE FAILED on process " + process);
-            }
-        } finally {
-            if (!wall) {
-                //removeWallOption();
-            }
-        }
-    }
-
-    private void runDumpHeap() throws Exception {
-        boolean managed = true;
-        int userId = UserHandle.USER_CURRENT;
-
-        String opt;
-        while ((opt=nextOption()) != null) {
-            if (opt.equals("--user")) {
-                userId = parseUserArg(nextArgRequired());
-                if (userId == UserHandle.USER_ALL) {
-                    System.err.println("Error: Can't dump heap with user 'all'");
-                    return;
-                }
-            } else if (opt.equals("-n")) {
-                managed = false;
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-        String process = nextArgRequired();
-        String heapFile = nextArgRequired();
-        ParcelFileDescriptor fd = null;
-
-        try {
-            File file = new File(heapFile);
-            file.delete();
-            fd = openForSystemServer(file,
-                    ParcelFileDescriptor.MODE_CREATE |
-                    ParcelFileDescriptor.MODE_TRUNCATE |
-                    ParcelFileDescriptor.MODE_WRITE_ONLY);
-        } catch (FileNotFoundException e) {
-            System.err.println("Error: Unable to open file: " + heapFile);
-            System.err.println("Consider using a file under /data/local/tmp/");
-            return;
-        }
-
-        if (!mAm.dumpHeap(process, userId, managed, heapFile, fd)) {
-            throw new AndroidException("HEAP DUMP FAILED on process " + process);
-        }
-    }
-
-    private void runSetDebugApp() throws Exception {
-        boolean wait = false;
-        boolean persistent = false;
-
-        String opt;
-        while ((opt=nextOption()) != null) {
-            if (opt.equals("-w")) {
-                wait = true;
-            } else if (opt.equals("--persistent")) {
-                persistent = true;
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-
-        String pkg = nextArgRequired();
-        mAm.setDebugApp(pkg, wait, persistent);
-    }
-
-    private void runClearDebugApp() throws Exception {
-        mAm.setDebugApp(null, false, true);
-    }
-
-    private void runSetWatchHeap() throws Exception {
-        String proc = nextArgRequired();
-        String limit = nextArgRequired();
-        mAm.setDumpHeapDebugLimit(proc, 0, Long.parseLong(limit), null);
-    }
-
-    private void runClearWatchHeap() throws Exception {
-        String proc = nextArgRequired();
-        mAm.setDumpHeapDebugLimit(proc, 0, -1, null);
-    }
-
-    private void runBugReport() throws Exception {
-        String opt;
-        int bugreportType = ActivityManager.BUGREPORT_OPTION_FULL;
-        while ((opt=nextOption()) != null) {
-            if (opt.equals("--progress")) {
-                bugreportType = ActivityManager.BUGREPORT_OPTION_INTERACTIVE;
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-        mAm.requestBugReport(bugreportType);
-        System.out.println("Your lovely bug report is being created; please be patient.");
-    }
-
-    private void runSwitchUser() throws Exception {
-        String user = nextArgRequired();
-        mAm.switchUser(Integer.parseInt(user));
-    }
-
-    private void runStartUserInBackground() throws Exception {
-        String user = nextArgRequired();
-        boolean success = mAm.startUserInBackground(Integer.parseInt(user));
-        if (success) {
-            System.out.println("Success: user started");
-        } else {
-            System.err.println("Error: could not start user");
-        }
-    }
-
-    private byte[] argToBytes(String arg) {
-        if (arg.equals("!")) {
-            return null;
-        } else {
-            return HexDump.hexStringToByteArray(arg);
-        }
-    }
-
-    private void runUnlockUser() throws Exception {
-        int userId = Integer.parseInt(nextArgRequired());
-        byte[] token = argToBytes(nextArgRequired());
-        byte[] secret = argToBytes(nextArgRequired());
-        boolean success = mAm.unlockUser(userId, token, secret, null);
-        if (success) {
-            System.out.println("Success: user unlocked");
-        } else {
-            System.err.println("Error: could not unlock user");
-        }
-    }
-
-    private static class StopUserCallback extends IStopUserCallback.Stub {
-        private boolean mFinished = false;
-
-        public synchronized void waitForFinish() {
-            try {
-                while (!mFinished) wait();
-            } catch (InterruptedException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-
-        @Override
-        public synchronized void userStopped(int userId) {
-            mFinished = true;
-            notifyAll();
-        }
-
-        @Override
-        public synchronized void userStopAborted(int userId) {
-            mFinished = true;
-            notifyAll();
-        }
-    }
-
-    private void runStopUser() throws Exception {
-        boolean wait = false;
-        boolean force = false;
-        String opt;
-        while ((opt = nextOption()) != null) {
-            if ("-w".equals(opt)) {
-                wait = true;
-            } else if ("-f".equals(opt)) {
-                force = true;
-            } else {
-                System.err.println("Error: unknown option: " + opt);
-                return;
-            }
-        }
-        int user = Integer.parseInt(nextArgRequired());
-        StopUserCallback callback = wait ? new StopUserCallback() : null;
-
-        int res = mAm.stopUser(user, force, callback);
-        if (res != ActivityManager.USER_OP_SUCCESS) {
-            String txt = "";
-            switch (res) {
-                case ActivityManager.USER_OP_IS_CURRENT:
-                    txt = " (Can't stop current user)";
-                    break;
-                case ActivityManager.USER_OP_UNKNOWN_USER:
-                    txt = " (Unknown user " + user + ")";
-                    break;
-                case ActivityManager.USER_OP_ERROR_IS_SYSTEM:
-                    txt = " (System user cannot be stopped)";
-                    break;
-                case ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP:
-                    txt = " (Can't stop user " + user
-                            + " - one of its related users can't be stopped)";
-                    break;
-            }
-            System.err.println("Switch failed: " + res + txt);
-        } else if (callback != null) {
-            callback.waitForFinish();
-        }
-    }
-
-    class MyActivityController extends IActivityController.Stub {
-        final String mGdbPort;
-        final boolean mMonkey;
-
-        static final int STATE_NORMAL = 0;
-        static final int STATE_CRASHED = 1;
-        static final int STATE_EARLY_ANR = 2;
-        static final int STATE_ANR = 3;
-
-        int mState;
-
-        static final int RESULT_DEFAULT = 0;
-
-        static final int RESULT_CRASH_DIALOG = 0;
-        static final int RESULT_CRASH_KILL = 1;
-
-        static final int RESULT_EARLY_ANR_CONTINUE = 0;
-        static final int RESULT_EARLY_ANR_KILL = 1;
-
-        static final int RESULT_ANR_DIALOG = 0;
-        static final int RESULT_ANR_KILL = 1;
-        static final int RESULT_ANR_WAIT = 1;
-
-        int mResult;
-
-        Process mGdbProcess;
-        Thread mGdbThread;
-        boolean mGotGdbPrint;
-
-        MyActivityController(String gdbPort, boolean monkey) {
-            mGdbPort = gdbPort;
-            mMonkey = monkey;
-        }
-
-        @Override
-        public boolean activityResuming(String pkg) {
-            synchronized (this) {
-                System.out.println("** Activity resuming: " + pkg);
-            }
-            return true;
-        }
-
-        @Override
-        public boolean activityStarting(Intent intent, String pkg) {
-            synchronized (this) {
-                System.out.println("** Activity starting: " + pkg);
-            }
-            return true;
-        }
-
-        @Override
-        public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg,
-                long timeMillis, String stackTrace) {
-            synchronized (this) {
-                System.out.println("** ERROR: PROCESS CRASHED");
-                System.out.println("processName: " + processName);
-                System.out.println("processPid: " + pid);
-                System.out.println("shortMsg: " + shortMsg);
-                System.out.println("longMsg: " + longMsg);
-                System.out.println("timeMillis: " + timeMillis);
-                System.out.println("stack:");
-                System.out.print(stackTrace);
-                System.out.println("#");
-                int result = waitControllerLocked(pid, STATE_CRASHED);
-                return result == RESULT_CRASH_KILL ? false : true;
-            }
-        }
-
-        @Override
-        public int appEarlyNotResponding(String processName, int pid, String annotation) {
-            synchronized (this) {
-                System.out.println("** ERROR: EARLY PROCESS NOT RESPONDING");
-                System.out.println("processName: " + processName);
-                System.out.println("processPid: " + pid);
-                System.out.println("annotation: " + annotation);
-                int result = waitControllerLocked(pid, STATE_EARLY_ANR);
-                if (result == RESULT_EARLY_ANR_KILL) return -1;
-                return 0;
-            }
-        }
-
-        @Override
-        public int appNotResponding(String processName, int pid, String processStats) {
-            synchronized (this) {
-                System.out.println("** ERROR: PROCESS NOT RESPONDING");
-                System.out.println("processName: " + processName);
-                System.out.println("processPid: " + pid);
-                System.out.println("processStats:");
-                System.out.print(processStats);
-                System.out.println("#");
-                int result = waitControllerLocked(pid, STATE_ANR);
-                if (result == RESULT_ANR_KILL) return -1;
-                if (result == RESULT_ANR_WAIT) return 1;
-                return 0;
-            }
-        }
-
-        @Override
-        public int systemNotResponding(String message) {
-            synchronized (this) {
-                System.out.println("** ERROR: PROCESS NOT RESPONDING");
-                System.out.println("message: " + message);
-                System.out.println("#");
-                System.out.println("Allowing system to die.");
-                return -1;
-            }
-        }
-
-        void killGdbLocked() {
-            mGotGdbPrint = false;
-            if (mGdbProcess != null) {
-                System.out.println("Stopping gdbserver");
-                mGdbProcess.destroy();
-                mGdbProcess = null;
-            }
-            if (mGdbThread != null) {
-                mGdbThread.interrupt();
-                mGdbThread = null;
-            }
-        }
-
-        int waitControllerLocked(int pid, int state) {
-            if (mGdbPort != null) {
-                killGdbLocked();
-
-                try {
-                    System.out.println("Starting gdbserver on port " + mGdbPort);
-                    System.out.println("Do the following:");
-                    System.out.println("  adb forward tcp:" + mGdbPort + " tcp:" + mGdbPort);
-                    System.out.println("  gdbclient app_process :" + mGdbPort);
-
-                    mGdbProcess = Runtime.getRuntime().exec(new String[] {
-                            "gdbserver", ":" + mGdbPort, "--attach", Integer.toString(pid)
-                    });
-                    final InputStreamReader converter = new InputStreamReader(
-                            mGdbProcess.getInputStream());
-                    mGdbThread = new Thread() {
-                        @Override
-                        public void run() {
-                            BufferedReader in = new BufferedReader(converter);
-                            String line;
-                            int count = 0;
-                            while (true) {
-                                synchronized (MyActivityController.this) {
-                                    if (mGdbThread == null) {
-                                        return;
-                                    }
-                                    if (count == 2) {
-                                        mGotGdbPrint = true;
-                                        MyActivityController.this.notifyAll();
-                                    }
-                                }
-                                try {
-                                    line = in.readLine();
-                                    if (line == null) {
-                                        return;
-                                    }
-                                    System.out.println("GDB: " + line);
-                                    count++;
-                                } catch (IOException e) {
-                                    return;
-                                }
-                            }
-                        }
-                    };
-                    mGdbThread.start();
-
-                    // Stupid waiting for .5s.  Doesn't matter if we end early.
-                    try {
-                        this.wait(500);
-                    } catch (InterruptedException e) {
-                    }
-
-                } catch (IOException e) {
-                    System.err.println("Failure starting gdbserver: " + e);
-                    killGdbLocked();
-                }
-            }
-            mState = state;
-            System.out.println("");
-            printMessageForState();
-
-            while (mState != STATE_NORMAL) {
-                try {
-                    wait();
-                } catch (InterruptedException e) {
-                }
-            }
-
-            killGdbLocked();
-
-            return mResult;
-        }
-
-        void resumeController(int result) {
-            synchronized (this) {
-                mState = STATE_NORMAL;
-                mResult = result;
-                notifyAll();
-            }
-        }
-
-        void printMessageForState() {
-            switch (mState) {
-                case STATE_NORMAL:
-                    System.out.println("Monitoring activity manager...  available commands:");
-                    break;
-                case STATE_CRASHED:
-                    System.out.println("Waiting after crash...  available commands:");
-                    System.out.println("(c)ontinue: show crash dialog");
-                    System.out.println("(k)ill: immediately kill app");
-                    break;
-                case STATE_EARLY_ANR:
-                    System.out.println("Waiting after early ANR...  available commands:");
-                    System.out.println("(c)ontinue: standard ANR processing");
-                    System.out.println("(k)ill: immediately kill app");
-                    break;
-                case STATE_ANR:
-                    System.out.println("Waiting after ANR...  available commands:");
-                    System.out.println("(c)ontinue: show ANR dialog");
-                    System.out.println("(k)ill: immediately kill app");
-                    System.out.println("(w)ait: wait some more");
-                    break;
-            }
-            System.out.println("(q)uit: finish monitoring");
-        }
-
-        void run() throws RemoteException {
-            try {
-                printMessageForState();
-
-                mAm.setActivityController(this, mMonkey);
-                mState = STATE_NORMAL;
-
-                InputStreamReader converter = new InputStreamReader(System.in);
-                BufferedReader in = new BufferedReader(converter);
-                String line;
-
-                while ((line = in.readLine()) != null) {
-                    boolean addNewline = true;
-                    if (line.length() <= 0) {
-                        addNewline = false;
-                    } else if ("q".equals(line) || "quit".equals(line)) {
-                        resumeController(RESULT_DEFAULT);
-                        break;
-                    } else if (mState == STATE_CRASHED) {
-                        if ("c".equals(line) || "continue".equals(line)) {
-                            resumeController(RESULT_CRASH_DIALOG);
-                        } else if ("k".equals(line) || "kill".equals(line)) {
-                            resumeController(RESULT_CRASH_KILL);
-                        } else {
-                            System.out.println("Invalid command: " + line);
-                        }
-                    } else if (mState == STATE_ANR) {
-                        if ("c".equals(line) || "continue".equals(line)) {
-                            resumeController(RESULT_ANR_DIALOG);
-                        } else if ("k".equals(line) || "kill".equals(line)) {
-                            resumeController(RESULT_ANR_KILL);
-                        } else if ("w".equals(line) || "wait".equals(line)) {
-                            resumeController(RESULT_ANR_WAIT);
-                        } else {
-                            System.out.println("Invalid command: " + line);
-                        }
-                    } else if (mState == STATE_EARLY_ANR) {
-                        if ("c".equals(line) || "continue".equals(line)) {
-                            resumeController(RESULT_EARLY_ANR_CONTINUE);
-                        } else if ("k".equals(line) || "kill".equals(line)) {
-                            resumeController(RESULT_EARLY_ANR_KILL);
-                        } else {
-                            System.out.println("Invalid command: " + line);
-                        }
-                    } else {
-                        System.out.println("Invalid command: " + line);
-                    }
-
-                    synchronized (this) {
-                        if (addNewline) {
-                            System.out.println("");
-                        }
-                        printMessageForState();
-                    }
-                }
-
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                mAm.setActivityController(null, mMonkey);
-            }
-        }
-    }
-
-    private void runMonitor() throws Exception {
-        String opt;
-        String gdbPort = null;
-        boolean monkey = false;
-        while ((opt=nextOption()) != null) {
-            if (opt.equals("--gdb")) {
-                gdbPort = nextArgRequired();
-            } else if (opt.equals("-m")) {
-                monkey = true;
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-
-        MyActivityController controller = new MyActivityController(gdbPort, monkey);
-        controller.run();
-    }
-
-    private void runHang() throws Exception {
-        String opt;
-        boolean allowRestart = false;
-        while ((opt=nextOption()) != null) {
-            if (opt.equals("--allow-restart")) {
-                allowRestart = true;
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-
-        System.out.println("Hanging the system...");
-        mAm.hang(new Binder(), allowRestart);
-    }
-
-    private void runRestart() throws Exception {
-        String opt;
-        while ((opt=nextOption()) != null) {
-            System.err.println("Error: Unknown option: " + opt);
-            return;
-        }
-
-        System.out.println("Restart the system...");
-        mAm.restart();
-    }
-
-    private void runIdleMaintenance() throws Exception {
-        String opt;
-        while ((opt=nextOption()) != null) {
-            System.err.println("Error: Unknown option: " + opt);
-            return;
-        }
-
-        System.out.println("Performing idle maintenance...");
-        try {
-            mAm.sendIdleJobTrigger();
-        } catch (RemoteException e) {
-        }
-    }
-
-    private void runScreenCompat() throws Exception {
-        String mode = nextArgRequired();
-        boolean enabled;
-        if ("on".equals(mode)) {
-            enabled = true;
-        } else if ("off".equals(mode)) {
-            enabled = false;
-        } else {
-            System.err.println("Error: enabled mode must be 'on' or 'off' at " + mode);
-            return;
-        }
-
-        String packageName = nextArgRequired();
-        do {
-            try {
-                mAm.setPackageScreenCompatMode(packageName, enabled
-                        ? ActivityManager.COMPAT_MODE_ENABLED
-                        : ActivityManager.COMPAT_MODE_DISABLED);
-            } catch (RemoteException e) {
-            }
-            packageName = nextArg();
-        } while (packageName != null);
-    }
-
-    private void runPackageImportance() throws Exception {
-        String packageName = nextArgRequired();
-        try {
-            int procState = mAm.getPackageProcessState(packageName, "com.android.shell");
-            System.out.println(
-                    ActivityManager.RunningAppProcessInfo.procStateToImportance(procState));
-        } catch (RemoteException e) {
-        }
-    }
-
-    private void runToUri(int flags) throws Exception {
-        Intent intent = makeIntent(UserHandle.USER_CURRENT);
-        System.out.println(intent.toUri(flags));
-    }
-
-    private class IntentReceiver extends IIntentReceiver.Stub {
-        private boolean mFinished = false;
-
-        @Override
-        public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
-                boolean ordered, boolean sticky, int sendingUser) {
-            String line = "Broadcast completed: result=" + resultCode;
-            if (data != null) line = line + ", data=\"" + data + "\"";
-            if (extras != null) line = line + ", extras: " + extras;
-            System.out.println(line);
-            synchronized (this) {
-              mFinished = true;
-              notifyAll();
-            }
-        }
-
-        public synchronized void waitForFinish() {
-            try {
-                while (!mFinished) wait();
-            } catch (InterruptedException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-    }
-
     private class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
         private boolean mFinished = false;
         private boolean mRawMode = false;
@@ -1580,833 +747,4 @@
             return true;
         }
     }
-
-    private void runStack() throws Exception {
-        String op = nextArgRequired();
-        switch (op) {
-            case "start":
-                runStackStart();
-                break;
-            case "movetask":
-                runStackMoveTask();
-                break;
-            case "resize":
-                runStackResize();
-                break;
-            case "resize-animated":
-                runStackResizeAnimated();
-                break;
-            case "resize-docked-stack":
-                runStackResizeDocked();
-                break;
-            case "positiontask":
-                runStackPositionTask();
-                break;
-            case "list":
-                runStackList();
-                break;
-            case "info":
-                runStackInfo();
-                break;
-            case "move-top-activity-to-pinned-stack":
-                runMoveTopActivityToPinnedStack();
-                break;
-            case "size-docked-stack-test":
-                runStackSizeDockedStackTest();
-                break;
-            case "remove":
-                runStackRemove();
-                break;
-            default:
-                showError("Error: unknown command '" + op + "'");
-                break;
-        }
-    }
-
-    private void runStackStart() throws Exception {
-        String displayIdStr = nextArgRequired();
-        int displayId = Integer.parseInt(displayIdStr);
-        Intent intent = makeIntent(UserHandle.USER_CURRENT);
-
-        try {
-            IActivityContainer container = mAm.createStackOnDisplay(displayId);
-            if (container != null) {
-                container.startActivity(intent);
-            }
-        } catch (RemoteException e) {
-        }
-    }
-
-    private void runStackMoveTask() throws Exception {
-        String taskIdStr = nextArgRequired();
-        int taskId = Integer.parseInt(taskIdStr);
-        String stackIdStr = nextArgRequired();
-        int stackId = Integer.parseInt(stackIdStr);
-        String toTopStr = nextArgRequired();
-        final boolean toTop;
-        if ("true".equals(toTopStr)) {
-            toTop = true;
-        } else if ("false".equals(toTopStr)) {
-            toTop = false;
-        } else {
-            System.err.println("Error: bad toTop arg: " + toTopStr);
-            return;
-        }
-
-        try {
-            mAm.moveTaskToStack(taskId, stackId, toTop);
-        } catch (RemoteException e) {
-        }
-    }
-
-    private void runStackResize() throws Exception {
-        String stackIdStr = nextArgRequired();
-        int stackId = Integer.parseInt(stackIdStr);
-        final Rect bounds = getBounds();
-        if (bounds == null) {
-            System.err.println("Error: invalid input bounds");
-            return;
-        }
-        resizeStack(stackId, bounds, 0);
-    }
-
-    private void runStackResizeAnimated() throws Exception {
-        String stackIdStr = nextArgRequired();
-        int stackId = Integer.parseInt(stackIdStr);
-        final Rect bounds;
-        if ("null".equals(mArgs.peekNextArg())) {
-            bounds = null;
-        } else {
-            bounds = getBounds();
-            if (bounds == null) {
-                System.err.println("Error: invalid input bounds");
-                return;
-            }
-        }
-        resizeStackUnchecked(stackId, bounds, 0, true);
-    }
-
-    private void resizeStackUnchecked(int stackId, Rect bounds, int delayMs, boolean animate) {
-        try {
-            mAm.resizeStack(stackId, bounds, false, false, animate, -1);
-            Thread.sleep(delayMs);
-        } catch (RemoteException e) {
-            showError("Error: resizing stack " + e);
-        } catch (InterruptedException e) {
-        }
-    }
-
-    private void runStackResizeDocked() throws Exception {
-        final Rect bounds = getBounds();
-        final Rect taskBounds = getBounds();
-        if (bounds == null || taskBounds == null) {
-            System.err.println("Error: invalid input bounds");
-            return;
-        }
-        try {
-            mAm.resizeDockedStack(bounds, taskBounds, null, null, null);
-        } catch (RemoteException e) {
-            showError("Error: resizing docked stack " + e);
-        }
-    }
-
-    private void resizeStack(int stackId, Rect bounds, int delayMs)
-            throws Exception {
-        if (bounds == null) {
-            showError("Error: invalid input bounds");
-            return;
-        }
-        resizeStackUnchecked(stackId, bounds, delayMs, false);
-    }
-
-    private void runStackPositionTask() throws Exception {
-        String taskIdStr = nextArgRequired();
-        int taskId = Integer.parseInt(taskIdStr);
-        String stackIdStr = nextArgRequired();
-        int stackId = Integer.parseInt(stackIdStr);
-        String positionStr = nextArgRequired();
-        int position = Integer.parseInt(positionStr);
-
-        try {
-            mAm.positionTaskInStack(taskId, stackId, position);
-        } catch (RemoteException e) {
-        }
-    }
-
-    private void runStackList() throws Exception {
-        try {
-            List<StackInfo> stacks = mAm.getAllStackInfos();
-            for (StackInfo info : stacks) {
-                System.out.println(info);
-            }
-        } catch (RemoteException e) {
-        }
-    }
-
-    private void runStackInfo() throws Exception {
-        try {
-            String stackIdStr = nextArgRequired();
-            int stackId = Integer.parseInt(stackIdStr);
-            StackInfo info = mAm.getStackInfo(stackId);
-            System.out.println(info);
-        } catch (RemoteException e) {
-        }
-    }
-
-    private void runStackRemove() throws Exception {
-        String stackIdStr = nextArgRequired();
-        int stackId = Integer.parseInt(stackIdStr);
-        mAm.removeStack(stackId);
-    }
-
-    private void runMoveTopActivityToPinnedStack() throws Exception {
-        int stackId = Integer.parseInt(nextArgRequired());
-        final Rect bounds = getBounds();
-        if (bounds == null) {
-            System.err.println("Error: invalid input bounds");
-            return;
-        }
-
-        try {
-            if (!mAm.moveTopActivityToPinnedStack(stackId, bounds)) {
-                showError("Didn't move top activity to pinned stack.");
-            }
-        } catch (RemoteException e) {
-            showError("Unable to move top activity: " + e);
-            return;
-        }
-    }
-
-    private void runStackSizeDockedStackTest() throws Exception {
-        final int stepSize = Integer.parseInt(nextArgRequired());
-        final String side = nextArgRequired();
-        final String delayStr = nextArg();
-        final int delayMs = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
-
-        Rect bounds;
-        try {
-            StackInfo info = mAm.getStackInfo(DOCKED_STACK_ID);
-            if (info == null) {
-                showError("Docked stack doesn't exist");
-                return;
-            }
-            if (info.bounds == null) {
-                showError("Docked stack doesn't have a bounds");
-                return;
-            }
-            bounds = info.bounds;
-        } catch (RemoteException e) {
-            showError("Unable to get docked stack info:" + e);
-            return;
-        }
-
-        final boolean horizontalGrowth = "l".equals(side) || "r".equals(side);
-        final int changeSize = (horizontalGrowth ? bounds.width() : bounds.height()) / 2;
-        int currentPoint;
-        switch (side) {
-            case "l":
-                currentPoint = bounds.left;
-                break;
-            case "r":
-                currentPoint = bounds.right;
-                break;
-            case "t":
-                currentPoint = bounds.top;
-                break;
-            case "b":
-                currentPoint = bounds.bottom;
-                break;
-            default:
-                showError("Unknown growth side: " + side);
-                return;
-        }
-
-        final int startPoint = currentPoint;
-        final int minPoint = currentPoint - changeSize;
-        final int maxPoint = currentPoint + changeSize;
-
-        int maxChange;
-        System.out.println("Shrinking docked stack side=" + side);
-        while (currentPoint > minPoint) {
-            maxChange = Math.min(stepSize, currentPoint - minPoint);
-            currentPoint -= maxChange;
-            setBoundsSide(bounds, side, currentPoint);
-            resizeStack(DOCKED_STACK_ID, bounds, delayMs);
-        }
-
-        System.out.println("Growing docked stack side=" + side);
-        while (currentPoint < maxPoint) {
-            maxChange = Math.min(stepSize, maxPoint - currentPoint);
-            currentPoint += maxChange;
-            setBoundsSide(bounds, side, currentPoint);
-            resizeStack(DOCKED_STACK_ID, bounds, delayMs);
-        }
-
-        System.out.println("Back to Original size side=" + side);
-        while (currentPoint > startPoint) {
-            maxChange = Math.min(stepSize, currentPoint - startPoint);
-            currentPoint -= maxChange;
-            setBoundsSide(bounds, side, currentPoint);
-            resizeStack(DOCKED_STACK_ID, bounds, delayMs);
-        }
-    }
-
-    private void setBoundsSide(Rect bounds, String side, int value) {
-        switch (side) {
-            case "l":
-                bounds.left = value;
-                break;
-            case "r":
-                bounds.right = value;
-                break;
-            case "t":
-                bounds.top = value;
-                break;
-            case "b":
-                bounds.bottom = value;
-                break;
-            default:
-                showError("Unknown set side: " + side);
-                break;
-        }
-    }
-
-    private void runTask() throws Exception {
-        String op = nextArgRequired();
-        if (op.equals("lock")) {
-            runTaskLock();
-        } else if (op.equals("resizeable")) {
-            runTaskResizeable();
-        } else if (op.equals("resize")) {
-            runTaskResize();
-        } else if (op.equals("drag-task-test")) {
-            runTaskDragTaskTest();
-        } else if (op.equals("size-task-test")) {
-            runTaskSizeTaskTest();
-        } else {
-            showError("Error: unknown command '" + op + "'");
-            return;
-        }
-    }
-
-    private void runTaskLock() throws Exception {
-        String taskIdStr = nextArgRequired();
-        try {
-            if (taskIdStr.equals("stop")) {
-                mAm.stopLockTaskMode();
-            } else {
-                int taskId = Integer.parseInt(taskIdStr);
-                mAm.startLockTaskMode(taskId);
-            }
-            System.err.println("Activity manager is " + (mAm.isInLockTaskMode() ? "" : "not ") +
-                    "in lockTaskMode");
-        } catch (RemoteException e) {
-        }
-    }
-
-    private void runTaskResizeable() throws Exception {
-        final String taskIdStr = nextArgRequired();
-        final int taskId = Integer.parseInt(taskIdStr);
-        final String resizeableStr = nextArgRequired();
-        final int resizeableMode = Integer.parseInt(resizeableStr);
-
-        try {
-            mAm.setTaskResizeable(taskId, resizeableMode);
-        } catch (RemoteException e) {
-        }
-    }
-
-    private void runTaskResize() throws Exception {
-        final String taskIdStr = nextArgRequired();
-        final int taskId = Integer.parseInt(taskIdStr);
-        final Rect bounds = getBounds();
-        if (bounds == null) {
-            System.err.println("Error: invalid input bounds");
-            return;
-        }
-        taskResize(taskId, bounds, 0, false);
-    }
-
-    private void taskResize(int taskId, Rect bounds, int delay_ms, boolean pretendUserResize) {
-        try {
-            final int resizeMode = pretendUserResize ? RESIZE_MODE_USER : RESIZE_MODE_SYSTEM;
-            mAm.resizeTask(taskId, bounds, resizeMode);
-            Thread.sleep(delay_ms);
-        } catch (RemoteException e) {
-            System.err.println("Error changing task bounds: " + e);
-        } catch (InterruptedException e) {
-        }
-    }
-
-    private void runTaskDragTaskTest() {
-        final int taskId = Integer.parseInt(nextArgRequired());
-        final int stepSize = Integer.parseInt(nextArgRequired());
-        final String delayStr = nextArg();
-        final int delay_ms = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
-        final StackInfo stackInfo;
-        Rect taskBounds;
-        try {
-            stackInfo = mAm.getStackInfo(mAm.getFocusedStackId());
-            taskBounds = mAm.getTaskBounds(taskId);
-        } catch (RemoteException e) {
-            System.err.println("Error getting focus stack info or task bounds: " + e);
-            return;
-        }
-        final Rect stackBounds = stackInfo.bounds;
-        int travelRight = stackBounds.width() - taskBounds.width();
-        int travelLeft = -travelRight;
-        int travelDown = stackBounds.height() - taskBounds.height();
-        int travelUp = -travelDown;
-        int passes = 0;
-
-        // We do 2 passes to get back to the original location of the task.
-        while (passes < 2) {
-            // Move right
-            System.out.println("Moving right...");
-            travelRight = moveTask(taskId, taskBounds, stackBounds, stepSize,
-                    travelRight, MOVING_FORWARD, MOVING_HORIZONTALLY, delay_ms);
-            System.out.println("Still need to travel right by " + travelRight);
-
-            // Move down
-            System.out.println("Moving down...");
-            travelDown = moveTask(taskId, taskBounds, stackBounds, stepSize,
-                    travelDown, MOVING_FORWARD, !MOVING_HORIZONTALLY, delay_ms);
-            System.out.println("Still need to travel down by " + travelDown);
-
-            // Move left
-            System.out.println("Moving left...");
-            travelLeft = moveTask(taskId, taskBounds, stackBounds, stepSize,
-                    travelLeft, !MOVING_FORWARD, MOVING_HORIZONTALLY, delay_ms);
-            System.out.println("Still need to travel left by " + travelLeft);
-
-            // Move up
-            System.out.println("Moving up...");
-            travelUp = moveTask(taskId, taskBounds, stackBounds, stepSize,
-                    travelUp, !MOVING_FORWARD, !MOVING_HORIZONTALLY, delay_ms);
-            System.out.println("Still need to travel up by " + travelUp);
-
-            try {
-                taskBounds = mAm.getTaskBounds(taskId);
-            } catch (RemoteException e) {
-                System.err.println("Error getting task bounds: " + e);
-                return;
-            }
-            passes++;
-        }
-    }
-
-    private int moveTask(int taskId, Rect taskRect, Rect stackRect, int stepSize,
-            int maxToTravel, boolean movingForward, boolean horizontal, int delay_ms) {
-        int maxMove;
-        if (movingForward) {
-            while (maxToTravel > 0
-                    && ((horizontal && taskRect.right < stackRect.right)
-                        ||(!horizontal && taskRect.bottom < stackRect.bottom))) {
-                if (horizontal) {
-                    maxMove = Math.min(stepSize, stackRect.right - taskRect.right);
-                    maxToTravel -= maxMove;
-                    taskRect.right += maxMove;
-                    taskRect.left += maxMove;
-                } else {
-                    maxMove = Math.min(stepSize, stackRect.bottom - taskRect.bottom);
-                    maxToTravel -= maxMove;
-                    taskRect.top += maxMove;
-                    taskRect.bottom += maxMove;
-                }
-                taskResize(taskId, taskRect, delay_ms, false);
-            }
-        } else {
-            while (maxToTravel < 0
-                    && ((horizontal && taskRect.left > stackRect.left)
-                    ||(!horizontal && taskRect.top > stackRect.top))) {
-                if (horizontal) {
-                    maxMove = Math.min(stepSize, taskRect.left - stackRect.left);
-                    maxToTravel -= maxMove;
-                    taskRect.right -= maxMove;
-                    taskRect.left -= maxMove;
-                } else {
-                    maxMove = Math.min(stepSize, taskRect.top - stackRect.top);
-                    maxToTravel -= maxMove;
-                    taskRect.top -= maxMove;
-                    taskRect.bottom -= maxMove;
-                }
-                taskResize(taskId, taskRect, delay_ms, false);
-            }
-        }
-        // Return the remaining distance we didn't travel because we reached the target location.
-        return maxToTravel;
-    }
-
-    private void runTaskSizeTaskTest() {
-        final int taskId = Integer.parseInt(nextArgRequired());
-        final int stepSize = Integer.parseInt(nextArgRequired());
-        final String delayStr = nextArg();
-        final int delay_ms = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
-        final StackInfo stackInfo;
-        final Rect initialTaskBounds;
-        try {
-            stackInfo = mAm.getStackInfo(mAm.getFocusedStackId());
-            initialTaskBounds = mAm.getTaskBounds(taskId);
-        } catch (RemoteException e) {
-            System.err.println("Error getting focus stack info or task bounds: " + e);
-            return;
-        }
-        final Rect stackBounds = stackInfo.bounds;
-        stackBounds.inset(STACK_BOUNDS_INSET, STACK_BOUNDS_INSET);
-        final Rect currentTaskBounds = new Rect(initialTaskBounds);
-
-        // Size by top-left
-        System.out.println("Growing top-left");
-        do {
-            currentTaskBounds.top -= getStepSize(
-                    currentTaskBounds.top, stackBounds.top, stepSize, GREATER_THAN_TARGET);
-
-            currentTaskBounds.left -= getStepSize(
-                    currentTaskBounds.left, stackBounds.left, stepSize, GREATER_THAN_TARGET);
-
-            taskResize(taskId, currentTaskBounds, delay_ms, true);
-        } while (stackBounds.top < currentTaskBounds.top
-                || stackBounds.left < currentTaskBounds.left);
-
-        // Back to original size
-        System.out.println("Shrinking top-left");
-        do {
-            currentTaskBounds.top += getStepSize(
-                    currentTaskBounds.top, initialTaskBounds.top, stepSize, !GREATER_THAN_TARGET);
-
-            currentTaskBounds.left += getStepSize(
-                    currentTaskBounds.left, initialTaskBounds.left, stepSize, !GREATER_THAN_TARGET);
-
-            taskResize(taskId, currentTaskBounds, delay_ms, true);
-        } while (initialTaskBounds.top > currentTaskBounds.top
-                || initialTaskBounds.left > currentTaskBounds.left);
-
-        // Size by top-right
-        System.out.println("Growing top-right");
-        do {
-            currentTaskBounds.top -= getStepSize(
-                    currentTaskBounds.top, stackBounds.top, stepSize, GREATER_THAN_TARGET);
-
-            currentTaskBounds.right += getStepSize(
-                    currentTaskBounds.right, stackBounds.right, stepSize, !GREATER_THAN_TARGET);
-
-            taskResize(taskId, currentTaskBounds, delay_ms, true);
-        } while (stackBounds.top < currentTaskBounds.top
-                || stackBounds.right > currentTaskBounds.right);
-
-        // Back to original size
-        System.out.println("Shrinking top-right");
-        do {
-            currentTaskBounds.top += getStepSize(
-                    currentTaskBounds.top, initialTaskBounds.top, stepSize, !GREATER_THAN_TARGET);
-
-            currentTaskBounds.right -= getStepSize(currentTaskBounds.right, initialTaskBounds.right,
-                    stepSize, GREATER_THAN_TARGET);
-
-            taskResize(taskId, currentTaskBounds, delay_ms, true);
-        } while (initialTaskBounds.top > currentTaskBounds.top
-                || initialTaskBounds.right < currentTaskBounds.right);
-
-        // Size by bottom-left
-        System.out.println("Growing bottom-left");
-        do {
-            currentTaskBounds.bottom += getStepSize(
-                    currentTaskBounds.bottom, stackBounds.bottom, stepSize, !GREATER_THAN_TARGET);
-
-            currentTaskBounds.left -= getStepSize(
-                    currentTaskBounds.left, stackBounds.left, stepSize, GREATER_THAN_TARGET);
-
-            taskResize(taskId, currentTaskBounds, delay_ms, true);
-        } while (stackBounds.bottom > currentTaskBounds.bottom
-                || stackBounds.left < currentTaskBounds.left);
-
-        // Back to original size
-        System.out.println("Shrinking bottom-left");
-        do {
-            currentTaskBounds.bottom -= getStepSize(currentTaskBounds.bottom,
-                    initialTaskBounds.bottom, stepSize, GREATER_THAN_TARGET);
-
-            currentTaskBounds.left += getStepSize(
-                    currentTaskBounds.left, initialTaskBounds.left, stepSize, !GREATER_THAN_TARGET);
-
-            taskResize(taskId, currentTaskBounds, delay_ms, true);
-        } while (initialTaskBounds.bottom < currentTaskBounds.bottom
-                || initialTaskBounds.left > currentTaskBounds.left);
-
-        // Size by bottom-right
-        System.out.println("Growing bottom-right");
-        do {
-            currentTaskBounds.bottom += getStepSize(
-                    currentTaskBounds.bottom, stackBounds.bottom, stepSize, !GREATER_THAN_TARGET);
-
-            currentTaskBounds.right += getStepSize(
-                    currentTaskBounds.right, stackBounds.right, stepSize, !GREATER_THAN_TARGET);
-
-            taskResize(taskId, currentTaskBounds, delay_ms, true);
-        } while (stackBounds.bottom > currentTaskBounds.bottom
-                || stackBounds.right > currentTaskBounds.right);
-
-        // Back to original size
-        System.out.println("Shrinking bottom-right");
-        do {
-            currentTaskBounds.bottom -= getStepSize(currentTaskBounds.bottom,
-                    initialTaskBounds.bottom, stepSize, GREATER_THAN_TARGET);
-
-            currentTaskBounds.right -= getStepSize(currentTaskBounds.right, initialTaskBounds.right,
-                    stepSize, GREATER_THAN_TARGET);
-
-            taskResize(taskId, currentTaskBounds, delay_ms, true);
-        } while (initialTaskBounds.bottom < currentTaskBounds.bottom
-                || initialTaskBounds.right < currentTaskBounds.right);
-    }
-
-    private int getStepSize(int current, int target, int inStepSize, boolean greaterThanTarget) {
-        int stepSize = 0;
-        if (greaterThanTarget && target < current) {
-            current -= inStepSize;
-            stepSize = inStepSize;
-            if (target > current) {
-                stepSize -= (target - current);
-            }
-        }
-        if (!greaterThanTarget && target > current) {
-            current += inStepSize;
-            stepSize = inStepSize;
-            if (target < current) {
-                stepSize += (current - target);
-            }
-        }
-        return stepSize;
-    }
-
-    private List<Configuration> getRecentConfigurations(int days) {
-        IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
-                    Context.USAGE_STATS_SERVICE));
-        final long now = System.currentTimeMillis();
-        final long nDaysAgo = now - (days * 24 * 60 * 60 * 1000);
-        try {
-            @SuppressWarnings("unchecked")
-            ParceledListSlice<ConfigurationStats> configStatsSlice = usm.queryConfigurationStats(
-                    UsageStatsManager.INTERVAL_BEST, nDaysAgo, now, "com.android.shell");
-            if (configStatsSlice == null) {
-                return Collections.emptyList();
-            }
-
-            final ArrayMap<Configuration, Integer> recentConfigs = new ArrayMap<>();
-            final List<ConfigurationStats> configStatsList = configStatsSlice.getList();
-            final int configStatsListSize = configStatsList.size();
-            for (int i = 0; i < configStatsListSize; i++) {
-                final ConfigurationStats stats = configStatsList.get(i);
-                final int indexOfKey = recentConfigs.indexOfKey(stats.getConfiguration());
-                if (indexOfKey < 0) {
-                    recentConfigs.put(stats.getConfiguration(), stats.getActivationCount());
-                } else {
-                    recentConfigs.setValueAt(indexOfKey,
-                            recentConfigs.valueAt(indexOfKey) + stats.getActivationCount());
-                }
-            }
-
-            final Comparator<Configuration> comparator = new Comparator<Configuration>() {
-                @Override
-                public int compare(Configuration a, Configuration b) {
-                    return recentConfigs.get(b).compareTo(recentConfigs.get(a));
-                }
-            };
-
-            ArrayList<Configuration> configs = new ArrayList<>(recentConfigs.size());
-            configs.addAll(recentConfigs.keySet());
-            Collections.sort(configs, comparator);
-            return configs;
-
-        } catch (RemoteException e) {
-            return Collections.emptyList();
-        }
-    }
-
-    private void runGetConfig() throws Exception {
-        int days = 14;
-        String option = nextOption();
-        if (option != null) {
-            if (!option.equals("--days")) {
-                throw new IllegalArgumentException("unrecognized option " + option);
-            }
-
-            days = Integer.parseInt(nextArgRequired());
-            if (days <= 0) {
-                throw new IllegalArgumentException("--days must be a positive integer");
-            }
-        }
-
-        try {
-            Configuration config = mAm.getConfiguration();
-            if (config == null) {
-                System.err.println("Activity manager has no configuration");
-                return;
-            }
-
-            System.out.println("config: " + Configuration.resourceQualifierString(config));
-            System.out.println("abi: " + TextUtils.join(",", Build.SUPPORTED_ABIS));
-
-            final List<Configuration> recentConfigs = getRecentConfigurations(days);
-            final int recentConfigSize = recentConfigs.size();
-            if (recentConfigSize > 0) {
-                System.out.println("recentConfigs:");
-            }
-
-            for (int i = 0; i < recentConfigSize; i++) {
-                System.out.println("  config: " + Configuration.resourceQualifierString(
-                        recentConfigs.get(i)));
-            }
-
-        } catch (RemoteException e) {
-        }
-    }
-
-    private void runSuppressResizeConfigChanges() throws Exception {
-        boolean suppress = Boolean.valueOf(nextArgRequired());
-
-        try {
-            mAm.suppressResizeConfigChanges(suppress);
-        } catch (RemoteException e) {
-            System.err.println("Error suppressing resize config changes: " + e);
-        }
-    }
-
-    private void runSetInactive() throws Exception {
-        int userId = UserHandle.USER_CURRENT;
-
-        String opt;
-        while ((opt=nextOption()) != null) {
-            if (opt.equals("--user")) {
-                userId = parseUserArg(nextArgRequired());
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-        String packageName = nextArgRequired();
-        String value = nextArgRequired();
-
-        IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
-                Context.USAGE_STATS_SERVICE));
-        usm.setAppInactive(packageName, Boolean.parseBoolean(value), userId);
-    }
-
-    private void runGetInactive() throws Exception {
-        int userId = UserHandle.USER_CURRENT;
-
-        String opt;
-        while ((opt=nextOption()) != null) {
-            if (opt.equals("--user")) {
-                userId = parseUserArg(nextArgRequired());
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-        String packageName = nextArgRequired();
-
-        IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
-                Context.USAGE_STATS_SERVICE));
-        boolean isIdle = usm.isAppInactive(packageName, userId);
-        System.out.println("Idle=" + isIdle);
-    }
-
-    private void runSendTrimMemory() throws Exception {
-        int userId = UserHandle.USER_CURRENT;
-        String opt;
-        while ((opt = nextOption()) != null) {
-            if (opt.equals("--user")) {
-                userId = parseUserArg(nextArgRequired());
-                if (userId == UserHandle.USER_ALL) {
-                    System.err.println("Error: Can't use user 'all'");
-                    return;
-                }
-            } else {
-                System.err.println("Error: Unknown option: " + opt);
-                return;
-            }
-        }
-
-        String proc = nextArgRequired();
-        String levelArg = nextArgRequired();
-        int level;
-        switch (levelArg) {
-            case "HIDDEN":
-                level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
-                break;
-            case "RUNNING_MODERATE":
-                level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
-                break;
-            case "BACKGROUND":
-                level = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
-                break;
-            case "RUNNING_LOW":
-                level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
-                break;
-            case "MODERATE":
-                level = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
-                break;
-            case "RUNNING_CRITICAL":
-                level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
-                break;
-            case "COMPLETE":
-                level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
-                break;
-            default:
-                System.err.println("Error: Unknown level option: " + levelArg);
-                return;
-        }
-        if (!mAm.setProcessMemoryTrimLevel(proc, userId, level)) {
-            System.err.println("Unknown error: failed to set trim level");
-        }
-    }
-
-    private void runGetCurrentUser() throws Exception {
-        UserInfo currentUser = Preconditions.checkNotNull(mAm.getCurrentUser(),
-                "Current user not set");
-        System.out.println(currentUser.id);
-    }
-
-    /**
-     * Open the given file for sending into the system process. This verifies
-     * with SELinux that the system will have access to the file.
-     */
-    private static ParcelFileDescriptor openForSystemServer(File file, int mode)
-            throws FileNotFoundException {
-        final ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, mode);
-        final String tcon = SELinux.getFileContext(file.getAbsolutePath());
-        if (!SELinux.checkSELinuxAccess("u:r:system_server:s0", tcon, "file", "read")) {
-            throw new FileNotFoundException("System server has no access to file context " + tcon);
-        }
-        return fd;
-    }
-
-    private Rect getBounds() {
-        String leftStr = nextArgRequired();
-        int left = Integer.parseInt(leftStr);
-        String topStr = nextArgRequired();
-        int top = Integer.parseInt(topStr);
-        String rightStr = nextArgRequired();
-        int right = Integer.parseInt(rightStr);
-        String bottomStr = nextArgRequired();
-        int bottom = Integer.parseInt(bottomStr);
-        if (left < 0) {
-            System.err.println("Error: bad left arg: " + leftStr);
-            return null;
-        }
-        if (top < 0) {
-            System.err.println("Error: bad top arg: " + topStr);
-            return null;
-        }
-        if (right <= 0) {
-            System.err.println("Error: bad right arg: " + rightStr);
-            return null;
-        }
-        if (bottom <= 0) {
-            System.err.println("Error: bad bottom arg: " + bottomStr);
-            return null;
-        }
-        return new Rect(left, top, right, bottom);
-    }
 }
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index e530184..e18de8e 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -62,7 +62,6 @@
 LOCAL_LDFLAGS := -ldl
 LOCAL_LDFLAGS_32 := -Wl,--version-script,art/sigchainlib/version-script32.txt -Wl,--export-dynamic
 LOCAL_LDFLAGS_64 := -Wl,--version-script,art/sigchainlib/version-script64.txt -Wl,--export-dynamic
-LOCAL_CPPFLAGS := -std=c++11
 
 LOCAL_MODULE := app_process__asan
 LOCAL_MULTILIB := both
@@ -70,7 +69,6 @@
 LOCAL_MODULE_STEM_64 := app_process64
 
 LOCAL_SANITIZE := address
-LOCAL_CLANG := true
 LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)/asan
 
 LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index 6d30f0d..ab6adfb 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -1,5 +1,6 @@
 #include <dirent.h>
 #include <inttypes.h>
+#include <sys/file.h>
 #include <sys/stat.h>
 
 #include "idmap.h"
@@ -35,16 +36,31 @@
 
     bool writePackagesList(const char *filename, const SortedVector<Overlay>& overlayVector)
     {
-        FILE* fout = fopen(filename, "w");
+        // the file is opened for appending so that it doesn't get truncated
+        // before we can guarantee mutual exclusion via the flock
+        FILE* fout = fopen(filename, "a");
         if (fout == NULL) {
             return false;
         }
 
+        if (TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_EX)) != 0) {
+            fclose(fout);
+            return false;
+        }
+
+        if (TEMP_FAILURE_RETRY(ftruncate(fileno(fout), 0)) != 0) {
+            TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN));
+            fclose(fout);
+            return false;
+        }
+
         for (size_t i = 0; i < overlayVector.size(); ++i) {
             const Overlay& overlay = overlayVector[i];
             fprintf(fout, "%s %s\n", overlay.apk_path.string(), overlay.idmap_path.string());
         }
 
+        TEMP_FAILURE_RETRY(fflush(fout));
+        TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN));
         fclose(fout);
 
         // Make file world readable since Zygote (running as root) will read
@@ -171,9 +187,6 @@
 {
     String8 filename = String8(idmap_dir);
     filename.appendPath("overlays.list");
-    if (unlink(filename.string()) != 0 && errno != ENOENT) {
-        return EXIT_FAILURE;
-    }
 
     SortedVector<Overlay> overlayVector;
     const size_t N = overlay_dirs->size();
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index ace4e32..718f141 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -41,6 +41,10 @@
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageInstaller.SessionParams;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.ApkLite;
+import android.content.pm.PackageParser.PackageLite;
+import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.UserInfo;
 import android.net.Uri;
 import android.os.Binder;
@@ -80,6 +84,7 @@
 
 public final class Pm {
     private static final String TAG = "Pm";
+    private static final String STDIN_PATH = "-";
 
     IPackageManager mPm;
     IPackageInstaller mInstaller;
@@ -398,12 +403,31 @@
      */
     private int runInstall() throws RemoteException {
         final InstallParams params = makeInstallParams();
+        final String inPath = nextArg();
+        if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
+            File file = new File(inPath);
+            if (file.isFile()) {
+                try {
+                    ApkLite baseApk = PackageParser.parseApkLite(file, 0);
+                    PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null);
+                    params.sessionParams.setSize(
+                            PackageHelper.calculateInstalledSize(pkgLite, false,
+                            params.sessionParams.abiOverride));
+                } catch (PackageParserException | IOException e) {
+                    System.err.println("Error: Failed to parse APK file: " + e);
+                    return 1;
+                }
+            } else {
+                System.err.println("Error: Can't open non-file: " + inPath);
+                return 1;
+            }
+        }
+
         final int sessionId = doCreateSession(params.sessionParams,
                 params.installerPackageName, params.userId);
 
         try {
-            final String inPath = nextArg();
-            if (inPath == null && params.sessionParams.sizeBytes == 0) {
+            if (inPath == null && params.sessionParams.sizeBytes == -1) {
                 System.err.println("Error: must either specify a package size or an APK file");
                 return 1;
             }
@@ -520,7 +544,11 @@
                     }
                     break;
                 case "-S":
-                    sessionParams.setSize(Long.parseLong(nextOptionData()));
+                    final long sizeBytes = Long.parseLong(nextOptionData());
+                    if (sizeBytes <= 0) {
+                        throw new IllegalArgumentException("Size must be positive");
+                    }
+                    sessionParams.setSize(sizeBytes);
                     break;
                 case "--abi":
                     sessionParams.abiOverride = checkAbiArgument(nextOptionData());
@@ -565,7 +593,7 @@
 
     private int doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName,
             boolean logSuccess) throws RemoteException {
-        if ("-".equals(inPath)) {
+        if (STDIN_PATH.equals(inPath)) {
             inPath = null;
         } else if (inPath != null) {
             final File file = new File(inPath);
@@ -981,7 +1009,7 @@
             } else if (userId < 0) {
                 info = mUm.createUser(name, flags);
             } else {
-                info = mUm.createProfileForUser(name, flags, userId);
+                info = mUm.createProfileForUser(name, flags, userId, null);
             }
 
             if (info != null) {
diff --git a/cmds/svc/src/com/android/commands/svc/UsbCommand.java b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
index a6ef25f..4dcb05e 100644
--- a/cmds/svc/src/com/android/commands/svc/UsbCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
@@ -50,7 +50,7 @@
                 IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
                         Context.USB_SERVICE));
                 try {
-                    usbMgr.setCurrentFunction((args.length >=3 ? args[2] : null));
+                    usbMgr.setCurrentFunction((args.length >=3 ? args[2] : null), false);
                 } catch (RemoteException e) {
                     System.err.println("Error communicating with UsbManager: " + e);
                 }
diff --git a/compiled-classes-phone b/compiled-classes-phone
index 221d687..6214306 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -1168,14 +1168,6 @@
 android.drm.DrmManagerClient$OnInfoListener
 android.drm.DrmOutputStream
 android.drm.DrmSupportInfo
-android.graphics.Atlas
-android.graphics.Atlas$Entry
-android.graphics.Atlas$Policy
-android.graphics.Atlas$SlicePolicy
-android.graphics.Atlas$SlicePolicy$Cell
-android.graphics.Atlas$SlicePolicy$MinAreaSplitDecision
-android.graphics.Atlas$SlicePolicy$SplitDecision
-android.graphics.Atlas$Type
 android.graphics.Bitmap
 android.graphics.Bitmap$1
 android.graphics.Bitmap$CompressFormat
@@ -4264,9 +4256,6 @@
 android.view.IAppTransitionAnimationSpecsFuture$Stub$Proxy
 android.view.IApplicationToken
 android.view.IApplicationToken$Stub
-android.view.IAssetAtlas
-android.view.IAssetAtlas$Stub
-android.view.IAssetAtlas$Stub$Proxy
 android.view.IDockedStackListener
 android.view.IDockedStackListener$Stub
 android.view.IDockedStackListener$Stub$Proxy
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java
index fd0bf0b..116d063 100644
--- a/core/java/android/animation/KeyframeSet.java
+++ b/core/java/android/animation/KeyframeSet.java
@@ -16,15 +16,15 @@
 
 package android.animation;
 
-import java.util.Arrays;
-import java.util.List;
-
-import android.animation.Keyframe.IntKeyframe;
 import android.animation.Keyframe.FloatKeyframe;
+import android.animation.Keyframe.IntKeyframe;
 import android.animation.Keyframe.ObjectKeyframe;
 import android.graphics.Path;
 import android.util.Log;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
  * This class holds a collection of Keyframe objects and is called by ValueAnimator to calculate
  * values between those keyframes for a given animation. The class internal to the animation
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index a09c920..ed7e89d 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -276,6 +276,23 @@
     }
 
     /**
+     * Returns whether animators are currently enabled, system-wide. By default, all
+     * animators are enabled. This can change if either the user sets a Developer Option
+     * to set the animator duration scale to 0 or by Battery Savery mode being enabled
+     * (which disables all animations).
+     *
+     * <p>Developers should not typically need to call this method, but should an app wish
+     * to show a different experience when animators are disabled, this return value
+     * can be used as a decider of which experience to offer.
+     *
+     * @return boolean Whether animators are currently enabled. The default value is
+     * <code>true</code>.
+     */
+    public static boolean areAnimatorsEnabled() {
+        return !(sDurationScale == 0);
+    }
+
+    /**
      * Creates a new ValueAnimator object. This default constructor is primarily for
      * use internally; the factory methods which take parameters are more generally
      * useful.
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index f798512..d91472b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1229,8 +1229,9 @@
         case UPDATE_CONFIGURATION_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             Configuration config = Configuration.CREATOR.createFromParcel(data);
-            updateConfiguration(config);
+            final boolean updated = updateConfiguration(config);
             reply.writeNoException();
+            reply.writeInt(updated ? 1 : 0);
             return true;
         }
 
@@ -4593,7 +4594,7 @@
         data.recycle();
         return res;
     }
-    public void updateConfiguration(Configuration values) throws RemoteException
+    public boolean updateConfiguration(Configuration values) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -4601,8 +4602,10 @@
         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 void setRequestedOrientation(IBinder token, int requestedOrientation)
             throws RemoteException {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 85a0403..6e2c464 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -32,6 +32,7 @@
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.DialogInterface;
+import android.content.res.Configuration;
 import android.content.pm.ApplicationInfo;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -288,9 +289,14 @@
         }
 
         mCanceled = false;
-        
+
         if (!mCreated) {
             dispatchOnCreate(null);
+        } else {
+            // Fill the DecorView in on any configuration changes that
+            // may have occured while it was removed from the WindowManager.
+            final Configuration config = mContext.getResources().getConfiguration();
+            mWindow.getDecorView().dispatchConfigurationChanged(config);
         }
 
         onStart();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 096f0cb..c9d3682 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -276,8 +276,9 @@
      * Updates global configuration and applies changes to the entire system.
      * @param values Update values for global configuration.
      * @throws RemoteException
+     * @return Returns true if the configuration was updated.
      */
-    public void updateConfiguration(Configuration values) throws RemoteException;
+    public boolean updateConfiguration(Configuration values) throws RemoteException;
 
     public void setRequestedOrientation(IBinder token,
             int requestedOrientation) throws RemoteException;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 28224e8..c87eef9 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -78,6 +78,8 @@
     void cancelNotificationFromListener(in INotificationListener token, String pkg, String tag, int id);
     void cancelNotificationsFromListener(in INotificationListener token, in String[] keys);
 
+    void snoozeNotificationFromListener(in INotificationListener token, String key, long until);
+
     void requestBindListener(in ComponentName component);
     void requestUnbindListener(in INotificationListener token);
     void requestBindProvider(in ComponentName component);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 680e518..bdb2685 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -19,6 +19,7 @@
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
@@ -1052,6 +1053,7 @@
             this(Icon.createWithResource("", icon), title, intent, new Bundle(), null, false);
         }
 
+        /** Keep in sync with {@link Notification.Action.Builder#Builder(Action)}! */
         private Action(Icon icon, CharSequence title, PendingIntent intent, Bundle extras,
                 RemoteInput[] remoteInputs, boolean allowGeneratedReplies) {
             this.mIcon = icon;
@@ -1118,7 +1120,7 @@
              */
             @Deprecated
             public Builder(int icon, CharSequence title, PendingIntent intent) {
-                this(Icon.createWithResource("", icon), title, intent, new Bundle(), null);
+                this(Icon.createWithResource("", icon), title, intent);
             }
 
             /**
@@ -1128,7 +1130,7 @@
              * @param intent the {@link PendingIntent} to fire when users trigger this action
              */
             public Builder(Icon icon, CharSequence title, PendingIntent intent) {
-                this(icon, title, intent, new Bundle(), null);
+                this(icon, title, intent, new Bundle(), null, false);
             }
 
             /**
@@ -1137,12 +1139,13 @@
              * @param action the action to read fields from.
              */
             public Builder(Action action) {
-                this(action.getIcon(), action.title, action.actionIntent, new Bundle(action.mExtras),
-                        action.getRemoteInputs());
+                this(action.getIcon(), action.title, action.actionIntent,
+                        new Bundle(action.mExtras), action.getRemoteInputs(),
+                        action.getAllowGeneratedReplies());
             }
 
             private Builder(Icon icon, CharSequence title, PendingIntent intent, Bundle extras,
-                    RemoteInput[] remoteInputs) {
+                    RemoteInput[] remoteInputs, boolean allowGeneratedReplies) {
                 mIcon = icon;
                 mTitle = title;
                 mIntent = intent;
@@ -1151,6 +1154,7 @@
                     mRemoteInputs = new ArrayList<RemoteInput>(remoteInputs.length);
                     Collections.addAll(mRemoteInputs, remoteInputs);
                 }
+                mAllowGeneratedReplies = allowGeneratedReplies;
             }
 
             /**
@@ -4683,12 +4687,12 @@
         }
 
         /**
-         * @param userDisplayName the name to be displayed for any replies sent by the user before the
-         * posting app reposts the notification with those messages after they've been actually
-         * sent and in previous messages sent by the user added in
+         * @param userDisplayName Required - the name to be displayed for any replies sent by the
+         * user before the posting app reposts the notification with those messages after they've
+         * been actually sent and in previous messages sent by the user added in
          * {@link #addMessage(Notification.MessagingStyle.Message)}
          */
-        public MessagingStyle(CharSequence userDisplayName) {
+        public MessagingStyle(@NonNull CharSequence userDisplayName) {
             mUserDisplayName = userDisplayName;
         }
 
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index c88cea0..2d15beb 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -839,19 +839,22 @@
                             tmpConfig = new Configuration();
                         }
                         tmpConfig.setTo(config);
+
+                        // Get new DisplayMetrics based on the DisplayAdjustments given
+                        // to the ResourcesImpl. Update a copy if the CompatibilityInfo
+                        // changed, because the ResourcesImpl object will handle the
+                        // update internally.
+                        DisplayAdjustments daj = r.getDisplayAdjustments();
+                        if (compat != null) {
+                            daj = new DisplayAdjustments(daj);
+                            daj.setCompatibilityInfo(compat);
+                        }
+                        dm = getDisplayMetrics(displayId, daj);
+
                         if (!isDefaultDisplay) {
-                            // Get new DisplayMetrics based on the DisplayAdjustments given
-                            // to the ResourcesImpl. Udate a copy if the CompatibilityInfo
-                            // changed, because the ResourcesImpl object will handle the
-                            // update internally.
-                            DisplayAdjustments daj = r.getDisplayAdjustments();
-                            if (compat != null) {
-                                daj = new DisplayAdjustments(daj);
-                                daj.setCompatibilityInfo(compat);
-                            }
-                            dm = getDisplayMetrics(displayId, daj);
                             applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
                         }
+
                         if (hasOverrideConfiguration) {
                             tmpConfig.updateFrom(key.mOverrideConfiguration);
                         }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a207a52..4ddcfe5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2352,18 +2352,23 @@
      * <p>The calling device admin must be a device or profile owner. If it is not,
      * a {@link SecurityException} will be thrown.
      *
+     * <p>The calling device admin can verify the value it has set by calling
+     * {@link #getRequiredStrongAuthTimeout(ComponentName)} and passing in its instance.
+     *
      * <p>This method can be called on the {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
      * profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param timeoutMs The new timeout, after which the user will have to unlock with strong
-     *         authentication method. If the timeout is lower than 1 hour (minimum) or higher than
-     *         72 hours (default and maximum) an {@link IllegalArgumentException} is thrown.
+     *         authentication method. A value of 0 means the admin is not participating in
+     *         controlling the timeout.
+     *         The minimum and maximum timeouts are platform-defined and are typically 1 hour and
+     *         72 hours, respectively. Though discouraged, the admin may choose to require strong
+     *         auth at all times using {@link #KEYGUARD_DISABLE_FINGERPRINT} and/or
+     *         {@link #KEYGUARD_DISABLE_TRUST_AGENTS}.
      *
      * @throws SecurityException if {@code admin} is not a device or profile owner.
-     * @throws IllegalArgumentException if the timeout is lower than 1 hour (minimum) or higher than
-     *         72 hours (default and maximum)
      *
      * @hide
      */
@@ -2389,7 +2394,7 @@
      *
      * @param admin The name of the admin component to check, or {@code null} to aggregate
      *         accross all participating admins.
-     * @return The timeout or default timeout if not configured
+     * @return The timeout or 0 if not configured for the provided admin.
      *
      * @hide
      */
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index bc82806..bad6325 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -35,6 +35,8 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import libcore.io.IoUtils;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
@@ -647,10 +649,11 @@
                 File file = scanQueue.remove(0);
                 String filePath;
                 try {
-                    // Ignore symlinks outright
+                    // Ignore things that aren't "real" files or dirs
                     StructStat stat = Os.lstat(file.getPath());
-                    if (OsConstants.S_ISLNK(stat.st_mode)) {
-                        if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file);
+                    if (!OsConstants.S_ISREG(stat.st_mode)
+                            && !OsConstants.S_ISDIR(stat.st_mode)) {
+                        if (DEBUG) Log.i(TAG, "Not a file/dir (skipping)!: " + file);
                         continue;
                     }
 
@@ -921,6 +924,13 @@
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
+
+                // Don't close the fd out from under the system service if this was local
+                if (Binder.getCallingPid() != Process.myPid()) {
+                    IoUtils.closeQuietly(oldState);
+                    IoUtils.closeQuietly(data);
+                    IoUtils.closeQuietly(newState);
+                }
             }
         }
 
@@ -951,6 +961,11 @@
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
+
+                if (Binder.getCallingPid() != Process.myPid()) {
+                    IoUtils.closeQuietly(data);
+                    IoUtils.closeQuietly(newState);
+                }
             }
         }
 
@@ -994,6 +1009,10 @@
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
+
+                if (Binder.getCallingPid() != Process.myPid()) {
+                    IoUtils.closeQuietly(data);
+                }
             }
         }
 
@@ -1041,6 +1060,10 @@
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
+
+                if (Binder.getCallingPid() != Process.myPid()) {
+                    IoUtils.closeQuietly(data);
+                }
             }
         }
 
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index c71dc7c..38788dc 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1522,6 +1522,36 @@
     }
 
     /**
+     * Gets the currently supported profiles by the adapter.
+     *
+     *<p> This can be used to check whether a profile is supported before attempting
+     * to connect to its respective proxy.
+     *
+     * @return a list of integers indicating the ids of supported profiles as defined in
+     * {@link BluetoothProfile}.
+     * @hide
+     */
+    public List<Integer> getSupportedProfiles() {
+        final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
+
+        try {
+            synchronized (mManagerCallback) {
+                if (mService != null) {
+                    final long supportedProfilesBitMask = mService.getSupportedProfiles();
+
+                    for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
+                        if ((supportedProfilesBitMask & (1 << i)) != 0) {
+                            supportedProfiles.add(i);
+                        }
+                    }
+                }
+            }
+        } catch (RemoteException e) {Log.e(TAG, "getSupportedProfiles:", e);}
+
+        return supportedProfiles;
+    }
+
+    /**
      * Get the current connection state of the local Bluetooth adapter.
      * This can be used to check whether the local Bluetooth adapter is connected
      * to any profile of any other remote Bluetooth Device.
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index cd5eff2..5c9e2ee 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -895,6 +895,14 @@
         return false;
     }
 
+    /** @hide */
+    public boolean isBondingInitiatedLocally() {
+        try {
+            return sService.isBondingInitiatedLocally(this);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}
+        return false;
+    }
+
     /**
      * Set the Out Of Band data for a remote device to be used later
      * in the pairing mechanism. Users can obtain this data through other
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index eee66d1..20d95cc 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -137,6 +137,13 @@
     public static final int PBAP_CLIENT = 17;
 
     /**
+     * Max profile ID. This value should be updated whenever a new profile is added to match
+     * the largest value assigned to a profile.
+     * @hide
+     */
+    public static final int MAX_PROFILE_ID = 17;
+
+    /**
      * Default priority for devices that we try to auto-connect to and
      * and allow incoming connections for the profile
      * @hide
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index a420539..96a1ae8 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -62,6 +62,8 @@
     boolean cancelBondProcess(in BluetoothDevice device);
     boolean removeBond(in BluetoothDevice device);
     int getBondState(in BluetoothDevice device);
+    boolean isBondingInitiatedLocally(in BluetoothDevice device);
+    long getSupportedProfiles();
     int getConnectionState(in BluetoothDevice device);
 
     String getRemoteName(in BluetoothDevice device);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 74f48c6..e031275 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3037,6 +3037,18 @@
             "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
 
     /**
+     * Broadcast sent to the system user when the 'device locked' state changes for any user.
+     * Carries an extra {@link #EXTRA_USER_HANDLE} that specifies the ID of the user for which
+     * the device was locked or unlocked.
+     *
+     * This is only sent to registered receivers.
+     *
+     * @hide
+     */
+    public static final String ACTION_DEVICE_LOCKED_CHANGED =
+            "android.intent.action.DEVICE_LOCKED_CHANGED";
+
+    /**
      * Sent when the user taps on the clock widget in the system's "quick settings" area.
      */
     public static final String ACTION_QUICK_CLOCK =
@@ -4184,6 +4196,16 @@
             "android.intent.extra.MEDIA_RESOURCE_TYPE";
 
     /**
+     * Used as a boolean extra field in {@link #ACTION_CHOOSER} intents to specify
+     * whether to show the chooser or not when there is only one application available
+     * to choose from.
+     *
+     * @hide
+     */
+    public static final String EXTRA_AUTO_LAUNCH_SINGLE_CHOICE =
+            "android.intent.extra.AUTO_LAUNCH_SINGLE_CHOICE";
+
+    /**
      * Used as an int value for {@link #EXTRA_MEDIA_RESOURCE_TYPE}
      * to represent that a video codec is allowed to use.
      *
@@ -6574,7 +6596,7 @@
      */
     public void removeUnsafeExtras() {
         if (mExtras != null) {
-            mExtras.filterValues();
+            mExtras = mExtras.filterValues();
         }
     }
 
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 5d2c6cd..4cbff5f 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -163,13 +163,14 @@
      */
     public static final int RESIZE_MODE_UNRESIZEABLE = 0;
     /**
-     * Activity can not be resized and always occupies the fullscreen area with all windows cropped
-     * to either the task or stack bounds.
+     * Activity didn't explicitly request to be resizeable, but we are making it resizeable because
+     * of the SDK version it targets. Only affects apps with target SDK >= N where the app is
+     * implied to be resizeable if it doesn't explicitly set the attribute to any value.
      * @hide
      */
-    public static final int RESIZE_MODE_CROP_WINDOWS = 1;
+    public static final int RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION = 1;
     /**
-     * Activity is resizeable.
+     * Activity explicitly requested to be resizeable.
      * @hide
      */
     public static final int RESIZE_MODE_RESIZEABLE = 2;
@@ -179,7 +180,8 @@
      */
     public static final int RESIZE_MODE_RESIZEABLE_AND_PIPABLE = 3;
     /**
-     * Activity is does not support resizing, but we are forcing it to be resizeable.
+     * Activity is does not support resizing, but we are forcing it to be resizeable. Only affects
+     * certain pre-N apps where we force them to be resizeable.
      * @hide
      */
     public static final int RESIZE_MODE_FORCE_RESIZEABLE = 4;
@@ -862,7 +864,8 @@
     public static boolean isResizeableMode(int mode) {
         return mode == RESIZE_MODE_RESIZEABLE
                 || mode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE
-                || mode == RESIZE_MODE_FORCE_RESIZEABLE;
+                || mode == RESIZE_MODE_FORCE_RESIZEABLE
+                || mode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
     }
 
     /** @hide */
@@ -870,8 +873,8 @@
         switch (mode) {
             case RESIZE_MODE_UNRESIZEABLE:
                 return "RESIZE_MODE_UNRESIZEABLE";
-            case RESIZE_MODE_CROP_WINDOWS:
-                return "RESIZE_MODE_CROP_WINDOWS";
+            case RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION:
+                return "RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION";
             case RESIZE_MODE_RESIZEABLE:
                 return "RESIZE_MODE_RESIZEABLE";
             case RESIZE_MODE_RESIZEABLE_AND_PIPABLE:
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index b7364e2..ecfc00f 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -520,12 +520,26 @@
     public static final int PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER = 1 << 10;
 
     /**
-     * When set, the activities associated with this application are resizeable by default.
+     * When set, the application explicitly requested that its activities by resizeable by default.
      * @see android.R.styleable#AndroidManifestActivity_resizeableActivity
      *
      * @hide
      */
-    public static final int PRIVATE_FLAG_RESIZEABLE_ACTIVITIES = 1 << 11;
+    public static final int PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET = 1 << 11;
+
+    /**
+     * The application isn't requesting explicitly requesting for its activities to be resizeable or
+     * non-resizeable by default. So, we are making it activities resizeable by default based on the
+     * target SDK version of the app.
+     * @see android.R.styleable#AndroidManifestActivity_resizeableActivity
+     *
+     * NOTE: This only affects apps with target SDK >= N where the resizeableActivity attribute was
+     * introduced. It shouldn't be confused with {@link ActivityInfo#RESIZE_MODE_FORCE_RESIZEABLE}
+     * where certain pre-N apps are forced to the resizeable.
+     *
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION = 1 << 12;
 
     /**
      * Value for {@link #privateFlags}: {@code true} means the OS should go ahead and
@@ -533,7 +547,7 @@
      * foreground-equivalent run state.  Defaults to {@code false} if unspecified.
      * @hide
      */
-    public static final int PRIVATE_FLAG_BACKUP_IN_FOREGROUND = 1 << 12;
+    public static final int PRIVATE_FLAG_BACKUP_IN_FOREGROUND = 1 << 13;
 
     /**
      * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index f5bcf64..da4eb2d 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -168,4 +168,25 @@
      * @return Whether was launched.
      */
     public abstract boolean wasPackageEverLaunched(String packageName, int userId);
+
+    /**
+     * Grants a runtime permission
+     * @param packageName The package name.
+     * @param name The name of the permission.
+     * @param userId The userId for which to grant the permission.
+     * @param overridePolicy If true, grant this permission even if it is fixed by policy.
+     */
+    public abstract void grantRuntimePermission(String packageName, String name, int userId,
+            boolean overridePolicy);
+
+    /**
+     * Revokes a runtime permission
+     * @param packageName The package name.
+     * @param name The name of the permission.
+     * @param userId The userId for which to revoke the permission.
+     * @param overridePolicy If true, revoke this permission even if it is fixed by policy.
+     */
+    public abstract void revokeRuntimePermission(String packageName, String name, int userId,
+            boolean overridePolicy);
+
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 201ada1..12e8d48 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -83,10 +83,12 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
-import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
@@ -2940,9 +2942,12 @@
             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
         }
 
-        if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity,
-                owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N)) {
-            ai.privateFlags |= PRIVATE_FLAG_RESIZEABLE_ACTIVITIES;
+        if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
+            if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
+                ai.privateFlags |= PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET;
+            }
+        } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
+            ai.privateFlags |= PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION;
         }
 
         ai.networkSecurityConfigRes = sa.getResourceId(
@@ -3548,31 +3553,7 @@
                     R.styleable.AndroidManifestActivity_screenOrientation,
                     SCREEN_ORIENTATION_UNSPECIFIED);
 
-            a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
-            final boolean appDefault = (owner.applicationInfo.privateFlags
-                    & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES) != 0;
-            // This flag is used to workaround the issue with ignored resizeableActivity param when
-            // either targetSdkVersion is not set at all or <uses-sdk> tag is below <application>
-            // tag in AndroidManifest. If this param was explicitly set to 'false' we need to set
-            // corresponding resizeMode regardless of targetSdkVersion value at this point in time.
-            final boolean resizeableSetExplicitly
-                    = sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity);
-            final boolean resizeable = sa.getBoolean(
-                    R.styleable.AndroidManifestActivity_resizeableActivity, appDefault);
-
-            if (resizeable) {
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
-                        false)) {
-                    a.info.resizeMode = RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
-                } else {
-                    a.info.resizeMode = RESIZE_MODE_RESIZEABLE;
-                }
-            } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N
-                    || resizeableSetExplicitly) {
-                a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
-            } else if (!a.info.isFixedOrientation() && (a.info.flags & FLAG_IMMERSIVE) == 0) {
-                a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
-            }
+            setActivityResizeMode(a.info, sa, owner);
 
             if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
                 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
@@ -3706,6 +3687,39 @@
         return a;
     }
 
+    private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
+        final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
+                & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET) != 0;
+        final boolean supportsPip =
+                sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture, false);
+
+        if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
+                || appExplicitDefault) {
+            // Activity or app explicitly set if it is resizeable or not;
+            if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
+                    appExplicitDefault)) {
+                aInfo.resizeMode =
+                        supportsPip ? RESIZE_MODE_RESIZEABLE_AND_PIPABLE : RESIZE_MODE_RESIZEABLE;
+            } else {
+                aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+            }
+            return;
+        }
+
+        if ((owner.applicationInfo.privateFlags
+                & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION) != 0) {
+            // The activity or app didn't explicitly set the resizing option, however we want to
+            // make it resize due to the sdk version it is targeting.
+            aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
+            return;
+        }
+
+        // resize preference isn't set and target sdk version doesn't support resizing apps by
+        // default. For the app to be resizeable if it isn't fixed orientation or immersive.
+        aInfo.resizeMode = (aInfo.isFixedOrientation() || (aInfo.flags & FLAG_IMMERSIVE) != 0)
+                ? RESIZE_MODE_UNRESIZEABLE : RESIZE_MODE_FORCE_RESIZEABLE;
+    }
+
     private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
         TypedArray sw = res.obtainAttributes(attrs,
                 com.android.internal.R.styleable.AndroidManifestLayout);
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index cd248ea..96ad67c 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -329,7 +329,7 @@
  * <p>Applications with a foreground activity or service are not rate-limited.
  *
  * <p>Rate-limiting will be reset upon certain events, so that even background applications
- * can call these APIs again until they are rate limit is reached again.
+ * can call these APIs again until the rate limit is reached again.
  * These events include the following:
  * <ul>
  *   <li>When an application comes to the foreground.
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 4ad86f7..b0d0d79 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -27,6 +27,8 @@
 import android.util.SparseArray;
 import android.util.TypedValue;
 
+import dalvik.annotation.optimization.FastNative;
+
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -752,6 +754,7 @@
      * applications.
      * {@hide}
      */
+    @FastNative
     public native final void setConfiguration(int mcc, int mnc, String locale,
             int orientation, int touchscreen, int density, int keyboard,
             int keyboardHidden, int navigation, int screenWidth, int screenHeight,
@@ -761,13 +764,18 @@
     /**
      * Retrieve the resource identifier for the given resource name.
      */
+    @FastNative
     /*package*/ native final int getResourceIdentifier(String type,
                                                        String name,
                                                        String defPackage);
 
+    @FastNative
     /*package*/ native final String getResourceName(int resid);
+    @FastNative
     /*package*/ native final String getResourcePackageName(int resid);
+    @FastNative
     /*package*/ native final String getResourceTypeName(int resid);
+    @FastNative
     /*package*/ native final String getResourceEntryName(int resid);
     
     private native final long openAsset(String fileName, int accessMode);
@@ -781,15 +789,19 @@
     private native final int readAssetChar(long asset);
     private native final int readAsset(long asset, byte[] b, int off, int len);
     private native final long seekAsset(long asset, long offset, int whence);
+    @FastNative
     private native final long getAssetLength(long asset);
+    @FastNative
     private native final long getAssetRemainingLength(long asset);
 
     /** Returns true if the resource was found, filling in mRetStringBlock and
      *  mRetData. */
+    @FastNative
     private native final int loadResourceValue(int ident, short density, TypedValue outValue,
             boolean resolve);
     /** Returns true if the resource was found, filling in mRetStringBlock and
      *  mRetData. */
+    @FastNative
     private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
                                                boolean resolve);
     /*package*/ static final int STYLE_NUM_ENTRIES = 6;
@@ -802,17 +814,24 @@
     static final int STYLE_CHANGING_CONFIGURATIONS = 4;
 
     /*package*/ static final int STYLE_DENSITY = 5;
+    @FastNative
     /*package*/ native static final boolean applyStyle(long theme,
             int defStyleAttr, int defStyleRes, long xmlParser,
             int[] inAttrs, int[] outValues, int[] outIndices);
+    @FastNative
     /*package*/ native static final boolean resolveAttrs(long theme,
             int defStyleAttr, int defStyleRes, int[] inValues,
             int[] inAttrs, int[] outValues, int[] outIndices);
+    @FastNative
     /*package*/ native final boolean retrieveAttributes(
             long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices);
+    @FastNative
     /*package*/ native final int getArraySize(int resource);
+    @FastNative
     /*package*/ native final int retrieveArray(int resource, int[] outValues);
+    @FastNative
     private native final int getStringBlockCount();
+    @FastNative
     private native final long getNativeStringBlock(int block);
 
     /**
@@ -845,17 +864,22 @@
     /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force);
     /*package*/ native static final void copyTheme(long dest, long source);
     /*package*/ native static final void clearTheme(long theme);
+    @FastNative
     /*package*/ native static final int loadThemeAttributeValue(long theme, int ident,
                                                                 TypedValue outValue,
                                                                 boolean resolve);
     /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix);
+    @FastNative
     /*package*/ native static final @NativeConfig int getThemeChangingConfigurations(long theme);
 
     private native final long openXmlAssetNative(int cookie, String fileName);
 
     private native final String[] getArrayStringResource(int arrayRes);
+    @FastNative
     private native final int[] getArrayStringInfo(int arrayRes);
+    @FastNative
     /*package*/ native final int[] getArrayIntResource(int arrayRes);
+    @FastNative
     /*package*/ native final int[] getStyleAttributes(int themeRes);
 
     private native final void init(boolean isSystem);
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 64b6bf1..b03ed1e 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -59,7 +59,8 @@
         mOverlayDirs = overlayDirs;
         mLibDirs = libDirs;
         mDisplayId = displayId;
-        mOverrideConfiguration = overrideConfig != null ? overrideConfig : Configuration.EMPTY;
+        mOverrideConfiguration = new Configuration(overrideConfig != null
+                ? overrideConfig : Configuration.EMPTY);
         mCompatInfo = compatInfo != null ? compatInfo : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
 
         int hash = 17;
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index 2f4d69b0..e6b95741 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -20,6 +20,8 @@
 
 import com.android.internal.util.XmlUtils;
 
+import dalvik.annotation.optimization.FastNative;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
@@ -492,25 +494,42 @@
                                                  int offset,
                                                  int size);
     private static final native long nativeGetStringBlock(long obj);
-
     private static final native long nativeCreateParseState(long obj);
-    /*package*/ static final native int nativeNext(long state);
-    private static final native int nativeGetNamespace(long state);
-    /*package*/ static final native int nativeGetName(long state);
-    private static final native int nativeGetText(long state);
-    private static final native int nativeGetLineNumber(long state);
-    private static final native int nativeGetAttributeCount(long state);
-    private static final native int nativeGetAttributeNamespace(long state, int idx);
-    private static final native int nativeGetAttributeName(long state, int idx);
-    private static final native int nativeGetAttributeResource(long state, int idx);
-    private static final native int nativeGetAttributeDataType(long state, int idx);
-    private static final native int nativeGetAttributeData(long state, int idx);
-    private static final native int nativeGetAttributeStringValue(long state, int idx);
-    private static final native int nativeGetIdAttribute(long state);
-    private static final native int nativeGetClassAttribute(long state);
-    private static final native int nativeGetStyleAttribute(long state);
-    private static final native int nativeGetAttributeIndex(long state, String namespace, String name);
     private static final native void nativeDestroyParseState(long state);
-
     private static final native void nativeDestroy(long obj);
+
+    // ----------- @FastNative ------------------
+
+    @FastNative
+    /*package*/ static final native int nativeNext(long state);
+    @FastNative
+    private static final native int nativeGetNamespace(long state);
+    @FastNative
+    /*package*/ static final native int nativeGetName(long state);
+    @FastNative
+    private static final native int nativeGetText(long state);
+    @FastNative
+    private static final native int nativeGetLineNumber(long state);
+    @FastNative
+    private static final native int nativeGetAttributeCount(long state);
+    @FastNative
+    private static final native int nativeGetAttributeNamespace(long state, int idx);
+    @FastNative
+    private static final native int nativeGetAttributeName(long state, int idx);
+    @FastNative
+    private static final native int nativeGetAttributeResource(long state, int idx);
+    @FastNative
+    private static final native int nativeGetAttributeDataType(long state, int idx);
+    @FastNative
+    private static final native int nativeGetAttributeData(long state, int idx);
+    @FastNative
+    private static final native int nativeGetAttributeStringValue(long state, int idx);
+    @FastNative
+    private static final native int nativeGetIdAttribute(long state);
+    @FastNative
+    private static final native int nativeGetClassAttribute(long state);
+    @FastNative
+    private static final native int nativeGetStyleAttribute(long state);
+    @FastNative
+    private static final native int nativeGetAttributeIndex(long state, String namespace, String name);
 }
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 2dd4800..bb8d9ff 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -20,6 +20,7 @@
 import android.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase.CursorFactory;
 import android.util.Log;
+import java.io.File;
 
 /**
  * A helper class to manage database creation and version management.
@@ -54,6 +55,7 @@
     private final String mName;
     private final CursorFactory mFactory;
     private final int mNewVersion;
+    private final int mMinimumSupportedVersion;
 
     private SQLiteDatabase mDatabase;
     private boolean mIsInitializing;
@@ -96,6 +98,34 @@
      */
     public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
             DatabaseErrorHandler errorHandler) {
+        this(context, name, factory, version, 0, errorHandler);
+    }
+
+    /**
+     * Same as {@link #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)}
+     * but also accepts an integer minimumSupportedVersion as a convenience for upgrading very old
+     * versions of this database that are no longer supported. If a database with older version that
+     * minimumSupportedVersion is found, it is simply deleted and a new database is created with the
+     * given name and version
+     *
+     * @param context to use to open or create the database
+     * @param name the name of the database file, null for a temporary in-memory database
+     * @param factory to use for creating cursor objects, null for default
+     * @param version the required version of the database
+     * @param minimumSupportedVersion the minimum version that is supported to be upgraded to
+     *            {@code version} via {@link #onUpgrade}. If the current database version is lower
+     *            than this, database is simply deleted and recreated with the version passed in
+     *            {@code version}. {@link #onBeforeDelete} is called before deleting the database
+     *            when this happens. This is 0 by default.
+     * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
+     *            corruption, or null to use the default error handler.
+     * @see #onBeforeDelete(SQLiteDatabase)
+     * @see #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)
+     * @see #onUpgrade(SQLiteDatabase, int, int)
+     * @hide
+     */
+    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
+            int minimumSupportedVersion, DatabaseErrorHandler errorHandler) {
         if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
 
         mContext = context;
@@ -103,6 +133,7 @@
         mFactory = factory;
         mNewVersion = version;
         mErrorHandler = errorHandler;
+        mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
     }
 
     /**
@@ -245,21 +276,34 @@
                             db.getVersion() + " to " + mNewVersion + ": " + mName);
                 }
 
-                db.beginTransaction();
-                try {
-                    if (version == 0) {
-                        onCreate(db);
+                if (version > 0 && version < mMinimumSupportedVersion) {
+                    File databaseFile = new File(db.getPath());
+                    onBeforeDelete(db);
+                    db.close();
+                    if (SQLiteDatabase.deleteDatabase(databaseFile)) {
+                        mIsInitializing = false;
+                        return getDatabaseLocked(writable);
                     } else {
-                        if (version > mNewVersion) {
-                            onDowngrade(db, version, mNewVersion);
-                        } else {
-                            onUpgrade(db, version, mNewVersion);
-                        }
+                        throw new IllegalStateException("Unable to delete obsolete database "
+                                + mName + " with version " + version);
                     }
-                    db.setVersion(mNewVersion);
-                    db.setTransactionSuccessful();
-                } finally {
-                    db.endTransaction();
+                } else {
+                    db.beginTransaction();
+                    try {
+                        if (version == 0) {
+                            onCreate(db);
+                        } else {
+                            if (version > mNewVersion) {
+                                onDowngrade(db, version, mNewVersion);
+                            } else {
+                                onUpgrade(db, version, mNewVersion);
+                            }
+                        }
+                        db.setVersion(mNewVersion);
+                        db.setTransactionSuccessful();
+                    } finally {
+                        db.endTransaction();
+                    }
                 }
             }
 
@@ -292,18 +336,18 @@
     }
 
     /**
-     * Called when the database connection is being configured, to enable features
-     * such as write-ahead logging or foreign key support.
+     * Called when the database connection is being configured, to enable features such as
+     * write-ahead logging or foreign key support.
      * <p>
-     * This method is called before {@link #onCreate}, {@link #onUpgrade},
-     * {@link #onDowngrade}, or {@link #onOpen} are called.  It should not modify
-     * the database except to configure the database connection as required.
-     * </p><p>
-     * This method should only call methods that configure the parameters of the
-     * database connection, such as {@link SQLiteDatabase#enableWriteAheadLogging}
-     * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled},
-     * {@link SQLiteDatabase#setLocale}, {@link SQLiteDatabase#setMaximumSize},
-     * or executing PRAGMA statements.
+     * This method is called before {@link #onCreate}, {@link #onUpgrade}, {@link #onDowngrade}, or
+     * {@link #onOpen} are called. It should not modify the database except to configure the
+     * database connection as required.
+     * </p>
+     * <p>
+     * This method should only call methods that configure the parameters of the database
+     * connection, such as {@link SQLiteDatabase#enableWriteAheadLogging}
+     * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled}, {@link SQLiteDatabase#setLocale},
+     * {@link SQLiteDatabase#setMaximumSize}, or executing PRAGMA statements.
      * </p>
      *
      * @param db The database.
@@ -311,6 +355,20 @@
     public void onConfigure(SQLiteDatabase db) {}
 
     /**
+     * Called before the database is deleted when the version returned by
+     * {@link SQLiteDatabase#getVersion()} is lower than the minimum supported version passed (if at
+     * all) while creating this helper. After the database is deleted, a fresh database with the
+     * given version is created. This will be followed by {@link #onConfigure(SQLiteDatabase)} and
+     * {@link #onCreate(SQLiteDatabase)} being called with a new SQLiteDatabase object
+     *
+     * @param db the database opened with this helper
+     * @see #SQLiteOpenHelper(Context, String, CursorFactory, int, int, DatabaseErrorHandler)
+     * @hide
+     */
+    public void onBeforeDelete(SQLiteDatabase db) {
+    }
+
+    /**
      * Called when the database is created for the first time. This is where the
      * creation of tables and the initial population of the tables should happen.
      *
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index fafe116..45aeb4a 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -88,15 +88,13 @@
     /* Returns true if the specified USB function is enabled. */
     boolean isFunctionEnabled(String function);
 
-    /* Sets the current USB function. */
-    void setCurrentFunction(String function);
-
-    /* Sets whether USB data (for example, MTP exposed pictures) should be made
-     * available on the USB connection. Unlocking data should only be done with
-     * user involvement, since exposing pictures or other data could leak sensitive
-     * user information.
+    /* Sets the current USB function as well as whether USB data 
+     * (for example, MTP exposed pictures) should be made available 
+     * on the USB connection. Unlocking data should only be done with
+     * user involvement, since exposing pictures or other data could 
+     * leak sensitive user information.
      */
-    void setUsbDataUnlocked(boolean unlock);
+    void setCurrentFunction(String function, boolean usbDataUnlocked);
 
     /* Allow USB debugging from the attached host. If alwaysAllow is true, add the
      * the public key to list of host keys that the user has approved.
diff --git a/core/java/android/hardware/usb/UsbAccessory.java b/core/java/android/hardware/usb/UsbAccessory.java
index 2f9178c..4aeb40c 100644
--- a/core/java/android/hardware/usb/UsbAccessory.java
+++ b/core/java/android/hardware/usb/UsbAccessory.java
@@ -16,8 +16,11 @@
 
 package android.hardware.usb;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
 
 /**
  * A class representing a USB accessory, which is an external hardware component
@@ -46,12 +49,12 @@
 
     private static final String TAG = "UsbAccessory";
 
-    private final String mManufacturer;
-    private final String mModel;
-    private final String mDescription;
-    private final String mVersion;
-    private final String mUri;
-    private final String mSerial;
+    private final @NonNull String mManufacturer;
+    private final @NonNull String mModel;
+    private final @Nullable String mDescription;
+    private final @Nullable String mVersion;
+    private final @Nullable String mUri;
+    private final @Nullable String mSerial;
 
     /** @hide */
     public static final int MANUFACTURER_STRING = 0;
@@ -70,10 +73,11 @@
      * UsbAccessory should only be instantiated by UsbService implementation
      * @hide
      */
-    public UsbAccessory(String manufacturer, String model, String description,
-            String version, String uri, String serial) {
-        mManufacturer = manufacturer;
-        mModel = model;
+    public UsbAccessory(@NonNull String manufacturer, @NonNull String model,
+            @Nullable String description, @Nullable String version, @Nullable String uri,
+            @Nullable String serial) {
+        mManufacturer = Preconditions.checkNotNull(manufacturer);
+        mModel = Preconditions.checkNotNull(model);
         mDescription = description;
         mVersion = version;
         mUri = uri;
@@ -85,12 +89,8 @@
      * @hide
      */
     public UsbAccessory(String[] strings) {
-        mManufacturer = strings[MANUFACTURER_STRING];
-        mModel = strings[MODEL_STRING];
-        mDescription = strings[DESCRIPTION_STRING];
-        mVersion = strings[VERSION_STRING];
-        mUri = strings[URI_STRING];
-        mSerial = strings[SERIAL_STRING];
+        this(strings[MANUFACTURER_STRING], strings[MODEL_STRING], strings[DESCRIPTION_STRING],
+                strings[VERSION_STRING], strings[URI_STRING], strings[SERIAL_STRING]);
     }
 
     /**
@@ -98,7 +98,7 @@
      *
      * @return the accessory manufacturer
      */
-    public String getManufacturer() {
+    public @NonNull String getManufacturer() {
         return mManufacturer;
     }
 
@@ -107,25 +107,25 @@
      *
      * @return the accessory model
      */
-    public String getModel() {
+    public @NonNull String getModel() {
         return mModel;
     }
 
     /**
      * Returns a user visible description of the accessory.
      *
-     * @return the accessory description
+     * @return the accessory description, or {@code null} if not set
      */
-    public String getDescription() {
+    public @Nullable String getDescription() {
         return mDescription;
     }
 
     /**
      * Returns the version of the accessory.
      *
-     * @return the accessory version
+     * @return the accessory version, or {@code null} if not set
      */
-    public String getVersion() {
+    public @Nullable String getVersion() {
         return mVersion;
     }
 
@@ -134,9 +134,9 @@
      * This is an optional URI that might show information about the accessory
      * or provide the option to download an application for the accessory
      *
-     * @return the accessory URI
+     * @return the accessory URI, or {@code null} if not set
      */
-    public String getUri() {
+    public @Nullable String getUri() {
         return mUri;
     }
 
@@ -145,9 +145,9 @@
      * This is an optional serial number that can be used to differentiate
      * between individual accessories of the same model and manufacturer
      *
-     * @return the unique serial number
+     * @return the unique serial number, or {@code null} if not set
      */
-    public String getSerial() {
+    public @Nullable String getSerial() {
         return mSerial;
     }
 
@@ -172,12 +172,10 @@
 
     @Override
     public int hashCode() {
-        return ((mManufacturer == null ? 0 : mManufacturer.hashCode()) ^
-                (mModel == null ? 0 : mModel.hashCode()) ^
+        return mManufacturer.hashCode() ^ mModel.hashCode() ^
                 (mDescription == null ? 0 : mDescription.hashCode()) ^
                 (mVersion == null ? 0 : mVersion.hashCode()) ^
-                (mUri == null ? 0 : mUri.hashCode()) ^
-                (mSerial == null ? 0 : mSerial.hashCode()));
+                (mUri == null ? 0 : mUri.hashCode()) ^ (mSerial == null ? 0 : mSerial.hashCode());
     }
 
     @Override
diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java
index da5c128..a171570 100644
--- a/core/java/android/hardware/usb/UsbConfiguration.java
+++ b/core/java/android/hardware/usb/UsbConfiguration.java
@@ -16,8 +16,11 @@
 
 package android.hardware.usb;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
 
 /**
  * A class representing a configuration on a {@link UsbDevice}.
@@ -35,20 +38,20 @@
 public class UsbConfiguration implements Parcelable {
 
     private final int mId;
-    private final String mName;
+    private final @Nullable String mName;
     private final int mAttributes;
     private final int mMaxPower;
-    private Parcelable[] mInterfaces;
+
+    /** All interfaces for this config, only null during creation */
+    private @Nullable Parcelable[] mInterfaces;
 
     /**
      * Mask for "self-powered" bit in the configuration's attributes.
-     * @see #getAttributes
      */
     private static final int ATTR_SELF_POWERED = 1 << 6;
 
     /**
      * Mask for "remote wakeup" bit in the configuration's attributes.
-     * @see #getAttributes
      */
     private static final int ATTR_REMOTE_WAKEUP = 1 << 5;
 
@@ -56,7 +59,7 @@
      * UsbConfiguration should only be instantiated by UsbService implementation
      * @hide
      */
-    public UsbConfiguration(int id, String name, int attributes, int maxPower) {
+    public UsbConfiguration(int id, @Nullable String name, int attributes, int maxPower) {
         mId = id;
         mName = name;
         mAttributes = attributes;
@@ -76,9 +79,9 @@
     /**
      * Returns the configuration's name.
      *
-     * @return the configuration's name
+     * @return the configuration's name, or {@code null} if the property could not be read
      */
-    public String getName() {
+    public @Nullable String getName() {
         return mName;
     }
 
@@ -125,7 +128,7 @@
      *
      * @return the interface
      */
-    public UsbInterface getInterface(int index) {
+    public @NonNull UsbInterface getInterface(int index) {
         return (UsbInterface)mInterfaces[index];
     }
 
@@ -133,8 +136,8 @@
      * Only used by UsbService implementation
      * @hide
      */
-    public void setInterfaces(Parcelable[] interfaces) {
-        mInterfaces = interfaces;
+    public void setInterfaces(@NonNull Parcelable[] interfaces) {
+        mInterfaces = Preconditions.checkArrayElementsNotNull(interfaces, "interfaces");
     }
 
     @Override
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index 410d550..425a89d 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -16,8 +16,11 @@
 
 package android.hardware.usb;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
 
 /**
  * This class represents a USB device attached to the android device with the android device
@@ -42,29 +45,31 @@
     private static final String TAG = "UsbDevice";
     private static final boolean DEBUG = false;
 
-    private final String mName;
-    private final String mManufacturerName;
-    private final String mProductName;
-    private final String mVersion;
-    private final String mSerialNumber;
+    private final @NonNull String mName;
+    private final @Nullable String mManufacturerName;
+    private final @Nullable String mProductName;
+    private final @NonNull String mVersion;
+    private final @Nullable String mSerialNumber;
     private final int mVendorId;
     private final int mProductId;
     private final int mClass;
     private final int mSubclass;
     private final int mProtocol;
-    private Parcelable[] mConfigurations;
 
-    // list of all interfaces on the device
-    private UsbInterface[] mInterfaces;
+    /** All configurations for this device, only null during creation */
+    private @Nullable Parcelable[] mConfigurations;
+
+    /** All interfaces on the device. Initialized on first call to getInterfaceList */
+    private @Nullable UsbInterface[] mInterfaces;
 
     /**
      * UsbDevice should only be instantiated by UsbService implementation
      * @hide
      */
-    public UsbDevice(String name, int vendorId, int productId,
-            int Class, int subClass, int protocol,
-            String manufacturerName, String productName, String version, String serialNumber) {
-        mName = name;
+    public UsbDevice(@NonNull String name, int vendorId, int productId, int Class, int subClass,
+            int protocol, @Nullable String manufacturerName, @Nullable String productName,
+            @NonNull String version, @Nullable String serialNumber) {
+        mName = Preconditions.checkNotNull(name);
         mVendorId = vendorId;
         mProductId = productId;
         mClass = Class;
@@ -72,7 +77,7 @@
         mProtocol = protocol;
         mManufacturerName = manufacturerName;
         mProductName = productName;
-        mVersion = version;
+        mVersion = Preconditions.checkStringNotEmpty(version);
         mSerialNumber = serialNumber;
     }
 
@@ -83,25 +88,25 @@
      *
      * @return the device name
      */
-    public String getDeviceName() {
+    public @NonNull String getDeviceName() {
         return mName;
     }
 
     /**
      * Returns the manufacturer name of the device.
      *
-     * @return the manufacturer name
+     * @return the manufacturer name, or {@code null} if the property could not be read
      */
-    public String getManufacturerName() {
+    public @Nullable String getManufacturerName() {
         return mManufacturerName;
     }
 
     /**
      * Returns the product name of the device.
      *
-     * @return the product name
+     * @return the product name, or {@code null} if the property could not be read
      */
-    public String getProductName() {
+    public @Nullable String getProductName() {
         return mProductName;
     }
 
@@ -110,16 +115,16 @@
      *
      * @return the device version
      */
-    public String getVersion() {
+    public @NonNull String getVersion() {
         return mVersion;
     }
 
     /**
      * Returns the serial number of the device.
      *
-     * @return the serial number name
+     * @return the serial number name, or {@code null} if the property could not be read
      */
-    public String getSerialNumber() {
+    public @Nullable String getSerialNumber() {
         return mSerialNumber;
     }
 
@@ -195,11 +200,11 @@
      *
      * @return the configuration
      */
-    public UsbConfiguration getConfiguration(int index) {
+    public @NonNull UsbConfiguration getConfiguration(int index) {
         return (UsbConfiguration)mConfigurations[index];
     }
 
-    private UsbInterface[] getInterfaceList() {
+    private @Nullable UsbInterface[] getInterfaceList() {
         if (mInterfaces == null) {
             int configurationCount = mConfigurations.length;
             int interfaceCount = 0;
@@ -240,7 +245,7 @@
      *
      * @return the interface
      */
-    public UsbInterface getInterface(int index) {
+    public @NonNull UsbInterface getInterface(int index) {
         return getInterfaceList()[index];
     }
 
@@ -248,8 +253,8 @@
      * Only used by UsbService implementation
      * @hide
      */
-    public void setConfigurations(Parcelable[] configuration) {
-        mConfigurations = configuration;
+    public void setConfigurations(@NonNull Parcelable[] configuration) {
+        mConfigurations = Preconditions.checkArrayElementsNotNull(configuration, "configuration");
     }
 
     @Override
diff --git a/core/java/android/hardware/usb/UsbInterface.java b/core/java/android/hardware/usb/UsbInterface.java
index de01a88..4b5278c 100644
--- a/core/java/android/hardware/usb/UsbInterface.java
+++ b/core/java/android/hardware/usb/UsbInterface.java
@@ -16,8 +16,10 @@
 
 package android.hardware.usb;
 
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
 
 /**
  * A class representing an interface on a {@link UsbDevice}.
@@ -36,17 +38,19 @@
 
     private final int mId;
     private final int mAlternateSetting;
-    private final String mName;
+    private @Nullable final String mName;
     private final int mClass;
     private final int mSubclass;
     private final int mProtocol;
+
+    /** All endpoints of this interface, only null during creation */
     private Parcelable[] mEndpoints;
 
     /**
      * UsbInterface should only be instantiated by UsbService implementation
      * @hide
      */
-    public UsbInterface(int id, int alternateSetting, String name,
+    public UsbInterface(int id, int alternateSetting, @Nullable String name,
             int Class, int subClass, int protocol) {
         mId = id;
         mAlternateSetting = alternateSetting;
@@ -83,9 +87,9 @@
     /**
      * Returns the interface's name.
      *
-     * @return the interface's name
+     * @return the interface's name, or {@code null} if the property could not be read
      */
-    public String getName() {
+    public @Nullable String getName() {
         return mName;
     }
 
@@ -140,7 +144,7 @@
      * @hide
      */
     public void setEndpoints(Parcelable[] endpoints) {
-        mEndpoints = endpoints;
+        mEndpoints = Preconditions.checkArrayElementsNotNull(endpoints, "endpoints");
     }
 
     @Override
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 1d20c78..3636e4e 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -542,33 +542,23 @@
      * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
      * or {@link #USB_FUNCTION_RNDIS}.
      * </p><p>
+     * Also sets whether USB data (for example, MTP exposed pictures) should be made available
+     * on the USB connection when in device mode. Unlocking usb data should only be done with
+     * user involvement, since exposing pictures or other data could leak sensitive
+     * user information.
+     * </p><p>
      * Note: This function is asynchronous and may fail silently without applying
      * the requested changes.
      * </p>
      *
      * @param function name of the USB function, or null to restore the default function
+     * @param usbDataUnlocked whether user data is accessible
      *
      * {@hide}
      */
-    public void setCurrentFunction(String function) {
+    public void setCurrentFunction(String function, boolean usbDataUnlocked) {
         try {
-            mService.setCurrentFunction(function);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Sets whether USB data (for example, MTP exposed pictures) should be made available
-     * on the USB connection when in device mode. Unlocking usb data should only be done with
-     * user involvement, since exposing pictures or other data could leak sensitive
-     * user information.
-     *
-     * {@hide}
-     */
-    public void setUsbDataUnlocked(boolean unlocked) {
-        try {
-            mService.setUsbDataUnlocked(unlocked);
+            mService.setCurrentFunction(function, usbDataUnlocked);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java
index ea53a71..eace8b2 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -124,6 +124,10 @@
         return false;
     }
 
+    public boolean isUp() {
+        return hasFlag(FLAG_UP);
+    }
+
     /** {@inheritDoc} */
     public int describeContents() {
         return 0;
diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java
index 59c5fb6..c3abcf7 100644
--- a/core/java/android/net/metrics/DhcpErrorEvent.java
+++ b/core/java/android/net/metrics/DhcpErrorEvent.java
@@ -50,9 +50,13 @@
     public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3);
     public static final int DHCP_NO_MSG_TYPE           = makeErrorCode(DHCP_ERROR, 4);
     public static final int DHCP_UNKNOWN_MSG_TYPE      = makeErrorCode(DHCP_ERROR, 5);
+    /** {@hide} */
+    public static final int DHCP_NO_COOKIE             = makeErrorCode(DHCP_ERROR, 6);
 
     public static final int BUFFER_UNDERFLOW           = makeErrorCode(MISC_ERROR, 1);
     public static final int RECEIVE_ERROR              = makeErrorCode(MISC_ERROR, 2);
+    /** {@hide} */
+    public static final int PARSING_ERROR              = makeErrorCode(MISC_ERROR, 3);
 
     public final String ifName;
     // error code byte format (MSB to LSB):
@@ -115,8 +119,9 @@
     }
 
     final static class Decoder {
-        static final SparseArray<String> constants =
-                MessageUtils.findMessageNames(new Class[]{DhcpErrorEvent.class},
-                new String[]{"L2_", "L3_", "L4_", "BOOTP_", "DHCP_", "BUFFER_", "RECEIVE_"});
+        static final SparseArray<String> constants = MessageUtils.findMessageNames(
+                new Class[]{DhcpErrorEvent.class},
+                new String[]{"L2_", "L3_", "L4_", "BOOTP_", "DHCP_", "BUFFER_", "RECEIVE_",
+                "PARSING_"});
     }
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 95dd148..3d5d900 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -5433,7 +5433,8 @@
         if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             if (dumpDurationSteps(pw, "  ", "Discharge step durations:",
                     getDischargeLevelStepTracker(), false)) {
-                long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
+                long timeRemaining = computeBatteryTimeRemaining(
+                    SystemClock.elapsedRealtime() * 1000);
                 if (timeRemaining >= 0) {
                     pw.print("  Estimated discharge time remaining: ");
                     TimeUtils.formatDuration(timeRemaining / 1000, pw);
@@ -5449,7 +5450,8 @@
             }
             if (dumpDurationSteps(pw, "  ", "Charge step durations:",
                     getChargeLevelStepTracker(), false)) {
-                long timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
+                long timeRemaining = computeChargeTimeRemaining(
+                    SystemClock.elapsedRealtime() * 1000);
                 if (timeRemaining >= 0) {
                     pw.print("  Estimated charge time remaining: ");
                     TimeUtils.formatDuration(timeRemaining / 1000, pw);
@@ -5612,14 +5614,14 @@
         if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             dumpDurationSteps(pw, "", DISCHARGE_STEP_DATA, getDischargeLevelStepTracker(), true);
             String[] lineArgs = new String[1];
-            long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
+            long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime() * 1000);
             if (timeRemaining >= 0) {
                 lineArgs[0] = Long.toString(timeRemaining);
                 dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
                         (Object[])lineArgs);
             }
             dumpDurationSteps(pw, "", CHARGE_STEP_DATA, getChargeLevelStepTracker(), true);
-            timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
+            timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime() * 1000);
             if (timeRemaining >= 0) {
                 lineArgs[0] = Long.toString(timeRemaining);
                 dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 7061589..d04d6c2 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -329,25 +329,49 @@
      * Filter values in Bundle to only basic types.
      * @hide
      */
-    public void filterValues() {
+    public Bundle filterValues() {
         unparcel();
+        Bundle bundle = this;
         if (mMap != null) {
-            for (int i = mMap.size() - 1; i >= 0; i--) {
-                Object value = mMap.valueAt(i);
+            ArrayMap<String, Object> map = mMap;
+            for (int i = map.size() - 1; i >= 0; i--) {
+                Object value = map.valueAt(i);
                 if (PersistableBundle.isValidType(value)) {
                     continue;
                 }
                 if (value instanceof Bundle) {
-                    ((Bundle)value).filterValues();
+                    Bundle newBundle = ((Bundle)value).filterValues();
+                    if (newBundle != value) {
+                        if (map == mMap) {
+                            // The filter had to generate a new bundle, but we have not yet
+                            // created a new one here.  Do that now.
+                            bundle = new Bundle(this);
+                            // Note the ArrayMap<> constructor is guaranteed to generate
+                            // a new object with items in the same order as the original.
+                            map = bundle.mMap;
+                        }
+                        // Replace this current entry with the new child bundle.
+                        map.setValueAt(i, newBundle);
+                    }
+                    continue;
                 }
                 if (value.getClass().getName().startsWith("android.")) {
                     continue;
                 }
-                mMap.removeAt(i);
+                if (map == mMap) {
+                    // This is the first time we have had to remove something, that means we
+                    // need to switch to a new Bundle.
+                    bundle = new Bundle(this);
+                    // Note the ArrayMap<> constructor is guaranteed to generate
+                    // a new object with items in the same order as the original.
+                    map = bundle.mMap;
+                }
+                map.removeAt(i);
             }
         }
         mFlags |= FLAG_HAS_FDS_KNOWN;
         mFlags &= ~FLAG_HAS_FDS;
+        return bundle;
     }
 
     /**
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index eeb641d..65c6093 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -36,7 +36,8 @@
     int getCredentialOwnerProfile(int userHandle);
 
     UserInfo createUser(in String name, int flags);
-    UserInfo createProfileForUser(in String name, int flags, int userHandle);
+    UserInfo createProfileForUser(in String name, int flags, int userHandle,
+            in String[] disallowedPackages);
     UserInfo createRestrictedProfile(String name, int parentUserHandle);
     void setUserEnabled(int userHandle);
     boolean removeUser(int userHandle);
@@ -82,4 +83,7 @@
     boolean someUserHasSeedAccount(in String accountName, in String accountType);
     boolean isManagedProfile(int userId);
     boolean isDemoUser(int userId);
+    UserInfo createProfileForUserEvenWhenDisallowed(in String name, int flags, int userHandle,
+            in String[] disallowedPackages);
+    boolean isUserUnlockingOrUnlocked(int userId);
 }
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index 9bbe8f9..c153184 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -53,24 +53,6 @@
      */
     public static final int WAKEFULNESS_DOZING = 3;
 
-
-    /**
-     * Power hint:
-     * Interaction: The user is interacting with the device. The corresponding data field must be
-     * the expected duration of the interaction, or 0 if unknown.
-     *
-     * Sustained Performance Mode: The corresponding data field must be Enable/Disable
-     * Sustained Performance Mode.
-     *
-     * Launch: This is specific for activity launching. The corresponding data field must be
-     * the expected duration of the required boost, or 0 if unknown.
-     *
-     * These must be kept in sync with the values in hardware/libhardware/include/hardware/power.h
-     */
-    public static final int POWER_HINT_INTERACTION = 2;
-    public static final int POWER_HINT_SUSTAINED_PERFORMANCE_MODE = 6;
-    public static final int POWER_HINT_LAUNCH = 8;
-
     public static String wakefulnessToString(int wakefulness) {
         switch (wakefulness) {
             case WAKEFULNESS_ASLEEP:
@@ -169,5 +151,9 @@
 
     public abstract void uidGone(int uid);
 
+    /**
+     * The hintId sent through this method should be in-line with the
+     * PowerHint defined in android/hardware/power/<version 1.0 & up>/IPower.h
+     */
     public abstract void powerHint(int hintId, int data);
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index e9ebe2d..f9dee92 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -17,8 +17,6 @@
 package android.os;
 
 import android.annotation.TestApi;
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
 import android.system.Os;
 import android.system.OsConstants;
 import android.util.Log;
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index 831c9b2..dbb9650 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -188,6 +188,25 @@
     }
 
     /**
+     * Helper for just system services to ask the shell to open an output file.
+     * @hide
+     */
+    public ParcelFileDescriptor openOutputFileForSystem(String path) {
+        try {
+            ParcelFileDescriptor pfd = getShellCallback().openOutputFile(path,
+                    "u:r:system_server:s0");
+            if (pfd != null) {
+                return pfd;
+            }
+        } catch (RuntimeException e) {
+            getErrPrintWriter().println("Failure opening file: " + e.getMessage());
+        }
+        getErrPrintWriter().println("Error: Unable to open file: " + path);
+        getErrPrintWriter().println("Consider using a file under /data/local/tmp/");
+        return null;
+    }
+
+    /**
      * Return the next option on the command line -- that is an argument that
      * starts with '-'.  If the next argument is not an option, null is returned.
      */
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 5dc18fb..bc5af81 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1094,10 +1094,8 @@
 
     /** {@hide} */
     public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) {
-        // TODO Switch to using UMS internal isUserUnlockingOrUnlocked
         try {
-            return ActivityManagerNative.getDefault().isUserRunning(userId,
-                    ActivityManager.FLAG_AND_UNLOCKING_OR_UNLOCKED);
+            return mService.isUserUnlockingOrUnlocked(userId);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -1340,15 +1338,52 @@
      *
      * @param name the user's name
      * @param flags flags that identify the type of user and other properties.
-     * @see UserInfo
-     * @param userHandle new user will be a profile of this use.
+     * @param userHandle new user will be a profile of this user.
      *
-     * @return the UserInfo object for the created user, or null if the user could not be created.
+     * @return the {@link UserInfo} object for the created user, or null if the user
+     *         could not be created.
      * @hide
      */
     public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userHandle) {
+        return createProfileForUser(name, flags, userHandle, null);
+    }
+
+    /**
+     * Version of {@link #createProfileForUser(String, int, int)} that allows you to specify
+     * any packages that should not be installed in the new profile by default, these packages can
+     * still be installed later by the user if needed.
+     *
+     * @param name the user's name
+     * @param flags flags that identify the type of user and other properties.
+     * @param userHandle new user will be a profile of this user.
+     * @param disallowedPackages packages that will not be installed in the profile being created.
+     *
+     * @return the {@link UserInfo} object for the created user, or null if the user
+     *         could not be created.
+     * @hide
+     */
+    public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userHandle,
+            String[] disallowedPackages) {
         try {
-            return mService.createProfileForUser(name, flags, userHandle);
+            return mService.createProfileForUser(name, flags, userHandle, disallowedPackages);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Similar to {@link #createProfileForUser(String, int, int, String[])}
+     * except bypassing the checking of {@link UserManager#DISALLOW_ADD_USER}.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     *
+     * @see #createProfileForUser(String, int, int, String[])
+     * @hide
+     */
+    public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags,
+            @UserIdInt int userHandle, String[] disallowedPackages) {
+        try {
+            return mService.createProfileForUserEvenWhenDisallowed(name, flags, userHandle,
+                    disallowedPackages);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 7399b7b..e399be0 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -437,7 +437,7 @@
 
         final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
-        intent.setData(uri);
+        intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
 
         // note that docsui treats this as *force* show advanced. So sending
         // false permits advanced to be shown based on user preferences.
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index f134943..3d094f7 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -586,8 +586,6 @@
      *
      * @param key The option key.
      * @return Whether the option is present.
-     *
-     * @hide
      */
     public boolean hasAdvancedOption(String key) {
         return mAdvancedOptions != null && mAdvancedOptions.containsKey(key);
@@ -598,8 +596,6 @@
      *
      * @param key The option key.
      * @return The option value.
-     *
-     * @hide
      */
     public String getAdvancedStringOption(String key) {
         if (mAdvancedOptions != null) {
@@ -613,8 +609,6 @@
      *
      * @param key The option key.
      * @return The option value.
-     *
-     * @hide
      */
     public int getAdvancedIntOption(String key) {
         if (mAdvancedOptions != null) {
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index 8f73518..ecf1770 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -18,6 +18,8 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.PendingIntent;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Context;
@@ -29,6 +31,7 @@
 import android.os.RemoteException;
 import android.print.PrintJobInfo;
 import android.print.PrinterId;
+import android.print.PrinterInfo;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
@@ -247,6 +250,26 @@
     public static final String EXTRA_PRINT_DOCUMENT_INFO =
             "android.printservice.extra.PRINT_DOCUMENT_INFO";
 
+    /**
+     * When the {@link PendingIntent} declared via
+     * {@link PrinterInfo.Builder#setInfoIntent(PendingIntent)} is called this boolean extra
+     * will be filled in if the activity can select the printer.
+     *
+     * @see #EXTRA_SELECT_PRINTER
+     */
+    public static final String EXTRA_CAN_SELECT_PRINTER =
+            "android.printservice.extra.CAN_SELECT_PRINTER";
+
+    /**
+     * If this boolean extra is set to {@code true} in the {@link Activity#setResult(int, Intent)
+     * result data} from the activity specified in
+     * {@link PrinterInfo.Builder#setInfoIntent(PendingIntent)} the printer will be selected.
+     *
+     * @see #EXTRA_CAN_SELECT_PRINTER
+     */
+    public static final String EXTRA_SELECT_PRINTER =
+            "android.printservice.extra.SELECT_PRINTER";
+
     private Handler mHandler;
 
     private IPrintServiceClient mClient;
diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java
index d409030..b31b295 100644
--- a/core/java/android/provider/Contacts.java
+++ b/core/java/android/provider/Contacts.java
@@ -438,21 +438,11 @@
         public static final String PRIMARY_ORGANIZATION_ID = "primary_organization";
 
         /**
-         * Mark a person as having been contacted.
-         *
-         * @param resolver the ContentResolver to use
-         * @param personId the person who was contacted
-         * @deprecated see {@link android.provider.ContactsContract}
+         * This API is no longer supported as of O.
          */
         @Deprecated
         public static void markAsContacted(ContentResolver resolver, long personId) {
-            Uri uri = ContentUris.withAppendedId(CONTENT_URI, personId);
-            uri = Uri.withAppendedPath(uri, "update_contact_time");
-            ContentValues values = new ContentValues();
-            // There is a trigger in place that will update TIMES_CONTACTED when
-            // LAST_TIME_CONTACTED is modified.
-            values.put(LAST_TIME_CONTACTED, System.currentTimeMillis());
-            resolver.update(uri, values, null, null);
+            // No longer supported.
         }
 
         /**
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index a1763c0..a07aee5 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -19,8 +19,6 @@
 import android.accounts.Account;
 import android.annotation.SystemApi;
 import android.app.Activity;
-import android.app.admin.DevicePolicyManager;
-import android.content.ActivityNotFoundException;
 import android.content.ContentProviderClient;
 import android.content.ContentProviderOperation;
 import android.content.ContentResolver;
@@ -44,7 +42,6 @@
 import android.util.DisplayMetrics;
 import android.util.Pair;
 import android.view.View;
-import android.widget.Toast;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -118,6 +115,12 @@
     public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
 
     /**
+     * Prefix for column names that are not visible to client apps.
+     * @hide
+     */
+    public static final String HIDDEN_COLUMN_PREFIX = "x_";
+
+    /**
      * An optional URI parameter for insert, update, or delete queries
      * that allows the caller
      * to specify that it is a sync adapter. The default value is false. If true
@@ -661,6 +664,12 @@
             ContentValues contentValues = new ContentValues();
             resolver.update(Directory.CONTENT_URI, contentValues, null, null);
         }
+
+        /**
+         * A query parameter that's passed to directory providers which indicates the client
+         * package name that has made the query requests.
+         */
+        public static final String CALLER_PACKAGE_PARAM_KEY = "callerPackage";
     }
 
     /**
@@ -863,6 +872,25 @@
          */
         public static final String LAST_TIME_CONTACTED = "last_time_contacted";
 
+        /** @hide Raw value. */
+        public static final String RAW_TIMES_CONTACTED = HIDDEN_COLUMN_PREFIX + TIMES_CONTACTED;
+
+        /** @hide Raw value. */
+        public static final String RAW_LAST_TIME_CONTACTED =
+                HIDDEN_COLUMN_PREFIX + LAST_TIME_CONTACTED;
+
+        /**
+         * @hide
+         * Low res version.  Same as {@link #TIMES_CONTACTED} but use it in CP2 for clarification.
+         */
+        public static final String LR_TIMES_CONTACTED = TIMES_CONTACTED;
+
+        /**
+         * @hide
+         * Low res version.  Same as {@link #TIMES_CONTACTED} but use it in CP2 for clarification.
+         */
+        public static final String LR_LAST_TIME_CONTACTED = LAST_TIME_CONTACTED;
+
         /**
          * Is the contact starred?
          * <P>Type: INTEGER (boolean)</P>
@@ -1669,7 +1697,7 @@
             Uri uri = ContentUris.withAppendedId(CONTENT_URI, contactId);
             ContentValues values = new ContentValues();
             // TIMES_CONTACTED will be incremented when LAST_TIME_CONTACTED is modified.
-            values.put(LAST_TIME_CONTACTED, System.currentTimeMillis());
+            values.put(LR_LAST_TIME_CONTACTED, System.currentTimeMillis());
             resolver.update(uri, values, null, null);
         }
 
@@ -4224,6 +4252,24 @@
 
         /** The number of times the referenced {@link Data} has been used. */
         public static final String TIMES_USED = "times_used";
+
+        /** @hide Raw value. */
+        public static final String RAW_LAST_TIME_USED = HIDDEN_COLUMN_PREFIX + LAST_TIME_USED;
+
+        /** @hide Raw value. */
+        public static final String RAW_TIMES_USED = HIDDEN_COLUMN_PREFIX + TIMES_USED;
+
+        /**
+         * @hide
+         * Low res version.  Same as {@link #LAST_TIME_USED} but use it in CP2 for clarification.
+         */
+        public static final String LR_LAST_TIME_USED = LAST_TIME_USED;
+
+        /**
+         * @hide
+         * Low res version.  Same as {@link #TIMES_USED} but use it in CP2 for clarification.
+         */
+        public static final String LR_TIMES_USED = TIMES_USED;
     }
 
     /**
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 6ddaf3b..a858324 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -19,6 +19,10 @@
 import static android.net.TrafficStats.KB_IN_BYTES;
 import static android.system.OsConstants.SEEK_SET;
 
+import static com.android.internal.util.Preconditions.checkArgument;
+import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
+import static com.android.internal.util.Preconditions.checkCollectionNotEmpty;
+
 import android.annotation.Nullable;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
@@ -36,8 +40,10 @@
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.OperationCanceledException;
+import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.OnCloseListener;
+import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.storage.StorageVolume;
 import android.system.ErrnoException;
@@ -53,6 +59,7 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Defines the contract between a documents provider and the platform.
@@ -644,6 +651,8 @@
     public static final String METHOD_REMOVE_DOCUMENT = "android:removeDocument";
     /** {@hide} */
     public static final String METHOD_EJECT_ROOT = "android:ejectRoot";
+    /** {@hide} */
+    public static final String METHOD_FIND_PATH = "android:findPath";
 
     /** {@hide} */
     public static final String EXTRA_PARENT_URI = "parentUri";
@@ -1307,6 +1316,59 @@
     }
 
     /**
+     * Finds the canonical path to the top of the tree. The return value starts
+     * from the top of the tree or the root document to the requested document,
+     * both inclusive.
+     *
+     * 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}
+     */
+    public static List<String> findPath(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();
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to find path", e);
+            return null;
+        } finally {
+            ContentProviderClient.releaseQuietly(client);
+        }
+    }
+
+    /**
+     * Finds the canonical path. If uri is a document uri returns path to a root and
+     * its associated root id. If uri is a tree uri returns the path to the top of
+     * the tree. The {@link Path#getPath()} in the return value starts from the top of
+     * the tree or the root document to the requested document, both inclusive.
+     *
+     * Document id should be unique across roots.
+     *
+     * @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)
+     *
+     * {@hide}
+     */
+    public static Path findPath(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);
+
+        return out.getParcelable(DocumentsContract.EXTRA_RESULT);
+    }
+
+    /**
      * Open the given image for thumbnail purposes, using any embedded EXIF
      * thumbnail if available, and providing orientation hints from the parent
      * image.
@@ -1345,4 +1407,102 @@
 
         return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH, extras);
     }
+
+    /**
+     * Holds a path from a root to a particular document under it.
+     *
+     * @hide
+     */
+    public static final class Path implements Parcelable {
+
+        private final @Nullable String mRootId;
+        private final List<String> mPath;
+
+        /**
+         * 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
+         *          position 0 to the child document.
+         */
+        public Path(String rootId, List<String> path) {
+            checkCollectionNotEmpty(path, "path");
+            checkCollectionElementsNotNull(path, "path");
+
+            mRootId = rootId;
+            mPath = path;
+        }
+
+        /**
+         * Returns the root id or null if the calling package doesn't have
+         * permission to access root information.
+         */
+        public @Nullable String getRootId() {
+            return mRootId;
+        }
+
+        /**
+         * Returns the path. The path is trimmed to the top of tree if
+         * calling package doesn't have permission to access those
+         * documents.
+         */
+        public List<String> getPath() {
+            return mPath;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || !(o instanceof Path)) {
+                return false;
+            }
+            Path path = (Path) o;
+            return Objects.equals(mRootId, path.mRootId) &&
+                    Objects.equals(mPath, path.mPath);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mRootId, mPath);
+        }
+
+        @Override
+        public String toString() {
+            return new StringBuilder()
+                    .append("DocumentsContract.Path{")
+                    .append("rootId=")
+                    .append(mRootId)
+                    .append(", path=")
+                    .append(mPath)
+                    .append("}")
+                    .toString();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeString(mRootId);
+            dest.writeStringList(mPath);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        public static final Creator<Path> CREATOR = new Creator<Path>() {
+            @Override
+            public Path createFromParcel(Parcel in) {
+                final String rootId = in.readString();
+                final List<String> path = in.createStringArrayList();
+                return new Path(rootId, path);
+            }
+
+            @Override
+            public Path[] newArray(int size) {
+                return new Path[size];
+            }
+        };
+    }
 }
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 6117ce4..d75781b 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -20,6 +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_IS_CHILD_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_MOVE_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_REMOVE_DOCUMENT;
@@ -33,7 +34,9 @@
 import static android.provider.DocumentsContract.getTreeDocumentId;
 import static android.provider.DocumentsContract.isTreeUri;
 
+import android.Manifest;
 import android.annotation.CallSuper;
+import android.annotation.Nullable;
 import android.content.ClipDescription;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -52,6 +55,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.OnCloseListener;
 import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Path;
 import android.provider.DocumentsContract.Root;
 import android.util.Log;
 
@@ -151,17 +155,7 @@
      */
     @Override
     public void attachInfo(Context context, ProviderInfo info) {
-        mAuthority = info.authority;
-
-        mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
-        mMatcher.addURI(mAuthority, "root", MATCH_ROOTS);
-        mMatcher.addURI(mAuthority, "root/*", MATCH_ROOT);
-        mMatcher.addURI(mAuthority, "root/*/recent", MATCH_RECENT);
-        mMatcher.addURI(mAuthority, "root/*/search", MATCH_SEARCH);
-        mMatcher.addURI(mAuthority, "document/*", MATCH_DOCUMENT);
-        mMatcher.addURI(mAuthority, "document/*/children", MATCH_CHILDREN);
-        mMatcher.addURI(mAuthority, "tree/*/document/*", MATCH_DOCUMENT_TREE);
-        mMatcher.addURI(mAuthority, "tree/*/document/*/children", MATCH_CHILDREN_TREE);
+        registerAuthority(info.authority);
 
         // Sanity check our setup
         if (!info.exported) {
@@ -178,6 +172,28 @@
         super.attachInfo(context, info);
     }
 
+    /** {@hide} */
+    @Override
+    public void attachInfoForTesting(Context context, ProviderInfo info) {
+        registerAuthority(info.authority);
+
+        super.attachInfoForTesting(context, info);
+    }
+
+    private void registerAuthority(String authority) {
+        mAuthority = authority;
+
+        mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+        mMatcher.addURI(mAuthority, "root", MATCH_ROOTS);
+        mMatcher.addURI(mAuthority, "root/*", MATCH_ROOT);
+        mMatcher.addURI(mAuthority, "root/*/recent", MATCH_RECENT);
+        mMatcher.addURI(mAuthority, "root/*/search", MATCH_SEARCH);
+        mMatcher.addURI(mAuthority, "document/*", MATCH_DOCUMENT);
+        mMatcher.addURI(mAuthority, "document/*/children", MATCH_CHILDREN);
+        mMatcher.addURI(mAuthority, "tree/*/document/*", MATCH_DOCUMENT_TREE);
+        mMatcher.addURI(mAuthority, "tree/*/document/*/children", MATCH_CHILDREN_TREE);
+    }
+
     /**
      * Test if a document is descendant (child, grandchild, etc) from the given
      * parent. For example, providers must implement this to support
@@ -323,6 +339,31 @@
     }
 
     /**
+     * Finds the canonical path for the requested document. The path must start
+     * from the parent document if parentDocumentId is not null or the root document
+     * if parentDocumentId is null. If there are more than one path to this document,
+     * return the most typical one. Include both the parent document or root document
+     * and the requested document in the returned path.
+     *
+     * <p>This API assumes that document ID has enough info to infer the root.
+     * Different roots should use different document ID to refer to the same
+     * 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.
+     * @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)
+            throws FileNotFoundException {
+        throw new UnsupportedOperationException("findPath not supported.");
+    }
+
+    /**
      * Return all roots currently provided. To display to users, you must define
      * at least one root. You should avoid making network requests to keep this
      * request fast.
@@ -873,6 +914,30 @@
 
             // 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)) {
+            final boolean isTreeUri = isTreeUri(documentUri);
+
+            if (isTreeUri) {
+                enforceReadPermissionInner(documentUri, getCallingPackage(), null);
+            } else {
+                getContext().enforceCallingPermission(Manifest.permission.MANAGE_DOCUMENTS, null);
+            }
+
+            final String parentDocumentId = isTreeUri
+                    ? DocumentsContract.getTreeDocumentId(documentUri)
+                    : null;
+
+            final Path path = findPath(documentId, parentDocumentId);
+
+            // Ensure provider doesn't leak information to unprivileged callers.
+            if (isTreeUri
+                    && (path.getRootId() != null
+                        || !Objects.equals(path.getPath().get(0), parentDocumentId))) {
+                throw new IllegalStateException(
+                        "Provider returns an invalid result for findPath.");
+            }
+
+            out.putParcelable(DocumentsContract.EXTRA_RESULT, path);
         } else {
             throw new UnsupportedOperationException("Method not supported " + method);
         }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bf73089..0f4afae 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1853,7 +1853,6 @@
             MOVED_TO_GLOBAL.add(Settings.Global.CALL_AUTO_RETRY);
             MOVED_TO_GLOBAL.add(Settings.Global.DEBUG_APP);
             MOVED_TO_GLOBAL.add(Settings.Global.WAIT_FOR_DEBUGGER);
-            MOVED_TO_GLOBAL.add(Settings.Global.SHOW_PROCESSES);
             MOVED_TO_GLOBAL.add(Settings.Global.ALWAYS_FINISH_ACTIVITIES);
             MOVED_TO_GLOBAL.add(Settings.Global.TZINFO_UPDATE_CONTENT_URL);
             MOVED_TO_GLOBAL.add(Settings.Global.TZINFO_UPDATE_METADATA_URL);
@@ -2791,7 +2790,8 @@
         /**
          * Control whether the process CPU usage meter should be shown.
          *
-         * @deprecated Use {@link Global#SHOW_PROCESSES} instead
+         * @deprecated This functionality is no longer available as of
+         * {@link android.os.Build.VERSION_CODES#N_MR1}.
          */
         @Deprecated
         public static final String SHOW_PROCESSES = Global.SHOW_PROCESSES;
@@ -6460,6 +6460,12 @@
         public static final String WEB_ACTION_ENABLED = "web_action_enabled";
 
         /**
+         * Has this pairable device been paired or upgraded from a previously paired system.
+         * @hide
+         */
+        public static final String DEVICE_PAIRED = "device_paired";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -8513,7 +8519,11 @@
 
         /**
          * Control whether the process CPU usage meter should be shown.
+         *
+         * @deprecated This functionality is no longer available as of
+         * {@link android.os.Build.VERSION_CODES#N_MR1}.
          */
+        @Deprecated
         public static final String SHOW_PROCESSES = "show_processes";
 
         /**
diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl
index 8689dce..641e1ad 100644
--- a/core/java/android/security/IKeystoreService.aidl
+++ b/core/java/android/security/IKeystoreService.aidl
@@ -76,4 +76,5 @@
     int onUserAdded(int userId, int parentId);
     int onUserRemoved(int userId);
     int attestKey(String alias, in KeymasterArguments params, out KeymasterCertificateChain chain);
+    int onDeviceOffBody();
 }
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index b13e162..e6f58f5 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -450,6 +450,28 @@
     }
 
     /**
+     * Inform the notification manager about snoozing a specific notification.
+     * <p>
+     * Use this if your listener has a user interface that allows the user to snooze a notification
+     * until a given time.  It should be called after the user snoozes a single notification using
+     * your UI; upon being informed, the notification manager will actually remove the notification
+     * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback. When the
+     * snoozing period expires, you will get a
+     * {@link #onNotificationPosted(StatusBarNotification, RankingMap)} callback for the
+     * notification.
+     * @param key The key of the notification to snooze
+     * @param snoozeUntil A time in the future, in milliseconds.
+     */
+    public final void snoozeNotification(String key, long snoozeUntil) {
+        if (!isBound()) return;
+        try {
+            getNotificationInterface().snoozeNotificationFromListener(mWrapper, key, snoozeUntil);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    /**
      * Inform the notification manager that these notifications have been viewed by the
      * user. This should only be called when there is sufficient confidence that the user is
      * looking at the notifications, such as when the notifications appear on the screen due to
diff --git a/core/java/android/service/notification/NotificationRankerService.java b/core/java/android/service/notification/NotificationRankerService.java
index 261d82d..928d5d8 100644
--- a/core/java/android/service/notification/NotificationRankerService.java
+++ b/core/java/android/service/notification/NotificationRankerService.java
@@ -102,6 +102,9 @@
     /** Notification was canceled by the user banning the channel. */
     public static final int REASON_CHANNEL_BANNED = 17;
 
+    /** Notification was snoozed. */
+    public static final int REASON_SNOOZED = 18;
+
     private Handler mHandler;
 
     /** @hide */
diff --git a/core/java/android/text/AutoText.java b/core/java/android/text/AutoText.java
index 04730ec..c5339a4 100644
--- a/core/java/android/text/AutoText.java
+++ b/core/java/android/text/AutoText.java
@@ -18,11 +18,10 @@
 
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.view.View;
 
 import com.android.internal.util.XmlUtils;
 
-import android.view.View;
-
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -97,10 +96,10 @@
                 sInstance = instance;
             }
         }
-        
+
         return instance;
     }
-    
+
     /**
      * Retrieves a possible spelling correction for the specified range
      * of text.  Returns null if no correction can be found.
@@ -119,7 +118,7 @@
      */
     public static int getSize(View view) {
 
-        return getInstance(view).getSize(); 
+        return getInstance(view).getSize();
     }
 
     /**
@@ -137,7 +136,7 @@
 
             for (; here != TRIE_NULL; here = mTrie[here + TRIE_NEXT]) {
                 if (c == mTrie[here + TRIE_C]) {
-                    if ((i == end - 1) 
+                    if ((i == end - 1)
                             && (mTrie[here + TRIE_OFF] != TRIE_NULL)) {
                         int off = mTrie[here + TRIE_OFF];
                         int len = mText.charAt(off);
@@ -174,7 +173,7 @@
             while (true) {
                 XmlUtils.nextElement(parser);
 
-                String element = parser.getName(); 
+                String element = parser.getName();
                 if (element == null || !(element.equals("word"))) {
                     break;
                 }
@@ -214,7 +213,7 @@
         int herep = TRIE_ROOT;
         // Keep track of the size of the dictionary
         mSize++;
-        
+
         for (int i = 0; i < slen; i++) {
             char c = src.charAt(i);
             boolean found = false;
diff --git a/core/java/android/text/BidiFormatter.java b/core/java/android/text/BidiFormatter.java
index 59273f4..d84502f 100644
--- a/core/java/android/text/BidiFormatter.java
+++ b/core/java/android/text/BidiFormatter.java
@@ -16,11 +16,11 @@
 
 package android.text;
 
+import static android.text.TextDirectionHeuristics.FIRSTSTRONG_LTR;
+
 import android.annotation.Nullable;
 import android.view.View;
 
-import static android.text.TextDirectionHeuristics.FIRSTSTRONG_LTR;
-
 import java.util.Locale;
 
 /**
diff --git a/core/java/android/text/GraphicsOperations.java b/core/java/android/text/GraphicsOperations.java
index 8674c66..6edf845 100644
--- a/core/java/android/text/GraphicsOperations.java
+++ b/core/java/android/text/GraphicsOperations.java
@@ -16,31 +16,30 @@
 
 package android.text;
 
+import android.graphics.BaseCanvas;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 
 /**
- * Please implement this interface if your CharSequence can do quick
- * draw/measure/widths calculations from an internal array.
- * {@hide}
+ * Please implement this interface if your CharSequence can do quick draw/measure/widths
+ * calculations from an internal array.
+ *
+ * @hide
  */
-public interface GraphicsOperations
-extends CharSequence
-{
+public interface GraphicsOperations extends CharSequence {
     /**
      * Just like {@link Canvas#drawText}.
      */
-    void drawText(Canvas c, int start, int end,
-                         float x, float y, Paint p);
+    void drawText(BaseCanvas c, int start, int end,
+            float x, float y, Paint p);
 
     /**
      * Just like {@link Canvas#drawTextRun}.
-     * {@hide}
      */
-    void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd,
+    void drawTextRun(BaseCanvas c, int start, int end, int contextStart, int contextEnd,
             float x, float y, boolean isRtl, Paint p);
 
-   /**
+    /**
      * Just like {@link Paint#measureText}.
      */
     float measureText(int start, int end, Paint p);
@@ -52,14 +51,12 @@
 
     /**
      * Just like {@link Paint#getTextRunAdvances}.
-     * @hide
      */
     float getTextRunAdvances(int start, int end, int contextStart, int contextEnd,
             boolean isRtl, float[] advances, int advancesIndex, Paint paint);
 
     /**
      * Just like {@link Paint#getTextRunCursor}.
-     * @hide
      */
     int getTextRunCursor(int contextStart, int contextEnd, int dir, int offset,
             int cursorOpt, Paint p);
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index 409994d..de8aa5a 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -16,19 +16,8 @@
 
 package android.text;
 
-import com.android.internal.util.ArrayUtils;
-import org.ccil.cowan.tagsoup.HTMLSchema;
-import org.ccil.cowan.tagsoup.Parser;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-
 import android.app.ActivityThread;
 import android.app.Application;
-import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Typeface;
@@ -47,11 +36,21 @@
 import android.text.style.StyleSpan;
 import android.text.style.SubscriptSpan;
 import android.text.style.SuperscriptSpan;
-import android.text.style.TextAppearanceSpan;
 import android.text.style.TypefaceSpan;
 import android.text.style.URLSpan;
 import android.text.style.UnderlineSpan;
 
+import com.android.internal.util.ArrayUtils;
+
+import org.ccil.cowan.tagsoup.HTMLSchema;
+import org.ccil.cowan.tagsoup.Parser;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
 import java.io.IOException;
 import java.io.StringReader;
 import java.util.HashMap;
diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java
index c596388..8967b70 100644
--- a/core/java/android/text/InputType.java
+++ b/core/java/android/text/InputType.java
@@ -16,8 +16,6 @@
 
 package android.text;
 
-import android.text.TextUtils;
-
 /**
  * Bit definitions for an integer defining the basic content type of text
  * held in an {@link Editable} object. Supported classes may be combined
@@ -51,19 +49,19 @@
      * or flags.<p>
      */
     public static final int TYPE_MASK_CLASS = 0x0000000f;
-    
+
     /**
      * Mask of bits that determine the variation of
      * the base content class.
      */
     public static final int TYPE_MASK_VARIATION = 0x00000ff0;
-    
+
     /**
      * Mask of bits that provide addition bit flags
      * of options.
      */
     public static final int TYPE_MASK_FLAGS = 0x00fff000;
-    
+
     /**
      * Special content type for when no explicit type has been specified.
      * This should be interpreted to mean that the target input connection
@@ -75,11 +73,11 @@
      * flag is set.
      */
     public static final int TYPE_NULL = 0x00000000;
-    
+
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
-    
+
     /**
      * Class for normal text.  This class supports the following flags (only
      * one of which should be set):
@@ -92,7 +90,7 @@
      * variation, normal should be assumed.
      */
     public static final int TYPE_CLASS_TEXT = 0x00000001;
-    
+
     /**
      * Flag for {@link #TYPE_CLASS_TEXT}: capitalize all characters.  Overrides
      * {@link #TYPE_TEXT_FLAG_CAP_WORDS} and
@@ -101,7 +99,7 @@
      * this only affects languages where there are upper-case and lower-case letters.
      */
     public static final int TYPE_TEXT_FLAG_CAP_CHARACTERS = 0x00001000;
-    
+
     /**
      * Flag for {@link #TYPE_CLASS_TEXT}: capitalize the first character of
      * every word.  Overrides {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}.  This
@@ -110,7 +108,7 @@
      * this only affects languages where there are upper-case and lower-case letters.
      */
     public static final int TYPE_TEXT_FLAG_CAP_WORDS = 0x00002000;
-    
+
     /**
      * Flag for {@link #TYPE_CLASS_TEXT}: capitalize the first character of
      * each sentence.  This value is explicitly defined
@@ -121,7 +119,7 @@
      * this only affects languages where there are upper-case and lower-case letters.
      */
     public static final int TYPE_TEXT_FLAG_CAP_SENTENCES = 0x00004000;
-    
+
     /**
      * Flag for {@link #TYPE_CLASS_TEXT}: the user is entering free-form
      * text that should have auto-correction applied to it. Without this flag,
@@ -135,7 +133,7 @@
      * the IME offers an interface to show suggestions.
      */
     public static final int TYPE_TEXT_FLAG_AUTO_CORRECT = 0x00008000;
-    
+
     /**
      * Flag for {@link #TYPE_CLASS_TEXT}: the text editor (which means
      * the application) is performing auto-completion of the text being entered
@@ -154,23 +152,23 @@
      * it will rely on the Editor to pass completions/corrections.
      */
     public static final int TYPE_TEXT_FLAG_AUTO_COMPLETE = 0x00010000;
-    
+
     /**
      * Flag for {@link #TYPE_CLASS_TEXT}: multiple lines of text can be
-     * entered into the field.  If this flag is not set, the text field 
+     * entered into the field.  If this flag is not set, the text field
      * will be constrained to a single line. The IME may also choose not to
      * display an enter key when this flag is not set, as there should be no
      * need to create new lines.
      */
     public static final int TYPE_TEXT_FLAG_MULTI_LINE = 0x00020000;
-    
+
     /**
      * Flag for {@link #TYPE_CLASS_TEXT}: the regular text view associated
      * with this should not be multi-line, but when a fullscreen input method
      * is providing text it should use multiple lines if it can.
      */
     public static final int TYPE_TEXT_FLAG_IME_MULTI_LINE = 0x00040000;
-    
+
     /**
      * Flag for {@link #TYPE_CLASS_TEXT}: the input method does not need to
      * display any dictionary-based candidates. This is useful for text views that
@@ -191,36 +189,36 @@
     public static final int TYPE_TEXT_FLAG_NO_SUGGESTIONS = 0x00080000;
 
     // ----------------------------------------------------------------------
-    
+
     /**
      * Default variation of {@link #TYPE_CLASS_TEXT}: plain old normal text.
      */
     public static final int TYPE_TEXT_VARIATION_NORMAL = 0x00000000;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering a URI.
      */
     public static final int TYPE_TEXT_VARIATION_URI = 0x00000010;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering an e-mail address.
      */
     public static final int TYPE_TEXT_VARIATION_EMAIL_ADDRESS = 0x00000020;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering the subject line of
      * an e-mail.
      */
     public static final int TYPE_TEXT_VARIATION_EMAIL_SUBJECT = 0x00000030;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering a short, possibly informal
      * message such as an instant message or a text message.
      */
     public static final int TYPE_TEXT_VARIATION_SHORT_MESSAGE = 0x00000040;
-    
+
     /**
-     * Variation of {@link #TYPE_CLASS_TEXT}: entering the content of a long, possibly 
+     * Variation of {@link #TYPE_CLASS_TEXT}: entering the content of a long, possibly
      * formal message such as the body of an e-mail.
      */
     public static final int TYPE_TEXT_VARIATION_LONG_MESSAGE = 0x00000050;
@@ -229,34 +227,34 @@
      * Variation of {@link #TYPE_CLASS_TEXT}: entering the name of a person.
      */
     public static final int TYPE_TEXT_VARIATION_PERSON_NAME = 0x00000060;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering a postal mailing address.
      */
     public static final int TYPE_TEXT_VARIATION_POSTAL_ADDRESS = 0x00000070;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering a password.
      */
     public static final int TYPE_TEXT_VARIATION_PASSWORD = 0x00000080;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering a password, which should
      * be visible to the user.
      */
     public static final int TYPE_TEXT_VARIATION_VISIBLE_PASSWORD = 0x00000090;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering text inside of a web form.
      */
     public static final int TYPE_TEXT_VARIATION_WEB_EDIT_TEXT = 0x000000a0;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering text to filter contents
      * of a list etc.
      */
     public static final int TYPE_TEXT_VARIATION_FILTER = 0x000000b0;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering text for phonetic
      * pronunciation, such as a phonetic name field in contacts. This is mostly
@@ -264,7 +262,7 @@
      * readings, like Japanese.
      */
     public static final int TYPE_TEXT_VARIATION_PHONETIC = 0x000000c0;
-    
+
     /**
      * Variation of {@link #TYPE_CLASS_TEXT}: entering e-mail address inside
      * of a web form.  This was added in
@@ -290,7 +288,7 @@
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
-    
+
     /**
      * Class for numeric text.  This class supports the following flags:
      * {@link #TYPE_NUMBER_FLAG_SIGNED} and
@@ -301,19 +299,19 @@
      * the variation, normal should be assumed.</p>
      */
     public static final int TYPE_CLASS_NUMBER = 0x00000002;
-    
+
     /**
      * Flag of {@link #TYPE_CLASS_NUMBER}: the number is signed, allowing
      * a positive or negative sign at the start.
      */
     public static final int TYPE_NUMBER_FLAG_SIGNED = 0x00001000;
-    
+
     /**
      * Flag of {@link #TYPE_CLASS_NUMBER}: the number is decimal, allowing
      * a decimal point to provide fractional values.
      */
     public static final int TYPE_NUMBER_FLAG_DECIMAL = 0x00002000;
-    
+
     // ----------------------------------------------------------------------
 
     /**
@@ -340,17 +338,17 @@
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
-    
+
     /**
      * Class for a phone number.  This class currently supports no variations
      * or flags.
      */
     public static final int TYPE_CLASS_PHONE = 0x00000003;
-    
+
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
-    
+
     /**
      * Class for dates and times.  It supports the
      * following variations:
@@ -359,19 +357,19 @@
      * {@link #TYPE_DATETIME_VARIATION_TIME}.
      */
     public static final int TYPE_CLASS_DATETIME = 0x00000004;
-    
+
     /**
      * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
      * both a date and time.
      */
     public static final int TYPE_DATETIME_VARIATION_NORMAL = 0x00000000;
-    
+
     /**
      * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
      * only a date.
      */
     public static final int TYPE_DATETIME_VARIATION_DATE = 0x00000010;
-    
+
     /**
      * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
      * only a time.
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index dc8e4b9..186d96b 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -17,7 +17,7 @@
 package android.text;
 
 import android.annotation.Nullable;
-import android.graphics.Canvas;
+import android.graphics.BaseCanvas;
 import android.graphics.Paint;
 import android.util.Log;
 
@@ -1357,7 +1357,8 @@
      * Don't call this yourself -- exists for Canvas to use internally.
      * {@hide}
      */
-    public void drawText(Canvas c, int start, int end, float x, float y, Paint p) {
+    @Override
+    public void drawText(BaseCanvas c, int start, int end, float x, float y, Paint p) {
         checkRange("drawText", start, end);
 
         if (end <= mGapStart) {
@@ -1378,7 +1379,8 @@
      * Don't call this yourself -- exists for Canvas to use internally.
      * {@hide}
      */
-    public void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd,
+    @Override
+    public void drawTextRun(BaseCanvas c, int start, int end, int contextStart, int contextEnd,
             float x, float y, boolean isRtl, Paint p) {
         checkRange("drawTextRun", start, end);
 
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 2a52961..03a2d62 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -16,11 +16,9 @@
 
 package android.text;
 
-import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Paint.FontMetricsInt;
-import android.graphics.RectF;
 import android.text.Layout.Directions;
 import android.text.Layout.TabStops;
 import android.text.style.CharacterStyle;
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 23b22d1..6262fc2 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -60,8 +60,6 @@
 import com.android.internal.R;
 import com.android.internal.util.ArrayUtils;
 
-import libcore.icu.ICU;
-
 import java.lang.reflect.Array;
 import java.util.Iterator;
 import java.util.List;
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 3ed37b36..b5a8aca 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -23,15 +23,15 @@
 import android.text.Spanned;
 import android.text.SpannedString;
 
+import libcore.icu.ICU;
+import libcore.icu.LocaleData;
+
+import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.Locale;
 import java.util.TimeZone;
-import java.text.SimpleDateFormat;
-
-import libcore.icu.ICU;
-import libcore.icu.LocaleData;
 
 /**
  * Utility class for producing strings with formatted date/time.
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index cb8852c..f16e714 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -16,12 +16,16 @@
 
 package android.text.format;
 
-import com.android.internal.R;
-
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 
+import com.android.internal.R;
+
+import libcore.icu.DateIntervalFormat;
+import libcore.icu.LocaleData;
+import libcore.icu.RelativeDateTimeFormatter;
+
 import java.io.IOException;
 import java.util.Calendar;
 import java.util.Date;
@@ -30,10 +34,6 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
-import libcore.icu.DateIntervalFormat;
-import libcore.icu.LocaleData;
-import libcore.icu.RelativeDateTimeFormatter;
-
 /**
  * This class contains various date-related utilities for creating text for things like
  * elapsed time and date ranges, strings for days of the week and months, and AM/PM text etc.
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index be52464..b67ac98 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -20,11 +20,10 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
+import android.net.NetworkUtils;
 import android.text.BidiFormatter;
 import android.text.TextUtils;
 import android.view.View;
-import android.net.NetworkUtils;
-import android.net.TrafficStats;
 
 import java.util.Locale;
 
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index 69c2cff..bbd9c9c 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -18,13 +18,13 @@
 
 import android.util.TimeFormatException;
 
+import libcore.util.ZoneInfo;
+import libcore.util.ZoneInfoDB;
+
 import java.io.IOException;
 import java.util.Locale;
 import java.util.TimeZone;
 
-import libcore.util.ZoneInfo;
-import libcore.util.ZoneInfoDB;
-
 /**
  * An alternative to the {@link java.util.Calendar} and
  * {@link java.util.GregorianCalendar} classes. An instance of the Time class represents
diff --git a/core/java/android/text/format/TimeFormatter.java b/core/java/android/text/format/TimeFormatter.java
index 3a63805..5a14092 100644
--- a/core/java/android/text/format/TimeFormatter.java
+++ b/core/java/android/text/format/TimeFormatter.java
@@ -22,12 +22,13 @@
 
 import android.content.res.Resources;
 
+import libcore.icu.LocaleData;
+import libcore.util.ZoneInfo;
+
 import java.nio.CharBuffer;
 import java.util.Formatter;
 import java.util.Locale;
 import java.util.TimeZone;
-import libcore.icu.LocaleData;
-import libcore.util.ZoneInfo;
 
 /**
  * Formatting logic for {@link Time}. Contains a port of Bionic's broken strftime_tz to Java.
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 14e0b4f..90559dc 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -19,19 +19,22 @@
 import android.graphics.Paint;
 import android.icu.lang.UCharacter;
 import android.icu.lang.UProperty;
-import android.view.KeyEvent;
-import android.view.View;
-import android.text.*;
+import android.text.Editable;
+import android.text.Emoji;
+import android.text.InputType;
+import android.text.Layout;
+import android.text.NoCopySpan;
+import android.text.Selection;
+import android.text.Spanned;
 import android.text.method.TextKeyListener.Capitalize;
 import android.text.style.ReplacementSpan;
+import android.view.KeyEvent;
+import android.view.View;
 import android.widget.TextView;
 
 import com.android.internal.annotations.GuardedBy;
 
 import java.text.BreakIterator;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
 
 /**
  * Abstract base class for key listeners.
diff --git a/core/java/android/text/method/CharacterPickerDialog.java b/core/java/android/text/method/CharacterPickerDialog.java
index 880e46d..7d838e0 100644
--- a/core/java/android/text/method/CharacterPickerDialog.java
+++ b/core/java/android/text/method/CharacterPickerDialog.java
@@ -16,24 +16,25 @@
 
 package android.text.method;
 
-import com.android.internal.R;
-
 import android.app.Dialog;
 import android.content.Context;
 import android.os.Bundle;
-import android.text.*;
+import android.text.Editable;
+import android.text.Selection;
 import android.view.LayoutInflater;
-import android.view.View.OnClickListener;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
-import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
 import android.widget.BaseAdapter;
 import android.widget.Button;
 import android.widget.GridView;
 
+import com.android.internal.R;
+
 /**
  * Dialog for choosing accented characters related to a base character.
  */
diff --git a/core/java/android/text/method/DateKeyListener.java b/core/java/android/text/method/DateKeyListener.java
index e6f63d1..88ef388 100644
--- a/core/java/android/text/method/DateKeyListener.java
+++ b/core/java/android/text/method/DateKeyListener.java
@@ -16,8 +16,8 @@
 
 package android.text.method;
 
-import android.view.KeyEvent;
 import android.text.InputType;
+import android.view.KeyEvent;
 
 /**
  * For entering dates in a text field.
@@ -32,7 +32,7 @@
         return InputType.TYPE_CLASS_DATETIME
                 | InputType.TYPE_DATETIME_VARIATION_DATE;
     }
-    
+
     @Override
     protected char[] getAcceptedChars()
     {
diff --git a/core/java/android/text/method/DialerKeyListener.java b/core/java/android/text/method/DialerKeyListener.java
index bb8b0de..17abed6 100644
--- a/core/java/android/text/method/DialerKeyListener.java
+++ b/core/java/android/text/method/DialerKeyListener.java
@@ -16,10 +16,10 @@
 
 package android.text.method;
 
-import android.view.KeyEvent;
-import android.view.KeyCharacterMap.KeyData;
 import android.text.InputType;
 import android.text.Spannable;
+import android.view.KeyCharacterMap.KeyData;
+import android.view.KeyEvent;
 
 /**
  * For dialing-only text entry
@@ -47,7 +47,7 @@
     public int getInputType() {
         return InputType.TYPE_CLASS_PHONE;
     }
-    
+
     /**
      * Overrides the superclass's lookup method to prefer the number field
      * from the KeyEvent.
diff --git a/core/java/android/text/method/DigitsKeyListener.java b/core/java/android/text/method/DigitsKeyListener.java
index c95df46..4aeb39a 100644
--- a/core/java/android/text/method/DigitsKeyListener.java
+++ b/core/java/android/text/method/DigitsKeyListener.java
@@ -17,8 +17,8 @@
 package android.text.method;
 
 import android.text.InputType;
-import android.text.Spanned;
 import android.text.SpannableStringBuilder;
+import android.text.Spanned;
 import android.view.KeyEvent;
 
 
@@ -133,7 +133,7 @@
         }
         return contentType;
     }
-    
+
     @Override
     public CharSequence filter(CharSequence source, int start, int end,
                                Spanned dest, int dstart, int dend) {
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
index e9db5fd..c3c7302 100644
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ b/core/java/android/text/method/MetaKeyKeyListener.java
@@ -20,9 +20,9 @@
 import android.text.NoCopySpan;
 import android.text.Spannable;
 import android.text.Spanned;
+import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
-import android.view.KeyCharacterMap;
 
 /**
  * This base class encapsulates the behavior for tracking the state of
@@ -86,7 +86,7 @@
      * Value equals {@link KeyEvent#META_SYM_ON}.
      */
     public static final int META_SYM_ON = KeyEvent.META_SYM_ON;
-    
+
     /**
      * Flag that indicates that the SHIFT key is locked in CAPS mode.
      */
@@ -111,11 +111,11 @@
     private static final long META_CAP_USED = 1L << 32;
     private static final long META_ALT_USED = 1L << 33;
     private static final long META_SYM_USED = 1L << 34;
-    
+
     private static final long META_CAP_PRESSED = 1L << 40;
     private static final long META_ALT_PRESSED = 1L << 41;
     private static final long META_SYM_PRESSED = 1L << 42;
-    
+
     private static final long META_CAP_RELEASED = 1L << 48;
     private static final long META_ALT_RELEASED = 1L << 49;
     private static final long META_SYM_RELEASED = 1L << 50;
@@ -129,7 +129,7 @@
     private static final long META_SYM_MASK = META_SYM_ON
             | META_SYM_LOCKED | META_SYM_USED
             | META_SYM_PRESSED | META_SYM_RELEASED;
-    
+
     private static final Object CAP = new NoCopySpan.Concrete();
     private static final Object ALT = new NoCopySpan.Concrete();
     private static final Object SYM = new NoCopySpan.Concrete();
@@ -150,7 +150,7 @@
 
     /**
      * Gets the state of the meta keys.
-     * 
+     *
      * @param text the buffer in which the meta key would have been pressed.
      *
      * @return an integer in which each bit set to one represents a pressed
@@ -448,7 +448,7 @@
 
     /**
      * Gets the state of the meta keys.
-     * 
+     *
      * @param state the current meta state bits.
      *
      * @return an integer in which each bit set to one represents a pressed
@@ -635,26 +635,26 @@
     /**
      * The meta key has been pressed but has not yet been used.
      */
-    private static final int PRESSED = 
+    private static final int PRESSED =
         Spannable.SPAN_MARK_MARK | (1 << Spannable.SPAN_USER_SHIFT);
 
     /**
      * The meta key has been pressed and released but has still
      * not yet been used.
      */
-    private static final int RELEASED = 
+    private static final int RELEASED =
         Spannable.SPAN_MARK_MARK | (2 << Spannable.SPAN_USER_SHIFT);
 
     /**
      * The meta key has been pressed and used but has not yet been released.
      */
-    private static final int USED = 
+    private static final int USED =
         Spannable.SPAN_MARK_MARK | (3 << Spannable.SPAN_USER_SHIFT);
 
     /**
      * The meta key has been pressed and released without use, and then
      * pressed again; it may also have been released again.
      */
-    private static final int LOCKED = 
+    private static final int LOCKED =
         Spannable.SPAN_MARK_MARK | (4 << Spannable.SPAN_USER_SHIFT);
 }
diff --git a/core/java/android/text/method/MovementMethod.java b/core/java/android/text/method/MovementMethod.java
index 01979fd..f6fe575 100644
--- a/core/java/android/text/method/MovementMethod.java
+++ b/core/java/android/text/method/MovementMethod.java
@@ -16,10 +16,10 @@
 
 package android.text.method;
 
-import android.widget.TextView;
+import android.text.Spannable;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
-import android.text.*;
+import android.widget.TextView;
 
 /**
  * Provides cursor positioning, scrolling and text selection functionality in a {@link TextView}.
diff --git a/core/java/android/text/method/MultiTapKeyListener.java b/core/java/android/text/method/MultiTapKeyListener.java
index 95ac0a1..5770482 100644
--- a/core/java/android/text/method/MultiTapKeyListener.java
+++ b/core/java/android/text/method/MultiTapKeyListener.java
@@ -16,13 +16,16 @@
 
 package android.text.method;
 
-import android.view.KeyEvent;
-import android.view.View;
 import android.os.Handler;
 import android.os.SystemClock;
-import android.text.*;
+import android.text.Editable;
+import android.text.Selection;
+import android.text.SpanWatcher;
+import android.text.Spannable;
 import android.text.method.TextKeyListener.Capitalize;
 import android.util.SparseArray;
+import android.view.KeyEvent;
+import android.view.View;
 
 /**
  * This is the standard key listener for alphabetic input on 12-key
@@ -81,7 +84,7 @@
     public int getInputType() {
         return makeTextContentType(mCapitalize, mAutoText);
     }
-    
+
     public boolean onKeyDown(View view, Editable content,
                              int keyCode, KeyEvent event) {
         int selStart, selEnd;
@@ -198,7 +201,7 @@
             if (selEnd != oldStart) {
                 Selection.setSelection(content, oldStart, selEnd);
 
-                content.setSpan(TextKeyListener.LAST_TYPED, 
+                content.setSpan(TextKeyListener.LAST_TYPED,
                                 oldStart, selEnd,
                                 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
 
diff --git a/core/java/android/text/method/NumberKeyListener.java b/core/java/android/text/method/NumberKeyListener.java
index 988d566..6b12b7e 100644
--- a/core/java/android/text/method/NumberKeyListener.java
+++ b/core/java/android/text/method/NumberKeyListener.java
@@ -16,14 +16,14 @@
 
 package android.text.method;
 
-import android.view.KeyEvent;
-import android.view.View;
 import android.text.Editable;
 import android.text.InputFilter;
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
+import android.view.KeyEvent;
+import android.view.View;
 
 /**
  * For numeric text entry
@@ -91,7 +91,7 @@
 
         return false;
     }
-    
+
     @Override
     public boolean onKeyDown(View view, Editable content,
                              int keyCode, KeyEvent event) {
diff --git a/core/java/android/text/method/PasswordTransformationMethod.java b/core/java/android/text/method/PasswordTransformationMethod.java
index 88a69b9..4485e38 100644
--- a/core/java/android/text/method/PasswordTransformationMethod.java
+++ b/core/java/android/text/method/PasswordTransformationMethod.java
@@ -16,18 +16,18 @@
 
 package android.text.method;
 
+import android.graphics.Rect;
 import android.os.Handler;
 import android.os.SystemClock;
-import android.graphics.Rect;
-import android.view.View;
 import android.text.Editable;
 import android.text.GetChars;
 import android.text.NoCopySpan;
+import android.text.Spannable;
+import android.text.Spanned;
 import android.text.TextUtils;
 import android.text.TextWatcher;
-import android.text.Spanned;
-import android.text.Spannable;
 import android.text.style.UpdateLayout;
+import android.view.View;
 
 import java.lang.ref.WeakReference;
 
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index b17f502..bea68b1 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -16,7 +16,12 @@
 
 package android.text.method;
 
-import android.text.*;
+import android.text.AutoText;
+import android.text.Editable;
+import android.text.NoCopySpan;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.TextUtils;
 import android.text.method.TextKeyListener.Capitalize;
 import android.util.SparseArray;
 import android.view.KeyCharacterMap;
@@ -80,7 +85,7 @@
     public int getInputType() {
         return makeTextContentType(mAutoCap, mAutoText);
     }
-    
+
     public boolean onKeyDown(View view, Editable content,
                              int keyCode, KeyEvent event) {
         int selStart, selEnd;
@@ -191,9 +196,9 @@
                 }
             }
 
-            if ((pref & TextKeyListener.AUTO_CAP) != 0 &&
-                Character.isLowerCase(i) && 
-                TextKeyListener.shouldCap(mAutoCap, content, selStart)) {
+            if ((pref & TextKeyListener.AUTO_CAP) != 0
+                    && Character.isLowerCase(i)
+                    && TextKeyListener.shouldCap(mAutoCap, content, selStart)) {
                 int where = content.getSpanEnd(TextKeyListener.CAPPED);
                 int flags = content.getSpanFlags(TextKeyListener.CAPPED);
 
@@ -361,9 +366,9 @@
                                   View view) {
         int len = end - start;
         boolean changecase = false;
-        
+
         String replacement = AutoText.get(src, start, end, view);
-        
+
         if (replacement == null) {
             String key = TextUtils.substring(src, start, end).toLowerCase();
             replacement = AutoText.get(key, 0, end - start, view);
@@ -372,7 +377,7 @@
             if (replacement == null)
                 return null;
         }
-        
+
         int caps = 0;
 
         if (changecase) {
diff --git a/core/java/android/text/method/ScrollingMovementMethod.java b/core/java/android/text/method/ScrollingMovementMethod.java
index b9f5d5f4..4f422cb 100644
--- a/core/java/android/text/method/ScrollingMovementMethod.java
+++ b/core/java/android/text/method/ScrollingMovementMethod.java
@@ -16,10 +16,11 @@
 
 package android.text.method;
 
+import android.text.Layout;
+import android.text.Spannable;
 import android.view.MotionEvent;
-import android.text.*;
-import android.widget.TextView;
 import android.view.View;
+import android.widget.TextView;
 
 /**
  * A movement method that interprets movement keys by scrolling the text buffer.
diff --git a/core/java/android/text/method/TextKeyListener.java b/core/java/android/text/method/TextKeyListener.java
index 994f3d7..9cbda9c 100644
--- a/core/java/android/text/method/TextKeyListener.java
+++ b/core/java/android/text/method/TextKeyListener.java
@@ -22,11 +22,16 @@
 import android.os.Handler;
 import android.provider.Settings;
 import android.provider.Settings.System;
-import android.text.*;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.NoCopySpan;
+import android.text.Selection;
+import android.text.SpanWatcher;
+import android.text.Spannable;
+import android.text.TextUtils;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
-import android.text.InputType;
 
 import java.lang.ref.WeakReference;
 
@@ -127,7 +132,7 @@
     public int getInputType() {
         return makeTextContentType(mAutoCap, mAutoText);
     }
-    
+
     @Override
     public boolean onKeyDown(View view, Editable content,
                              int keyCode, KeyEvent event) {
@@ -213,7 +218,7 @@
         public int getInputType() {
             return InputType.TYPE_NULL;
         }
-        
+
         public boolean onKeyDown(View view, Editable content,
                                  int keyCode, KeyEvent event) {
             return false;
@@ -230,7 +235,7 @@
 
         public void clearMetaKeyState(View view, Editable content, int states) {
         }
-        
+
         public static NullKeyListener getInstance() {
             if (sInstance != null)
                 return sInstance;
diff --git a/core/java/android/text/method/TimeKeyListener.java b/core/java/android/text/method/TimeKeyListener.java
index c5bfd5c..01f4086 100644
--- a/core/java/android/text/method/TimeKeyListener.java
+++ b/core/java/android/text/method/TimeKeyListener.java
@@ -16,8 +16,8 @@
 
 package android.text.method;
 
-import android.view.KeyEvent;
 import android.text.InputType;
+import android.view.KeyEvent;
 
 /**
  * For entering times in a text field.
@@ -32,7 +32,7 @@
         return InputType.TYPE_CLASS_DATETIME
         | InputType.TYPE_DATETIME_VARIATION_TIME;
     }
-    
+
     @Override
     protected char[] getAcceptedChars()
     {
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
index 89ed08c..17938a8 100644
--- a/core/java/android/text/method/WordIterator.java
+++ b/core/java/android/text/method/WordIterator.java
@@ -18,8 +18,8 @@
 
 import android.annotation.NonNull;
 import android.icu.text.BreakIterator;
-import android.text.Selection;
 import android.text.CharSequenceCharacterIterator;
+import android.text.Selection;
 
 import java.util.Locale;
 
diff --git a/core/java/android/text/style/DrawableMarginSpan.java b/core/java/android/text/style/DrawableMarginSpan.java
index 20b6886..3524179 100644
--- a/core/java/android/text/style/DrawableMarginSpan.java
+++ b/core/java/android/text/style/DrawableMarginSpan.java
@@ -16,11 +16,11 @@
 
 package android.text.style;
 
-import android.graphics.drawable.Drawable;
-import android.graphics.Paint;
 import android.graphics.Canvas;
-import android.text.Spanned;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
 import android.text.Layout;
+import android.text.Spanned;
 
 public class DrawableMarginSpan
 implements LeadingMarginSpan, LineHeightSpan
diff --git a/core/java/android/text/style/IconMarginSpan.java b/core/java/android/text/style/IconMarginSpan.java
index cf9a705..304c83f 100644
--- a/core/java/android/text/style/IconMarginSpan.java
+++ b/core/java/android/text/style/IconMarginSpan.java
@@ -16,11 +16,11 @@
 
 package android.text.style;
 
-import android.graphics.Paint;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.text.Spanned;
+import android.graphics.Paint;
 import android.text.Layout;
+import android.text.Spanned;
 
 public class IconMarginSpan
 implements LeadingMarginSpan, LineHeightSpan
diff --git a/core/java/android/text/style/LeadingMarginSpan.java b/core/java/android/text/style/LeadingMarginSpan.java
index 339d885..5bd2d60 100644
--- a/core/java/android/text/style/LeadingMarginSpan.java
+++ b/core/java/android/text/style/LeadingMarginSpan.java
@@ -16,8 +16,8 @@
 
 package android.text.style;
 
-import android.graphics.Paint;
 import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.os.Parcel;
 import android.text.Layout;
 import android.text.ParcelableSpan;
@@ -39,7 +39,7 @@
      * Returns the amount by which to adjust the leading margin. Positive values
      * move away from the leading edge of the paragraph, negative values move
      * towards it.
-     * 
+     *
      * @param first true if the request is for the first line of a paragraph,
      * false for subsequent lines
      * @return the offset for the margin.
@@ -49,7 +49,7 @@
     /**
      * Renders the leading margin.  This is called before the margin has been
      * adjusted by the value returned by {@link #getLeadingMargin(boolean)}.
-     * 
+     *
      * @param c the canvas
      * @param p the paint. The this should be left unchanged on exit.
      * @param x the current position of the margin
@@ -98,11 +98,11 @@
      */
     public static class Standard implements LeadingMarginSpan, ParcelableSpan {
         private final int mFirst, mRest;
-        
+
         /**
          * Constructor taking separate indents for the first and subsequent
          * lines.
-         * 
+         *
          * @param first the indent for the first line of the paragraph
          * @param rest the indent for the remaining lines of the paragraph
          */
@@ -123,7 +123,7 @@
             mFirst = src.readInt();
             mRest = src.readInt();
         }
-        
+
         public int getSpanTypeId() {
         return getSpanTypeIdInternal();
     }
@@ -132,7 +132,7 @@
     public int getSpanTypeIdInternal() {
             return TextUtils.LEADING_MARGIN_SPAN;
         }
-        
+
         public int describeContents() {
             return 0;
         }
diff --git a/core/java/android/text/style/LineBackgroundSpan.java b/core/java/android/text/style/LineBackgroundSpan.java
index 854aeaf..9c7859f 100644
--- a/core/java/android/text/style/LineBackgroundSpan.java
+++ b/core/java/android/text/style/LineBackgroundSpan.java
@@ -16,8 +16,8 @@
 
 package android.text.style;
 
-import android.graphics.Paint;
 import android.graphics.Canvas;
+import android.graphics.Paint;
 
 public interface LineBackgroundSpan
 extends ParagraphStyle
diff --git a/core/java/android/text/style/LocaleSpan.java b/core/java/android/text/style/LocaleSpan.java
index b842851..479ff0e 100644
--- a/core/java/android/text/style/LocaleSpan.java
+++ b/core/java/android/text/style/LocaleSpan.java
@@ -16,8 +16,6 @@
 
 package android.text.style;
 
-import com.android.internal.util.Preconditions;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Paint;
@@ -27,6 +25,8 @@
 import android.text.TextPaint;
 import android.text.TextUtils;
 
+import com.android.internal.util.Preconditions;
+
 import java.util.Locale;
 
 /**
diff --git a/core/java/android/text/style/QuoteSpan.java b/core/java/android/text/style/QuoteSpan.java
index 0b0a82c..7217e1e 100644
--- a/core/java/android/text/style/QuoteSpan.java
+++ b/core/java/android/text/style/QuoteSpan.java
@@ -17,8 +17,8 @@
 package android.text.style;
 
 import android.annotation.ColorInt;
-import android.graphics.Paint;
 import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.os.Parcel;
 import android.text.Layout;
 import android.text.ParcelableSpan;
@@ -34,7 +34,7 @@
         super();
         mColor = 0xff0000ff;
     }
-    
+
     public QuoteSpan(@ColorInt int color) {
         super();
         mColor = color;
@@ -43,7 +43,7 @@
     public QuoteSpan(Parcel src) {
         mColor = src.readInt();
     }
-    
+
     public int getSpanTypeId() {
         return getSpanTypeIdInternal();
     }
@@ -52,7 +52,7 @@
     public int getSpanTypeIdInternal() {
         return TextUtils.QUOTE_SPAN;
     }
-    
+
     public int describeContents() {
         return 0;
     }
@@ -70,7 +70,7 @@
     public int getColor() {
         return mColor;
     }
-    
+
     public int getLeadingMargin(boolean first) {
         return STRIPE_WIDTH + GAP_WIDTH;
     }
diff --git a/core/java/android/text/style/ReplacementSpan.java b/core/java/android/text/style/ReplacementSpan.java
index 07190b2..5f94ad0 100644
--- a/core/java/android/text/style/ReplacementSpan.java
+++ b/core/java/android/text/style/ReplacementSpan.java
@@ -19,8 +19,8 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.graphics.Paint;
 import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.text.TextPaint;
 
 public abstract class ReplacementSpan extends MetricAffectingSpan {
diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java
index e9153dd..c5e5df0 100644
--- a/core/java/android/text/style/TtsSpan.java
+++ b/core/java/android/text/style/TtsSpan.java
@@ -16,14 +16,14 @@
 
 package android.text.style;
 
-import java.text.NumberFormat;
-import java.util.Locale;
-
 import android.os.Parcel;
 import android.os.PersistableBundle;
 import android.text.ParcelableSpan;
 import android.text.TextUtils;
 
+import java.text.NumberFormat;
+import java.util.Locale;
+
 /**
  * A span that supplies additional meta-data for the associated text intended
  * for text-to-speech engines. If the text is being processed by a
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index ca037a2..7e6eb49 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -20,16 +20,21 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.telephony.PhoneNumberUtils;
-import android.text.method.LinkMovementMethod;
-import android.text.method.MovementMethod;
-import android.text.style.URLSpan;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.text.method.MovementMethod;
+import android.text.style.URLSpan;
 import android.util.Patterns;
 import android.webkit.WebView;
 import android.widget.TextView;
 
+import com.android.i18n.phonenumbers.PhoneNumberMatch;
+import com.android.i18n.phonenumbers.PhoneNumberUtil;
+import com.android.i18n.phonenumbers.PhoneNumberUtil.Leniency;
+
+import libcore.util.EmptyArray;
 
 import java.io.UnsupportedEncodingException;
 import java.lang.annotation.Retention;
@@ -42,12 +47,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import com.android.i18n.phonenumbers.PhoneNumberMatch;
-import com.android.i18n.phonenumbers.PhoneNumberUtil;
-import com.android.i18n.phonenumbers.PhoneNumberUtil.Leniency;
-
-import libcore.util.EmptyArray;
-
 /**
  *  Linkify take a piece of text and a regular expression and turns all of the
  *  regex matches in the text into clickable links.  This is particularly
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index a95da97..b6d8aa4 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -16,19 +16,18 @@
 
 package android.transition;
 
-import android.animation.AnimatorSet;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.PointF;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.RectEvaluator;
+import android.content.Context;
+import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Path;
+import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
diff --git a/core/java/android/transition/ChangeScroll.java b/core/java/android/transition/ChangeScroll.java
index e092685..8a3fd1c 100644
--- a/core/java/android/transition/ChangeScroll.java
+++ b/core/java/android/transition/ChangeScroll.java
@@ -19,8 +19,6 @@
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
 import android.content.Context;
-import android.transition.Transition;
-import android.transition.TransitionValues;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index 9749121..4b0b065 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -30,6 +30,7 @@
 import android.view.GhostView;
 import android.view.View;
 import android.view.ViewGroup;
+
 import com.android.internal.R;
 
 /**
diff --git a/core/java/android/transition/Explode.java b/core/java/android/transition/Explode.java
index 3445ef2..5f078ca 100644
--- a/core/java/android/transition/Explode.java
+++ b/core/java/android/transition/Explode.java
@@ -15,8 +15,6 @@
  */
 package android.transition;
 
-import com.android.internal.R;
-
 import android.animation.Animator;
 import android.animation.TimeInterpolator;
 import android.content.Context;
@@ -26,6 +24,8 @@
 import android.view.ViewGroup;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
+
+import com.android.internal.R;
 /**
  * This transition tracks changes to the visibility of target views in the
  * start and end scenes and moves views in or out from the edges of the
diff --git a/core/java/android/transition/PatternPathMotion.java b/core/java/android/transition/PatternPathMotion.java
index f23863f..7a2c191 100644
--- a/core/java/android/transition/PatternPathMotion.java
+++ b/core/java/android/transition/PatternPathMotion.java
@@ -15,8 +15,6 @@
  */
 package android.transition;
 
-import com.android.internal.R;
-
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Matrix;
@@ -25,6 +23,8 @@
 import android.util.AttributeSet;
 import android.util.PathParser;
 
+import com.android.internal.R;
+
 /**
  * A PathMotion that takes a Path pattern and applies it to the separation between two points.
  * The starting point of the Path will be moved to the origin and the end point will be scaled
diff --git a/core/java/android/transition/Slide.java b/core/java/android/transition/Slide.java
index 2645f86..9cf3210 100644
--- a/core/java/android/transition/Slide.java
+++ b/core/java/android/transition/Slide.java
@@ -26,6 +26,7 @@
 import android.view.ViewGroup;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
+
 import com.android.internal.R;
 
 import java.lang.annotation.Retention;
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index cbf76bc..4c5a717 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -17,11 +17,6 @@
 package android.transition;
 
 import android.annotation.TransitionRes;
-import com.android.internal.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -32,6 +27,11 @@
 import android.view.InflateException;
 import android.view.ViewGroup;
 
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
diff --git a/core/java/android/transition/TranslationAnimationCreator.java b/core/java/android/transition/TranslationAnimationCreator.java
index b07f3f8..ae76e62 100644
--- a/core/java/android/transition/TranslationAnimationCreator.java
+++ b/core/java/android/transition/TranslationAnimationCreator.java
@@ -15,8 +15,6 @@
  */
 package android.transition;
 
-import com.android.internal.R;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
@@ -25,6 +23,8 @@
 import android.transition.Transition.TransitionListener;
 import android.view.View;
 
+import com.android.internal.R;
+
 /**
  * This class is used by Slide and Explode to create an animator that goes from the start
  * position to the end position. It takes into account the canceled position so that it
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index f4db4d6..b7099b6 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -268,6 +268,10 @@
     }
     
     public void setTo(DisplayMetrics o) {
+        if (this == o) {
+            return;
+        }
+
         widthPixels = o.widthPixels;
         heightPixels = o.heightPixels;
         density = o.density;
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index 39f66a5..665c583 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -20,44 +20,49 @@
 import java.io.PrintWriter;
 import java.util.Calendar;
 import java.util.Iterator;
-import java.util.LinkedList;
+import java.util.Deque;
+import java.util.ArrayDeque;
 
 /**
  * @hide
  */
 public final class LocalLog {
 
-    private LinkedList<String> mLog;
-    private int mMaxLines;
-    private long mNow;
+    private final Deque<String> mLog;
+    private final int mMaxLines;
 
     public LocalLog(int maxLines) {
-        mLog = new LinkedList<String>();
-        mMaxLines = maxLines;
+        mMaxLines = Math.max(0, maxLines);
+        mLog = new ArrayDeque<>(mMaxLines);
     }
 
-    public synchronized void log(String msg) {
-        if (mMaxLines > 0) {
-            mNow = System.currentTimeMillis();
-            StringBuilder sb = new StringBuilder();
-            Calendar c = Calendar.getInstance();
-            c.setTimeInMillis(mNow);
-            sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
-            mLog.add(sb.toString() + " - " + msg);
-            while (mLog.size() > mMaxLines) mLog.remove();
+    public void log(String msg) {
+        if (mMaxLines <= 0) {
+            return;
         }
+        Calendar c = Calendar.getInstance();
+        c.setTimeInMillis(System.currentTimeMillis());
+        append(String.format("%tm-%td %tH:%tM:%tS.%tL - %s", c, c, c, c, c, c, msg));
+    }
+
+    private synchronized void append(String logLine) {
+        while (mLog.size() >= mMaxLines) {
+            mLog.remove();
+        }
+        mLog.add(logLine);
     }
 
     public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        Iterator<String> itr = mLog.listIterator(0);
+        Iterator<String> itr = mLog.iterator();
         while (itr.hasNext()) {
             pw.println(itr.next());
         }
     }
 
     public synchronized void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        for (int i = mLog.size() - 1; i >= 0; i--) {
-            pw.println(mLog.get(i));
+        Iterator<String> itr = mLog.descendingIterator();
+        while (itr.hasNext()) {
+            pw.println(itr.next());
         }
     }
 
@@ -69,6 +74,9 @@
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             mLog.dump(fd, pw, args);
         }
+        public void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            mLog.reverseDump(fd, pw, args);
+        }
     }
 
     public ReadOnlyLocalLog readOnlyLocalLog() {
diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java
index f1c8c7d..6f314d0 100644
--- a/core/java/android/util/PathParser.java
+++ b/core/java/android/util/PathParser.java
@@ -16,6 +16,8 @@
 
 import android.graphics.Path;
 
+import dalvik.annotation.optimization.FastNative;
+
 /**
  * @hide
  */
@@ -119,14 +121,24 @@
     // Native functions are defined below.
     private static native void nParseStringForPath(long pathPtr, String pathString,
             int stringLength);
-    private static native void nCreatePathFromPathData(long outPathPtr, long pathData);
-    private static native long nCreateEmptyPathData();
-    private static native long nCreatePathData(long nativePtr);
     private static native long nCreatePathDataFromString(String pathString, int stringLength);
+
+    // ----------------- @FastNative -----------------------
+
+    @FastNative
+    private static native void nCreatePathFromPathData(long outPathPtr, long pathData);
+    @FastNative
+    private static native long nCreateEmptyPathData();
+    @FastNative
+    private static native long nCreatePathData(long nativePtr);
+    @FastNative
     private static native boolean nInterpolatePathData(long outDataPtr, long fromDataPtr,
             long toDataPtr, float fraction);
+    @FastNative
     private static native void nFinalize(long nativePtr);
+    @FastNative
     private static native boolean nCanMorph(long fromDataPtr, long toDataPtr);
+    @FastNative
     private static native void nSetPathData(long outDataPtr, long fromDataPtr);
 }
 
diff --git a/core/java/android/util/proto/EncodedBuffer.java b/core/java/android/util/proto/EncodedBuffer.java
new file mode 100644
index 0000000..ed38e6f
--- /dev/null
+++ b/core/java/android/util/proto/EncodedBuffer.java
@@ -0,0 +1,678 @@
+/*
+ * 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 android.util.proto;
+
+import android.annotation.TestApi;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * A stream of bytes containing a read pointer and a write pointer,
+ * backed by a set of fixed-size buffers.  There are write functions for the
+ * primitive types stored by protocol buffers, but none of the logic
+ * for tags, inner objects, or any of that.
+ *
+ * Terminology:
+ *      *Pos:       Position in the whole data set (as if it were a single buffer).
+ *      *Index:     Position within a buffer.
+ *      *BufIndex:  Index of a buffer within the mBuffers list
+ * @hide
+ */
+@TestApi
+public final class EncodedBuffer {
+    private static final String TAG = "EncodedBuffer";
+
+    private final ArrayList<byte[]> mBuffers = new ArrayList<byte[]>();
+
+    private final int mChunkSize;
+
+    /**
+     * The number of buffers in mBuffers. Stored separately to avoid the extra
+     * function call to size() everywhere for bounds checking.
+     */
+    private int mBufferCount;
+
+    /**
+     * The buffer we are currently writing to.
+     */
+    private byte[] mWriteBuffer;
+
+    /**
+     * The index into mWriteBuffer that we will write to next.
+     * It may point to the end of the buffer, in which case,
+     * the NEXT write will allocate a new buffer.
+     */
+    private int mWriteIndex;
+
+    /**
+     * The index of mWriteBuffer in mBuffers.
+     */
+    private int mWriteBufIndex;
+
+    /**
+     * The buffer we are currently reading from.
+     */
+    private byte[] mReadBuffer;
+
+    /**
+     * The index of mReadBuffer in mBuffers.
+     */
+    private int mReadBufIndex;
+
+    /**
+     * The index into mReadBuffer that we will read from next.
+     * It may point to the end of the buffer, in which case,
+     * the NEXT read will advance to the next buffer.
+     */
+    private int mReadIndex;
+
+    /**
+     * The amount of data in the last buffer.
+     */
+    private int mReadLimit = -1;
+
+    /**
+     * How much data there is total.
+     */
+    private int mReadableSize = -1;
+
+    public EncodedBuffer() {
+        this(0);
+    }
+
+    /**
+     * Construct an EncodedBuffer object.
+     *
+     * @param chunkSize The size of the buffers to use.  If chunkSize &lt;= 0, a default
+     *                  size will be used instead.
+     */
+    public EncodedBuffer(int chunkSize) {
+        if (chunkSize <= 0) {
+            chunkSize = 8 * 1024;
+        }
+        mChunkSize = chunkSize;
+        mWriteBuffer = new byte[mChunkSize];
+        mBuffers.add(mWriteBuffer);
+        mBufferCount = 1;
+    }
+
+    //
+    // Buffer management.
+    //
+
+    /**
+     * Rewind the read and write pointers, and record how much data was last written.
+     */
+    public void startEditing() {
+        mReadableSize = ((mWriteBufIndex) * mChunkSize) + mWriteIndex;
+        mReadLimit = mWriteIndex;
+
+        mWriteBuffer = mBuffers.get(0);
+        mWriteIndex = 0;
+        mWriteBufIndex = 0;
+
+        mReadBuffer = mWriteBuffer;
+        mReadBufIndex = 0;
+        mReadIndex = 0;
+    }
+
+    /**
+     * Rewind the read pointer. Don't touch the write pointer.
+     */
+    public void rewindRead() {
+        mReadBuffer = mBuffers.get(0);
+        mReadBufIndex = 0;
+        mReadIndex = 0;
+    }
+
+    /**
+     * Only valid after startEditing. Returns -1 before that.
+     */
+    public int getReadableSize() {
+        return mReadableSize;
+    }
+
+    //
+    // Reading from the read position.
+    //
+
+    /**
+     * Only valid after startEditing.
+     */
+    public int getReadPos() {
+        return ((mReadBufIndex) * mChunkSize) + mReadIndex;
+    }
+
+    /**
+     * Skip over _amount_ bytes.
+     */
+    public void skipRead(int amount) {
+        if (amount < 0) {
+            throw new RuntimeException("skipRead with negative amount=" + amount);
+        }
+        if (amount == 0) {
+            return;
+        }
+        if (amount <= mChunkSize - mReadIndex) {
+            mReadIndex += amount;
+        } else {
+            amount -= mChunkSize - mReadIndex;
+            mReadIndex = amount % mChunkSize;
+            if (mReadIndex == 0) {
+                mReadIndex = mChunkSize;
+                mReadBufIndex += (amount / mChunkSize);
+            } else {
+                mReadBufIndex += 1 + (amount / mChunkSize);
+            }
+            mReadBuffer = mBuffers.get(mReadBufIndex);
+        }
+    }
+
+    /**
+     * Read one byte from the stream and advance the read pointer.
+     *
+     * @throws IndexOutOfBoundsException if the read point is past the end of
+     * the buffer or past the read limit previously set by startEditing().
+     */
+    public byte readRawByte() {
+        if (mReadBufIndex > mBufferCount
+                || (mReadBufIndex == mBufferCount - 1 && mReadIndex >= mReadLimit)) {
+            throw new IndexOutOfBoundsException("Trying to read too much data"
+                    + " mReadBufIndex=" + mReadBufIndex + " mBufferCount=" + mBufferCount
+                    + " mReadIndex=" + mReadIndex + " mReadLimit=" + mReadLimit);
+        }
+        if (mReadIndex >= mChunkSize) {
+            mReadBufIndex++;
+            mReadBuffer = mBuffers.get(mReadBufIndex);
+            mReadIndex = 0;
+        }
+        return mReadBuffer[mReadIndex++];
+    }
+
+    /**
+     * Read an unsigned varint. The value will be returend in a java signed long.
+     */
+    public long readRawUnsigned() {
+        int bits = 0;
+        long result = 0;
+        while (true) {
+            final byte b = readRawByte();
+            result |= ((long)(b & 0x7F)) << bits;
+            if ((b & 0x80) == 0) {
+                return result;
+            }
+            bits += 7;
+            if (bits > 64) {
+                throw new ProtoParseException("Varint too long -- " + getDebugString());
+            }
+        }
+    }
+
+    /**
+     * Read 32 little endian bits from the stream.
+     */
+    public int readRawFixed32() {
+        return (readRawByte() & 0x0ff)
+                | ((readRawByte() & 0x0ff) << 8)
+                | ((readRawByte() & 0x0ff) << 16)
+                | ((readRawByte() & 0x0ff) << 24);
+    }
+
+    //
+    // Writing at a the end of the stream.
+    //
+
+    /**
+     * Advance to the next write buffer, allocating it if necessary.
+     *
+     * Must be called immediately <b>before</b> the next write, not after a write,
+     * so that a dangling empty buffer is not created.  Doing so will interfere
+     * with the expectation that mWriteIndex will point past the end of the buffer
+     * until the next read happens.
+     */
+    private void nextWriteBuffer() {
+        mWriteBufIndex++;
+        if (mWriteBufIndex >= mBufferCount) {
+            mWriteBuffer = new byte[mChunkSize];
+            mBuffers.add(mWriteBuffer);
+            mBufferCount++;
+        } else {
+            mWriteBuffer = mBuffers.get(mWriteBufIndex);
+        }
+        mWriteIndex = 0;
+    }
+
+    /**
+     * Write a single byte to the stream.
+     */
+    public void writeRawByte(byte val) {
+        if (mWriteIndex >= mChunkSize) {
+            nextWriteBuffer();
+        }
+        mWriteBuffer[mWriteIndex++] = val;
+    }
+
+    /**
+     * Return how many bytes a 32 bit unsigned varint will take when written to the stream.
+     */
+    public static int getRawVarint32Size(int val) {
+        if ((val & (0xffffffff << 7)) == 0) return 1;
+        if ((val & (0xffffffff << 14)) == 0) return 2;
+        if ((val & (0xffffffff << 21)) == 0) return 3;
+        if ((val & (0xffffffff << 28)) == 0) return 4;
+        return 5;
+    }
+
+    /**
+     * Write an unsigned varint to the stream. A signed value would need to take 10 bytes.
+     *
+     * @param val treated as unsigned.
+     */
+    public void writeRawVarint32(int val) {
+        while (true) {
+            if ((val & ~0x7F) == 0) {
+                writeRawByte((byte)val);
+                return;
+            } else {
+                writeRawByte((byte)((val & 0x7F) | 0x80));
+                val >>>= 7;
+            }
+        }
+    }
+
+    /**
+     * Return how many bytes a 32 bit signed zig zag value will take when written to the stream.
+     */
+    public static int getRawZigZag32Size(int val) {
+        return getRawVarint32Size(zigZag32(val));
+    }
+
+    /**
+     *  Write a zig-zag encoded value.
+     *
+     *  @param val treated as signed
+     */
+    public void writeRawZigZag32(int val) {
+        writeRawVarint32(zigZag32(val));
+    }
+
+    /**
+     * Return how many bytes a 64 bit varint will take when written to the stream.
+     */
+    public static int getRawVarint64Size(long val) {
+        if ((val & (0xffffffffffffffffL << 7)) == 0) return 1;
+        if ((val & (0xffffffffffffffffL << 14)) == 0) return 2;
+        if ((val & (0xffffffffffffffffL << 21)) == 0) return 3;
+        if ((val & (0xffffffffffffffffL << 28)) == 0) return 4;
+        if ((val & (0xffffffffffffffffL << 35)) == 0) return 5;
+        if ((val & (0xffffffffffffffffL << 42)) == 0) return 6;
+        if ((val & (0xffffffffffffffffL << 49)) == 0) return 7;
+        if ((val & (0xffffffffffffffffL << 56)) == 0) return 8;
+        if ((val & (0xffffffffffffffffL << 63)) == 0) return 9;
+        return 10;
+    }
+
+    /**
+     * Write a 64 bit varint to the stream.
+     */
+    public void writeRawVarint64(long val) {
+        while (true) {
+            if ((val & ~0x7FL) == 0) {
+                writeRawByte((byte)val);
+                return;
+            } else {
+                writeRawByte((byte)((val & 0x7F) | 0x80));
+                val >>>= 7;
+            }
+        }
+    }
+
+    /**
+     * Return how many bytes a signed 64 bit zig zag value will take when written to the stream.
+     */
+    public static int getRawZigZag64Size(long val) {
+        return getRawVarint64Size(zigZag64(val));
+    }
+
+    /**
+     * Write a 64 bit signed zig zag value to the stream.
+     */
+    public void writeRawZigZag64(long val) {
+        writeRawVarint64(zigZag64(val));
+    }
+
+    /**
+     * Write 4 little endian bytes to the stream.
+     */
+    public void writeRawFixed32(int val) {
+        writeRawByte((byte)(val));
+        writeRawByte((byte)(val >> 8));
+        writeRawByte((byte)(val >> 16));
+        writeRawByte((byte)(val >> 24));
+    }
+
+    /**
+     * Write 8 little endian bytes to the stream.
+     */
+    public void writeRawFixed64(long val) {
+        writeRawByte((byte)(val));
+        writeRawByte((byte)(val >> 8));
+        writeRawByte((byte)(val >> 16));
+        writeRawByte((byte)(val >> 24));
+        writeRawByte((byte)(val >> 32));
+        writeRawByte((byte)(val >> 40));
+        writeRawByte((byte)(val >> 48));
+        writeRawByte((byte)(val >> 56));
+    }
+
+    /**
+     * Write a buffer to the stream. Writes nothing if val is null or zero-length.
+     */
+    public void writeRawBuffer(byte[] val) {
+        if (val != null && val.length > 0) {
+            writeRawBuffer(val, 0, val.length);
+        }
+    }
+
+    /**
+     * Write part of an array of bytes.
+     */
+    public void writeRawBuffer(byte[] val, int offset, int length) {
+        if (val == null) {
+            return;
+        }
+        // Write up to the amount left in the first chunk to write.
+        int amt = length < (mChunkSize - mWriteIndex) ? length : (mChunkSize - mWriteIndex);
+        if (amt > 0) {
+            System.arraycopy(val, offset, mWriteBuffer, mWriteIndex, amt);
+            mWriteIndex += amt;
+            length -= amt;
+            offset += amt;
+        }
+        while (length > 0) {
+            // We know we're now at the beginning of a chunk
+            nextWriteBuffer();
+            amt = length < mChunkSize ? length : mChunkSize;
+            System.arraycopy(val, offset, mWriteBuffer, mWriteIndex, amt);
+            mWriteIndex += amt;
+            length -= amt;
+            offset += amt;
+        }
+    }
+
+    /**
+     * Copies data _size_ bytes of data within this buffer from _srcOffset_
+     * to the current write position. Like memmov but handles the chunked buffer.
+     */
+    public void writeFromThisBuffer(int srcOffset, int size) {
+        if (mReadLimit < 0) {
+            throw new IllegalStateException("writeFromThisBuffer before startEditing");
+        }
+        if (srcOffset < getWritePos()) {
+            throw new IllegalArgumentException("Can only move forward in the buffer --"
+                    + " srcOffset=" + srcOffset + " size=" + size + " " + getDebugString());
+        }
+        if (srcOffset + size > mReadableSize) {
+            throw new IllegalArgumentException("Trying to move more data than there is --"
+                    + " srcOffset=" + srcOffset + " size=" + size + " " + getDebugString());
+        }
+        if (size == 0) {
+            return;
+        }
+        if (srcOffset == ((mWriteBufIndex) * mChunkSize) + mWriteIndex /* write pos */) {
+            // Writing to the same location. Just advance the write pointer.  We already
+            // checked that size is in bounds, so we don't need to do any more range
+            // checking.
+            if (size <= mChunkSize - mWriteIndex) {
+                mWriteIndex += size;
+            } else {
+                size -= mChunkSize - mWriteIndex;
+                mWriteIndex = size % mChunkSize;
+                if (mWriteIndex == 0) {
+                    // Roll it back so nextWriteBuffer can do its job
+                    // on the next call (also makes mBuffers.get() not
+                    // fail if we're at the end).
+                    mWriteIndex = mChunkSize;
+                    mWriteBufIndex += (size / mChunkSize);
+                } else {
+                    mWriteBufIndex += 1 + (size / mChunkSize);
+                }
+                mWriteBuffer = mBuffers.get(mWriteBufIndex);
+            }
+        } else {
+            // Loop through the buffer, copying as much as we can each time.
+            // We already bounds checked so we don't need to do it again here,
+            // and nextWriteBuffer will never allocate.
+            int readBufIndex = srcOffset / mChunkSize;
+            byte[] readBuffer = mBuffers.get(readBufIndex);
+            int readIndex = srcOffset % mChunkSize;
+            while (size > 0) {
+                if (mWriteIndex >= mChunkSize) {
+                    nextWriteBuffer();
+                }
+                if (readIndex >= mChunkSize) {
+                    readBufIndex++;
+                    readBuffer = mBuffers.get(readBufIndex);
+                    readIndex = 0;
+                }
+                final int spaceInWriteBuffer = mChunkSize - mWriteIndex;
+                final int availableInReadBuffer = mChunkSize - readIndex;
+                final int amt = Math.min(size, Math.min(spaceInWriteBuffer, availableInReadBuffer));
+                System.arraycopy(readBuffer, readIndex, mWriteBuffer, mWriteIndex, amt);
+                mWriteIndex += amt;
+                readIndex += amt;
+                size -= amt;
+            }
+        }
+    }
+
+    //
+    // Writing at a particular location.
+    //
+
+    /**
+     * Returns the index into the virtual array of the write pointer.
+     */
+    public int getWritePos() {
+        return ((mWriteBufIndex) * mChunkSize) + mWriteIndex;
+    }
+
+    /**
+     * Resets the write pointer to a virtual location as returned by getWritePos.
+     */
+    public void rewindWriteTo(int writePos) {
+        if (writePos > getWritePos()) {
+            throw new RuntimeException("rewindWriteTo only can go backwards" + writePos);
+        }
+        mWriteBufIndex = writePos / mChunkSize;
+        mWriteIndex = writePos % mChunkSize;
+        if (mWriteIndex == 0 && mWriteBufIndex != 0) {
+            // Roll back so nextWriteBuffer can do its job on the next call
+            // but at the first write we're at 0.
+            mWriteIndex = mChunkSize;
+            mWriteBufIndex--;
+        }
+        mWriteBuffer = mBuffers.get(mWriteBufIndex);
+    }
+
+    /**
+     * Read a 32 bit value from the stream.
+     *
+     * Doesn't touch or affect mWritePos.
+     */
+    public int getRawFixed32At(int pos) {
+        return (0x00ff & (int)mBuffers.get(pos / mChunkSize)[pos % mChunkSize])
+                | ((0x0ff & (int)mBuffers.get((pos+1) / mChunkSize)[(pos+1) % mChunkSize]) << 8)
+                | ((0x0ff & (int)mBuffers.get((pos+2) / mChunkSize)[(pos+2) % mChunkSize]) << 16)
+                | ((0x0ff & (int)mBuffers.get((pos+3) / mChunkSize)[(pos+3) % mChunkSize]) << 24);
+    }
+
+    /**
+     * Overwrite a 32 bit value in the stream.
+     *
+     * Doesn't touch or affect mWritePos.
+     */
+    public void editRawFixed32(int pos, int val) {
+        mBuffers.get(pos / mChunkSize)[pos % mChunkSize] = (byte)(val);
+        mBuffers.get((pos+1) / mChunkSize)[(pos+1) % mChunkSize] = (byte)(val >> 8);
+        mBuffers.get((pos+2) / mChunkSize)[(pos+2) % mChunkSize] = (byte)(val >> 16);
+        mBuffers.get((pos+3) / mChunkSize)[(pos+3) % mChunkSize] = (byte)(val >> 24);
+    }
+
+    //
+    // Zigging and zagging
+    //
+
+    /**
+     * Zig-zag encode a 32 bit value.
+     */
+    private static int zigZag32(int val) {
+        return (val << 1) ^ (val >> 31);
+    }
+
+    /**
+     * Zig-zag encode a 64 bit value.
+     */
+    private static long zigZag64(long val) {
+        return (val << 1) ^ (val >> 63);
+    }
+
+    //
+    // Debugging / testing
+    //
+    // VisibleForTesting
+
+    /**
+     * Get a copy of the first _size_ bytes of data. This is not range
+     * checked, and if the bounds are outside what has been written you will
+     * get garbage and if it is outside the buffers that have been allocated,
+     * you will get an exception.
+     */
+    public byte[] getBytes(int size) {
+        final byte[] result = new byte[size];
+
+        final int bufCount = size / mChunkSize;
+        int bufIndex;
+        int writeIndex = 0;
+
+        for (bufIndex=0; bufIndex<bufCount; bufIndex++) {
+            System.arraycopy(mBuffers.get(bufIndex), 0, result, writeIndex, mChunkSize);
+            writeIndex += mChunkSize;
+        }
+
+        final int lastSize = size - (bufCount * mChunkSize);
+        if (lastSize > 0) {
+            System.arraycopy(mBuffers.get(bufIndex), 0, result, writeIndex, lastSize);
+        }
+
+        return result;
+    }
+
+    /**
+     * Get the number of chunks allocated.
+     */
+    // VisibleForTesting
+    public int getChunkCount() {
+        return mBuffers.size();
+    }
+
+    /**
+     * Get the write position inside the current write chunk.
+     */
+     // VisibleForTesting
+    public int getWriteIndex() {
+        return mWriteIndex;
+    }
+
+    /**
+     * Get the index of the current write chunk in the list of chunks.
+     */
+    // VisibleForTesting
+    public int getWriteBufIndex() {
+        return mWriteBufIndex;
+    }
+
+    /**
+     * Return debugging information about this EncodedBuffer object.
+     */
+    public String getDebugString() {
+        return "EncodedBuffer( mChunkSize=" + mChunkSize + " mBuffers.size=" + mBuffers.size()
+                + " mBufferCount=" + mBufferCount + " mWriteIndex=" + mWriteIndex
+                + " mWriteBufIndex=" + mWriteBufIndex + " mReadBufIndex=" + mReadBufIndex
+                + " mReadIndex=" + mReadIndex + " mReadableSize=" + mReadableSize
+                + " mReadLimit=" + mReadLimit + " )";
+    }
+
+    /**
+     * Print the internal buffer chunks.
+     */
+    public void dumpBuffers(String tag) {
+        final int N = mBuffers.size();
+        int start = 0;
+        for (int i=0; i<N; i++) {
+            start += dumpByteString(tag, "{" + i + "} ", start, mBuffers.get(i));
+        }
+    }
+
+    /**
+     * Print the internal buffer chunks.
+     */
+    public static void dumpByteString(String tag, String prefix, byte[] buf) {
+        dumpByteString(tag, prefix, 0, buf);
+    }
+
+    /**
+     * Print the internal buffer chunks.
+     */
+    private static int dumpByteString(String tag, String prefix, int start, byte[] buf) {
+        StringBuffer sb = new StringBuffer();
+        final int length = buf.length;
+        final int lineLen = 16;
+        int i;
+        for (i=0; i<length; i++) {
+            if (i % lineLen == 0) {
+                if (i != 0) {
+                    Log.d(tag, sb.toString());
+                    sb = new StringBuffer();
+                }
+                sb.append(prefix);
+                sb.append('[');
+                sb.append(start + i);
+                sb.append(']');
+                sb.append(' ');
+            } else {
+                sb.append(' ');
+            }
+            byte b = buf[i];
+            byte c = (byte)((b >> 4) & 0x0f);
+            if (c < 10) {
+                sb.append((char)('0' + c));
+            } else {
+                sb.append((char)('a' - 10 + c));
+            }
+            byte d = (byte)(b & 0x0f);
+            if (d < 10) {
+                sb.append((char)('0' + d));
+            } else {
+                sb.append((char)('a' - 10 + d));
+            }
+        }
+        Log.d(tag, sb.toString());
+        return length;
+    }
+}
diff --git a/core/java/android/util/proto/ProtoOutputStream.java b/core/java/android/util/proto/ProtoOutputStream.java
new file mode 100644
index 0000000..8f99399
--- /dev/null
+++ b/core/java/android/util/proto/ProtoOutputStream.java
@@ -0,0 +1,1599 @@
+/*
+ * 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 android.util.proto;
+
+import android.annotation.TestApi;
+import android.util.Log;
+
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+/**
+ * Class to write to a protobuf stream.
+ *
+ * Each write method takes an ID code from the protoc generated classes
+ * and the value to write.  To make a nested object, call startObject
+ * and then endObject when you are done.
+ *
+ * The ID codes have type information embedded into them, so if you call
+ * the incorrect function you will get an IllegalArgumentException.
+ *
+ * To retrieve the encoded protobuf stream, call getBytes().
+ *
+ * TODO: Add a constructor that takes an OutputStream and write to that
+ * stream as the top-level objects are finished.
+ *
+ * @hide
+ */
+
+/* IMPLEMENTATION NOTES
+ *
+ * Because protobuf has inner values, and they are length prefixed, and
+ * those sizes themselves are stored with a variable length encoding, it
+ * is impossible to know how big an object will be in a single pass.
+ *
+ * The traditional way is to copy the in-memory representation of an object
+ * into the generated proto Message objects, do a traversal of those to
+ * cache the size, and then write the size-prefixed buffers.
+ *
+ * We are trying to avoid too much generated code here, but this class still
+ * needs to have a somewhat sane API.  We can't have the multiple passes be
+ * done by the calling code.  In addition, we want to avoid the memory high
+ * water mark of duplicating all of the values into the traditional in-memory
+ * Message objects. We need to find another way.
+ *
+ * So what we do here is to let the calling code write the data into a
+ * byte[] (actually a collection of them wrapped in the EncodedBuffer) class,
+ * but not do the varint encoding of the sub-message sizes.  Then, we do a
+ * recursive traversal of the buffer itself, calculating the sizes (which are
+ * then knowable, although still not the actual sizes in the buffer because of
+ * possible further nesting).  Then we do a third pass, compacting the
+ * buffer and varint encoding the sizes.
+ *
+ * This gets us a relatively small number number of fixed-size allocations,
+ * which is less likely to cause memory fragmentation or churn the GC, and
+ * the same number of data copies as would have gotten with setting it
+ * field-by-field in generated code, and no code bloat from generated code.
+ * The final data copy is also done with System.arraycopy, which will be
+ * more efficient, in general, than doing the individual fields twice (as in
+ * the traditional way).
+ *
+ * To accomplish the multiple passes, whenever we write a
+ * WIRE_TYPE_LENGTH_DELIMITED field, we write the size occupied in our
+ * buffer as a fixed 32 bit int (called childRawSize), not variable length
+ * one. We reserve another 32 bit slot for the computed size (called
+ * childEncodedSize).  If we know the size up front, as we do for strings
+ * and byte[], then we also put that into childEncodedSize, if we don't, we
+ * write the negative of childRawSize, as a sentiel that we need to
+ * compute it during the second pass and recursively compact it during the
+ * third pass.
+ *
+ * Unsgigned size varints can be up to five bytes long, but we reserve eight
+ * bytes for overhead, so we know that when we compact the buffer, there
+ * will always be space for the encoded varint.
+ *
+ * When we can figure out the size ahead of time, we do, in order
+ * to save overhead with recalculating it, and with the later arraycopy.
+ *
+ * During the period between when the caller has called startObject, but
+ * not yet called endObject, we maintain a linked list of the tokens
+ * returned by startObject, stored in those 8 bytes of size storage space.
+ * We use that linked list of tokens to ensure that the caller has
+ * correctly matched pairs of startObject and endObject calls, and issue
+ * errors if they are not matched.
+ */
+@TestApi
+public final class ProtoOutputStream {
+    public static final String TAG = "ProtoOutputStream";
+
+    public static final int FIELD_ID_SHIFT = 3;
+    public static final int WIRE_TYPE_MASK = (1<<FIELD_ID_SHIFT)-1;
+    public static final int FIELD_ID_MASK = ~WIRE_TYPE_MASK;
+
+    public static final int WIRE_TYPE_VARINT = 0;
+    public static final int WIRE_TYPE_FIXED64 = 1;
+    public static final int WIRE_TYPE_LENGTH_DELIMITED = 2;
+    public static final int WIRE_TYPE_START_GROUP = 3;
+    public static final int WIRE_TYPE_END_GROUP = 4;
+    public static final int WIRE_TYPE_FIXED32 = 5;
+
+    /**
+     * Position of the field type in a (long) fieldId.
+     */
+    public static final int FIELD_TYPE_SHIFT = 32;
+
+    /**
+     * Mask for the field types stored in a fieldId.  Leaves a whole
+     * byte for future expansion, even though there are currently only 17 types.
+     */
+    public static final long FIELD_TYPE_MASK = 0x0ffL << FIELD_TYPE_SHIFT;
+
+    public static final long FIELD_TYPE_UNKNOWN = 0;
+
+    public static final long FIELD_TYPE_DOUBLE = 1L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_FLOAT = 2L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_INT32 = 3L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_INT64 = 4L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_UINT32 = 5L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_UINT64 = 6L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_SINT32 = 7L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_SINT64 = 8L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_FIXED32 = 9L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_FIXED64 = 10L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_SFIXED32 = 11L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_SFIXED64 = 12L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_BOOL = 13L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_STRING = 14L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_BYTES = 15L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_ENUM = 16L << FIELD_TYPE_SHIFT;
+    public static final long FIELD_TYPE_OBJECT = 17L << FIELD_TYPE_SHIFT;
+
+    private static final String[] FIELD_TYPE_NAMES = new String[] {
+        "Double",
+        "Float",
+        "Int32",
+        "Int64",
+        "UInt32",
+        "UInt64",
+        "SInt32",
+        "SInt64",
+        "Fixed32",
+        "Fixed64",
+        "SFixed32",
+        "SFixed64",
+        "Bool",
+        "String",
+        "Bytes",
+        "Enum",
+        "Object",
+    };
+
+    //
+    // FieldId flags for whether the field is single, repeated or packed.
+    //
+    public static final int FIELD_COUNT_SHIFT = 40;
+    public static final long FIELD_COUNT_MASK = 0x0fL << FIELD_COUNT_SHIFT;
+
+    public static final long FIELD_COUNT_UNKNOWN = 0;
+    public static final long FIELD_COUNT_SINGLE = 1L << FIELD_COUNT_SHIFT;
+    public static final long FIELD_COUNT_REPEATED = 2L << FIELD_COUNT_SHIFT;
+    public static final long FIELD_COUNT_PACKED = 5L << FIELD_COUNT_SHIFT;
+
+    /**
+     * Our buffer.
+     */
+    private EncodedBuffer mBuffer;
+
+    /**
+     * Current nesting depth of startObject calls.
+     */
+    private int mDepth;
+
+    /**
+     * An ID given to objects and returned in the token from startObject
+     * and stored in the buffer until endObject is called, where the two
+     * are checked.  Starts at -1 and becomes more negative, so the values
+     * aren't likely to alias with the size it will be overwritten with,
+     * which tend to be small, and we will be more likely to catch when
+     * the caller of endObject uses a stale token that they didn't intend
+     * to (e.g. copy and paste error).
+     */
+    private int mNextObjectId = -1;
+
+    /**
+     * The object token we are expecting in endObject.  If another call to
+     * startObject happens, this is written to that location, which gives
+     * us a stack, stored in the space for the as-yet unused size fields.
+     */
+    private long mExpectedObjectToken;
+
+    /**
+     * Index in mBuffer that we should start copying from on the next
+     * pass of compaction.
+     */
+    private int mCopyBegin;
+
+    /**
+     * Whether we've already compacted
+     */
+    private boolean mCompacted;
+
+    /**
+     * Construct a ProtoOutputStream with the default chunk size.
+     */
+    public ProtoOutputStream() {
+        this(0);
+    }
+
+    /**
+     * Construct a ProtoOutputStream with the given chunk size.
+     */
+    public ProtoOutputStream(int chunkSize) {
+        mBuffer = new EncodedBuffer(chunkSize);
+    }
+
+    //
+    // proto3 type: double
+    // java type: double
+    // encoding: fixed64
+    // wire type: WIRE_TYPE_FIXED64
+    //
+
+    /**
+     * Write a single proto "double" type field value.
+     */
+    public void writeDouble(long fieldId, double val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_DOUBLE);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_FIXED64);
+            mBuffer.writeRawFixed64(Double.doubleToLongBits(val));
+        }
+    }
+
+    /**
+     * Write a single repeated proto "double" type field value.
+     */
+    public void writeRepeatedDouble(long fieldId, double val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_DOUBLE);
+
+        writeTag(id, WIRE_TYPE_FIXED64);
+        mBuffer.writeRawFixed64(Double.doubleToLongBits(val));
+    }
+
+    /**
+     * Write a list of packed proto "double" type field values.
+     */
+    public void writePackedDouble(long fieldId, double[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_DOUBLE);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            writeKnownLengthHeader(id, N * 8);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawFixed64(Double.doubleToLongBits(val[i]));
+            }
+        }
+    }
+
+    //
+    // proto3 type: float
+    // java type: float
+    // encoding: fixed32
+    // wire type: WIRE_TYPE_FIXED32
+    //
+
+    /**
+     * Write a single proto "float" type field value.
+     */
+    public void writeFloat(long fieldId, float val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FLOAT);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_FIXED32);
+            mBuffer.writeRawFixed32(Float.floatToIntBits(val));
+        }
+    }
+
+    /**
+     * Write a single repeated proto "float" type field value.
+     */
+    public void writeRepeatedFloat(long fieldId, float val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FLOAT);
+
+        writeTag(id, WIRE_TYPE_FIXED32);
+        mBuffer.writeRawFixed32(Float.floatToIntBits(val));
+    }
+
+    /**
+     * Write a list of packed proto "float" type field value.
+     */
+    public void writePackedFloat(long fieldId, float[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FLOAT);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            writeKnownLengthHeader(id, N * 4);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawFixed32(Float.floatToIntBits(val[i]));
+            }
+        }
+    }
+
+    //
+    // proto3 type: int32
+    // java type: int
+    // signed/unsigned: signed
+    // encoding: varint
+    // wire type: WIRE_TYPE_VARINT
+    //
+
+    /**
+     * Writes a java int as an usigned varint.
+     *
+     * The unadorned int32 type in protobuf is unfortunate because it
+     * is stored in memory as a signed value, but encodes as unsigned
+     * varints, which are formally always longs.  So here, we encode
+     * negative values as 64 bits, which will get the sign-extension,
+     * and positive values as 32 bits, which saves a marginal amount
+     * of work in that it processes ints instead of longs.
+     */
+    private void writeUnsignedVarintFromSignedInt(int val) {
+        if (val >= 0) {
+            mBuffer.writeRawVarint32(val);
+        } else {
+            mBuffer.writeRawVarint64(val);
+        }
+    }
+
+    /**
+     * Write a single proto "int32" type field value.
+     *
+     * Note that these are stored in memory as signed values and written as unsigned
+     * varints, which if negative, are 10 bytes long. If you know the data is likely
+     * to be negative, use "sint32".
+     */
+    public void writeInt32(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_INT32);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_VARINT);
+            writeUnsignedVarintFromSignedInt(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "int32" type field value.
+     *
+     * Note that these are stored in memory as signed values and written as unsigned
+     * varints, which if negative, are 10 bytes long. If you know the data is likely
+     * to be negative, use "sint32".
+     */
+    public void writeRepeatedInt32(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_INT32);
+
+        writeTag(id, WIRE_TYPE_VARINT);
+        writeUnsignedVarintFromSignedInt(val);
+    }
+
+    /**
+     * Write a list of packed proto "int32" type field value.
+     *
+     * Note that these are stored in memory as signed values and written as unsigned
+     * varints, which if negative, are 10 bytes long. If you know the data is likely
+     * to be negative, use "sint32".
+     */
+    public void writePackedInt32(long fieldId, int[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_INT32);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            int size = 0;
+            for (int i=0; i<N; i++) {
+                final int v = val[i];
+                size += v >= 0 ? EncodedBuffer.getRawVarint32Size(v) : 10;
+            }
+            writeKnownLengthHeader(id, size);
+            for (int i=0; i<N; i++) {
+                writeUnsignedVarintFromSignedInt(val[i]);
+            }
+        }
+    }
+
+    //
+    // proto3 type: int64
+    // java type: int
+    // signed/unsigned: signed
+    // encoding: varint
+    // wire type: WIRE_TYPE_VARINT
+    //
+
+    /**
+     * Write a single proto "int64" type field value.
+     */
+    public void writeInt64(long fieldId, long val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_INT64);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_VARINT);
+            mBuffer.writeRawVarint64(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "int64" type field value.
+     */
+    public void writeRepeatedInt64(long fieldId, long val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_INT64);
+
+        writeTag(id, WIRE_TYPE_VARINT);
+        mBuffer.writeRawVarint64(val);
+    }
+
+    /**
+     * Write a list of packed proto "int64" type field value.
+     */
+    public void writePackedInt64(long fieldId, long[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_INT64);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            int size = 0;
+            for (int i=0; i<N; i++) {
+                size += EncodedBuffer.getRawVarint64Size(val[i]);
+            }
+            writeKnownLengthHeader(id, size);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawVarint64(val[i]);
+            }
+        }
+    }
+
+    //
+    // proto3 type: uint32
+    // java type: int
+    // signed/unsigned: unsigned
+    // encoding: varint
+    // wire type: WIRE_TYPE_VARINT
+    //
+
+    /**
+     * Write a single proto "uint32" type field value.
+     */
+    public void writeUInt32(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_UINT32);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_VARINT);
+            mBuffer.writeRawVarint32(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "uint32" type field value.
+     */
+    public void writeRepeatedUInt32(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_UINT32);
+
+        writeTag(id, WIRE_TYPE_VARINT);
+        mBuffer.writeRawVarint32(val);
+    }
+
+    /**
+     * Write a list of packed proto "uint32" type field value.
+     */
+    public void writePackedUInt32(long fieldId, int[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_UINT32);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            int size = 0;
+            for (int i=0; i<N; i++) {
+                size += EncodedBuffer.getRawVarint32Size(val[i]);
+            }
+            writeKnownLengthHeader(id, size);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawVarint32(val[i]);
+            }
+        }
+    }
+
+    //
+    // proto3 type: uint64
+    // java type: int
+    // signed/unsigned: unsigned
+    // encoding: varint
+    // wire type: WIRE_TYPE_VARINT
+    //
+
+    /**
+     * Write a single proto "uint64" type field value.
+     */
+    public void writeUInt64(long fieldId, long val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_UINT64);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_VARINT);
+            mBuffer.writeRawVarint64(val);
+        }
+    }
+
+    /**
+     * Write a single proto "uint64" type field value.
+     */
+    public void writeRepeatedUInt64(long fieldId, long val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_UINT64);
+
+        writeTag(id, WIRE_TYPE_VARINT);
+        mBuffer.writeRawVarint64(val);
+    }
+
+    /**
+     * Write a single proto "uint64" type field value.
+     */
+    public void writePackedUInt64(long fieldId, long[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_UINT64);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            int size = 0;
+            for (int i=0; i<N; i++) {
+                size += EncodedBuffer.getRawVarint64Size(val[i]);
+            }
+            writeKnownLengthHeader(id, size);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawVarint64(val[i]);
+            }
+        }
+    }
+
+    //
+    // proto3 type: sint32
+    // java type: int
+    // signed/unsigned: signed
+    // encoding: zig-zag
+    // wire type: WIRE_TYPE_VARINT
+    //
+
+    /**
+     * Write a single proto "sint32" type field value.
+     */
+    public void writeSInt32(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SINT32);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_VARINT);
+            mBuffer.writeRawZigZag32(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "sint32" type field value.
+     */
+    public void writeRepeatedSInt32(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SINT32);
+
+        writeTag(id, WIRE_TYPE_VARINT);
+        mBuffer.writeRawZigZag32(val);
+    }
+
+    /**
+     * Write a list of packed proto "sint32" type field value.
+     */
+    public void writePackedSInt32(long fieldId, int[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SINT32);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            int size = 0;
+            for (int i=0; i<N; i++) {
+                size += EncodedBuffer.getRawZigZag32Size(val[i]);
+            }
+            writeKnownLengthHeader(id, size);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawZigZag32(val[i]);
+            }
+        }
+    }
+
+    //
+    // proto3 type: sint64
+    // java type: int
+    // signed/unsigned: signed
+    // encoding: zig-zag
+    // wire type: WIRE_TYPE_VARINT
+    //
+
+    /**
+     * Write a single proto "sint64" type field value.
+     */
+    public void writeSInt64(long fieldId, long val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SINT64);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_VARINT);
+            mBuffer.writeRawZigZag64(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "sint64" type field value.
+     */
+    public void writeRepeatedSInt64(long fieldId, long val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SINT64);
+
+        writeTag(id, WIRE_TYPE_VARINT);
+        mBuffer.writeRawZigZag64(val);
+    }
+
+    /**
+     * Write a list of packed proto "sint64" type field value.
+     */
+    public void writePackedSInt64(long fieldId, long[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SINT64);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            int size = 0;
+            for (int i=0; i<N; i++) {
+                size += EncodedBuffer.getRawZigZag64Size(val[i]);
+            }
+            writeKnownLengthHeader(id, size);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawZigZag64(val[i]);
+            }
+        }
+    }
+
+    //
+    // proto3 type: fixed32
+    // java type: int
+    // encoding: little endian
+    // wire type: WIRE_TYPE_FIXED32
+    //
+
+    /**
+     * Write a single proto "fixed32" type field value.
+     */
+    public void writeFixed32(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FIXED32);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_FIXED32);
+            mBuffer.writeRawFixed32(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "fixed32" type field value.
+     */
+    public void writeRepeatedFixed32(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FIXED32);
+
+        writeTag(id, WIRE_TYPE_FIXED32);
+        mBuffer.writeRawFixed32(val);
+    }
+
+    /**
+     * Write a list of packed proto "fixed32" type field value.
+     */
+    public void writePackedFixed32(long fieldId, int[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FIXED32);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            writeKnownLengthHeader(id, N * 4);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawFixed32(val[i]);
+            }
+        }
+    }
+
+    //
+    // proto3 type: fixed64
+    // java type: long
+    // encoding: fixed64
+    // wire type: WIRE_TYPE_FIXED64
+    //
+
+    /**
+     * Write a single proto "fixed64" type field value.
+     */
+    public void writeFixed64(long fieldId, long val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FIXED64);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_FIXED64);
+            mBuffer.writeRawFixed64(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "fixed64" type field value.
+     */
+    public void writeRepeatedFixed64(long fieldId, long val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FIXED64);
+
+        writeTag(id, WIRE_TYPE_FIXED64);
+        mBuffer.writeRawFixed64(val);
+    }
+
+    /**
+     * Write a list of packed proto "fixed64" type field value.
+     */
+    public void writePackedFixed64(long fieldId, long[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FIXED64);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            writeKnownLengthHeader(id, N * 8);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawFixed64(val[i]);
+            }
+        }
+    }
+
+    //
+    // proto3 type: sfixed32
+    // java type: int
+    // encoding: little endian
+    // wire type: WIRE_TYPE_FIXED32
+    //
+    /**
+     * Write a single proto "sfixed32" type field value.
+     */
+    public void writeSFixed32(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SFIXED32);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_FIXED32);
+            mBuffer.writeRawFixed32(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "sfixed32" type field value.
+     */
+    public void writeRepeatedSFixed32(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SFIXED32);
+
+        writeTag(id, WIRE_TYPE_FIXED32);
+        mBuffer.writeRawFixed32(val);
+    }
+
+    /**
+     * Write a list of packed proto "sfixed32" type field value.
+     */
+    public void writePackedSFixed32(long fieldId, int[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SFIXED32);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            writeKnownLengthHeader(id, N * 4);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawFixed32(val[i]);
+            }
+        }
+    }
+
+    //
+    // proto3 type: sfixed64
+    // java type: long
+    // encoding: little endian
+    // wire type: WIRE_TYPE_FIXED64
+    //
+
+    /**
+     * Write a single proto "sfixed64" type field value.
+     */
+    public void writeSFixed64(long fieldId, long val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SFIXED64);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_FIXED64);
+            mBuffer.writeRawFixed64(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "sfixed64" type field value.
+     */
+    public void writeRepeatedSFixed64(long fieldId, long val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SFIXED64);
+
+        writeTag(id, WIRE_TYPE_FIXED64);
+        mBuffer.writeRawFixed64(val);
+    }
+
+    /**
+     * Write a list of packed proto "sfixed64" type field value.
+     */
+    public void writePackedSFixed64(long fieldId, long[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SFIXED64);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            writeKnownLengthHeader(id, N * 8);
+            for (int i=0; i<N; i++) {
+                mBuffer.writeRawFixed64(val[i]);
+            }
+        }
+    }
+
+    //
+    // proto3 type: bool
+    // java type: boolean
+    // encoding: varint
+    // wire type: WIRE_TYPE_VARINT
+    //
+
+    /**
+     * Write a single proto "bool" type field value.
+     */
+    public void writeBool(long fieldId, boolean val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_BOOL);
+
+        if (val) {
+            writeTag(id, WIRE_TYPE_VARINT);
+            // 0 and 1 are the same as their varint counterparts
+            mBuffer.writeRawByte((byte)1);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "bool" type field value.
+     */
+    public void writeRepeatedBool(long fieldId, boolean val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BOOL);
+
+        writeTag(id, WIRE_TYPE_VARINT);
+        mBuffer.writeRawByte((byte)(val ? 1 : 0));
+    }
+
+    /**
+     * Write a list of packed proto "bool" type field value.
+     */
+    public void writePackedBool(long fieldId, boolean[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_BOOL);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            // Write the header
+            writeKnownLengthHeader(id, N);
+
+            // Write the data
+            for (int i=0; i<N; i++) {
+                // 0 and 1 are the same as their varint counterparts
+                mBuffer.writeRawByte((byte)(val[i] ? 1 : 0));
+            }
+        }
+    }
+
+    //
+    // proto3 type: string
+    // java type: String
+    // encoding: utf-8
+    // wire type: WIRE_TYPE_LENGTH_DELIMITED
+    //
+
+    /**
+     * Write a single proto "string" type field value.
+     */
+    public void writeString(long fieldId, String val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_STRING);
+
+        if (val != null && val.length() > 0) {
+            writeUtf8String(id, val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "string" type field value.
+     */
+    public void writeRepeatedString(long fieldId, String val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_STRING);
+
+        if (val == null || val.length() == 0) {
+            writeKnownLengthHeader(id, 0);
+        } else {
+            writeUtf8String(id, val);
+        }
+    }
+
+    /**
+     * Write a list of packed proto "string" type field value.
+     */
+    private void writeUtf8String(int id, String val) {
+        // TODO: Is it worth converting by hand in order to not allocate?
+        try {
+            final byte[] buf = val.getBytes("UTF-8");
+            writeKnownLengthHeader(id, buf.length);
+            mBuffer.writeRawBuffer(buf);
+        } catch (UnsupportedEncodingException ex) {
+            throw new RuntimeException("not possible");
+        }
+    }
+
+    //
+    // proto3 type: bytes
+    // java type: byte[]
+    // encoding: varint
+    // wire type: WIRE_TYPE_VARINT
+    //
+
+    /**
+     * Write a single proto "bytes" type field value.
+     */
+    public void writeBytes(long fieldId, byte[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_BYTES);
+
+        if (val != null && val.length > 0) {
+            writeKnownLengthHeader(id, val.length);
+            mBuffer.writeRawBuffer(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto "bytes" type field value.
+     */
+    public void writeRepeatedBytes(long fieldId, byte[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BYTES);
+
+        writeKnownLengthHeader(id, val == null ? 0 : val.length);
+        mBuffer.writeRawBuffer(val);
+    }
+
+    //
+    // proto3 type: enum
+    // java type: int
+    // signed/unsigned: unsigned
+    // encoding: varint
+    // wire type: WIRE_TYPE_VARINT
+    //
+
+    /**
+     * Write a single proto enum type field value.
+     */
+    public void writeEnum(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_ENUM);
+
+        if (val != 0) {
+            writeTag(id, WIRE_TYPE_VARINT);
+            writeUnsignedVarintFromSignedInt(val);
+        }
+    }
+
+    /**
+     * Write a single repeated proto enum type field value.
+     */
+    public void writeRepeatedEnum(long fieldId, int val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_ENUM);
+
+        writeTag(id, WIRE_TYPE_VARINT);
+        writeUnsignedVarintFromSignedInt(val);
+    }
+
+    /**
+     * Write a list of packed proto enum type field value.
+     */
+    public void writePackedEnum(long fieldId, int[] val) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_ENUM);
+
+        final int N = val != null ? val.length : 0;
+        if (N > 0) {
+            int size = 0;
+            for (int i=0; i<N; i++) {
+                final int v = val[i];
+                size += v >= 0 ? EncodedBuffer.getRawVarint32Size(v) : 10;
+            }
+            writeKnownLengthHeader(id, size);
+            for (int i=0; i<N; i++) {
+                writeUnsignedVarintFromSignedInt(val[i]);
+            }
+        }
+    }
+
+    //
+    // Child objects
+    //
+
+    /**
+     * Make a token.
+     *  Bits 61-63 - tag size (So we can go backwards later if the object had not data)
+     *                - 3 bits, max value 7, max value needed 5
+     *  Bit  60    - true if the object is repeated (lets us require endObject or endRepeatedObject)
+     *  Bits 59-51 - depth (For error checking)
+     *                - 9 bits, max value 512, when checking, value is masked (if we really
+     *                  are more than 512 levels deep)
+     *  Bits 32-50 - objectId (For error checking)
+     *                - 19 bits, max value 524,288. that's a lot of objects. IDs will wrap
+     *                  because of the overflow, and only the tokens are compared.
+     *  Bits  0-31 - offset of the first size field in the buffer.
+     */
+    // VisibleForTesting
+    public static long makeToken(int tagSize, boolean repeated, int depth, int objectId,
+            int sizePos) {
+        return ((0x07L & (long)tagSize) << 61)
+                | (repeated ? (1L << 60) : 0)
+                | (0x01ffL & (long)depth) << 51
+                | (0x07ffffL & (long)objectId) << 32
+                | (0x0ffffffffL & (long)sizePos);
+    }
+
+    /**
+     * Get the encoded tag size from the token.
+     */
+    public static int getTagSizeFromToken(long token) {
+        return (int)(0x7 & (token >> 61));
+    }
+
+    /**
+     * Get whether this is a call to startObject (false) or startRepeatedObject (true).
+     */
+    public static boolean getRepeatedFromToken(long token) {
+        return (0x1 & (token >> 60)) != 0;
+    }
+
+    /**
+     * Get the nesting depth of startObject calls from the token.
+     */
+    public static int getDepthFromToken(long token) {
+        return (int)(0x01ff & (token >> 51));
+    }
+
+    /**
+     * Get the object ID from the token. The object ID is a serial number for the
+     * startObject calls that have happened on this object.  The values are truncated
+     * to 9 bits, but that is sufficient for error checking.
+     */
+    public static int getObjectIdFromToken(long token) {
+        return (int)(0x07ffff & (token >> 32));
+    }
+
+    /**
+     * Get the location of the childRawSize (the first 32 bit size field) in this object.
+     */
+    public static int getSizePosFromToken(long token) {
+        return (int)token;
+    }
+
+    /**
+     * Convert the object ID to the ordinal value -- the n-th call to startObject.
+     * The object IDs start at -1 and count backwards, so that the value is unlikely
+     * to alias with an actual size field that had been written.
+     */
+    public static int convertObjectIdToOrdinal(int objectId) {
+        return (-1 & 0x07ffff) - objectId;
+    }
+
+    /**
+     * Return a debugging string of a token.
+     */
+    public static String token2String(long token) {
+        if (token == 0L) {
+            return "Token(0)";
+        } else {
+            return "Token(val=0x" + Long.toHexString(token)
+                    + " depth=" + getDepthFromToken(token)
+                    + " object=" + convertObjectIdToOrdinal(getObjectIdFromToken(token))
+                    + " tagSize=" + getTagSizeFromToken(token)
+                    + " sizePos=" + getSizePosFromToken(token)
+                    + ')';
+        }
+    }
+
+    /**
+     * Start a child object.
+     *
+     * Returns a token which should be passed to endObject.  Calls to endObject must be
+     * nested properly.
+     */
+    public long startObject(long fieldId) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_OBJECT);
+
+        return startObjectImpl(id, false);
+    }
+
+    /**
+     * End a child object. Pass in the token from the correspoinding startObject call.
+     */
+    public void endObject(long token) {
+        assertNotCompacted();
+
+        endObjectImpl(token, false);
+    }
+
+    /**
+     * Start a repeated child object.
+     *
+     * Returns a token which should be passed to endObject.  Calls to endObject must be
+     * nested properly.
+     */
+    public long startRepeatedObject(long fieldId) {
+        assertNotCompacted();
+        final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_OBJECT);
+
+        return startObjectImpl(id, true);
+    }
+
+    /**
+     * End a child object. Pass in the token from the correspoinding startRepeatedObject call.
+     */
+    public void endRepeatedObject(long token) {
+        assertNotCompacted();
+
+        endObjectImpl(token, true);
+    }
+
+    /**
+     * Common implementation of startObject and startRepeatedObject.
+     */
+    private long startObjectImpl(final int id, boolean repeated) {
+        writeTag(id, WIRE_TYPE_LENGTH_DELIMITED);
+        final int sizePos = mBuffer.getWritePos();
+        mDepth++;
+        mNextObjectId--;
+
+        // Write the previous token, giving us a stack of expected tokens.
+        // After endObject returns, the first fixed32 becomeschildRawSize (set in endObject)
+        // and the second one becomes childEncodedSize (set in editEncodedSize).
+        mBuffer.writeRawFixed32((int)(mExpectedObjectToken >> 32));
+        mBuffer.writeRawFixed32((int)mExpectedObjectToken);
+
+        long old = mExpectedObjectToken;
+
+        mExpectedObjectToken = makeToken(getTagSize(id), repeated, mDepth, mNextObjectId, sizePos);
+        return mExpectedObjectToken;
+    }
+
+    /**
+     * Common implementation of endObject and endRepeatedObject.
+     */
+    private void endObjectImpl(long token, boolean repeated) {
+        // The upper 32 bits of the token is the depth of startObject /
+        // endObject calls.  We could get aritrarily sophisticated, but
+        // that's enough to prevent the common error of missing an
+        // endObject somewhere.
+        // The lower 32 bits of the token is the offset in the buffer
+        // at which to write the size.
+        final int depth = getDepthFromToken(token);
+        final boolean expectedRepeated = getRepeatedFromToken(token);
+        final int sizePos = getSizePosFromToken(token);
+        final int childRawSize = mBuffer.getWritePos() - sizePos - 8;
+
+        if (repeated != expectedRepeated) {
+            if (repeated) {
+                throw new IllegalArgumentException("endRepeatedObject called where endObject should"
+                        + " have been");
+            } else {
+                throw new IllegalArgumentException("endObject called where endRepeatedObject should"
+                        + " have been");
+            }
+        }
+
+        // Check that we're getting the token and depth that we are expecting.
+        if ((mDepth & 0x01ff) != depth || mExpectedObjectToken != token) {
+            // This text of exception is united tested.  That test also implicity checks
+            // that we're tracking the objectIds and depths correctly.
+            throw new IllegalArgumentException("Mismatched startObject/endObject calls."
+                    + " Current depth " + mDepth
+                    + " token=" + token2String(token)
+                    + " expectedToken=" + token2String(mExpectedObjectToken));
+        }
+
+        // Get the next expected token that we stashed away in the buffer.
+        mExpectedObjectToken = (((long)mBuffer.getRawFixed32At(sizePos)) << 32)
+                | (0x0ffffffffL & (long)mBuffer.getRawFixed32At(sizePos+4));
+
+        mDepth--;
+        if (childRawSize > 0) {
+            mBuffer.editRawFixed32(sizePos, -childRawSize);
+            mBuffer.editRawFixed32(sizePos+4, -1);
+        } else if (repeated) {
+            mBuffer.editRawFixed32(sizePos, 0);
+            mBuffer.editRawFixed32(sizePos+4, 0);
+        } else {
+            // The object has no data.  Don't include it.
+            mBuffer.rewindWriteTo(sizePos - getTagSizeFromToken(token));
+        }
+    }
+
+    //
+    // Tags
+    //
+
+    /**
+     * Combine a fieldId (the field keys in the proto file) and the field flags.
+     * Mostly useful for testing because the generated code contains the fieldId
+     * constants.
+     */
+    public static long makeFieldId(int id, long fieldFlags) {
+        return fieldFlags | (((long)id) & 0x0ffffffffL);
+    }
+
+    /**
+     * Validates that the fieldId providied is of the type and count from expectedType.
+     *
+     * The type must match exactly to pass this check.
+     *
+     * The count must match according to this truth table to pass the check:
+     *
+     *                  expectedFlags
+     *                  UNKNOWN     SINGLE      REPEATED    PACKED
+     *    fieldId
+     *    UNKNOWN       true        false       false       false
+     *    SINGLE        x           true        false       false
+     *    REPEATED      x           false       true        false
+     *    PACKED        x           false       true        true
+     *
+     * @throws IllegalArgumentException if it is not.
+     *
+     * @return The raw ID of that field.
+     */
+    public static int checkFieldId(long fieldId, long expectedFlags) {
+        final long fieldCount = fieldId & FIELD_COUNT_MASK;
+        final long fieldType = fieldId & FIELD_TYPE_MASK;
+        final long expectedCount = expectedFlags & FIELD_COUNT_MASK;
+        final long expectedType = expectedFlags & FIELD_TYPE_MASK;
+        if (((int)fieldId) == 0) {
+            throw new IllegalArgumentException("Invalid proto field " + (int)fieldId
+                    + " fieldId=" + Long.toHexString(fieldId));
+        }
+        if (fieldType != expectedType
+                || !((fieldCount == expectedCount)
+                    || (fieldCount == FIELD_COUNT_PACKED
+                        && expectedCount == FIELD_COUNT_REPEATED))) {
+            final String countString = getFieldCountString(fieldCount);
+            final String typeString = getFieldTypeString(fieldType);
+            if (typeString != null && countString != null) {
+                final StringBuilder sb = new StringBuilder();
+                if (expectedType == FIELD_TYPE_OBJECT) {
+                    sb.append("start");
+                } else {
+                    sb.append("write");
+                }
+                sb.append(getFieldCountString(expectedCount));
+                sb.append(getFieldTypeString(expectedType));
+                sb.append(" called for field ");
+                sb.append((int)fieldId);
+                sb.append(" which should be used with ");
+                if (fieldType == FIELD_TYPE_OBJECT) {
+                    sb.append("start");
+                } else {
+                    sb.append("write");
+                }
+                sb.append(countString);
+                sb.append(typeString);
+                if (fieldCount == FIELD_COUNT_PACKED) {
+                    sb.append(" or writeRepeated");
+                    sb.append(typeString);
+                }
+                sb.append('.');
+                throw new IllegalArgumentException(sb.toString());
+            } else {
+                final StringBuilder sb = new StringBuilder();
+                if (expectedType == FIELD_TYPE_OBJECT) {
+                    sb.append("start");
+                } else {
+                    sb.append("write");
+                }
+                sb.append(getFieldCountString(expectedCount));
+                sb.append(getFieldTypeString(expectedType));
+                sb.append(" called with an invalid fieldId: 0x");
+                sb.append(Long.toHexString(fieldId));
+                sb.append(". The proto field ID might be ");
+                sb.append((int)fieldId);
+                sb.append('.');
+                throw new IllegalArgumentException(sb.toString());
+            }
+        }
+        return (int)fieldId;
+    }
+
+    /**
+     * Get the developer-usable name of a field type.
+     */
+    private static String getFieldTypeString(long fieldType) {
+        int index = ((int)((fieldType & FIELD_TYPE_MASK) >>> FIELD_TYPE_SHIFT)) - 1;
+        if (index >= 0 && index < FIELD_TYPE_NAMES.length) {
+            return FIELD_TYPE_NAMES[index];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get the developer-usable name of a field count.
+     */
+    private static String getFieldCountString(long fieldCount) {
+        if (fieldCount == FIELD_COUNT_SINGLE) {
+            return "";
+        } else if (fieldCount == FIELD_COUNT_REPEATED) {
+            return "Repeated";
+        } else if (fieldCount == FIELD_COUNT_PACKED) {
+            return "Packed";
+        } else {
+            return null;
+        }
+    }
+
+
+    /**
+     * Return how many bytes an encoded field tag will require.
+     */
+    private static int getTagSize(int id) {
+        return EncodedBuffer.getRawVarint32Size(id << FIELD_ID_SHIFT);
+    }
+
+    /**
+     * Write a field tage to the stream.
+     */
+    public void writeTag(int id, int wireType) {
+        mBuffer.writeRawVarint32((id << FIELD_ID_SHIFT) | wireType);
+    }
+
+    /**
+     * Write the header of a WIRE_TYPE_LENGTH_DELIMITED field for one where
+     * we know the size in advance and do not need to compute and compact.
+     */
+    private void writeKnownLengthHeader(int id, int size) {
+        // Write the tag
+        writeTag(id, WIRE_TYPE_LENGTH_DELIMITED);
+        // Size will be compacted later, but we know the size, so write it,
+        // once for the rawSize and once for the encodedSize.
+        mBuffer.writeRawFixed32(size);
+        mBuffer.writeRawFixed32(size);
+    }
+
+    //
+    // Getting the buffer and compaction
+    //
+
+    /**
+     * Assert that the compact call has not already occured.
+     *
+     * TODO: Will change when we add the OutputStream version of ProtoOutputStream.
+     */
+    private void assertNotCompacted() {
+        if (mCompacted) {
+            throw new IllegalArgumentException("write called after compact");
+        }
+    }
+
+    /**
+     * Finish the encoding of the data, and return a byte[] with
+     * the protobuf formatted data.
+     *
+     * After this call, do not call any of the write* functions. The
+     * behavior is undefined.
+     */
+    public byte[] getBytes() {
+        compactIfNecessary();
+
+        return mBuffer.getBytes(mBuffer.getReadableSize());
+    }
+
+    /**
+     * If the buffer hasn't already had the nested object size fields compacted
+     * and turned into an actual protobuf format, then do so.
+     */
+    private void compactIfNecessary() {
+        if (!mCompacted) {
+            if (mDepth != 0) {
+                throw new IllegalArgumentException("Trying to compact with " + mDepth
+                        + " missing calls to endObject");
+            }
+
+            // The buffer must be compacted.
+            mBuffer.startEditing();
+            final int readableSize = mBuffer.getReadableSize();
+
+            // Cache the sizes of the objects
+            editEncodedSize(readableSize);
+
+            // Re-write the buffer with the sizes as proper varints instead
+            // of pairs of uint32s. We know this will always fit in the same
+            // buffer because the pair of uint32s is exactly 8 bytes long, and
+            // the single varint size will be no more than 5 bytes long.
+            mBuffer.rewindRead();
+            compactSizes(readableSize);
+
+            // If there is any data left over that wasn't copied yet, copy it.
+            if (mCopyBegin < readableSize) {
+                mBuffer.writeFromThisBuffer(mCopyBegin, readableSize - mCopyBegin);
+            }
+
+            // Set the new readableSize
+            mBuffer.startEditing();
+
+            // It's not valid to write to this object anymore. The write
+            // pointers are off, and then some of the data would be compacted
+            // and some not.
+            mCompacted = true;
+        }
+    }
+
+    /**
+     * First compaction pass.  Iterate through the data, and fill in the
+     * nested object sizes so the next pass can compact them.
+     */
+    private int editEncodedSize(int rawSize) {
+        int objectStart = mBuffer.getReadPos();
+        int objectEnd = objectStart + rawSize;
+        int encodedSize = 0;
+        int tagPos;
+
+        while ((tagPos = mBuffer.getReadPos()) < objectEnd) {
+            int tag = readRawTag();
+            encodedSize += EncodedBuffer.getRawVarint32Size(tag);
+
+            final int wireType = tag & WIRE_TYPE_MASK;
+            switch (wireType) {
+                case WIRE_TYPE_VARINT:
+                    encodedSize++;
+                    while ((mBuffer.readRawByte() & 0x80) != 0) {
+                        encodedSize++;
+                    }
+                    break;
+                case WIRE_TYPE_FIXED64:
+                    encodedSize += 8;
+                    mBuffer.skipRead(8);
+                    break;
+                case WIRE_TYPE_LENGTH_DELIMITED: {
+                    // This object is not of a fixed-size type.  So we need to figure
+                    // out how big it should be.
+                    final int childRawSize = mBuffer.readRawFixed32();
+                    final int childEncodedSizePos = mBuffer.getReadPos();
+                    int childEncodedSize = mBuffer.readRawFixed32();
+                    if (childRawSize >= 0) {
+                        // We know the size, just skip ahead.
+                        if (childEncodedSize != childRawSize) {
+                            throw new RuntimeException("Pre-computed size where the"
+                                    + " precomputed size and the raw size in the buffer"
+                                    + " don't match! childRawSize=" + childRawSize
+                                    + " childEncodedSize=" + childEncodedSize
+                                    + " childEncodedSizePos=" + childEncodedSizePos);
+                        }
+                        mBuffer.skipRead(childRawSize);
+                    } else {
+                        // We need to compute the size.  Recurse.
+                        childEncodedSize = editEncodedSize(-childRawSize);
+                        mBuffer.editRawFixed32(childEncodedSizePos, childEncodedSize);
+                    }
+                    encodedSize += EncodedBuffer.getRawVarint32Size(childEncodedSize)
+                            + childEncodedSize;
+                    break;
+                }
+                case WIRE_TYPE_START_GROUP:
+                case WIRE_TYPE_END_GROUP:
+                    throw new RuntimeException("groups not supported at index " + tagPos);
+                case WIRE_TYPE_FIXED32:
+                    encodedSize += 4;
+                    mBuffer.skipRead(4);
+                    break;
+                default:
+                    throw new ProtoParseException("editEncodedSize Bad tag tag=0x"
+                            + Integer.toHexString(tag) + " wireType=" + wireType
+                            + " -- " + mBuffer.getDebugString());
+            }
+        }
+
+        return encodedSize;
+    }
+
+    /**
+     * Second compaction pass.  Iterate through the data, and copy the data
+     * forward in the buffer, converting the pairs of uint32s into a single
+     * unsigned varint of the size.
+     */
+    private void compactSizes(int rawSize) {
+        int objectStart = mBuffer.getReadPos();
+        int objectEnd = objectStart + rawSize;
+        int tagPos;
+        while ((tagPos = mBuffer.getReadPos()) < objectEnd) {
+            int tag = readRawTag();
+
+            // For all the non-length-delimited field types, just skip over them,
+            // and we'll just System.arraycopy it later, either in the case for
+            // WIRE_TYPE_LENGTH_DELIMITED or at the top of the stack in compactIfNecessary().
+            final int wireType = tag & WIRE_TYPE_MASK;
+            switch (wireType) {
+                case WIRE_TYPE_VARINT:
+                    while ((mBuffer.readRawByte() & 0x80) != 0) { }
+                    break;
+                case WIRE_TYPE_FIXED64:
+                    mBuffer.skipRead(8);
+                    break;
+                case WIRE_TYPE_LENGTH_DELIMITED: {
+                    // Copy everything up to now, including the tag for this field.
+                    mBuffer.writeFromThisBuffer(mCopyBegin, mBuffer.getReadPos() - mCopyBegin);
+                    // Write the new size.
+                    final int childRawSize = mBuffer.readRawFixed32();
+                    final int childEncodedSize = mBuffer.readRawFixed32();
+                    mBuffer.writeRawVarint32(childEncodedSize);
+                    // Next time, start copying from here.
+                    mCopyBegin = mBuffer.getReadPos();
+                    if (childRawSize >= 0) {
+                        // This is raw data, not an object. Skip ahead by the size.
+                        // Recurse into the child
+                        mBuffer.skipRead(childEncodedSize);
+                    } else {
+                        compactSizes(-childRawSize);
+                    }
+                    break;
+                    // TODO: What does regular proto do if the object would be 0 size
+                    // (e.g. if it is all default values).
+                }
+                case WIRE_TYPE_START_GROUP:
+                case WIRE_TYPE_END_GROUP:
+                    throw new RuntimeException("groups not supported at index " + tagPos);
+                case WIRE_TYPE_FIXED32:
+                    mBuffer.skipRead(4);
+                    break;
+                default:
+                    throw new ProtoParseException("compactSizes Bad tag tag=0x"
+                            + Integer.toHexString(tag) + " wireType=" + wireType
+                            + " -- " + mBuffer.getDebugString());
+            }
+        }
+    }
+
+    /**
+     * Read a raw tag from the buffer.
+     */
+    private int readRawTag() {
+        if (mBuffer.getReadPos() == mBuffer.getReadableSize()) {
+            return 0;
+        }
+        return (int)mBuffer.readRawUnsigned();
+    }
+
+    /**
+     * Dump debugging data about the buffers with the given log tag.
+     */
+    public void dump(String tag) {
+        Log.d(tag, mBuffer.getDebugString());
+        mBuffer.dumpBuffers(tag);
+    }
+}
diff --git a/core/java/android/util/proto/ProtoParseException.java b/core/java/android/util/proto/ProtoParseException.java
new file mode 100644
index 0000000..5ba9bf8
--- /dev/null
+++ b/core/java/android/util/proto/ProtoParseException.java
@@ -0,0 +1,38 @@
+/*
+ * 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 android.util.proto;
+
+import android.annotation.TestApi;
+
+/**
+ * Thrown when there is an error parsing protobuf data.
+ *
+ * @hide
+ */
+@TestApi
+public class ProtoParseException extends RuntimeException {
+
+    /**
+     * Construct a ProtoParseException.
+     *
+     * @param msg The message.
+     */
+    public ProtoParseException(String msg) {
+        super(msg);
+    }
+}
+
diff --git a/core/java/android/util/proto/package.html b/core/java/android/util/proto/package.html
new file mode 100644
index 0000000..a636bd4
--- /dev/null
+++ b/core/java/android/util/proto/package.html
@@ -0,0 +1,5 @@
+<body>
+Provides utility classes to export protocol buffers from the system.
+
+{@hide}
+</body>
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 85a4bf9..3beb00f 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -16,11 +16,11 @@
 
 package android.view;
 
+import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE;
+
 import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
-import android.content.Context;
 import android.content.res.CompatibilityInfo;
-import android.content.res.Resources;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -36,8 +36,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 
-import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE;
-
 /**
  * Provides information about the size and density of a logical display.
  * <p>
diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java
index dd86062..790029b 100644
--- a/core/java/android/view/DisplayAdjustments.java
+++ b/core/java/android/view/DisplayAdjustments.java
@@ -26,18 +26,20 @@
     public static final DisplayAdjustments DEFAULT_DISPLAY_ADJUSTMENTS = new DisplayAdjustments();
 
     private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
-    private Configuration mConfiguration = Configuration.EMPTY;
+    private Configuration mConfiguration;
 
     public DisplayAdjustments() {
     }
 
     public DisplayAdjustments(Configuration configuration) {
-        mConfiguration = configuration;
+        mConfiguration = new Configuration(configuration != null
+                ? configuration : Configuration.EMPTY);
     }
 
     public DisplayAdjustments(DisplayAdjustments daj) {
         setCompatibilityInfo(daj.mCompatInfo);
-        mConfiguration = daj.mConfiguration;
+        mConfiguration = new Configuration(daj.mConfiguration != null
+                ? daj.mConfiguration : Configuration.EMPTY);
     }
 
     public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
@@ -62,7 +64,7 @@
             throw new IllegalArgumentException(
                     "setConfiguration: Cannot modify DEFAULT_DISPLAY_ADJUSTMENTS");
         }
-        mConfiguration = configuration != null ? configuration : Configuration.EMPTY;
+        mConfiguration.setTo(configuration != null ? configuration : Configuration.EMPTY);
     }
 
     public Configuration getConfiguration() {
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 4393992..67cdfc5 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -16,13 +16,13 @@
 
 package android.view;
 
-import dalvik.annotation.optimization.FastNative;
-import dalvik.system.CloseGuard;
-
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.util.Log;
 
+import dalvik.annotation.optimization.FastNative;
+import dalvik.system.CloseGuard;
+
 import java.lang.ref.WeakReference;
 
 /**
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index bc40849..1aef6ec 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -23,10 +23,10 @@
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 
-import java.util.Arrays;
-
 import libcore.util.Objects;
 
+import java.util.Arrays;
+
 /**
  * Describes the characteristics of a particular logical display.
  * @hide
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 44d7a86..eb41f9e 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -19,11 +19,12 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.CanvasProperty;
 import android.graphics.Paint;
 import android.util.Pools.SynchronizedPool;
 
+import dalvik.annotation.optimization.FastNative;
+
 /**
  * A Canvas implementation that records view system drawing operations for deferred rendering.
  * This is intended for use with a DisplayList. This class keeps a list of all the Paint and
@@ -32,7 +33,7 @@
  *
  * @hide
  */
-public class DisplayListCanvas extends Canvas {
+public final class DisplayListCanvas extends RecordingCanvas {
     // The recording canvas pool should be large enough to handle a deeply nested
     // view hierarchy because display lists are generated recursively.
     private static final int POOL_LIMIT = 25;
@@ -40,7 +41,7 @@
     private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
 
     private static final SynchronizedPool<DisplayListCanvas> sPool =
-            new SynchronizedPool<DisplayListCanvas>(POOL_LIMIT);
+            new SynchronizedPool<>(POOL_LIMIT);
 
     RenderNode mNode;
     private int mWidth;
@@ -83,9 +84,6 @@
         mDensity = 0; // disable bitmap density scaling
     }
 
-    private static native long nCreateDisplayListCanvas(int width, int height);
-    private static native void nResetDisplayListCanvas(long canvas, int width, int height);
-
     ///////////////////////////////////////////////////////////////////////////
     // Canvas management
     ///////////////////////////////////////////////////////////////////////////
@@ -131,9 +129,6 @@
         return nGetMaximumTextureHeight();
     }
 
-    private static native int nGetMaximumTextureWidth();
-    private static native int nGetMaximumTextureHeight();
-
     ///////////////////////////////////////////////////////////////////////////
     // Setup
     ///////////////////////////////////////////////////////////////////////////
@@ -148,8 +143,6 @@
         nInsertReorderBarrier(mNativeCanvasWrapper, false);
     }
 
-    private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
-
     ///////////////////////////////////////////////////////////////////////////
     // Functor
     ///////////////////////////////////////////////////////////////////////////
@@ -180,15 +173,10 @@
         nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunctor, releasedCallback);
     }
 
-    private static native void nCallDrawGLFunction(long renderer,
-            long drawGLFunction, Runnable releasedCallback);
-
     ///////////////////////////////////////////////////////////////////////////
     // Display list
     ///////////////////////////////////////////////////////////////////////////
 
-    protected static native long nFinishRecording(long renderer);
-
     /**
      * Draws the specified display list onto this canvas. The display list can only
      * be drawn if {@link android.view.RenderNode#isValid()} returns true.
@@ -199,8 +187,6 @@
         nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList());
     }
 
-    private static native void nDrawRenderNode(long renderer, long renderNode);
-
     ///////////////////////////////////////////////////////////////////////////
     // Hardware layer
     ///////////////////////////////////////////////////////////////////////////
@@ -214,8 +200,6 @@
         nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle());
     }
 
-    private static native void nDrawLayer(long renderer, long layer);
-
     ///////////////////////////////////////////////////////////////////////////
     // Drawing
     ///////////////////////////////////////////////////////////////////////////
@@ -226,9 +210,6 @@
                 radius.getNativeContainer(), paint.getNativeContainer());
     }
 
-    private static native void nDrawCircle(long renderer, long propCx,
-            long propCy, long propRadius, long propPaint);
-
     public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
             CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
             CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
@@ -238,9 +219,6 @@
                 paint.getNativeContainer());
     }
 
-    private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
-            long propRight, long propBottom, long propRx, long propRy, long propPaint);
-
     @Override
     protected void throwIfCannotDraw(Bitmap bitmap) {
         super.throwIfCannotDraw(bitmap);
@@ -250,4 +228,30 @@
                     "Canvas: trying to draw too large(" + bitmapSize + "bytes) bitmap.");
         }
     }
+
+    @FastNative
+    private static native long nCreateDisplayListCanvas(int width, int height);
+    @FastNative
+    private static native void nResetDisplayListCanvas(long canvas, int width, int height);
+    @FastNative
+    private static native int nGetMaximumTextureWidth();
+    @FastNative
+    private static native int nGetMaximumTextureHeight();
+    @FastNative
+    private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
+    @FastNative
+    private static native void nCallDrawGLFunction(long renderer,
+            long drawGLFunction, Runnable releasedCallback);
+    @FastNative
+    private static native long nFinishRecording(long renderer);
+    @FastNative
+    private static native void nDrawRenderNode(long renderer, long renderNode);
+    @FastNative
+    private static native void nDrawLayer(long renderer, long layer);
+    @FastNative
+    private static native void nDrawCircle(long renderer, long propCx,
+            long propCy, long propRadius, long propPaint);
+    @FastNative
+    private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
+            long propRight, long propBottom, long propRx, long propRy, long propPaint);
 }
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index 2baa0b4..16f2d7d 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -26,7 +26,7 @@
 //TODO: Improve Javadoc
 /**
  * Represents an event that is sent out by the system at various times during a drag and drop
- * operation. It is a complex data structure that contains several important pieces of data about
+ * operation. It is a data structure that contains several important pieces of data about
  * the operation and the underlying data.
  * <p>
  *  View objects that receive a DragEvent call {@link #getAction()}, which returns
@@ -161,8 +161,8 @@
      *  event when they are added or becoming visible.
      * </p>
      * <p>
-     *  A View only receives further drag events if it returns {@code true} in response to
-     *  ACTION_DRAG_STARTED.
+     *  A View only receives further drag events for the drag operation if it returns {@code true}
+     *  in response to ACTION_DRAG_STARTED.
      * </p>
      * @see #ACTION_DRAG_ENDED
      * @see #getX()
@@ -172,8 +172,9 @@
 
     /**
      * Action constant returned by {@link #getAction()}: Sent to a View after
-     * {@link #ACTION_DRAG_ENTERED} if the drag shadow is still within the View object's bounding
-     * box. The {@link #getX()} and {@link #getY()} methods supply
+     * {@link #ACTION_DRAG_ENTERED} while the drag shadow is still within the View object's bounding
+     * box, but not within a descendant view that can accept the data. The {@link #getX()} and
+     * {@link #getY()} methods supply
      * the X and Y position of of the drag point within the View object's bounding box.
      * <p>
      * A View receives an {@link #ACTION_DRAG_ENTERED} event before receiving any
@@ -355,9 +356,10 @@
     /**
      * Returns the {@link android.content.ClipData} object sent to the system as part of the call
      * to
-     * {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+     * {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+     * startDragAndDrop()}.
      * This method only returns valid data if the event action is {@link #ACTION_DROP}.
-     * @return The ClipData sent to the system by startDrag().
+     * @return The ClipData sent to the system by startDragAndDrop().
      */
     public ClipData getClipData() {
         return mClipData;
@@ -366,12 +368,14 @@
     /**
      * Returns the {@link android.content.ClipDescription} object contained in the
      * {@link android.content.ClipData} object sent to the system as part of the call to
-     * {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+     * {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+     * startDragAndDrop()}.
      * The drag handler or listener for a View can use the metadata in this object to decide if the
      * View can accept the dragged View object's data.
      * <p>
      * This method returns valid data for all event actions except for {@link #ACTION_DRAG_ENDED}.
-     * @return The ClipDescription that was part of the ClipData sent to the system by startDrag().
+     * @return The ClipDescription that was part of the ClipData sent to the system by
+     *     startDragAndDrop().
      */
     public ClipDescription getClipDescription() {
         return mClipDescription;
@@ -384,7 +388,8 @@
 
     /**
      * Returns the local state object sent to the system as part of the call to
-     * {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+     * {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+     * startDragAndDrop()}.
      * The object is intended to provide local information about the drag and drop operation. For
      * example, it can indicate whether the drag and drop operation is a copy or a move.
      * <p>
@@ -394,7 +399,7 @@
      * <p>
      *  This method returns valid data for all event actions except for {@link #ACTION_DRAG_ENDED}.
      * </p>
-     * @return The local state object sent to the system by startDrag().
+     * @return The local state object sent to the system by startDragAndDrop().
      */
     public Object getLocalState() {
         return mLocalState;
diff --git a/core/java/android/view/FallbackEventHandler.java b/core/java/android/view/FallbackEventHandler.java
index dd68d89..8e00d6d 100644
--- a/core/java/android/view/FallbackEventHandler.java
+++ b/core/java/android/view/FallbackEventHandler.java
@@ -24,4 +24,3 @@
     public void preDispatchKeyEvent(KeyEvent event);
     public boolean dispatchKeyEvent(KeyEvent event);
 }
-
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 2b938d0..800a63f 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -17,7 +17,6 @@
 package android.view;
 
 import android.annotation.IntDef;
-import android.view.Window;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
index 6331357..9e81de0 100644
--- a/core/java/android/view/FrameMetricsObserver.java
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -17,15 +17,12 @@
 package android.view;
 
 import android.annotation.NonNull;
-import android.util.Log;
 import android.os.Looper;
 import android.os.MessageQueue;
 
 import com.android.internal.util.VirtualRefBasePtr;
 
-import java.lang.NullPointerException;
 import java.lang.ref.WeakReference;
-import java.lang.SuppressWarnings;
 
 /**
  * Provides streaming access to frame stats information from the rendering
diff --git a/core/java/android/view/HandlerActionQueue.java b/core/java/android/view/HandlerActionQueue.java
index 4758a34..d016a74 100644
--- a/core/java/android/view/HandlerActionQueue.java
+++ b/core/java/android/view/HandlerActionQueue.java
@@ -16,11 +16,9 @@
 
 package android.view;
 
-import com.android.internal.util.GrowingArrayUtils;
-
 import android.os.Handler;
 
-import java.util.ArrayList;
+import com.android.internal.util.GrowingArrayUtils;
 
 /**
  * Class used to enqueue pending work from Views when no Handler is attached.
diff --git a/core/java/android/view/IAssetAtlas.aidl b/core/java/android/view/IAssetAtlas.aidl
deleted file mode 100644
index edce059..0000000
--- a/core/java/android/view/IAssetAtlas.aidl
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Copyright (c) 2013, 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.view.GraphicBuffer;
-
-/**
- * Programming interface to the system assets atlas. This atlas, when
- * present, holds preloaded drawable in a single, shareable graphics
- * buffer. This allows multiple processes to share the same data to
- * save up on memory.
- *
- * @hide
- */
-interface IAssetAtlas {
-    /**
-     * Indicates whether the atlas is compatible with the specified
-     * parent process id. If the atlas' ppid does not match, this
-     * method will return false.
-     */
-    boolean isCompatible(int ppid);
-
-    /**
-     * Returns the atlas buffer (texture) or null if the atlas is
-     * not available yet.
-     */
-    GraphicBuffer getBuffer();
-
-    /**
-     * Returns the map of the bitmaps stored in the atlas or null
-     * if the atlas is not available yet.
-     *
-     * Each bitmap is represented by several entries in the array:
-     * long0: SkBitmap*, the native bitmap object
-     * long1: x position
-     * long2: y position
-     * long3: rotated, 1 if the bitmap must be rotated, 0 otherwise
-     */
-    long[] getMap();
-}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 897e29b..717b675 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -454,12 +454,13 @@
     void registerShortcutKey(in long shortcutCode, IShortcutService keySubscriber);
 
     /**
-     * Create the input consumer for wallpaper events.
+     * Create an input consumer by name.
      */
-    void createWallpaperInputConsumer(out InputChannel inputChannel);
+    void createInputConsumer(String name, out InputChannel inputChannel);
 
     /**
-     * Remove the input consumer for wallpaper events.
+     * Destroy an input consumer by name.  This method will also dispose the input channels
+     * associated with that InputConsumer.
      */
-    void removeWallpaperInputConsumer();
+    boolean destroyInputConsumer(String name);
 }
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index f8796c3..55f64d9 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -19,10 +19,10 @@
 import android.content.Context;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
+import android.os.NullVibrator;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Vibrator;
-import android.os.NullVibrator;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 91ef50d..20ab539 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -16,13 +16,13 @@
 
 package android.view;
 
-import dalvik.system.CloseGuard;
-
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.util.Log;
 import android.util.SparseIntArray;
 
+import dalvik.system.CloseGuard;
+
 import java.lang.ref.WeakReference;
 
 /**
diff --git a/core/java/android/view/InputEventSender.java b/core/java/android/view/InputEventSender.java
index 304ea3f..b25fb65 100644
--- a/core/java/android/view/InputEventSender.java
+++ b/core/java/android/view/InputEventSender.java
@@ -16,12 +16,12 @@
 
 package android.view;
 
-import dalvik.system.CloseGuard;
-
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.util.Log;
 
+import dalvik.system.CloseGuard;
+
 import java.lang.ref.WeakReference;
 
 /**
diff --git a/core/java/android/view/InputFilter.java b/core/java/android/view/InputFilter.java
index 4aba30c..d0dab40 100644
--- a/core/java/android/view/InputFilter.java
+++ b/core/java/android/view/InputFilter.java
@@ -20,12 +20,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.view.IInputFilter;
-import android.view.InputEvent;
-import android.view.InputEventConsistencyVerifier;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.WindowManagerPolicy;
 
 /**
  * Filters input events before they are dispatched to the system.
diff --git a/core/java/android/view/InputQueue.java b/core/java/android/view/InputQueue.java
index aebc601..582ae79 100644
--- a/core/java/android/view/InputQueue.java
+++ b/core/java/android/view/InputQueue.java
@@ -16,13 +16,13 @@
 
 package android.view;
 
-import dalvik.system.CloseGuard;
-
 import android.os.Looper;
 import android.os.MessageQueue;
+import android.util.LongSparseArray;
 import android.util.Pools.Pool;
 import android.util.Pools.SimplePool;
-import android.util.LongSparseArray;
+
+import dalvik.system.CloseGuard;
 
 import java.lang.ref.WeakReference;
 
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index c8b89e7..88f2d34 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -16,14 +16,13 @@
 
 package android.view;
 
+import android.hardware.input.InputManager;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.method.MetaKeyKeyListener;
 import android.util.AndroidRuntimeException;
 import android.util.SparseIntArray;
-import android.hardware.input.InputManager;
 
-import java.lang.Character;
 import java.text.Normalizer;
 
 /**
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index b73acda..5d8f336 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -21,7 +21,6 @@
 import android.text.method.MetaKeyKeyListener;
 import android.util.Log;
 import android.util.SparseIntArray;
-import android.view.KeyCharacterMap;
 import android.view.KeyCharacterMap.KeyData;
 
 /**
diff --git a/core/java/android/view/KeyboardShortcutGroup.java b/core/java/android/view/KeyboardShortcutGroup.java
index 57d07c0..78f0b30 100644
--- a/core/java/android/view/KeyboardShortcutGroup.java
+++ b/core/java/android/view/KeyboardShortcutGroup.java
@@ -15,6 +15,8 @@
  */
 package android.view;
 
+import static com.android.internal.util.Preconditions.checkNotNull;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
@@ -24,8 +26,6 @@
 import java.util.Collections;
 import java.util.List;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 /**
  * A group of {@link KeyboardShortcutInfo}.
  */
diff --git a/core/java/android/view/KeyboardShortcutInfo.java b/core/java/android/view/KeyboardShortcutInfo.java
index a9f2699..c934a4e 100644
--- a/core/java/android/view/KeyboardShortcutInfo.java
+++ b/core/java/android/view/KeyboardShortcutInfo.java
@@ -15,14 +15,15 @@
  */
 package android.view;
 
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import static java.lang.Character.MIN_VALUE;
+
 import android.annotation.Nullable;
 import android.graphics.drawable.Icon;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import static com.android.internal.util.Preconditions.checkArgument;
-import static java.lang.Character.MIN_VALUE;
-
 /**
  * Information about a Keyboard Shortcut.
  */
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 914bd56..e3ac40c 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -16,11 +16,6 @@
 
 package android.view;
 
-import com.android.internal.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.annotation.LayoutRes;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -37,6 +32,11 @@
 import android.util.Xml;
 import android.widget.FrameLayout;
 
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.lang.reflect.Constructor;
 import java.util.HashMap;
@@ -51,20 +51,20 @@
  *
  * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
  *      (Context.LAYOUT_INFLATER_SERVICE);</pre>
- * 
+ *
  * <p>
  * To create a new LayoutInflater with an additional {@link Factory} for your
  * own views, you can use {@link #cloneInContext} to clone an existing
  * ViewFactory, and then call {@link #setFactory} on it to include your
  * Factory.
- * 
+ *
  * <p>
  * For performance reasons, view inflation relies heavily on pre-processing of
  * XML files that is done at build time. Therefore, it is not currently possible
  * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
  * it only works with an XmlPullParser returned from a compiled resource
  * (R.<em>something</em> file.)
- * 
+ *
  * @see Context#getSystemService
  */
 public abstract class LayoutInflater {
@@ -95,7 +95,7 @@
 
     private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
             new HashMap<String, Constructor<? extends View>>();
-    
+
     private HashMap<String, Boolean> mFilterMap;
 
     private TypedValue mTempValue;
@@ -114,36 +114,36 @@
     /**
      * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
      * to be inflated.
-     * 
+     *
      */
     public interface Filter {
         /**
-         * Hook to allow clients of the LayoutInflater to restrict the set of Views 
+         * Hook to allow clients of the LayoutInflater to restrict the set of Views
          * that are allowed to be inflated.
-         * 
+         *
          * @param clazz The class object for the View that is about to be inflated
-         * 
+         *
          * @return True if this class is allowed to be inflated, or false otherwise
          */
         @SuppressWarnings("unchecked")
         boolean onLoadClass(Class clazz);
     }
-    
+
     public interface Factory {
         /**
          * Hook you can supply that is called when inflating from a LayoutInflater.
          * You can use this to customize the tag names available in your XML
          * layout files.
-         * 
+         *
          * <p>
          * Note that it is good practice to prefix these custom names with your
          * package (i.e., com.coolcompany.apps) to avoid conflicts with system
          * names.
-         * 
+         *
          * @param name Tag name to be inflated.
          * @param context The context the view is being created in.
          * @param attrs Inflation attributes as specified in XML file.
-         * 
+         *
          * @return View Newly created view. Return null for the default
          *         behavior.
          */
@@ -171,14 +171,14 @@
     private static class FactoryMerger implements Factory2 {
         private final Factory mF1, mF2;
         private final Factory2 mF12, mF22;
-        
+
         FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
             mF1 = f1;
             mF2 = f2;
             mF12 = f12;
             mF22 = f22;
         }
-        
+
         public View onCreateView(String name, Context context, AttributeSet attrs) {
             View v = mF1.onCreateView(name, context, attrs);
             if (v != null) return v;
@@ -193,13 +193,13 @@
                     : mF2.onCreateView(name, context, attrs);
         }
     }
-    
+
     /**
      * Create a new LayoutInflater instance associated with a particular Context.
      * Applications will almost always want to use
      * {@link Context#getSystemService Context.getSystemService()} to retrieve
      * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
-     * 
+     *
      * @param context The Context in which this LayoutInflater will create its
      * Views; most importantly, this supplies the theme from which the default
      * values for their attributes are retrieved.
@@ -212,7 +212,7 @@
      * Create a new LayoutInflater instance that is a copy of an existing
      * LayoutInflater, optionally with its Context changed.  For use in
      * implementing {@link #cloneInContext}.
-     * 
+     *
      * @param original The original LayoutInflater to copy.
      * @param newContext The new Context to use.
      */
@@ -223,7 +223,7 @@
         mPrivateFactory = original.mPrivateFactory;
         setFilter(original.mFilter);
     }
-    
+
     /**
      * Obtains the LayoutInflater from the given context.
      */
@@ -241,15 +241,15 @@
      * pointing to a different Context than the original.  This is used by
      * {@link ContextThemeWrapper} to create a new LayoutInflater to go along
      * with the new Context theme.
-     * 
+     *
      * @param newContext The new Context to associate with the new LayoutInflater.
      * May be the same as the original Context if desired.
-     * 
+     *
      * @return Returns a brand spanking new LayoutInflater object associated with
      * the given Context.
      */
     public abstract LayoutInflater cloneInContext(Context newContext);
-    
+
     /**
      * Return the context we are running in, for access to resources, class
      * loader, etc.
@@ -285,7 +285,7 @@
      * called on each element name as the xml is parsed. If the factory returns
      * a View, that is added to the hierarchy. If it returns null, the next
      * factory default {@link #onCreateView} method is called.
-     * 
+     *
      * <p>If you have an existing
      * LayoutInflater and want to add your own factory to it, use
      * {@link #cloneInContext} to clone the existing instance and then you
@@ -345,13 +345,13 @@
     public Filter getFilter() {
         return mFilter;
     }
-    
+
     /**
      * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
      * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
      * throw an {@link InflateException}. This filter will replace any previous filter set on this
      * LayoutInflater.
-     * 
+     *
      * @param filter The Filter which restricts the set of Views that are allowed to be inflated.
      *        This filter will replace any previous filter set on this LayoutInflater.
      */
@@ -365,7 +365,7 @@
     /**
      * Inflate a new view hierarchy from the specified xml resource. Throws
      * {@link InflateException} if there is an error.
-     * 
+     *
      * @param resource ID for an XML layout resource to load (e.g.,
      *        <code>R.layout.main_page</code>)
      * @param root Optional view to be the parent of the generated hierarchy.
@@ -385,7 +385,7 @@
      * reasons, view inflation relies heavily on pre-processing of XML files
      * that is done at build time. Therefore, it is not currently possible to
      * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
-     * 
+     *
      * @param parser XML dom node containing the description of the view
      *        hierarchy.
      * @param root Optional view to be the parent of the generated hierarchy.
@@ -400,7 +400,7 @@
     /**
      * Inflate a new view hierarchy from the specified xml resource. Throws
      * {@link InflateException} if there is an error.
-     * 
+     *
      * @param resource ID for an XML layout resource to load (e.g.,
      *        <code>R.layout.main_page</code>)
      * @param root Optional view to be the parent of the generated hierarchy (if
@@ -437,7 +437,7 @@
      * reasons, view inflation relies heavily on pre-processing of XML files
      * that is done at build time. Therefore, it is not currently possible to
      * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
-     * 
+     *
      * @param parser XML dom node containing the description of the view
      *        hierarchy.
      * @param root Optional view to be the parent of the generated hierarchy (if
@@ -475,7 +475,7 @@
                 }
 
                 final String name = parser.getName();
-                
+
                 if (DEBUG) {
                     System.out.println("**************************");
                     System.out.println("Creating root view: "
@@ -579,17 +579,17 @@
      * Low-level function for instantiating a view by name. This attempts to
      * instantiate a view class of the given <var>name</var> found in this
      * LayoutInflater's ClassLoader.
-     * 
+     *
      * <p>
      * There are two things that can happen in an error case: either the
      * exception describing the error will be thrown, or a null will be
      * returned. You must deal with both possibilities -- the former will happen
      * the first time createView() is called for a class of a particular name,
      * the latter every time there-after for that class name.
-     * 
+     *
      * @param name The full name of the class to be instantiated.
      * @param attrs The XML attributes supplied for this instance.
-     * 
+     *
      * @return View The newly instantiated view, or null.
      */
     public final View createView(String name, String prefix, AttributeSet attrs)
@@ -608,7 +608,7 @@
                 // Class not found in the cache, see if it's real, and try to add it
                 clazz = mContext.getClassLoader().loadClass(
                         prefix != null ? (prefix + name) : name).asSubclass(View.class);
-                
+
                 if (mFilter != null && clazz != null) {
                     boolean allowed = mFilter.onLoadClass(clazz);
                     if (!allowed) {
@@ -627,7 +627,7 @@
                         // New class -- remember whether it is allowed
                         clazz = mContext.getClassLoader().loadClass(
                                 prefix != null ? (prefix + name) : name).asSubclass(View.class);
-                        
+
                         boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
                         mFilterMap.put(name, allowed);
                         if (!allowed) {
@@ -689,10 +689,10 @@
      * given the xml element name. Override it to handle custom view objects. If
      * you override this in your subclass be sure to call through to
      * super.onCreateView(name) for names you do not recognize.
-     * 
+     *
      * @param name The fully qualified class name of the View to be create.
      * @param attrs An AttributeSet of attributes to apply to the View.
-     * 
+     *
      * @return View The View created.
      */
     protected View onCreateView(String name, AttributeSet attrs)
@@ -842,7 +842,7 @@
             }
 
             final String name = parser.getName();
-            
+
             if (TAG_REQUEST_FOCUS.equals(name)) {
                 parseRequestFocus(parser, parent);
             } else if (TAG_TAG.equals(name)) {
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index 1c67ba7..73ea9ee 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -16,11 +16,6 @@
 
 package android.view;
 
-import com.android.internal.view.menu.MenuItemImpl;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.annotation.MenuRes;
 import android.app.Activity;
 import android.content.Context;
@@ -31,6 +26,11 @@
 import android.util.Log;
 import android.util.Xml;
 
+import com.android.internal.view.menu.MenuItemImpl;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
@@ -49,15 +49,15 @@
 
     /** Menu tag name in XML. */
     private static final String XML_MENU = "menu";
-    
+
     /** Group tag name in XML. */
     private static final String XML_GROUP = "group";
-    
+
     /** Item tag name in XML. */
     private static final String XML_ITEM = "item";
 
     private static final int NO_ID = 0;
-    
+
     private static final Class<?>[] ACTION_VIEW_CONSTRUCTOR_SIGNATURE = new Class[] {Context.class};
 
     private static final Class<?>[] ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE = ACTION_VIEW_CONSTRUCTOR_SIGNATURE;
@@ -71,7 +71,7 @@
 
     /**
      * Constructs a menu inflater.
-     * 
+     *
      * @see Activity#getMenuInflater()
      */
     public MenuInflater(Context context) {
@@ -96,7 +96,7 @@
     /**
      * Inflate a menu hierarchy from the specified XML resource. Throws
      * {@link InflateException} if there is an error.
-     * 
+     *
      * @param menuRes Resource ID for an XML layout resource to load (e.g.,
      *            <code>R.menu.main_activity</code>)
      * @param menu The Menu to inflate into. The items and submenus will be
@@ -107,7 +107,7 @@
         try {
             parser = mContext.getResources().getLayout(menuRes);
             AttributeSet attrs = Xml.asAttributeSet(parser);
-            
+
             parseMenu(parser, attrs, menu);
         } catch (XmlPullParserException e) {
             throw new InflateException("Error inflating menu XML", e);
@@ -140,12 +140,12 @@
                     eventType = parser.next();
                     break;
                 }
-                
+
                 throw new RuntimeException("Expecting menu, got " + tagName);
             }
             eventType = parser.next();
         } while (eventType != XmlPullParser.END_DOCUMENT);
-        
+
         boolean reachedEndOfMenu = false;
         while (!reachedEndOfMenu) {
             switch (eventType) {
@@ -153,7 +153,7 @@
                     if (lookingForEndOfUnknownTag) {
                         break;
                     }
-                    
+
                     tagName = parser.getName();
                     if (tagName.equals(XML_GROUP)) {
                         menuState.readGroup(attrs);
@@ -171,7 +171,7 @@
                         unknownTagName = tagName;
                     }
                     break;
-                    
+
                 case XmlPullParser.END_TAG:
                     tagName = parser.getName();
                     if (lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) {
@@ -194,11 +194,11 @@
                         reachedEndOfMenu = true;
                     }
                     break;
-                    
+
                 case XmlPullParser.END_DOCUMENT:
                     throw new RuntimeException("Unexpected end of document");
             }
-            
+
             eventType = parser.next();
         }
     }
@@ -229,10 +229,10 @@
     private static class InflatedOnMenuItemClickListener
             implements MenuItem.OnMenuItemClickListener {
         private static final Class<?>[] PARAM_TYPES = new Class[] { MenuItem.class };
-        
+
         private Object mRealOwner;
         private Method mMethod;
-        
+
         public InflatedOnMenuItemClickListener(Object realOwner, String methodName) {
             mRealOwner = realOwner;
             Class<?> c = realOwner.getClass();
@@ -246,7 +246,7 @@
                 throw ex;
             }
         }
-        
+
         public boolean onMenuItemClick(MenuItem item) {
             try {
                 if (mMethod.getReturnType() == Boolean.TYPE) {
@@ -277,7 +277,7 @@
         }
         return owner;
     }
-    
+
     /**
      * State for the current menu.
      * <p>
@@ -316,7 +316,7 @@
         private boolean itemChecked;
         private boolean itemVisible;
         private boolean itemEnabled;
-        
+
         /**
          * Sync to attrs.xml enum, values in MenuItem:
          * - 0: never
@@ -331,7 +331,7 @@
         private String itemActionProviderClassName;
 
         private String itemListenerMethodName;
-        
+
         private ActionProvider itemActionProvider;
 
         private static final int defaultGroupId = NO_ID;
@@ -342,13 +342,13 @@
         private static final boolean defaultItemChecked = false;
         private static final boolean defaultItemVisible = true;
         private static final boolean defaultItemEnabled = true;
-        
+
         public MenuState(final Menu menu) {
             this.menu = menu;
-            
+
             resetGroup();
         }
-        
+
         public void resetGroup() {
             groupId = defaultGroupId;
             groupCategory = defaultItemCategory;
@@ -364,7 +364,7 @@
         public void readGroup(AttributeSet attrs) {
             TypedArray a = mContext.obtainStyledAttributes(attrs,
                     com.android.internal.R.styleable.MenuGroup);
-            
+
             groupId = a.getResourceId(com.android.internal.R.styleable.MenuGroup_id, defaultGroupId);
             groupCategory = a.getInt(com.android.internal.R.styleable.MenuGroup_menuCategory, defaultItemCategory);
             groupOrder = a.getInt(com.android.internal.R.styleable.MenuGroup_orderInCategory, defaultItemOrder);
@@ -374,7 +374,7 @@
 
             a.recycle();
         }
-        
+
         /**
          * Called when the parser is pointing to an item tag.
          */
@@ -436,7 +436,7 @@
                 return shortcutString.charAt(0);
             }
         }
-        
+
         private void setItem(MenuItem item) {
             item.setChecked(itemChecked)
                 .setVisible(itemVisible)
@@ -446,11 +446,11 @@
                 .setIcon(itemIconResId)
                 .setAlphabeticShortcut(itemAlphabeticShortcut)
                 .setNumericShortcut(itemNumericShortcut);
-            
+
             if (itemShowAsAction >= 0) {
                 item.setShowAsAction(itemShowAsAction);
             }
-            
+
             if (itemListenerMethodName != null) {
                 if (mContext.isRestricted()) {
                     throw new IllegalStateException("The android:onClick attribute cannot "
@@ -494,14 +494,14 @@
             setItem(item);
             return item;
         }
-        
+
         public SubMenu addSubMenuItem() {
             itemAdded = true;
             SubMenu subMenu = menu.addSubMenu(groupId, itemId, itemCategoryOrder, itemTitle);
             setItem(subMenu.getItem());
             return subMenu;
         }
-        
+
         public boolean hasAddedItem() {
             return itemAdded;
         }
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 3e8d577..2316b38 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -436,6 +436,14 @@
     public static final int FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 0x2;
 
     /**
+     * This private flag is only set on {@link #ACTION_HOVER_MOVE} events and indicates that
+     * this event will be immediately followed by a {@link #ACTION_HOVER_EXIT}. It is used to
+     * prevent generating redundant {@link #ACTION_HOVER_ENTER} events.
+     * @hide
+     */
+    public static final int FLAG_HOVER_EXIT_PENDING = 0x4;
+
+    /**
      * Private flag that indicates when the system has detected that this motion event
      * may be inconsistent with respect to the sequence of previously delivered motion events,
      * such as when a pointer move event is sent but the pointer is not down.
@@ -1947,6 +1955,20 @@
                 : flags & ~FLAG_TARGET_ACCESSIBILITY_FOCUS);
     }
 
+    /** @hide */
+    public final boolean isHoverExitPending() {
+        final int flags = getFlags();
+        return (flags & FLAG_HOVER_EXIT_PENDING) != 0;
+    }
+
+    /** @hide */
+    public void setHoverExitPending(boolean hoverExitPending) {
+        final int flags = getFlags();
+        nativeSetFlags(mNativePtr, hoverExitPending
+                ? flags | FLAG_HOVER_EXIT_PENDING
+                : flags & ~FLAG_HOVER_EXIT_PENDING);
+    }
+
     /**
      * Returns the time (in ms) when the user originally pressed down to start
      * a stream of position events.
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index fc79f53..998fd01 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -17,9 +17,6 @@
 package android.view;
 
 import android.annotation.NonNull;
-import android.util.SparseArray;
-import com.android.internal.util.XmlUtils;
-
 import android.annotation.XmlRes;
 import android.content.Context;
 import android.content.res.Resources;
@@ -32,6 +29,9 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.util.XmlUtils;
 
 /**
  * Represents an icon that can be used as a mouse pointer.
diff --git a/core/java/android/view/RecordingCanvas.java b/core/java/android/view/RecordingCanvas.java
new file mode 100644
index 0000000..e4b91b7
--- /dev/null
+++ b/core/java/android/view/RecordingCanvas.java
@@ -0,0 +1,641 @@
+/*
+ * 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.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.Size;
+import android.graphics.BaseCanvas;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.NinePatch;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Picture;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.TemporaryBuffer;
+import android.text.GraphicsOperations;
+import android.text.SpannableString;
+import android.text.SpannedString;
+import android.text.TextUtils;
+
+import dalvik.annotation.optimization.FastNative;
+
+/**
+ * This class is a base class for canvases that defer drawing operations, so all
+ * the draw operations can be marked @FastNative. It contains a re-implementation of
+ * all the methods in {@link BaseCanvas}.
+ *
+ * @hide
+ */
+public class RecordingCanvas extends Canvas {
+
+    public RecordingCanvas(long nativeCanvas) {
+        super(nativeCanvas);
+    }
+
+    @Override
+    public final void drawArc(float left, float top, float right, float bottom, float startAngle,
+            float sweepAngle, boolean useCenter, @NonNull Paint paint) {
+        nDrawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
+                useCenter, paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle,
+            boolean useCenter, @NonNull Paint paint) {
+        drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
+                paint);
+    }
+
+    @Override
+    public final void drawARGB(int a, int r, int g, int b) {
+        drawColor(Color.argb(a, r, g, b));
+    }
+
+    @Override
+    public final void drawBitmap(@NonNull Bitmap bitmap, float left, float top,
+            @Nullable Paint paint) {
+        throwIfCannotDraw(bitmap);
+        nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top,
+                paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity,
+                bitmap.mDensity);
+    }
+
+    @Override
+    public final void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix,
+            @Nullable Paint paint) {
+        nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(),
+                paint != null ? paint.getNativeInstance() : 0);
+    }
+
+    @Override
+    public final void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
+            @Nullable Paint paint) {
+        if (dst == null) {
+            throw new NullPointerException();
+        }
+        throwIfCannotDraw(bitmap);
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+
+        int left, top, right, bottom;
+        if (src == null) {
+            left = top = 0;
+            right = bitmap.getWidth();
+            bottom = bitmap.getHeight();
+        } else {
+            left = src.left;
+            right = src.right;
+            top = src.top;
+            bottom = src.bottom;
+        }
+
+        nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
+                dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
+                bitmap.mDensity);
+    }
+
+    @Override
+    public final void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
+            @Nullable Paint paint) {
+        if (dst == null) {
+            throw new NullPointerException();
+        }
+        throwIfCannotDraw(bitmap);
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+
+        float left, top, right, bottom;
+        if (src == null) {
+            left = top = 0;
+            right = bitmap.getWidth();
+            bottom = bitmap.getHeight();
+        } else {
+            left = src.left;
+            right = src.right;
+            top = src.top;
+            bottom = src.bottom;
+        }
+
+        nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
+                dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
+                bitmap.mDensity);
+    }
+
+    /** @deprecated checkstyle */
+    @Override
+    @Deprecated
+    public final void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y,
+            int width, int height, boolean hasAlpha, @Nullable Paint paint) {
+        // check for valid input
+        if (width < 0) {
+            throw new IllegalArgumentException("width must be >= 0");
+        }
+        if (height < 0) {
+            throw new IllegalArgumentException("height must be >= 0");
+        }
+        if (Math.abs(stride) < width) {
+            throw new IllegalArgumentException("abs(stride) must be >= width");
+        }
+        int lastScanline = offset + (height - 1) * stride;
+        int length = colors.length;
+        if (offset < 0 || (offset + width > length) || lastScanline < 0
+                || (lastScanline + width > length)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        // quick escape if there's nothing to draw
+        if (width == 0 || height == 0) {
+            return;
+        }
+        // punch down to native for the actual draw
+        nDrawBitmap(mNativeCanvasWrapper, colors, offset, stride, x, y, width, height, hasAlpha,
+                paint != null ? paint.getNativeInstance() : 0);
+    }
+
+    /** @deprecated checkstyle */
+    @Override
+    @Deprecated
+    public final void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y,
+            int width, int height, boolean hasAlpha, @Nullable Paint paint) {
+        // call through to the common float version
+        drawBitmap(colors, offset, stride, (float) x, (float) y, width, height,
+                hasAlpha, paint);
+    }
+
+    @Override
+    public final void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
+            @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
+            @Nullable Paint paint) {
+        if ((meshWidth | meshHeight | vertOffset | colorOffset) < 0) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (meshWidth == 0 || meshHeight == 0) {
+            return;
+        }
+        int count = (meshWidth + 1) * (meshHeight + 1);
+        // we mul by 2 since we need two floats per vertex
+        checkRange(verts.length, vertOffset, count * 2);
+        if (colors != null) {
+            // no mul by 2, since we need only 1 color per vertex
+            checkRange(colors.length, colorOffset, count);
+        }
+        nDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight,
+                verts, vertOffset, colors, colorOffset,
+                paint != null ? paint.getNativeInstance() : 0);
+    }
+
+    @Override
+    public final void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
+        nDrawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawColor(@ColorInt int color) {
+        nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
+    }
+
+    @Override
+    public final void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
+        nDrawColor(mNativeCanvasWrapper, color, mode.nativeInt);
+    }
+
+    @Override
+    public final void drawLine(float startX, float startY, float stopX, float stopY,
+            @NonNull Paint paint) {
+        nDrawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
+            @NonNull Paint paint) {
+        nDrawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) {
+        drawLines(pts, 0, pts.length, paint);
+    }
+
+    @Override
+    public final void drawOval(float left, float top, float right, float bottom,
+            @NonNull Paint paint) {
+        nDrawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
+        if (oval == null) {
+            throw new NullPointerException();
+        }
+        drawOval(oval.left, oval.top, oval.right, oval.bottom, paint);
+    }
+
+    @Override
+    public final void drawPaint(@NonNull Paint paint) {
+        nDrawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst,
+            @Nullable Paint paint) {
+        Bitmap bitmap = patch.getBitmap();
+        throwIfCannotDraw(bitmap);
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+        nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
+                dst.left, dst.top, dst.right, dst.bottom, nativePaint,
+                mDensity, patch.getDensity());
+    }
+
+    @Override
+    public final void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst,
+            @Nullable Paint paint) {
+        Bitmap bitmap = patch.getBitmap();
+        throwIfCannotDraw(bitmap);
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+        nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
+                dst.left, dst.top, dst.right, dst.bottom, nativePaint,
+                mDensity, patch.getDensity());
+    }
+
+    @Override
+    public final void drawPath(@NonNull Path path, @NonNull Paint paint) {
+        if (path.isSimplePath && path.rects != null) {
+            nDrawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
+        } else {
+            nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
+        }
+    }
+
+    @Override
+    public final void drawPicture(@NonNull Picture picture) {
+        picture.endRecording();
+        int restoreCount = save();
+        picture.draw(this);
+        restoreToCount(restoreCount);
+    }
+
+    @Override
+    public final void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
+        save();
+        translate(dst.left, dst.top);
+        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
+            scale((float) dst.width() / picture.getWidth(),
+                    (float) dst.height() / picture.getHeight());
+        }
+        drawPicture(picture);
+        restore();
+    }
+
+    @Override
+    public final void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
+        save();
+        translate(dst.left, dst.top);
+        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
+            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
+        }
+        drawPicture(picture);
+        restore();
+    }
+
+    @Override
+    public final void drawPoint(float x, float y, @NonNull Paint paint) {
+        nDrawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
+            @NonNull Paint paint) {
+        nDrawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) {
+        drawPoints(pts, 0, pts.length, paint);
+    }
+
+    /** @deprecated checkstyle */
+    @Override
+    @Deprecated
+    public final void drawPosText(@NonNull char[] text, int index, int count,
+            @NonNull @Size(multiple = 2) float[] pos,
+            @NonNull Paint paint) {
+        if (index < 0 || index + count > text.length || count * 2 > pos.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        for (int i = 0; i < count; i++) {
+            drawText(text, index + i, 1, pos[i * 2], pos[i * 2 + 1], paint);
+        }
+    }
+
+    /** @deprecated checkstyle */
+    @Override
+    @Deprecated
+    public final void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos,
+            @NonNull Paint paint) {
+        drawPosText(text.toCharArray(), 0, text.length(), pos, paint);
+    }
+
+    @Override
+    public final void drawRect(float left, float top, float right, float bottom,
+            @NonNull Paint paint) {
+        nDrawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawRect(@NonNull Rect r, @NonNull Paint paint) {
+        drawRect(r.left, r.top, r.right, r.bottom, paint);
+    }
+
+    @Override
+    public final void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
+        nDrawRect(mNativeCanvasWrapper,
+                rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawRGB(int r, int g, int b) {
+        drawColor(Color.rgb(r, g, b));
+    }
+
+    @Override
+    public final void drawRoundRect(float left, float top, float right, float bottom,
+            float rx, float ry, @NonNull Paint paint) {
+        nDrawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry,
+                paint.getNativeInstance());
+    }
+
+    @Override
+    public final void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
+        drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
+    }
+
+    @Override
+    public final void drawText(@NonNull char[] text, int index, int count, float x, float y,
+            @NonNull Paint paint) {
+        if ((index | count | (index + count)
+                | (text.length - index - count)) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+        nDrawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
+                paint.getNativeInstance(), paint.mNativeTypeface);
+    }
+
+    @Override
+    public final void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
+            @NonNull Paint paint) {
+        if ((start | end | (end - start) | (text.length() - end)) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (text instanceof String || text instanceof SpannedString
+                || text instanceof SpannableString) {
+            nDrawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
+                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+        } else if (text instanceof GraphicsOperations) {
+            ((GraphicsOperations) text).drawText(this, start, end, x, y,
+                    paint);
+        } else {
+            char[] buf = TemporaryBuffer.obtain(end - start);
+            TextUtils.getChars(text, start, end, buf, 0);
+            nDrawText(mNativeCanvasWrapper, buf, 0, end - start, x, y,
+                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+            TemporaryBuffer.recycle(buf);
+        }
+    }
+
+    @Override
+    public final void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
+        nDrawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
+                paint.getNativeInstance(), paint.mNativeTypeface);
+    }
+
+    @Override
+    public final void drawText(@NonNull String text, int start, int end, float x, float y,
+            @NonNull Paint paint) {
+        if ((start | end | (end - start) | (text.length() - end)) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+        nDrawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
+                paint.getNativeInstance(), paint.mNativeTypeface);
+    }
+
+    @Override
+    public final void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
+            float hOffset, float vOffset, @NonNull Paint paint) {
+        if (index < 0 || index + count > text.length) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        nDrawTextOnPath(mNativeCanvasWrapper, text, index, count,
+                path.readOnlyNI(), hOffset, vOffset,
+                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+    }
+
+    @Override
+    public final void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
+            float vOffset, @NonNull Paint paint) {
+        if (text.length() > 0) {
+            nDrawTextOnPath(mNativeCanvasWrapper, text, path.readOnlyNI(), hOffset, vOffset,
+                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+        }
+    }
+
+    @Override
+    public final void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
+            int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
+
+        if (text == null) {
+            throw new NullPointerException("text is null");
+        }
+        if (paint == null) {
+            throw new NullPointerException("paint is null");
+        }
+        if ((index | count | contextIndex | contextCount | index - contextIndex
+                | (contextIndex + contextCount) - (index + count)
+                | text.length - (contextIndex + contextCount)) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        nDrawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount,
+                x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+    }
+
+    @Override
+    public final void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
+            int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
+
+        if (text == null) {
+            throw new NullPointerException("text is null");
+        }
+        if (paint == null) {
+            throw new NullPointerException("paint is null");
+        }
+        if ((start | end | contextStart | contextEnd | start - contextStart | end - start
+                | contextEnd - end | text.length() - contextEnd) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        if (text instanceof String || text instanceof SpannedString
+                || text instanceof SpannableString) {
+            nDrawTextRun(mNativeCanvasWrapper, text.toString(), start, end, contextStart,
+                    contextEnd, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+        } else if (text instanceof GraphicsOperations) {
+            ((GraphicsOperations) text).drawTextRun(this, start, end,
+                    contextStart, contextEnd, x, y, isRtl, paint);
+        } else {
+            int contextLen = contextEnd - contextStart;
+            int len = end - start;
+            char[] buf = TemporaryBuffer.obtain(contextLen);
+            TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
+            nDrawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
+                    0, contextLen, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+            TemporaryBuffer.recycle(buf);
+        }
+    }
+
+    @Override
+    public final void drawVertices(@NonNull VertexMode mode, int vertexCount,
+            @NonNull float[] verts, int vertOffset, @Nullable float[] texs, int texOffset,
+            @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset,
+            int indexCount, @NonNull Paint paint) {
+        checkRange(verts.length, vertOffset, vertexCount);
+        if (isHardwareAccelerated()) {
+            return;
+        }
+        if (texs != null) {
+            checkRange(texs.length, texOffset, vertexCount);
+        }
+        if (colors != null) {
+            checkRange(colors.length, colorOffset, vertexCount / 2);
+        }
+        if (indices != null) {
+            checkRange(indices.length, indexOffset, indexCount);
+        }
+        nDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
+                vertOffset, texs, texOffset, colors, colorOffset,
+                indices, indexOffset, indexCount, paint.getNativeInstance());
+    }
+
+    @FastNative
+    private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top,
+            long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity);
+
+    @FastNative
+    private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap,
+            float srcLeft, float srcTop, float srcRight, float srcBottom,
+            float dstLeft, float dstTop, float dstRight, float dstBottom,
+            long nativePaintOrZero, int screenDensity, int bitmapDensity);
+
+    @FastNative
+    private static native void nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride,
+            float x, float y, int width, int height, boolean hasAlpha, long nativePaintOrZero);
+
+    @FastNative
+    private static native void nDrawColor(long nativeCanvas, int color, int mode);
+
+    @FastNative
+    private static native void nDrawPaint(long nativeCanvas, long nativePaint);
+
+    @FastNative
+    private static native void nDrawPoint(long canvasHandle, float x, float y, long paintHandle);
+
+    @FastNative
+    private static native void nDrawPoints(long canvasHandle, float[] pts, int offset, int count,
+            long paintHandle);
+
+    @FastNative
+    private static native void nDrawLine(long nativeCanvas, float startX, float startY, float stopX,
+            float stopY, long nativePaint);
+
+    @FastNative
+    private static native void nDrawLines(long canvasHandle, float[] pts, int offset, int count,
+            long paintHandle);
+
+    @FastNative
+    private static native void nDrawRect(long nativeCanvas, float left, float top, float right,
+            float bottom, long nativePaint);
+
+    @FastNative
+    private static native void nDrawOval(long nativeCanvas, float left, float top, float right,
+            float bottom, long nativePaint);
+
+    @FastNative
+    private static native void nDrawCircle(long nativeCanvas, float cx, float cy, float radius,
+            long nativePaint);
+
+    @FastNative
+    private static native void nDrawArc(long nativeCanvas, float left, float top, float right,
+            float bottom, float startAngle, float sweep, boolean useCenter, long nativePaint);
+
+    @FastNative
+    private static native void nDrawRoundRect(long nativeCanvas, float left, float top, float right,
+            float bottom, float rx, float ry, long nativePaint);
+
+    @FastNative
+    private static native void nDrawPath(long nativeCanvas, long nativePath, long nativePaint);
+
+    @FastNative
+    private static native void nDrawRegion(long nativeCanvas, long nativeRegion, long nativePaint);
+
+    @FastNative
+    private static native void nDrawNinePatch(long nativeCanvas, long nativeBitmap, long ninePatch,
+            float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero,
+            int screenDensity, int bitmapDensity);
+
+    @FastNative
+    private static native void nDrawBitmapMatrix(long nativeCanvas, Bitmap bitmap,
+            long nativeMatrix, long nativePaint);
+
+    @FastNative
+    private static native void nDrawBitmapMesh(long nativeCanvas, Bitmap bitmap, int meshWidth,
+            int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset,
+            long nativePaint);
+
+    @FastNative
+    private static native void nDrawVertices(long nativeCanvas, int mode, int n, float[] verts,
+            int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset,
+            short[] indices, int indexOffset, int indexCount, long nativePaint);
+
+    @FastNative
+    private static native void nDrawText(long nativeCanvas, char[] text, int index, int count,
+            float x, float y, int flags, long nativePaint, long nativeTypeface);
+
+    @FastNative
+    private static native void nDrawText(long nativeCanvas, String text, int start, int end,
+            float x, float y, int flags, long nativePaint, long nativeTypeface);
+
+    @FastNative
+    private static native void nDrawTextRun(long nativeCanvas, String text, int start, int end,
+            int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint,
+            long nativeTypeface);
+
+    @FastNative
+    private static native void nDrawTextRun(long nativeCanvas, char[] text, int start, int count,
+            int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint,
+            long nativeTypeface);
+
+    @FastNative
+    private static native void nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count,
+            long nativePath, float hOffset, float vOffset, int bidiFlags, long nativePaint,
+            long nativeTypeface);
+
+    @FastNative
+    private static native void nDrawTextOnPath(long nativeCanvas, String text, long nativePath,
+            float hOffset, float vOffset, int flags, long nativePaint, long nativeTypeface);
+}
diff --git a/core/java/android/view/RemotableViewMethod.java b/core/java/android/view/RemotableViewMethod.java
index e5cae84..03aed9a 100644
--- a/core/java/android/view/RemotableViewMethod.java
+++ b/core/java/android/view/RemotableViewMethod.java
@@ -36,6 +36,3 @@
      */
     String asyncImpl() default "";
 }
-
-
-
diff --git a/core/java/android/view/RenderNodeAnimatorSetHelper.java b/core/java/android/view/RenderNodeAnimatorSetHelper.java
index ba592d29..e1ef059 100644
--- a/core/java/android/view/RenderNodeAnimatorSetHelper.java
+++ b/core/java/android/view/RenderNodeAnimatorSetHelper.java
@@ -16,6 +16,7 @@
 package android.view;
 
 import android.animation.TimeInterpolator;
+
 import com.android.internal.view.animation.FallbackLUTInterpolator;
 import com.android.internal.view.animation.NativeInterpolatorFactory;
 import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
diff --git a/core/java/android/view/RoundScrollbarRenderer.java b/core/java/android/view/RoundScrollbarRenderer.java
index b77be8c..4c555ae 100644
--- a/core/java/android/view/RoundScrollbarRenderer.java
+++ b/core/java/android/view/RoundScrollbarRenderer.java
@@ -19,8 +19,8 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
-import android.graphics.RectF;
 import android.graphics.Rect;
+import android.graphics.RectF;
 
 /**
  * Helper class for drawing round scroll bars on round Wear devices.
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 7cd161c..9787494 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -20,7 +20,6 @@
 import android.content.res.Resources;
 import android.os.Build;
 import android.os.Handler;
-import android.os.SystemClock;
 
 /**
  * Detects scaling transformation gestures using the supplied {@link MotionEvent}s.
diff --git a/core/java/android/view/SearchEvent.java b/core/java/android/view/SearchEvent.java
index 643cc3e..72b5e4b 100644
--- a/core/java/android/view/SearchEvent.java
+++ b/core/java/android/view/SearchEvent.java
@@ -16,8 +16,6 @@
 
 package android.view;
 
-import android.view.InputDevice;
-
 /**
  * Class that contains information about an event that triggers a search.
  */
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 22e68a3..ecd5e3b 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -26,11 +26,11 @@
 import android.os.Parcelable;
 import android.util.Log;
 
+import dalvik.system.CloseGuard;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-import dalvik.system.CloseGuard;
-
 /**
  * Handle onto a raw buffer that is being managed by the screen compositor.
  *
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 6456826..b87250e 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -16,7 +16,6 @@
 
 package android.view;
 
-import dalvik.system.CloseGuard;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -24,6 +23,8 @@
 import android.util.Log;
 import android.view.Surface.OutOfResourcesException;
 
+import dalvik.system.CloseGuard;
+
 /**
  * SurfaceControl
  *  @hide
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 816bcf0..80f447e 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,11 +16,9 @@
 
 package android.view;
 
-import com.android.internal.view.BaseIWindow;
-
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.CompatibilityInfo.Translator;
+import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
@@ -28,12 +26,14 @@
 import android.graphics.Region;
 import android.os.Handler;
 import android.os.Message;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.ParcelFileDescriptor;
 import android.util.AttributeSet;
 import android.util.Log;
 
+import com.android.internal.view.BaseIWindow;
+
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.concurrent.locks.ReentrantLock;
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index ce390a2..0bb84cc 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,9 +16,9 @@
 
 package android.view;
 
-import android.app.ActivityManagerNative;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.app.ActivityManagerNative;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
@@ -916,7 +916,6 @@
             mInitialized = true;
             initSched(context, renderProxy);
             initGraphicsStats(context, renderProxy);
-            initAssetAtlas(context, renderProxy);
         }
 
         private static void initSched(Context context, long renderProxy) {
@@ -944,32 +943,6 @@
                 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
             }
         }
-
-        private static void initAssetAtlas(Context context, long renderProxy) {
-            IBinder binder = ServiceManager.getService("assetatlas");
-            if (binder == null) return;
-
-            IAssetAtlas atlas = IAssetAtlas.Stub.asInterface(binder);
-            try {
-                if (atlas.isCompatible(android.os.Process.myPpid())) {
-                    GraphicBuffer buffer = atlas.getBuffer();
-                    if (buffer != null) {
-                        long[] map = atlas.getMap();
-                        if (map != null) {
-                            nSetAtlas(renderProxy, buffer, map);
-                        }
-                        // If IAssetAtlas is not the same class as the IBinder
-                        // we are using a remote service and we can safely
-                        // destroy the graphic buffer
-                        if (atlas.getClass() != binder.getClass()) {
-                            buffer.destroy();
-                        }
-                    }
-                }
-            } catch (RemoteException e) {
-                Log.w(LOG_TAG, "Could not acquire atlas", e);
-            }
-        }
     }
 
     void addFrameMetricsObserver(FrameMetricsObserver observer) {
@@ -984,7 +957,6 @@
 
     static native void setupShadersDiskCache(String cacheFile);
 
-    private static native void nSetAtlas(long nativeProxy, GraphicBuffer buffer, long[] map);
     private static native void nSetProcessStatsBuffer(long nativeProxy, int fd);
     private static native int nGetRenderThreadTid(long nativeProxy);
 
diff --git a/core/java/android/view/TouchDelegate.java b/core/java/android/view/TouchDelegate.java
index 27b49db..cf36f43 100644
--- a/core/java/android/view/TouchDelegate.java
+++ b/core/java/android/view/TouchDelegate.java
@@ -17,9 +17,6 @@
 package android.view;
 
 import android.graphics.Rect;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
 
 /**
  * Helper class to handle situations where you want a view to have a larger touch area than its
@@ -33,24 +30,24 @@
  * </p>
  */
 public class TouchDelegate {
-    
+
     /**
-     * View that should receive forwarded touch events 
+     * View that should receive forwarded touch events
      */
     private View mDelegateView;
-    
+
     /**
      * Bounds in local coordinates of the containing view that should be mapped to the delegate
      * view. This rect is used for initial hit testing.
      */
     private Rect mBounds;
-    
+
     /**
      * mBounds inflated to include some slop. This rect is to track whether the motion events
      * should be considered to be be within the delegate view.
      */
     private Rect mSlopBounds;
-    
+
     /**
      * True if the delegate had been targeted on a down event (intersected mBounds).
      */
@@ -82,7 +79,7 @@
 
     /**
      * Constructor
-     * 
+     *
      * @param bounds Bounds in local coordinates of the containing view that should be mapped to
      *        the delegate view
      * @param delegateView The view that should receive motion events
@@ -99,7 +96,7 @@
     /**
      * Will forward touch events to the delegate view if the event is within the bounds
      * specified in the constructor.
-     * 
+     *
      * @param event The touch event to forward
      * @return True if the event was forwarded to the delegate, false otherwise.
      */
@@ -136,7 +133,7 @@
         }
         if (sendToDelegate) {
             final View delegateView = mDelegateView;
-            
+
             if (hit) {
                 // Offset event coordinates to be inside the target view
                 event.setLocation(delegateView.getWidth() / 2, delegateView.getHeight() / 2);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index deb3f90..20876a9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,6 +16,14 @@
 
 package android.view;
 
+import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
+import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
+import static android.os.Build.VERSION_CODES.KITKAT;
+import static android.os.Build.VERSION_CODES.M;
+import static android.os.Build.VERSION_CODES.N;
+
+import static java.lang.Math.max;
+
 import android.animation.AnimatorInflater;
 import android.animation.StateListAnimator;
 import android.annotation.CallSuper;
@@ -40,6 +48,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Insets;
 import android.graphics.Interpolator;
 import android.graphics.LinearGradient;
@@ -79,11 +88,11 @@
 import android.util.StateSet;
 import android.util.SuperNotCalledException;
 import android.util.TypedValue;
-import android.view.ContextMenu.ContextMenuInfo;
 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
 import android.view.AccessibilityIterators.TextSegmentIterator;
 import android.view.AccessibilityIterators.WordTextSegmentIterator;
+import android.view.ContextMenu.ContextMenuInfo;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityEventSource;
 import android.view.accessibility.AccessibilityManager;
@@ -99,17 +108,15 @@
 import android.widget.Checkable;
 import android.widget.FrameLayout;
 import android.widget.ScrollBarDrawable;
-import static android.os.Build.VERSION_CODES.*;
-import static java.lang.Math.max;
 
 import com.android.internal.R;
 import com.android.internal.util.Predicate;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.widget.ScrollBarUtils;
+
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
-import java.lang.NullPointerException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
@@ -757,6 +764,9 @@
         AccessibilityEventSource {
     private static final boolean DBG = false;
 
+    /** @hide */
+    public static boolean DEBUG_DRAW = false;
+
     /**
      * The logging tag used by this class with android.util.Log.
      */
@@ -1184,6 +1194,8 @@
      */
     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
 
+    private static Paint sDebugPaint;
+
     /** @hide */
     @IntDef(flag = true,
             value = {
@@ -1655,6 +1667,10 @@
             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
 
+    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
+
+    static final int DEBUG_CORNERS_SIZE_DIP = 8;
+
     /**
      * Temporary Rect currently for use in setBackground().  This will probably
      * be extended in the future to hold our own class with more than just
@@ -4743,6 +4759,10 @@
         mRenderNode = RenderNode.create(getClass().getName(), this);
     }
 
+    final boolean debugDraw() {
+        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
+    }
+
     private static SparseArray<String> getAttributeMap() {
         if (mAttributeMap == null) {
             mAttributeMap = new SparseArray<>();
@@ -16137,6 +16157,9 @@
                         if (mOverlay != null && !mOverlay.isEmpty()) {
                             mOverlay.getOverlayView().draw(canvas);
                         }
+                        if (debugDraw()) {
+                            debugDrawFocus(canvas);
+                        }
                     } else {
                         draw(canvas);
                     }
@@ -17115,6 +17138,44 @@
         return more;
     }
 
+    static Paint getDebugPaint() {
+        if (sDebugPaint == null) {
+            sDebugPaint = new Paint();
+            sDebugPaint.setAntiAlias(false);
+        }
+        return sDebugPaint;
+    }
+
+    final int dipsToPixels(int dips) {
+        float scale = getContext().getResources().getDisplayMetrics().density;
+        return (int) (dips * scale + 0.5f);
+    }
+
+    final private void debugDrawFocus(Canvas canvas) {
+        if (isFocused()) {
+            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
+            final int l = mScrollX;
+            final int r = l + mRight - mLeft;
+            final int t = mScrollY;
+            final int b = t + mBottom - mTop;
+
+            final Paint paint = getDebugPaint();
+            paint.setColor(DEBUG_CORNERS_COLOR);
+
+            // Draw squares in corners.
+            paint.setStyle(Paint.Style.FILL);
+            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
+            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
+            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
+            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
+
+            // Draw big X across the view.
+            paint.setStyle(Paint.Style.STROKE);
+            canvas.drawLine(l, t, r, b, paint);
+            canvas.drawLine(l, b, r, t, paint);
+        }
+    }
+
     /**
      * Manually render this view (and all of its children) to the given Canvas.
      * The view must have already done a full layout before this function is
@@ -17169,6 +17230,10 @@
             // Step 6, draw decorations (foreground, scrollbars)
             onDrawForeground(canvas);
 
+            if (debugDraw()) {
+                debugDrawFocus(canvas);
+            }
+
             // we're done...
             return;
         }
@@ -17317,6 +17382,10 @@
 
         // Step 6, draw decorations (foreground, scrollbars)
         onDrawForeground(canvas);
+
+        if (debugDraw()) {
+            debugDrawFocus(canvas);
+        }
     }
 
     /**
@@ -20832,6 +20901,9 @@
      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
      *  {@code false} if it didn't.
      * </p>
+     * <p>
+     *  For all other events, the return value is ignored.
+     * </p>
      */
     public boolean onDragEvent(DragEvent event) {
         return false;
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index e1ff0d6..047a515 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -51,8 +51,8 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeoutException;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 2e428a7..e39cb96 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
+
 import android.animation.LayoutTransition;
 import android.annotation.IdRes;
 import android.annotation.NonNull;
@@ -62,8 +64,6 @@
 import java.util.List;
 import java.util.Map;
 
-import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
-
 /**
  * <p>
  * A <code>ViewGroup</code> is a special view that can contain other views
@@ -116,8 +116,6 @@
     private static final String TAG = "ViewGroup";
 
     private static final boolean DBG = false;
-    /** @hide */
-    public static boolean DEBUG_DRAW = false;
 
     /**
      * Views which have been hidden or removed which need to be animated on
@@ -476,7 +474,6 @@
     private static final int ARRAY_INITIAL_CAPACITY = 12;
     private static final int ARRAY_CAPACITY_INCREMENT = 12;
 
-    private static Paint sDebugPaint;
     private static float[] sDebugLines;
 
     // Used to draw cached views
@@ -586,10 +583,6 @@
         initFromAttributes(context, attrs, defStyleAttr, defStyleRes);
     }
 
-    private boolean debugDraw() {
-        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
-    }
-
     private void initViewGroup() {
         // ViewGroup doesn't draw by default
         if (!debugDraw()) {
@@ -1865,8 +1858,11 @@
                 // Synthesize an exit from a move or enter.
                 // Ignore the result because hover focus has moved to a different view.
                 if (action == MotionEvent.ACTION_HOVER_MOVE) {
+                    final boolean hoverExitPending = event.isHoverExitPending();
+                    event.setHoverExitPending(true);
                     dispatchTransformedGenericPointerEvent(
                             event, child); // move
+                    event.setHoverExitPending(hoverExitPending);
                 }
                 eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
                 eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
@@ -1880,8 +1876,10 @@
             firstOldHoverTarget = nextOldHoverTarget;
         }
 
-        // Send events to the view group itself if no children have handled it.
-        boolean newHoveredSelf = !handled;
+        // Send events to the view group itself if no children have handled it and the view group
+        // itself is not currently being hover-exited.
+        boolean newHoveredSelf = !handled &&
+                (action != MotionEvent.ACTION_HOVER_EXIT) && !event.isHoverExitPending();
         if (newHoveredSelf == mHoveredSelf) {
             if (newHoveredSelf) {
                 // Send event to the view group as before.
@@ -3375,11 +3373,6 @@
         fillRect(c, paint, x1, y1, x1 + lw * sign(dx), y1 + dy);
     }
 
-    private int dipsToPixels(int dips) {
-        float scale = getContext().getResources().getDisplayMetrics().density;
-        return (int) (dips * scale + 0.5f);
-    }
-
     private static void drawRectCorners(Canvas canvas, int x1, int y1, int x2, int y2, Paint paint,
             int lineLength, int lineWidth) {
         drawCorner(canvas, paint, x1, y1, lineLength, lineLength, lineWidth);
@@ -3448,10 +3441,10 @@
 
         // Draw clip bounds
         {
-            paint.setColor(Color.rgb(63, 127, 255));
+            paint.setColor(DEBUG_CORNERS_COLOR);
             paint.setStyle(Paint.Style.FILL);
 
-            int lineLength = dipsToPixels(8);
+            int lineLength = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
             int lineWidth = dipsToPixels(1);
             for (int i = 0; i < getChildCount(); i++) {
                 View c = getChildAt(i);
@@ -7926,14 +7919,6 @@
         }
     }
 
-    private static Paint getDebugPaint() {
-        if (sDebugPaint == null) {
-            sDebugPaint = new Paint();
-            sDebugPaint.setAntiAlias(false);
-        }
-        return sDebugPaint;
-    }
-
     private static void drawRect(Canvas canvas, Paint paint, int x1, int y1, int x2, int y2) {
         if (sDebugLines== null) {
             // TODO: This won't work with multiple UI threads in a single process
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index c604234..6c84b63 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -17,8 +17,9 @@
 package android.view;
 
 import android.animation.Animator;
-import android.animation.ValueAnimator;
 import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Set;
@@ -42,7 +43,7 @@
  * <p>This class is not constructed by the caller, but rather by the View whose properties
  * it will animate. Calls to {@link android.view.View#animate()} will return a reference
  * to the appropriate ViewPropertyAnimator object for that View.</p>
- * 
+ *
  */
 public class ViewPropertyAnimator {
 
@@ -332,7 +333,7 @@
      * Sets the interpolator for the underlying animator that animates the requested properties.
      * By default, the animator uses the default interpolator for ValueAnimator. Calling this method
      * will cause the declared object to be used instead.
-     * 
+     *
      * @param interpolator The TimeInterpolator to be used for ensuing property animations. A value
      * of <code>null</code> will result in linear interpolation.
      * @return This object, allowing calls to methods in this class to be chained.
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index b046e2d..2c13831 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
 import android.annotation.IdRes;
@@ -24,7 +26,6 @@
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
 import android.annotation.SystemApi;
-import android.app.ActivityManagerNative;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -44,8 +45,6 @@
 import android.transition.TransitionManager;
 import android.view.accessibility.AccessibilityEvent;
 
-import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-
 import java.util.List;
 
 /**
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 395f738..abb3051 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -64,6 +64,13 @@
     /** @hide */
     int DOCKED_BOTTOM = 4;
 
+    /** @hide */
+    final static String INPUT_CONSUMER_PIP = "pip_input_consumer";
+    /** @hide */
+    final static String INPUT_CONSUMER_NAVIGATION = "nav_input_consumer";
+    /** @hide */
+    final static String INPUT_CONSUMER_WALLPAPER = "wallpaper_input_consumer";
+
     /**
      * Exception that is thrown when trying to add view whose
      * {@link LayoutParams} {@link LayoutParams#token}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index dd4e096..c1b8f04 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -23,7 +23,6 @@
 import android.os.RemoteException;
 
 import com.android.internal.os.IResultReceiver;
-import com.android.internal.R;
 
 import java.util.List;
 
@@ -38,11 +37,11 @@
  * Additional window manager specific layout parameters are defined for
  * control over how windows are displayed.  It also implements the {@link WindowManager}
  * interface, allowing you to control the displays attached to the device.
- * 
+ *
  * <p>Applications will not normally use WindowManager directly, instead relying
  * on the higher-level facilities in {@link android.app.Activity} and
  * {@link android.app.Dialog}.
- * 
+ *
  * <p>Even for low-level window manager access, it is almost never correct to use
  * this class.  For example, {@link android.app.Activity#getWindowManager}
  * provides a window manager for adding windows that are associated with that
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index da361c1..a6be493 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -25,12 +25,12 @@
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.graphics.RectF;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.view.animation.Animation;
+
 import com.android.internal.policy.IShortcutService;
 
 import java.io.PrintWriter;
@@ -458,7 +458,7 @@
         /**
          * Add a input consumer which will consume all input events going to any window below it.
          */
-        public InputConsumer addInputConsumer(Looper looper,
+        public InputConsumer createInputConsumer(Looper looper, String name,
                 InputEventReceiver.Factory inputEventReceiverFactory);
 
         /**
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 44f6fac..8084195 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -21,7 +21,6 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
 import android.content.pm.ServiceInfo;
 import android.os.Binder;
 import android.os.Handler;
@@ -92,9 +91,6 @@
     /** @hide */
     public static final int AUTOCLICK_DELAY_DEFAULT = 600;
 
-    /** @hide */
-    public static final int MAX_A11Y_EVENTS_PER_SERVICE_CALL = 20;
-
     static final Object sInstanceSync = new Object();
 
     private static AccessibilityManager sInstance;
@@ -103,8 +99,6 @@
 
     private IAccessibilityManager mService;
 
-    private EventDispatchThread mEventDispatchThread;
-
     final int mUserId;
 
     final Handler mHandler;
@@ -303,32 +297,44 @@
      * their descendants.
      */
     public void sendAccessibilityEvent(AccessibilityEvent event) {
-        if (!isEnabled()) {
-            Looper myLooper = Looper.myLooper();
-            if (myLooper == Looper.getMainLooper()) {
-                throw new IllegalStateException(
-                        "Accessibility off. Did you forget to check that?");
-            } else {
-                // If we're not running on the thread with the main looper, it's possible for
-                // the state of accessibility to change between checking isEnabled and
-                // calling this method. So just log the error rather than throwing the
-                // exception.
-                Log.e(LOG_TAG, "AccessibilityEvent sent with accessibility disabled");
+        final IAccessibilityManager service;
+        final int userId;
+        synchronized (mLock) {
+            service = getServiceLocked();
+            if (service == null) {
                 return;
             }
-        }
-        event.setEventTime(SystemClock.uptimeMillis());
-
-        getEventDispatchThread().scheduleEvent(event);
-    }
-
-    private EventDispatchThread getEventDispatchThread() {
-        synchronized (mLock) {
-            if (mEventDispatchThread == null) {
-                mEventDispatchThread = new EventDispatchThread(mService, mUserId);
-                mEventDispatchThread.start();
+            if (!mIsEnabled) {
+                Looper myLooper = Looper.myLooper();
+                if (myLooper == Looper.getMainLooper()) {
+                    throw new IllegalStateException(
+                            "Accessibility off. Did you forget to check that?");
+                } else {
+                    // If we're not running on the thread with the main looper, it's possible for
+                    // the state of accessibility to change between checking isEnabled and
+                    // calling this method. So just log the error rather than throwing the
+                    // exception.
+                    Log.e(LOG_TAG, "AccessibilityEvent sent with accessibility disabled");
+                    return;
+                }
             }
-            return mEventDispatchThread;
+            userId = mUserId;
+        }
+        try {
+            event.setEventTime(SystemClock.uptimeMillis());
+            // it is possible that this manager is in the same process as the service but
+            // client using it is called through Binder from another process. Example: MMS
+            // app adds a SMS notification and the NotificationManagerService calls this method
+            long identityToken = Binder.clearCallingIdentity();
+            service.sendAccessibilityEvent(event, userId);
+            Binder.restoreCallingIdentity(identityToken);
+            if (DEBUG) {
+                Log.i(LOG_TAG, event + " sent");
+            }
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error during sending " + event + " ", re);
+        } finally {
+            event.recycle();
         }
     }
 
@@ -713,99 +719,4 @@
             }
         }
     }
-
-    private static class EventDispatchThread extends Thread {
-        // Second lock used to keep UI thread performant. Never try to grab mLock when holding
-        // this one, or the UI thread will block in send AccessibilityEvent.
-        private final Object mEventQueueLock = new Object();
-
-        // Two lists to hold events. The app thread fills one while we empty the other.
-        private final ArrayList<AccessibilityEvent> mEventLists0 =
-                new ArrayList<>(MAX_A11Y_EVENTS_PER_SERVICE_CALL);
-        private final ArrayList<AccessibilityEvent> mEventLists1 =
-                new ArrayList<>(MAX_A11Y_EVENTS_PER_SERVICE_CALL);
-
-        private boolean mPingPongListToggle;
-
-        private final IAccessibilityManager mService;
-
-        private final int mUserId;
-
-        EventDispatchThread(IAccessibilityManager service, int userId) {
-            mService = service;
-            mUserId = userId;
-        }
-
-        @Override
-        public void run() {
-            while (true) {
-                ArrayList<AccessibilityEvent> listBeingDrained;
-                synchronized (mEventQueueLock) {
-                    ArrayList<AccessibilityEvent> listBeingFilled = getListBeingFilledLocked();
-                    if (listBeingFilled.isEmpty()) {
-                        try {
-                            mEventQueueLock.wait();
-                        } catch (InterruptedException e) {
-                            // Treat as a notify
-                        }
-                    }
-                    // Swap buffers
-                    mPingPongListToggle = !mPingPongListToggle;
-                    listBeingDrained = listBeingFilled;
-                }
-                dispatchEvents(listBeingDrained);
-            }
-        }
-
-        public void scheduleEvent(AccessibilityEvent event) {
-            synchronized (mEventQueueLock) {
-                getListBeingFilledLocked().add(event);
-                mEventQueueLock.notifyAll();
-            }
-        }
-
-        private ArrayList<AccessibilityEvent> getListBeingFilledLocked() {
-            return (mPingPongListToggle) ? mEventLists0 : mEventLists1;
-        }
-
-        private void dispatchEvents(ArrayList<AccessibilityEvent> events) {
-            int eventListCapacityLowerBound = events.size();
-            while (events.size() > 0) {
-                // We don't want to consume extra memory if an app sends a lot of events in a
-                // one-off event. Cap the list length at double the max events per call.
-                // We'll end up with extra GC for apps that send huge numbers of events, but
-                // sending that many events will lead to bad performance in any case.
-                if ((eventListCapacityLowerBound > 2 * MAX_A11Y_EVENTS_PER_SERVICE_CALL)
-                        && (events.size() <= 2 * MAX_A11Y_EVENTS_PER_SERVICE_CALL)) {
-                    events.trimToSize();
-                    eventListCapacityLowerBound = events.size();
-                }
-                // We only expect this loop to run once, as the app shouldn't be sending
-                // huge numbers of events.
-                // The clear in the called method will remove the sent events
-                dispatchOneBatchOfEvents(events.subList(0,
-                        Math.min(events.size(), MAX_A11Y_EVENTS_PER_SERVICE_CALL)));
-            }
-        }
-
-        private void dispatchOneBatchOfEvents(List<AccessibilityEvent> events) {
-            if (events.isEmpty()) {
-                return;
-            }
-            long identityToken = Binder.clearCallingIdentity();
-            try {
-                mService.sendAccessibilityEvents(new ParceledListSlice<>(events),
-                        mUserId);
-            } catch (RemoteException re) {
-                Log.e(LOG_TAG, "Error sending multiple events");
-            }
-            Binder.restoreCallingIdentity(identityToken);
-            if (DEBUG) {
-                Log.i(LOG_TAG, events.size() + " events sent");
-            }
-            for (int i = events.size() - 1; i >= 0; i--) {
-                events.remove(i).recycle();
-            }
-        }
-    }
 }
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index aa9cb39..71e77c4 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -21,7 +21,6 @@
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.content.ComponentName;
-import android.content.pm.ParceledListSlice;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.IAccessibilityInteractionConnection;
@@ -30,7 +29,7 @@
 
 /**
  * Interface implemented by the AccessibilityManagerService called by
- * the AccessibilityMasngers.
+ * the AccessibilityManagers.
  *
  * @hide
  */
@@ -40,8 +39,6 @@
 
     void sendAccessibilityEvent(in AccessibilityEvent uiEvent, int userId);
 
-    void sendAccessibilityEvents(in ParceledListSlice events, int userId);
-
     List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId);
 
     List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId);
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index d89c172..474db12 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -26,6 +26,7 @@
 import android.os.SystemProperties;
 import android.util.AttributeSet;
 import android.util.TypedValue;
+
 import dalvik.system.CloseGuard;
 
 /**
@@ -80,13 +81,13 @@
      * order.
      */
     public static final int ZORDER_NORMAL = 0;
-    
+
     /**
      * Requests that the content being animated be forced on top of all other
      * content for the duration of the animation.
      */
     public static final int ZORDER_TOP = 1;
-    
+
     /**
      * Requests that the content being animated be forced under all other
      * content for the duration of the animation.
@@ -138,7 +139,7 @@
     /**
      * Indicates whether fillBefore should be taken into account.
      */
-    boolean mFillEnabled = false;    
+    boolean mFillEnabled = false;
 
     /**
      * The time in milliseconds at which the animation must start;
@@ -240,7 +241,7 @@
 
         setDuration((long) a.getInt(com.android.internal.R.styleable.Animation_duration, 0));
         setStartOffset((long) a.getInt(com.android.internal.R.styleable.Animation_startOffset, 0));
-        
+
         setFillEnabled(a.getBoolean(com.android.internal.R.styleable.Animation_fillEnabled, mFillEnabled));
         setFillBefore(a.getBoolean(com.android.internal.R.styleable.Animation_fillBefore, mFillBefore));
         setFillAfter(a.getBoolean(com.android.internal.R.styleable.Animation_fillAfter, mFillAfter));
@@ -249,7 +250,7 @@
         setRepeatMode(a.getInt(com.android.internal.R.styleable.Animation_repeatMode, RESTART));
 
         setZAdjustment(a.getInt(com.android.internal.R.styleable.Animation_zAdjustment, ZORDER_NORMAL));
-        
+
         setBackgroundColor(a.getInt(com.android.internal.R.styleable.Animation_background, 0));
 
         setDetachWallpaper(a.getBoolean(com.android.internal.R.styleable.Animation_detachWallpaper, false));
@@ -294,13 +295,13 @@
     /**
      * Cancel the animation. Cancelling an animation invokes the animation
      * listener, if set, to notify the end of the animation.
-     * 
+     *
      * If you cancel an animation manually, you must call {@link #reset()}
      * before starting the animation again.
-     * 
-     * @see #reset() 
-     * @see #start() 
-     * @see #startNow() 
+     *
+     * @see #reset()
+     * @see #start()
+     * @see #startNow()
      */
     public void cancel() {
         if (mStarted && !mEnded) {
@@ -356,7 +357,7 @@
 
     /**
      * Sets the handler used to invoke listeners.
-     * 
+     *
      * @hide
      */
     public void setListenerHandler(Handler handler) {
@@ -424,7 +425,7 @@
 
     /**
      * How long this animation should last. The duration cannot be negative.
-     * 
+     *
      * @param durationMillis Duration in milliseconds
      *
      * @throws java.lang.IllegalArgumentException if the duration is < 0
@@ -443,7 +444,7 @@
      * than <var>durationMillis</var>.  In addition to adjusting the duration
      * itself, this ensures that the repeat count also will not make it run
      * longer than the given time.
-     * 
+     *
      * @param durationMillis The maximum duration the animation is allowed
      * to run.
      */
@@ -455,7 +456,7 @@
             mRepeatCount = 0;
             return;
         }
-        
+
         long dur = mDuration + mStartOffset;
         if (dur > durationMillis) {
             mDuration = durationMillis-mStartOffset;
@@ -480,7 +481,7 @@
             }
         }
     }
-    
+
     /**
      * How much to scale the duration by.
      *
@@ -528,7 +529,7 @@
     /**
      * Defines what this animation should do when it reaches the end. This
      * setting is applied only when the repeat count is either greater than
-     * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}. 
+     * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
      *
      * @param repeatMode {@link #RESTART} or {@link #REVERSE}
      * @attr ref android.R.styleable#Animation_repeatMode
@@ -606,7 +607,7 @@
      * @param fillAfter true if the animation should apply its transformation after it ends
      * @attr ref android.R.styleable#Animation_fillAfter
      *
-     * @see #setFillEnabled(boolean) 
+     * @see #setFillEnabled(boolean)
      */
     public void setFillAfter(boolean fillAfter) {
         mFillAfter = fillAfter;
@@ -614,7 +615,7 @@
 
     /**
      * Set the Z ordering mode to use while running the animation.
-     * 
+     *
      * @param zAdjustment The desired mode, one of {@link #ZORDER_NORMAL},
      * {@link #ZORDER_TOP}, or {@link #ZORDER_BOTTOM}.
      * @attr ref android.R.styleable#Animation_zAdjustment
@@ -622,7 +623,7 @@
     public void setZAdjustment(int zAdjustment) {
         mZAdjustment = zAdjustment;
     }
-    
+
     /**
      * Set background behind animation.
      *
@@ -634,11 +635,11 @@
     }
 
     /**
-     * The scale factor is set by the call to <code>getTransformation</code>. Overrides of 
+     * The scale factor is set by the call to <code>getTransformation</code>. Overrides of
      * {@link #getTransformation(long, Transformation, float)} will get this value
      * directly. Overrides of {@link #applyTransformation(float, Transformation)} can
      * call this method to get the value.
-     * 
+     *
      * @return float The scale factor that should be applied to pre-scaled values in
      * an Animation such as the pivot points in {@link ScaleAnimation} and {@link RotateAnimation}.
      */
@@ -748,7 +749,7 @@
     /**
      * Returns the Z ordering mode to use while running the animation as
      * previously set by {@link #setZAdjustment}.
-     * 
+     *
      * @return Returns one of {@link #ZORDER_NORMAL},
      * {@link #ZORDER_TOP}, or {@link #ZORDER_BOTTOM}.
      * @attr ref android.R.styleable#Animation_zAdjustment
@@ -827,7 +828,7 @@
     public long computeDurationHint() {
         return (getStartOffset() + getDuration()) * (getRepeatCount() + 1);
     }
-    
+
     /**
      * Gets the transformation to apply at a specified point in time. Implementations of this
      * method should always replace the specified Transformation or document they are doing
@@ -975,7 +976,7 @@
      * their transforms given an interpolation value.  Implementations of this
      * method should always replace the specified Transformation or document
      * they are doing otherwise.
-     * 
+     *
      * @param interpolatedTime The value of the normalized time (0.0 to 1.0)
      *        after it has been run through the interpolation function.
      * @param t The Transformation object to fill in with the current
@@ -1015,7 +1016,7 @@
      * @param bottom
      * @param invalidate
      * @param transformation
-     * 
+     *
      * @hide
      */
     public void getInvalidateRegion(int left, int top, int right, int bottom,
@@ -1072,7 +1073,7 @@
 
     /**
      * Return true if this animation changes the view's alpha property.
-     * 
+     *
      * @hide
      */
     public boolean hasAlpha() {
diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java
index 71c7450..09d4dfc 100644
--- a/core/java/android/view/animation/AnimationSet.java
+++ b/core/java/android/view/animation/AnimationSet.java
@@ -18,17 +18,17 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.RectF;
 import android.os.Build;
 import android.util.AttributeSet;
-import android.graphics.RectF;
 
 import java.util.ArrayList;
 import java.util.List;
 
 /**
  * Represents a group of Animations that should be played together.
- * The transformation of each individual animation are composed 
- * together into a single transform. 
+ * The transformation of each individual animation are composed
+ * together into a single transform.
  * If AnimationSet sets any properties that its children also set
  * (for example, duration or fillBefore), the values of AnimationSet
  * override the child values.
@@ -72,17 +72,17 @@
     private long[] mStoredOffsets;
 
     /**
-     * Constructor used when an AnimationSet is loaded from a resource. 
-     * 
+     * Constructor used when an AnimationSet is loaded from a resource.
+     *
      * @param context Application context to use
      * @param attrs Attribute set from which to read values
      */
     public AnimationSet(Context context, AttributeSet attrs) {
         super(context, attrs);
-        
+
         TypedArray a =
             context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AnimationSet);
-        
+
         setFlag(PROPERTY_SHARE_INTERPOLATOR_MASK,
                 a.getBoolean(com.android.internal.R.styleable.AnimationSet_shareInterpolator, true));
         init();
@@ -108,11 +108,11 @@
 
         a.recycle();
     }
-    
-    
+
+
     /**
      * Constructor to use when building an AnimationSet from code
-     * 
+     *
      * @param shareInterpolator Pass true if all of the animations in this set
      *        should use the interpolator associated with this AnimationSet.
      *        Pass false if each animation should use its own interpolator.
@@ -244,10 +244,10 @@
 
         mDirty = true;
     }
-    
+
     /**
      * Sets the start time of this animation and all child animations
-     * 
+     *
      * @see android.view.animation.Animation#setStartTime(long)
      */
     @Override
@@ -289,11 +289,11 @@
             animations.get(i).restrictDuration(durationMillis);
         }
     }
-    
+
     /**
-     * The duration of an AnimationSet is defined to be the 
+     * The duration of an AnimationSet is defined to be the
      * duration of the longest child animation.
-     * 
+     *
      * @see android.view.animation.Animation#getDuration()
      */
     @Override
@@ -317,7 +317,7 @@
     /**
      * The duration hint of an animation set is the maximum of the duration
      * hints of all of its component animations.
-     * 
+     *
      * @see android.view.animation.Animation#computeDurationHint
      */
     public long computeDurationHint() {
@@ -362,7 +362,7 @@
     /**
      * The transformation of an animation set is the concatenation of all of its
      * component animations.
-     * 
+     *
      * @see android.view.animation.Animation#getTransformation
      */
     @Override
@@ -404,7 +404,7 @@
 
         return more;
     }
-    
+
     /**
      * @see android.view.animation.Animation#scaleCurrentDuration(float)
      */
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 351b6db..f5c3613 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -16,19 +16,19 @@
 
 package android.view.animation;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.annotation.AnimRes;
 import android.annotation.InterpolatorRes;
 import android.content.Context;
 import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
 import android.content.res.Resources.Theme;
 import android.content.res.XmlResourceParser;
-import android.content.res.Resources.NotFoundException;
+import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.Xml;
-import android.os.SystemClock;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
 
diff --git a/core/java/android/view/animation/AnticipateInterpolator.java b/core/java/android/view/animation/AnticipateInterpolator.java
index fb66c31..7a837c3 100644
--- a/core/java/android/view/animation/AnticipateInterpolator.java
+++ b/core/java/android/view/animation/AnticipateInterpolator.java
@@ -18,8 +18,8 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
 import android.util.AttributeSet;
 
 import com.android.internal.R;
diff --git a/core/java/android/view/animation/AnticipateOvershootInterpolator.java b/core/java/android/view/animation/AnticipateOvershootInterpolator.java
index 1af72da..9a75134 100644
--- a/core/java/android/view/animation/AnticipateOvershootInterpolator.java
+++ b/core/java/android/view/animation/AnticipateOvershootInterpolator.java
@@ -16,6 +16,10 @@
 
 package android.view.animation;
 
+import static com.android.internal.R.styleable.AnticipateOvershootInterpolator;
+import static com.android.internal.R.styleable.AnticipateOvershootInterpolator_extraTension;
+import static com.android.internal.R.styleable.AnticipateOvershootInterpolator_tension;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -26,10 +30,6 @@
 import com.android.internal.view.animation.NativeInterpolatorFactory;
 import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
 
-import static com.android.internal.R.styleable.AnticipateOvershootInterpolator_extraTension;
-import static com.android.internal.R.styleable.AnticipateOvershootInterpolator_tension;
-import static com.android.internal.R.styleable.AnticipateOvershootInterpolator;
-
 /**
  * An interpolator where the change starts backward then flings forward and overshoots
  * the target value and finally goes back to the final value.
diff --git a/core/java/android/view/animation/CycleInterpolator.java b/core/java/android/view/animation/CycleInterpolator.java
index 663c109..72d64a1 100644
--- a/core/java/android/view/animation/CycleInterpolator.java
+++ b/core/java/android/view/animation/CycleInterpolator.java
@@ -18,8 +18,8 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
 import android.util.AttributeSet;
 
 import com.android.internal.R;
diff --git a/core/java/android/view/animation/DecelerateInterpolator.java b/core/java/android/view/animation/DecelerateInterpolator.java
index f426f60..f89743c 100644
--- a/core/java/android/view/animation/DecelerateInterpolator.java
+++ b/core/java/android/view/animation/DecelerateInterpolator.java
@@ -18,8 +18,8 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
 import android.util.AttributeSet;
 
 import com.android.internal.R;
diff --git a/core/java/android/view/animation/GridLayoutAnimationController.java b/core/java/android/view/animation/GridLayoutAnimationController.java
index 9161d8b..0f189ae 100644
--- a/core/java/android/view/animation/GridLayoutAnimationController.java
+++ b/core/java/android/view/animation/GridLayoutAnimationController.java
@@ -16,11 +16,11 @@
 
 package android.view.animation;
 
-import android.view.View;
-import android.view.ViewGroup;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
 
 import java.util.Random;
 
@@ -43,7 +43,7 @@
  *
  * @see LayoutAnimationController
  * @see android.widget.GridView
- * 
+ *
  * @attr ref android.R.styleable#GridLayoutAnimation_columnDelay
  * @attr ref android.R.styleable#GridLayoutAnimation_rowDelay
  * @attr ref android.R.styleable#GridLayoutAnimation_direction
@@ -206,7 +206,7 @@
      *
      * @see #getRowDelay()
      * @see #getColumnDelay()
-     * @see #setColumnDelay(float) 
+     * @see #setColumnDelay(float)
      */
     public void setRowDelay(float rowDelay) {
         mRowDelay = rowDelay;
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 38962a3..5f7a0f7 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -1,12 +1,12 @@
 /*
  * Copyright (C) 2008 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
@@ -35,7 +35,6 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
-import android.view.ViewRootImpl;
 
 class ComposingText implements NoCopySpan {
 }
@@ -56,25 +55,25 @@
     protected final InputMethodManager mIMM;
     final View mTargetView;
     final boolean mDummyMode;
-    
+
     private Object[] mDefaultComposingSpans;
-    
+
     Editable mEditable;
     KeyCharacterMap mKeyCharacterMap;
-    
+
     BaseInputConnection(InputMethodManager mgr, boolean fullEditor) {
         mIMM = mgr;
         mTargetView = null;
         mDummyMode = !fullEditor;
     }
-    
+
     public BaseInputConnection(View targetView, boolean fullEditor) {
         mIMM = (InputMethodManager)targetView.getContext().getSystemService(
                 Context.INPUT_METHOD_SERVICE);
         mTargetView = targetView;
         mDummyMode = !fullEditor;
     }
-    
+
     public static final void removeComposingSpans(Spannable text) {
         text.removeSpan(COMPOSING);
         Object[] sps = text.getSpans(0, text.length(), Object.class);
@@ -104,8 +103,8 @@
                 }
 
                 final int fl = text.getSpanFlags(o);
-                if ((fl&(Spanned.SPAN_COMPOSING|Spanned.SPAN_POINT_MARK_MASK)) 
-                        != (Spanned.SPAN_COMPOSING|Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)) {
+                if ((fl & (Spanned.SPAN_COMPOSING | Spanned.SPAN_POINT_MARK_MASK))
+                        != (Spanned.SPAN_COMPOSING | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)) {
                     text.setSpan(o, text.getSpanStart(o), text.getSpanEnd(o),
                             (fl & ~Spanned.SPAN_POINT_MARK_MASK)
                                     | Spanned.SPAN_COMPOSING
@@ -117,15 +116,15 @@
         text.setSpan(COMPOSING, start, end,
                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
     }
-    
+
     public static int getComposingSpanStart(Spannable text) {
         return text.getSpanStart(COMPOSING);
     }
-    
+
     public static int getComposingSpanEnd(Spannable text) {
         return text.getSpanEnd(COMPOSING);
     }
-    
+
     /**
      * Return the target of edit operations.  The default implementation
      * returns its own fake editable that is just used for composing text;
@@ -139,7 +138,7 @@
         }
         return mEditable;
     }
-    
+
     /**
      * Default implementation does nothing.
      */
@@ -452,10 +451,10 @@
      */
     public int getCursorCapsMode(int reqModes) {
         if (mDummyMode) return 0;
-        
+
         final Editable content = getEditable();
         if (content == null) return 0;
-        
+
         int a = Selection.getSelectionStart(content);
         int b = Selection.getSelectionEnd(content);
 
@@ -495,7 +494,7 @@
         if (a <= 0) {
             return "";
         }
-        
+
         if (length > a) {
             length = a;
         }
@@ -702,7 +701,7 @@
         if (!mDummyMode) {
             return;
         }
-        
+
         Editable content = getEditable();
         if (content != null) {
             final int N = content.length();
@@ -727,7 +726,7 @@
                     return;
                 }
             }
-            
+
             // Otherwise, revert to the special key event containing
             // the actual characters.
             KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(),
@@ -768,7 +767,7 @@
         if (content == null) {
             return;
         }
-        
+
         beginBatchEdit();
 
         // delete composing text set previously.
@@ -776,7 +775,7 @@
         int b = getComposingSpanEnd(content);
 
         if (DEBUG) Log.v(TAG, "Composing span: " + a + " to " + b);
-        
+
         if (b < a) {
             int tmp = a;
             a = b;
@@ -814,11 +813,11 @@
             }
             setComposingSpans(sp);
         }
-        
+
         if (DEBUG) Log.v(TAG, "Replacing from " + a + " to " + b + " with \""
                 + text + "\", composing=" + composing
                 + ", type=" + text.getClass().getCanonicalName());
-        
+
         if (DEBUG) {
             LogPrinter lp = new LogPrinter(Log.VERBOSE, TAG);
             lp.println("Current text:");
@@ -842,13 +841,13 @@
         Selection.setSelection(content, newCursorPosition);
 
         content.replace(a, b, text);
-        
+
         if (DEBUG) {
             LogPrinter lp = new LogPrinter(Log.VERBOSE, TAG);
             lp.println("Final text:");
             TextUtils.dumpSpans(content, lp, "  ");
         }
-        
+
         endBatchEdit();
     }
 
diff --git a/core/java/android/view/inputmethod/InputConnectionInspector.java b/core/java/android/view/inputmethod/InputConnectionInspector.java
index 2b292bb..5f25bf5 100644
--- a/core/java/android/view/inputmethod/InputConnectionInspector.java
+++ b/core/java/android/view/inputmethod/InputConnectionInspector.java
@@ -16,6 +16,8 @@
 
 package android.view.inputmethod;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -28,8 +30,6 @@
 import java.util.Map;
 import java.util.WeakHashMap;
 
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
 /**
  * @hide
  */
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 661b52f..5c8e6dc 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -16,9 +16,6 @@
 
 package android.view.inputmethod;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -39,6 +36,9 @@
 import android.util.Xml;
 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index ca370dc..2e99092 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1,12 +1,12 @@
 /*
  * Copyright (C) 2007-2008 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
@@ -16,15 +16,7 @@
 
 package android.view.inputmethod;
 
-import com.android.internal.inputmethod.IInputContentUriToken;
-import com.android.internal.os.SomeArgs;
-import com.android.internal.view.IInputConnectionWrapper;
-import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethodClient;
-import com.android.internal.view.IInputMethodManager;
-import com.android.internal.view.IInputMethodSession;
-import com.android.internal.view.InputBindResult;
-import com.android.internal.view.InputMethodClient;
+import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -40,8 +32,8 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
-import android.os.Trace;
 import android.os.ServiceManager.ServiceNotFoundException;
+import android.os.Trace;
 import android.text.TextUtils;
 import android.text.style.SuggestionSpan;
 import android.util.Log;
@@ -56,11 +48,19 @@
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewRootImpl;
-import android.view.textservice.TextServicesManager;
+
+import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.internal.os.SomeArgs;
+import com.android.internal.view.IInputConnectionWrapper;
+import com.android.internal.view.IInputContext;
+import com.android.internal.view.IInputMethodClient;
+import com.android.internal.view.IInputMethodManager;
+import com.android.internal.view.IInputMethodSession;
+import com.android.internal.view.InputBindResult;
+import com.android.internal.view.InputMethodClient;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.security.InvalidParameterException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -70,14 +70,12 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
-
 /**
  * Central system API to the overall input method framework (IMF) architecture,
  * which arbitrates interaction between applications and the current input method.
  * You can retrieve an instance of this interface with
  * {@link Context#getSystemService(String) Context.getSystemService()}.
- * 
+ *
  * <p>Topics covered here:
  * <ol>
  * <li><a href="#ArchitectureOverview">Architecture Overview</a>
@@ -85,13 +83,13 @@
  * <li><a href="#InputMethods">Input Methods</a>
  * <li><a href="#Security">Security</a>
  * </ol>
- * 
+ *
  * <a name="ArchitectureOverview"></a>
  * <h3>Architecture Overview</h3>
- * 
+ *
  * <p>There are three primary parties involved in the input method
  * framework (IMF) architecture:</p>
- * 
+ *
  * <ul>
  * <li> The <strong>input method manager</strong> as expressed by this class
  * is the central point of the system that manages interaction between all
@@ -106,16 +104,16 @@
  * method manager for input focus and control over the state of the IME.  Only
  * one such client is ever active (working with the IME) at a time.
  * </ul>
- * 
- * 
+ *
+ *
  * <a name="Applications"></a>
  * <h3>Applications</h3>
- * 
+ *
  * <p>In most cases, applications that are using the standard
  * {@link android.widget.TextView} or its subclasses will have little they need
  * to do to work well with soft input methods.  The main things you need to
  * be aware of are:</p>
- * 
+ *
  * <ul>
  * <li> Properly set the {@link android.R.attr#inputType} in your editable
  * text views, so that the input method will have enough context to help the
@@ -131,43 +129,43 @@
  * for your window using the same {@link android.R.attr#windowSoftInputMode}
  * attribute.
  * </ul>
- * 
+ *
  * <p>More finer-grained control is available through the APIs here to directly
  * interact with the IMF and its IME -- either showing or hiding the input
  * area, letting the user pick an input method, etc.</p>
- * 
+ *
  * <p>For the rare people amongst us writing their own text editors, you
  * will need to implement {@link android.view.View#onCreateInputConnection}
  * to return a new instance of your own {@link InputConnection} interface
  * allowing the IME to interact with your editor.</p>
- * 
- * 
+ *
+ *
  * <a name="InputMethods"></a>
  * <h3>Input Methods</h3>
- * 
+ *
  * <p>An input method (IME) is implemented
  * as a {@link android.app.Service}, typically deriving from
  * {@link android.inputmethodservice.InputMethodService}.  It must provide
  * the core {@link InputMethod} interface, though this is normally handled by
  * {@link android.inputmethodservice.InputMethodService} and implementors will
  * only need to deal with the higher-level API there.</p>
- * 
+ *
  * See the {@link android.inputmethodservice.InputMethodService} class for
  * more information on implementing IMEs.
- * 
- * 
+ *
+ *
  * <a name="Security"></a>
  * <h3>Security</h3>
- * 
+ *
  * <p>There are a lot of security issues associated with input methods,
  * since they essentially have freedom to completely drive the UI and monitor
  * everything the user enters.  The Android input method framework also allows
  * arbitrary third party IMEs, so care must be taken to restrict their
  * selection and interactions.</p>
- * 
+ *
  * <p>Here are some key points about the security architecture behind the
  * IMF:</p>
- * 
+ *
  * <ul>
  * <li> <p>Only the system is allowed to directly access an IME's
  * {@link InputMethod} interface, via the
@@ -175,11 +173,11 @@
  * enforced in the system by not binding to an input method service that does
  * not require this permission, so the system can guarantee no other untrusted
  * clients are accessing the current input method outside of its control.</p>
- * 
+ *
  * <li> <p>There may be many client processes of the IMF, but only one may
  * be active at a time.  The inactive clients can not interact with key
  * parts of the IMF through the mechanisms described below.</p>
- * 
+ *
  * <li> <p>Clients of an input method are only given access to its
  * {@link InputMethodSession} interface.  One instance of this interface is
  * created for each client, and only calls from the session associated with
@@ -187,19 +185,19 @@
  * by {@link android.inputmethodservice.AbstractInputMethodService} for normal
  * IMEs, but must be explicitly handled by an IME that is customizing the
  * raw {@link InputMethodSession} implementation.</p>
- * 
+ *
  * <li> <p>Only the active client's {@link InputConnection} will accept
  * operations.  The IMF tells each client process whether it is active, and
  * the framework enforces that in inactive processes calls on to the current
  * InputConnection will be ignored.  This ensures that the current IME can
  * only deliver events and text edits to the UI that the user sees as
  * being in focus.</p>
- * 
+ *
  * <li> <p>An IME can never interact with an {@link InputConnection} while
  * the screen is off.  This is enforced by making all clients inactive while
  * the screen is off, and prevents bad IMEs from driving the UI when the user
  * can not be aware of its behavior.</p>
- * 
+ *
  * <li> <p>A client application can ask that the system let the user pick a
  * new IME, but can not programmatically switch to one itself.  This avoids
  * malicious applications from switching the user to their own IME, which
@@ -207,7 +205,7 @@
  * IME, on the other hand, <em>is</em> allowed to programmatically switch
  * the system to another IME, since it already has full control of user
  * input.</p>
- * 
+ *
  * <li> <p>The user must explicitly enable a new IME in settings before
  * they can switch to it, to confirm with the system that they know about it
  * and want to make it available for use.</p>
@@ -268,11 +266,11 @@
 
     final IInputMethodManager mService;
     final Looper mMainLooper;
-    
+
     // For scheduling work on the main thread.  This also serves as our
     // global lock.
     final H mH;
-    
+
     // Our generic input connection if the current target does not have its own.
     final IInputContext mIInputContext;
 
@@ -280,20 +278,20 @@
      * True if this input method client is active, initially false.
      */
     boolean mActive = false;
-    
+
     /**
      * Set whenever this client becomes inactive, to know we need to reset
      * state with the IME the next time we receive focus.
      */
     boolean mHasBeenInactive = true;
-    
+
     /**
      * As reported by IME through InputConnection.
      */
     boolean mFullscreenMode;
-    
+
     // -----------------------------------------------------------
-    
+
     /**
      * This is the root view of the overall window that currently has input
      * method focus.
@@ -328,7 +326,7 @@
      * The completions that were last provided by the served view.
      */
     CompletionInfo[] mCompletions;
-    
+
     // Cursor position on the screen.
     Rect mTmpCursorRect = new Rect();
     Rect mCursorRect = new Rect();
@@ -389,7 +387,7 @@
     final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20);
 
     // -----------------------------------------------------------
-    
+
     static final int MSG_DUMP = 1;
     static final int MSG_BIND = 2;
     static final int MSG_UNBIND = 3;
@@ -403,7 +401,7 @@
         H(Looper looper) {
             super(looper, null, true);
         }
-        
+
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -654,7 +652,7 @@
             return sInstance;
         }
     }
-    
+
     /**
      * Private optimization: retrieve the global InputMethodManager instance,
      * if it exists.
@@ -663,17 +661,17 @@
     public static InputMethodManager peekInstance() {
         return sInstance;
     }
-    
+
     /** @hide */
     public IInputMethodClient getClient() {
         return mClient;
     }
-    
+
     /** @hide */
     public IInputContext getInputContext() {
         return mIInputContext;
     }
-    
+
     public List<InputMethodInfo> getInputMethodList() {
         try {
             return mService.getInputMethodList();
@@ -784,7 +782,7 @@
                     && mCurrentTextBoxAttribute != null;
         }
     }
-    
+
     /**
      * Return true if any view is currently active in the input method.
      */
@@ -794,7 +792,7 @@
             return mServedView != null && mCurrentTextBoxAttribute != null;
         }
     }
-    
+
     /**
      * Return true if the currently served view is accepting full text edits.
      * If false, it has no input connection, so can only handle raw key events.
@@ -871,7 +869,7 @@
                             || !mServedView.checkInputConnectionProxy(view))) {
                 return;
             }
-            
+
             mCompletions = completions;
             if (mCurMethod != null) {
                 try {
@@ -881,7 +879,7 @@
             }
         }
     }
-    
+
     public void updateExtractedText(View view, int token, ExtractedText text) {
         checkFocus();
         synchronized (mH) {
@@ -889,7 +887,7 @@
                     || !mServedView.checkInputConnectionProxy(view))) {
                 return;
             }
-            
+
             if (mCurMethod != null) {
                 try {
                     mCurMethod.updateExtractedText(token, text);
@@ -898,26 +896,26 @@
             }
         }
     }
-    
+
     /**
      * Flag for {@link #showSoftInput} to indicate that this is an implicit
      * request to show the input window, not as the result of a direct request
      * by the user.  The window may not be shown in this case.
      */
     public static final int SHOW_IMPLICIT = 0x0001;
-    
+
     /**
      * Flag for {@link #showSoftInput} to indicate that the user has forced
      * the input method open (such as by long-pressing menu) so it should
      * not be closed until they explicitly do so.
      */
     public static final int SHOW_FORCED = 0x0002;
-    
+
     /**
      * Synonym for {@link #showSoftInput(View, int, ResultReceiver)} without
      * a result receiver: explicitly request that the current input method's
      * soft input area be shown to the user, if needed.
-     * 
+     *
      * @param view The currently focused view, which would like to receive
      * soft keyboard input.
      * @param flags Provides additional operating flags.  Currently may be
@@ -926,7 +924,7 @@
     public boolean showSoftInput(View view, int flags) {
         return showSoftInput(view, flags, null);
     }
-    
+
     /**
      * Flag for the {@link ResultReceiver} result code from
      * {@link #showSoftInput(View, int, ResultReceiver)} and
@@ -934,7 +932,7 @@
      * state of the soft input window was unchanged and remains shown.
      */
     public static final int RESULT_UNCHANGED_SHOWN = 0;
-    
+
     /**
      * Flag for the {@link ResultReceiver} result code from
      * {@link #showSoftInput(View, int, ResultReceiver)} and
@@ -942,7 +940,7 @@
      * state of the soft input window was unchanged and remains hidden.
      */
     public static final int RESULT_UNCHANGED_HIDDEN = 1;
-    
+
     /**
      * Flag for the {@link ResultReceiver} result code from
      * {@link #showSoftInput(View, int, ResultReceiver)} and
@@ -950,7 +948,7 @@
      * state of the soft input window changed from hidden to shown.
      */
     public static final int RESULT_SHOWN = 2;
-    
+
     /**
      * Flag for the {@link ResultReceiver} result code from
      * {@link #showSoftInput(View, int, ResultReceiver)} and
@@ -958,7 +956,7 @@
      * state of the soft input window changed from shown to hidden.
      */
     public static final int RESULT_HIDDEN = 3;
-    
+
     /**
      * Explicitly request that the current input method's soft input area be
      * shown to the user, if needed.  Call this if the user interacts with
@@ -1000,7 +998,7 @@
             }
         }
     }
-    
+
     /** @hide */
     public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
         try {
@@ -1009,14 +1007,14 @@
             throw e.rethrowFromSystemServer();
         }
     }
-    
+
     /**
      * Flag for {@link #hideSoftInputFromWindow} to indicate that the soft
      * input window should only be hidden if it was not explicitly shown
      * by the user.
      */
     public static final int HIDE_IMPLICIT_ONLY = 0x0001;
-    
+
     /**
      * Flag for {@link #hideSoftInputFromWindow} to indicate that the soft
      * input window should normally be hidden, unless it was originally
@@ -1028,7 +1026,7 @@
      * Synonym for {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}
      * without a result: request to hide the soft input window from the
      * context of the window that is currently accepting input.
-     * 
+     *
      * @param windowToken The token of the window that is making the request,
      * as returned by {@link View#getWindowToken() View.getWindowToken()}.
      * @param flags Provides additional operating flags.  Currently may be
@@ -1037,7 +1035,7 @@
     public boolean hideSoftInputFromWindow(IBinder windowToken, int flags) {
         return hideSoftInputFromWindow(windowToken, flags, null);
     }
-    
+
     /**
      * Request to hide the soft input window from the context of the window
      * that is currently accepting input.  This should be called as a result
@@ -1079,11 +1077,11 @@
             }
         }
     }
-    
+
 
     /**
      * This method toggles the input method window display.
-     * If the input window is already displayed, it gets hidden. 
+     * If the input window is already displayed, it gets hidden.
      * If not the input window will be displayed.
      * @param windowToken The token of the window that is making the request,
      * as returned by {@link View#getWindowToken() View.getWindowToken()}.
@@ -1110,7 +1108,7 @@
 
     /*
      * This method toggles the input method window display.
-     * If the input window is already displayed, it gets hidden. 
+     * If the input window is already displayed, it gets hidden.
      * If not the input window will be displayed.
      * @param showFlags Provides additional operating flags.  May be
      * 0 or have the {@link #SHOW_IMPLICIT},
@@ -1134,7 +1132,7 @@
      * restart it with its new contents.  You should call this when the text
      * within your view changes outside of the normal input method or key
      * input flow, such as when an application calls TextView.setText().
-     * 
+     *
      * @param view The view whose text has changed.
      */
     public void restartInput(View view) {
@@ -1144,7 +1142,7 @@
                     || !mServedView.checkInputConnectionProxy(view))) {
                 return;
             }
-            
+
             mServedConnecting = true;
         }
 
@@ -1196,7 +1194,7 @@
             });
             return false;
         }
-        
+
         // Okay we are now ready to call into the served view and have it
         // do its stuff.
         // Life is good: let's hook everything up!
@@ -1465,7 +1463,7 @@
 
         return true;
     }
-    
+
     void closeCurrentInput() {
         try {
             mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS, null);
@@ -1504,7 +1502,7 @@
         if (first) {
             controlFlags |= CONTROL_WINDOW_FIRST;
         }
-        
+
         if (checkFocusNoStartInput(forceNewFocus)) {
             // We need to restart input on the current focus view.  This
             // should be done in conjunction with telling the system service
@@ -1792,7 +1790,7 @@
      * Close/hide the input method's soft input area, so the user no longer
      * sees it or can interact with it.  This can only be called
      * from the currently active input method, as validated by the given token.
-     * 
+     *
      * @param token Supplies the identifying token given to an input method
      * when it was started, which allows it to perform this operation on
      * itself.
@@ -1807,13 +1805,13 @@
             throw e.rethrowFromSystemServer();
         }
     }
-    
+
     /**
-     * Show the input method's soft input area, so the user 
+     * Show the input method's soft input area, so the user
      * sees the input method window and can interact with it.
      * This can only be called from the currently active input method,
      * as validated by the given token.
-     * 
+     *
      * @param token Supplies the identifying token given to an input method
      * when it was started, which allows it to perform this operation on
      * itself.
@@ -2335,7 +2333,7 @@
     void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
         final Printer p = new PrintWriterPrinter(fout);
         p.println("Input method client state for " + this + ":");
-        
+
         p.println("  mService=" + mService);
         p.println("  mMainLooper=" + mMainLooper);
         p.println("  mIInputContext=" + mIInputContext);
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java
index fc17f7a..7aa2c23 100644
--- a/core/java/android/view/textservice/SpellCheckerInfo.java
+++ b/core/java/android/view/textservice/SpellCheckerInfo.java
@@ -16,9 +16,6 @@
 
 package android.view.textservice;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -35,6 +32,9 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index e77dc0d..729eb8d 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -16,11 +16,6 @@
 
 package android.view.textservice;
 
-import com.android.internal.textservice.ISpellCheckerSession;
-import com.android.internal.textservice.ISpellCheckerSessionListener;
-import com.android.internal.textservice.ITextServicesManager;
-import com.android.internal.textservice.ITextServicesSessionListener;
-
 import android.os.Binder;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -29,6 +24,11 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+import com.android.internal.textservice.ITextServicesManager;
+import com.android.internal.textservice.ITextServicesSessionListener;
+
 import java.util.LinkedList;
 import java.util.Queue;
 
diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java
index 8dff0c6..026610e 100644
--- a/core/java/android/view/textservice/SpellCheckerSubtype.java
+++ b/core/java/android/view/textservice/SpellCheckerSubtype.java
@@ -16,8 +16,6 @@
 
 package android.view.textservice;
 
-import com.android.internal.inputmethod.InputMethodUtils;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -27,6 +25,8 @@
 import android.text.TextUtils;
 import android.util.Slog;
 
+import com.android.internal.inputmethod.InputMethodUtils;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
diff --git a/core/java/android/view/textservice/SuggestionsInfo.java b/core/java/android/view/textservice/SuggestionsInfo.java
index 78bc1a9..dc2051c 100644
--- a/core/java/android/view/textservice/SuggestionsInfo.java
+++ b/core/java/android/view/textservice/SuggestionsInfo.java
@@ -16,11 +16,11 @@
 
 package android.view.textservice;
 
-import com.android.internal.util.ArrayUtils;
-
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.util.ArrayUtils;
+
 /**
  * This class contains a metadata of suggestions from the text service
  */
diff --git a/core/java/android/webkit/IWebViewUpdateService.aidl b/core/java/android/webkit/IWebViewUpdateService.aidl
index 9434f0c..894f080 100644
--- a/core/java/android/webkit/IWebViewUpdateService.aidl
+++ b/core/java/android/webkit/IWebViewUpdateService.aidl
@@ -64,6 +64,11 @@
     String getCurrentWebViewPackageName();
 
     /**
+     * Used by public API for debugging purposes.
+     */
+    PackageInfo getCurrentWebViewPackage();
+
+    /**
      * Used by Settings to determine whether a certain package can be enabled/disabled by the user -
      * the package should not be modifiable in this way if it is a fallback package.
      */
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 8c725cf..939f45f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -21,6 +21,7 @@
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -36,6 +37,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.StrictMode;
+import android.os.RemoteException;
 import android.print.PrintDocumentAdapter;
 import android.security.KeyChain;
 import android.util.AttributeSet;
@@ -2674,6 +2676,26 @@
     }
 
     /**
+     * If WebView has already been loaded into the current process this method will return the
+     * package that was used to load it. Otherwise, the package that would be used if the WebView
+     * was loaded right now will be returned; this does not cause WebView to be loaded, so this
+     * information may become outdated at any time.
+     * @return the current WebView package, or null if there is none.
+     */
+    public static PackageInfo getCurrentWebViewPackage() {
+        PackageInfo webviewPackage = WebViewFactory.getLoadedPackageInfo();
+        if (webviewPackage != null) {
+            return webviewPackage;
+        }
+
+        try {
+            return WebViewFactory.getUpdateService().getCurrentWebViewPackage();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
      *
      * @param requestCode The integer request code originally supplied to
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 4bfc718..884a86c 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -135,7 +135,9 @@
     }
 
     public static PackageInfo getLoadedPackageInfo() {
-        return sPackageInfo;
+        synchronized (sProviderLock) {
+            return sPackageInfo;
+        }
     }
 
     /**
@@ -170,9 +172,8 @@
             Log.e(LOGTAG, "Couldn't find package " + packageName);
             return LIBLOAD_WRONG_PACKAGE_NAME;
         }
-        sPackageInfo = packageInfo;
 
-        int loadNativeRet = loadNativeLibrary(clazzLoader);
+        int loadNativeRet = loadNativeLibrary(clazzLoader, packageInfo);
         // If we failed waiting for relro we want to return that fact even if we successfully load
         // the relro file.
         if (loadNativeRet == LIBLOAD_SUCCESS) return response.status;
@@ -358,7 +359,7 @@
                 ClassLoader clazzLoader = webViewContext.getClassLoader();
 
                 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
-                loadNativeLibrary(clazzLoader);
+                loadNativeLibrary(clazzLoader, sPackageInfo);
                 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
 
                 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
@@ -637,14 +638,14 @@
         }
     }
 
-    // Assumes that we have waited for relro creation and set sPackageInfo
-    private static int loadNativeLibrary(ClassLoader clazzLoader) {
+    // Assumes that we have waited for relro creation
+    private static int loadNativeLibrary(ClassLoader clazzLoader, PackageInfo packageInfo) {
         if (!sAddressSpaceReserved) {
             Log.e(LOGTAG, "can't load with relro file; address space not reserved");
             return LIBLOAD_ADDRESS_SPACE_NOT_RESERVED;
         }
 
-        String[] args = getWebViewNativeLibraryPaths(sPackageInfo);
+        String[] args = getWebViewNativeLibraryPaths(packageInfo);
         int result = nativeLoadWithRelroFile(args[0] /* path32 */,
                                              args[1] /* path64 */,
                                              CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 01a95a4..5d136dc 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -36,6 +34,8 @@
 import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import com.android.internal.R;
+
 
 /**
  * AbsSeekBar extends the capabilities of ProgressBar by adding a draggable thumb.
@@ -469,7 +469,7 @@
     /**
      * Returns the amount of progress changed via the arrow keys.
      * <p>
-     * By default, this will be a value that is derived from the max progress.
+     * By default, this will be a value that is derived from the progress range.
      *
      * @return The amount to increment or decrement when the user presses the
      *         arrow keys. This will be positive.
@@ -479,13 +479,27 @@
     }
 
     @Override
-    public synchronized void setMax(int max) {
-        super.setMax(max);
+    public synchronized void setMin(int min) {
+        super.setMin(min);
+        int range = getMax() - getMin();
 
-        if ((mKeyProgressIncrement == 0) || (getMax() / mKeyProgressIncrement > 20)) {
+        if ((mKeyProgressIncrement == 0) || (range / mKeyProgressIncrement > 20)) {
+
             // It will take the user too long to change this via keys, change it
             // to something more reasonable
-            setKeyProgressIncrement(Math.max(1, Math.round((float) getMax() / 20)));
+            setKeyProgressIncrement(Math.max(1, Math.round((float) range / 20)));
+        }
+    }
+
+    @Override
+    public synchronized void setMax(int max) {
+        super.setMax(max);
+        int range = getMax() - getMin();
+
+        if ((mKeyProgressIncrement == 0) || (range / mKeyProgressIncrement > 20)) {
+            // It will take the user too long to change this via keys, change it
+            // to something more reasonable
+            setKeyProgressIncrement(Math.max(1, Math.round((float) range / 20)));
         }
     }
 
@@ -596,8 +610,10 @@
     }
 
     private float getScale() {
-        final int max = getMax();
-        return max > 0 ? getProgress() / (float) max : 0;
+        int min = getMin();
+        int max = getMax();
+        int range = max - min;
+        return range > 0 ? (getProgress() - min) / (float) range : 0;
     }
 
     /**
@@ -691,7 +707,7 @@
      */
     void drawTickMarks(Canvas canvas) {
         if (mTickMark != null) {
-            final int count = getMax();
+            final int count = getMax() - getMin();
             if (count > 1) {
                 final int w = mTickMark.getIntrinsicWidth();
                 final int h = mTickMark.getIntrinsicHeight();
@@ -847,8 +863,8 @@
             }
         }
 
-        final int max = getMax();
-        progress += scale * max;
+        final int range = getMax() - getMin();
+        progress += scale * range;
 
         setHotspot(x, y);
         setProgressInternal(Math.round(progress), true, false);
@@ -922,7 +938,7 @@
 
         if (isEnabled()) {
             final int progress = getProgress();
-            if (progress > 0) {
+            if (progress > getMin()) {
                 info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
             }
             if (progress < getMax()) {
@@ -960,7 +976,8 @@
                 if (!canUserSetProgress()) {
                     return false;
                 }
-                int increment = Math.max(1, Math.round((float) getMax() / 20));
+                int range = getMax() - getMin();
+                int increment = Math.max(1, Math.round((float) range / 20));
                 if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
                     increment = -increment;
                 }
diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
index 18db54e..bc3dfff 100644
--- a/core/java/android/widget/AbsSpinner.java
+++ b/core/java/android/widget/AbsSpinner.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
@@ -29,10 +27,12 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.R;
+
 /**
  * An abstract base class for spinner widgets. SDK users will probably not
  * need to use this class.
- * 
+ *
  * @attr ref android.R.styleable#AbsSpinner_entries
  */
 public abstract class AbsSpinner extends AdapterView<SpinnerAdapter> {
@@ -104,12 +104,12 @@
             mAdapter.unregisterDataSetObserver(mDataSetObserver);
             resetList();
         }
-        
+
         mAdapter = adapter;
-        
+
         mOldSelectedPosition = INVALID_POSITION;
         mOldSelectedRowId = INVALID_ROW_ID;
-        
+
         if (mAdapter != null) {
             mOldItemCount = mItemCount;
             mItemCount = mAdapter.getCount();
@@ -122,14 +122,14 @@
 
             setSelectedPositionInt(position);
             setNextSelectedPositionInt(position);
-            
+
             if (mItemCount == 0) {
                 // Nothing selected
                 checkSelectionChanged();
             }
-            
+
         } else {
-            checkFocus();            
+            checkFocus();
             resetList();
             // Nothing selected
             checkSelectionChanged();
@@ -144,23 +144,23 @@
     void resetList() {
         mDataChanged = false;
         mNeedSync = false;
-        
+
         removeAllViewsInLayout();
         mOldSelectedPosition = INVALID_POSITION;
         mOldSelectedRowId = INVALID_ROW_ID;
-        
+
         setSelectedPositionInt(INVALID_POSITION);
         setNextSelectedPositionInt(INVALID_POSITION);
         invalidate();
     }
 
-    /** 
+    /**
      * @see android.view.View#measure(int, int)
-     * 
+     *
      * Figure out the dimensions of this Spinner. The width comes from
      * the widthMeasureSpec as Spinnners can't have their width set to
      * UNSPECIFIED. The height is based on the height of the selected item
-     * plus padding. 
+     * plus padding.
      */
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
@@ -180,11 +180,11 @@
         if (mDataChanged) {
             handleDataChanged();
         }
-        
+
         int preferredHeight = 0;
         int preferredWidth = 0;
         boolean needsMeasuring = true;
-        
+
         int selectedPosition = getSelectedItemPosition();
         if (selectedPosition >= 0 && mAdapter != null && selectedPosition < mAdapter.getCount()) {
             // Try looking in the recycler. (Maybe we were measured once already)
@@ -208,14 +208,14 @@
                     mBlockLayoutRequests = false;
                 }
                 measureChild(view, widthMeasureSpec, heightMeasureSpec);
-                
+
                 preferredHeight = getChildHeight(view) + mSpinnerPadding.top + mSpinnerPadding.bottom;
                 preferredWidth = getChildWidth(view) + mSpinnerPadding.left + mSpinnerPadding.right;
-                
+
                 needsMeasuring = false;
             }
         }
-        
+
         if (needsMeasuring) {
             // No views -- just use padding
             preferredHeight = mSpinnerPadding.top + mSpinnerPadding.bottom;
@@ -238,18 +238,18 @@
     int getChildHeight(View child) {
         return child.getMeasuredHeight();
     }
-    
+
     int getChildWidth(View child) {
         return child.getMeasuredWidth();
     }
-    
+
     @Override
     protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
         return new ViewGroup.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT);
     }
-    
+
     void recycleAllViews() {
         final int childCount = getChildCount();
         final AbsSpinner.RecycleBin recycleBin = mRecycler;
@@ -260,7 +260,7 @@
             View v = getChildAt(i);
             int index = position + i;
             recycleBin.put(index, v);
-        }  
+        }
     }
 
     /**
@@ -279,14 +279,14 @@
         requestLayout();
         invalidate();
     }
-    
+
 
     /**
      * Makes the item at the supplied position selected.
-     * 
+     *
      * @param position Position to select
      * @param animate Should the transition be animated
-     * 
+     *
      */
     void setSelectionInt(int position, boolean animate) {
         if (position != mOldSelectedPosition) {
@@ -308,11 +308,11 @@
             return null;
         }
     }
-   
+
     /**
      * Override to prevent spamming ourselves with layout requests
      * as we place views
-     * 
+     *
      * @see android.view.View#requestLayout()
      */
     @Override
@@ -334,7 +334,7 @@
 
     /**
      * Maps a point to a position in the list.
-     * 
+     *
      * @param x X in local coordinate
      * @param y Y in local coordinate
      * @return The position of the item which contains the specified point, or
@@ -378,7 +378,7 @@
         SavedState(Parcelable superState) {
             super(superState);
         }
-        
+
         /**
          * Constructor called from {@link #CREATOR}
          */
@@ -431,7 +431,7 @@
     @Override
     public void onRestoreInstanceState(Parcelable state) {
         SavedState ss = (SavedState) state;
-  
+
         super.onRestoreInstanceState(ss.getSuperState());
 
         if (ss.selectedId >= 0) {
@@ -450,7 +450,7 @@
         public void put(int position, View v) {
             mScrapHeap.put(position, v);
         }
-        
+
         View get(int position) {
             // System.out.print("Looking for " + position);
             View result = mScrapHeap.get(position);
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index ac8d578..46269c6 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -39,6 +39,7 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityNodeInfo;
+
 import com.android.internal.view.ActionBarPolicy;
 import com.android.internal.view.menu.ActionMenuItemView;
 import com.android.internal.view.menu.BaseMenuPresenter;
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 4d0a1c8..c4bbdb0 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -31,6 +31,7 @@
 import android.view.ViewGroup;
 import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
+
 import com.android.internal.view.menu.ActionMenuItemView;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuItemImpl;
@@ -45,7 +46,7 @@
  */
 public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvoker, MenuView {
     private static final String TAG = "ActionMenuView";
-    
+
     static final int MIN_CELL_SIZE = 56; // dips
     static final int GENERATED_ITEM_PADDING = 4; // dips
 
@@ -71,7 +72,7 @@
     public ActionMenuView(Context context) {
         this(context, null);
     }
-    
+
     public ActionMenuView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setBaselineAligned(false);
@@ -579,7 +580,7 @@
         params.gravity = Gravity.CENTER_VERTICAL;
         return params;
     }
-    
+
     @Override
     public LayoutParams generateLayoutParams(AttributeSet attrs) {
         return new LayoutParams(getContext(), attrs);
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index f5c46db..51587a7 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -16,9 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-import com.android.internal.view.menu.ShowableListMenu;
-
 import android.annotation.StringRes;
 import android.content.Context;
 import android.content.Intent;
@@ -39,6 +36,9 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ActivityChooserModel.ActivityChooserModelClient;
 
+import com.android.internal.R;
+import com.android.internal.view.menu.ShowableListMenu;
+
 /**
  * This class is a view for choosing an activity for handling a given {@link Intent}.
  * <p>
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 7f5e2133..bde5f7f 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -16,15 +16,14 @@
 
 package android.widget;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.BroadcastReceiver;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
-import android.os.Handler;
 import android.text.format.DateUtils;
 import android.text.format.Time;
 import android.util.AttributeSet;
@@ -258,7 +257,7 @@
             }
 
             onTimeChanged();
-            
+
             invalidate();
         }
     };
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 1a1680a..68e6809 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -16,10 +16,6 @@
 */
 package android.widget;
 
-import android.annotation.SystemApi;
-import android.os.UserHandle;
-import com.android.internal.R;
-
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -31,6 +27,7 @@
 import android.content.pm.PermissionInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
+import android.os.UserHandle;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -39,6 +36,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.R;
+
 import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -57,7 +56,7 @@
  * extended information consisting of all groups and permissions.
  * To use this view define a LinearLayout or any ViewGroup and add this
  * view by instantiating AppSecurityPermissions and invoking getPermissionsView.
- * 
+ *
  * {@hide}
  */
 public class AppSecurityPermissions {
@@ -324,7 +323,7 @@
         return getPermissionItemViewOld(context, inflater, grpName,
                 description, dangerous, icon);
     }
-    
+
     private void getAllUsedPermissions(int sharedUid, Set<MyPermissionInfo> permSet) {
         String sharedPkgList[] = mPm.getPackagesForUid(sharedUid);
         if(sharedPkgList == null || (sharedPkgList.length == 0)) {
@@ -334,7 +333,7 @@
             getPermissionsForPackage(sharedPkg, permSet);
         }
     }
-    
+
     private void getPermissionsForPackage(String packageName, Set<MyPermissionInfo> permSet) {
         try {
             PackageInfo pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
@@ -417,7 +416,7 @@
             }
         }
     }
-    
+
     public int getPermissionCount() {
         return getPermissionCount(WHICH_ALL);
     }
@@ -570,7 +569,7 @@
         }
         return false;
     }
-    
+
     private static class PermissionGroupInfoComparator implements Comparator<MyPermissionGroupInfo> {
         private final Collator sCollator = Collator.getInstance();
         @Override
@@ -578,7 +577,7 @@
             return sCollator.compare(a.mLabel, b.mLabel);
         }
     }
-    
+
     private static class PermissionInfoComparator implements Comparator<MyPermissionInfo> {
         private final Collator sCollator = Collator.getInstance();
         PermissionInfoComparator() {
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 6a4e36a..49741d4 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -39,7 +39,9 @@
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
+
 import com.android.internal.R;
+
 import java.lang.ref.WeakReference;
 
 /**
@@ -362,22 +364,22 @@
      * <p>Returns the current width for the auto-complete drop down list. This can
      * be a fixed width, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill the screen, or
      * {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p>
-     * 
+     *
      * @return the width for the drop down list
-     * 
+     *
      * @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth
      */
     public int getDropDownWidth() {
         return mPopup.getWidth();
     }
-    
+
     /**
      * <p>Sets the current width for the auto-complete drop down list. This can
      * be a fixed width, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill the screen, or
      * {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p>
-     * 
+     *
      * @param width the width to use
-     * 
+     *
      * @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth
      */
     public void setDropDownWidth(int width) {
@@ -411,68 +413,68 @@
     public void setDropDownHeight(int height) {
         mPopup.setHeight(height);
     }
-    
+
     /**
      * <p>Returns the id for the view that the auto-complete drop down list is anchored to.</p>
-     *  
+     *
      * @return the view's id, or {@link View#NO_ID} if none specified
-     * 
+     *
      * @attr ref android.R.styleable#AutoCompleteTextView_dropDownAnchor
      */
     public int getDropDownAnchor() {
         return mDropDownAnchorId;
     }
-    
+
     /**
      * <p>Sets the view to which the auto-complete drop down list should anchor. The view
      * corresponding to this id will not be loaded until the next time it is needed to avoid
      * loading a view which is not yet instantiated.</p>
-     * 
+     *
      * @param id the id to anchor the drop down list view to
-     * 
-     * @attr ref android.R.styleable#AutoCompleteTextView_dropDownAnchor 
+     *
+     * @attr ref android.R.styleable#AutoCompleteTextView_dropDownAnchor
      */
     public void setDropDownAnchor(int id) {
         mDropDownAnchorId = id;
         mPopup.setAnchorView(null);
     }
-    
+
     /**
      * <p>Gets the background of the auto-complete drop-down list.</p>
-     * 
+     *
      * @return the background drawable
-     * 
+     *
      * @attr ref android.R.styleable#PopupWindow_popupBackground
      */
     public Drawable getDropDownBackground() {
         return mPopup.getBackground();
     }
-    
+
     /**
      * <p>Sets the background of the auto-complete drop-down list.</p>
-     * 
+     *
      * @param d the drawable to set as the background
-     * 
+     *
      * @attr ref android.R.styleable#PopupWindow_popupBackground
      */
     public void setDropDownBackgroundDrawable(Drawable d) {
         mPopup.setBackgroundDrawable(d);
     }
-    
+
     /**
      * <p>Sets the background of the auto-complete drop-down list.</p>
-     * 
+     *
      * @param id the id of the drawable to set as the background
-     * 
+     *
      * @attr ref android.R.styleable#PopupWindow_popupBackground
      */
     public void setDropDownBackgroundResource(@DrawableRes int id) {
         mPopup.setBackgroundDrawable(getContext().getDrawable(id));
     }
-    
+
     /**
      * <p>Sets the vertical offset used for the auto-complete drop-down list.</p>
-     * 
+     *
      * @param offset the vertical offset
      *
      * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset
@@ -480,10 +482,10 @@
     public void setDropDownVerticalOffset(int offset) {
         mPopup.setVerticalOffset(offset);
     }
-    
+
     /**
      * <p>Gets the vertical offset used for the auto-complete drop-down list.</p>
-     * 
+     *
      * @return the vertical offset
      *
      * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset
@@ -491,10 +493,10 @@
     public int getDropDownVerticalOffset() {
         return mPopup.getVerticalOffset();
     }
-    
+
     /**
      * <p>Sets the horizontal offset used for the auto-complete drop-down list.</p>
-     * 
+     *
      * @param offset the horizontal offset
      *
      * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset
@@ -502,10 +504,10 @@
     public void setDropDownHorizontalOffset(int offset) {
         mPopup.setHorizontalOffset(offset);
     }
-    
+
     /**
      * <p>Gets the horizontal offset used for the auto-complete drop-down list.</p>
-     * 
+     *
      * @return the horizontal offset
      *
      * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset
@@ -567,10 +569,10 @@
     public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) {
         mPopup.setDropDownAlwaysVisible(dropDownAlwaysVisible);
     }
-   
+
     /**
      * Checks whether the drop-down is dismissed when a suggestion is clicked.
-     * 
+     *
      * @hide Pending API council approval
      */
     public boolean isDropDownDismissedOnCompletion() {
@@ -578,17 +580,17 @@
     }
 
     /**
-     * Sets whether the drop-down is dismissed when a suggestion is clicked. This is 
+     * Sets whether the drop-down is dismissed when a suggestion is clicked. This is
      * true by default.
-     * 
+     *
      * @param dropDownDismissedOnCompletion Whether to dismiss the drop-down.
-     * 
+     *
      * @hide Pending API council approval
      */
     public void setDropDownDismissedOnCompletion(boolean dropDownDismissedOnCompletion) {
         mDropDownDismissedOnCompletion = dropDownDismissedOnCompletion;
     }
- 
+
     /**
      * <p>Returns the number of characters the user must type before the drop
      * down list is shown.</p>
@@ -720,13 +722,13 @@
     /**
      * <p>Changes the list of data used for auto completion. The provided list
      * must be a filterable list adapter.</p>
-     * 
+     *
      * <p>The caller is still responsible for managing any resources used by the adapter.
      * Notably, when the AutoCompleteTextView is closed or released, the adapter is not notified.
      * A common case is the use of {@link android.widget.CursorAdapter}, which
      * contains a {@link android.database.Cursor} that must be closed.  This can be done
-     * automatically (see 
-     * {@link android.app.Activity#startManagingCursor(android.database.Cursor) 
+     * automatically (see
+     * {@link android.app.Activity#startManagingCursor(android.database.Cursor)
      * startManagingCursor()}),
      * or by manually closing the cursor when the AutoCompleteTextView is dismissed.</p>
      *
@@ -811,7 +813,7 @@
         if (mPopup.onKeyDown(keyCode, event)) {
             return true;
         }
-        
+
         if (!isPopupShowing()) {
             switch(keyCode) {
             case KeyEvent.KEYCODE_DPAD_DOWN:
@@ -924,18 +926,18 @@
     protected CharSequence convertSelectionToString(Object selectedItem) {
         return mFilter.convertResultToString(selectedItem);
     }
-    
+
     /**
-     * <p>Clear the list selection.  This may only be temporary, as user input will often bring 
+     * <p>Clear the list selection.  This may only be temporary, as user input will often bring
      * it back.
      */
     public void clearListSelection() {
         mPopup.clearListSelection();
     }
-    
+
     /**
      * Set the position of the dropdown view selection.
-     * 
+     *
      * @param position The position to move the selector to.
      */
     public void setListSelection(int position) {
@@ -943,13 +945,13 @@
     }
 
     /**
-     * Get the position of the dropdown view selection, if there is one.  Returns 
+     * Get the position of the dropdown view selection, if there is one.  Returns
      * {@link ListView#INVALID_POSITION ListView.INVALID_POSITION} if there is no dropdown or if
      * there is no selection.
-     * 
-     * @return the position of the current selection, if there is one, or 
+     *
+     * @return the position of the current selection, if there is one, or
      * {@link ListView#INVALID_POSITION ListView.INVALID_POSITION} if not.
-     * 
+     *
      * @see ListView#getSelectedItemPosition()
      */
     public int getListSelection() {
@@ -1020,7 +1022,7 @@
             dismissDropDown();
         }
     }
-    
+
     /**
      * Identifies whether the view is currently performing a text completion, so subclasses
      * can decide whether to respond to text changed events.
@@ -1172,7 +1174,7 @@
     public void showDropDownAfterLayout() {
         mPopup.postShow();
     }
-    
+
     /**
      * Ensures that the drop down is not obscuring the IME.
      * @param visible whether the ime should be in front. If false, the ime is pushed to
@@ -1220,7 +1222,7 @@
      * Forces outside touches to be ignored. Normally if {@link #isDropDownAlwaysVisible()} is
      * false, we allow outside touch to dismiss the dropdown. If this is set to true, then we
      * ignore outside touch even when the drop down is not set to always visible.
-     * 
+     *
      * @hide used only by SearchDialog
      */
     public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) {
@@ -1245,7 +1247,7 @@
                         realCount++;
                     }
                 }
-                
+
                 if (realCount != count) {
                     CompletionInfo[] tmp = new CompletionInfo[realCount];
                     System.arraycopy(completions, 0, tmp, 0, realCount);
@@ -1340,7 +1342,7 @@
          */
         CharSequence fixText(CharSequence invalidText);
     }
-    
+
     /**
      * Listener to respond to the AutoCompleteTextView's completion list being dismissed.
      * @see AutoCompleteTextView#setOnDismissListener(OnDismissListener)
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 6ef1576..db50e34 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.AttrRes;
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
@@ -36,6 +34,8 @@
 import android.util.AttributeSet;
 import android.util.Log;
 
+import com.android.internal.R;
+
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index bcda83f..557d411 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.app.Service;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -38,10 +36,12 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import java.util.Locale;
+import com.android.internal.R;
 
 import libcore.icu.LocaleData;
 
+import java.util.Locale;
+
 /**
  * A delegate implementing the legacy CalendarView
  */
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
index 15bbdd2..046f75f 100644
--- a/core/java/android/widget/CheckBox.java
+++ b/core/java/android/widget/CheckBox.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.util.AttributeSet;
 
-
 /**
  * <p>
  * A checkbox is a specific type of two-states button that can be either
@@ -44,12 +43,12 @@
  *
  * <p>See the <a href="{@docRoot}guide/topics/ui/controls/checkbox.html">Checkboxes</a>
  * guide.</p>
- *  
- * <p><strong>XML attributes</strong></p> 
+ *
+ * <p><strong>XML attributes</strong></p>
  * <p>
- * See {@link android.R.styleable#CompoundButton CompoundButton Attributes}, 
- * {@link android.R.styleable#Button Button Attributes}, 
- * {@link android.R.styleable#TextView TextView Attributes}, 
+ * See {@link android.R.styleable#CompoundButton CompoundButton Attributes},
+ * {@link android.R.styleable#Button Button Attributes},
+ * {@link android.R.styleable#TextView TextView Attributes},
  * {@link android.R.styleable#View View Attributes}
  * </p>
  */
@@ -57,7 +56,7 @@
     public CheckBox(Context context) {
         this(context, null);
     }
-    
+
     public CheckBox(Context context, AttributeSet attrs) {
         this(context, attrs, com.android.internal.R.attr.checkboxStyle);
     }
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 21595d15..92bfd56 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -16,11 +16,8 @@
 
 package android.widget;
 
-import android.annotation.NonNull;
-import android.view.ViewHierarchyEncoder;
-import com.android.internal.R;
-
 import android.annotation.DrawableRes;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -34,9 +31,12 @@
 import android.view.Gravity;
 import android.view.RemotableViewMethod;
 import android.view.ViewDebug;
+import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import com.android.internal.R;
+
 /**
  * An extension to {@link TextView} that supports the {@link Checkable}
  * interface and displays.
@@ -394,7 +394,7 @@
                     y = (getHeight() - height) / 2;
                     break;
             }
-            
+
             final boolean checkMarkAtStart = isCheckMarkAtStart();
             final int width = getWidth();
             final int top = y;
@@ -417,7 +417,7 @@
             }
         }
     }
-    
+
     @Override
     protected int[] onCreateDrawableState(int extraSpace) {
         final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index adcb012..b9224f3 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -24,7 +24,6 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
 import android.widget.RemoteViews.RemoteView;
 
 import com.android.internal.R;
@@ -80,7 +79,7 @@
     private OnChronometerTickListener mOnChronometerTickListener;
     private StringBuilder mRecycle = new StringBuilder(8);
     private boolean mCountDown;
-    
+
     /**
      * Initialize this Chronometer object.
      * Sets the base to the current time.
@@ -191,7 +190,7 @@
 
     /**
      * Sets the listener to be called when the chronometer changes.
-     * 
+     *
      * @param listener The listener.
      */
     public void setOnChronometerTickListener(OnChronometerTickListener listener) {
@@ -209,10 +208,10 @@
     /**
      * Start counting up.  This does not affect the base as set from {@link #setBase}, just
      * the view display.
-     * 
-     * Chronometer works by regularly scheduling messages to the handler, even when the 
-     * Widget is not visible.  To make sure resource leaks do not occur, the user should 
-     * make sure that each start() call has a reciprocal call to {@link #stop}. 
+     *
+     * Chronometer works by regularly scheduling messages to the handler, even when the
+     * Widget is not visible.  To make sure resource leaks do not occur, the user should
+     * make sure that each start() call has a reciprocal call to {@link #stop}.
      */
     public void start() {
         mStarted = true;
@@ -222,9 +221,9 @@
     /**
      * Stop counting up.  This does not affect the base as set from {@link #setBase}, just
      * the view display.
-     * 
+     *
      * This stops the messages to the handler, effectively releasing resources that would
-     * be held as the chronometer is running, via {@link #start}. 
+     * be held as the chronometer is running, via {@link #start}.
      */
     public void stop() {
         mStarted = false;
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 0357834..dd63fef 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -19,14 +19,11 @@
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.graphics.PorterDuff;
-import android.view.ViewHierarchyEncoder;
-import com.android.internal.R;
-
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
+import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -34,9 +31,12 @@
 import android.view.Gravity;
 import android.view.SoundEffectConstants;
 import android.view.ViewDebug;
+import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import com.android.internal.R;
+
 /**
  * <p>
  * A button with two states, checked and unchecked. When the button is pressed
@@ -159,7 +159,7 @@
                 mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
             }
 
-            mBroadcasting = false;            
+            mBroadcasting = false;
         }
     }
 
@@ -492,7 +492,7 @@
         SavedState(Parcelable superState) {
             super(superState);
         }
-        
+
         /**
          * Constructor called from {@link #CREATOR}
          */
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 80f25d4..517e20cd 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
@@ -35,6 +33,8 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 
+import com.android.internal.R;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Locale;
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 1bf0c87..f712685 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -40,6 +38,8 @@
 import android.widget.DayPickerView.OnDaySelectedListener;
 import android.widget.YearPickerView.OnYearSelectedListener;
 
+import com.android.internal.R;
+
 import java.util.Locale;
 
 /**
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
index 9ecf8a5..702b2a5 100644
--- a/core/java/android/widget/DatePickerSpinnerDelegate.java
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -33,14 +33,14 @@
 import android.widget.DatePicker.AbstractDatePickerDelegate;
 import android.widget.NumberPicker.OnValueChangeListener;
 
+import libcore.icu.ICU;
+
 import java.text.DateFormatSymbols;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Locale;
 
-import libcore.icu.ICU;
-
 /**
  * A delegate implementing the basic DatePicker
  */
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index f748d3a..8d5bf8f 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -16,9 +16,6 @@
 
 package android.widget;
 
-import android.graphics.Rect;
-import com.android.internal.widget.PagerAdapter;
-
 import android.annotation.IdRes;
 import android.annotation.LayoutRes;
 import android.annotation.NonNull;
@@ -26,6 +23,7 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
+import android.graphics.Rect;
 import android.icu.util.Calendar;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
@@ -33,6 +31,8 @@
 import android.view.ViewGroup;
 import android.widget.SimpleMonthView.OnDayClickListener;
 
+import com.android.internal.widget.PagerAdapter;
+
 /**
  * An adapter for a list of {@link android.widget.SimpleMonthView} items.
  */
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index 0c02a2b..919c1e2 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -18,15 +18,11 @@
 
 import static android.os.Build.VERSION_CODES.N_MR1;
 
-import android.graphics.Rect;
-import com.android.internal.R;
-import com.android.internal.widget.ViewPager;
-import com.android.internal.widget.ViewPager.OnPageChangeListener;
-
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
+import android.graphics.Rect;
 import android.icu.util.Calendar;
 import android.util.AttributeSet;
 import android.util.MathUtils;
@@ -35,10 +31,14 @@
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
 
-import java.util.Locale;
+import com.android.internal.R;
+import com.android.internal.widget.ViewPager;
+import com.android.internal.widget.ViewPager.OnPageChangeListener;
 
 import libcore.icu.LocaleData;
 
+import java.util.Locale;
+
 class DayPickerView extends ViewGroup {
     private static final int DEFAULT_LAYOUT = R.layout.day_picker_content_material;
     private static final int DEFAULT_START_YEAR = 1900;
diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java
index 5f0ae29..94022ae 100644
--- a/core/java/android/widget/DayPickerViewPager.java
+++ b/core/java/android/widget/DayPickerViewPager.java
@@ -16,17 +16,12 @@
 
 package android.widget;
 
-import android.annotation.Nullable;
 import android.content.Context;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 
 import com.android.internal.util.Predicate;
-import com.android.internal.widget.PagerAdapter;
 import com.android.internal.widget.ViewPager;
 
 import java.util.ArrayList;
diff --git a/core/java/android/widget/DialerFilter.java b/core/java/android/widget/DialerFilter.java
index e37e3ba7..8f9c96c 100644
--- a/core/java/android/widget/DialerFilter.java
+++ b/core/java/android/widget/DialerFilter.java
@@ -17,7 +17,7 @@
 package android.widget;
 
 import android.content.Context;
-import android.view.KeyEvent;
+import android.graphics.Rect;
 import android.text.Editable;
 import android.text.InputFilter;
 import android.text.Selection;
@@ -28,8 +28,8 @@
 import android.text.method.KeyListener;
 import android.text.method.TextKeyListener;
 import android.util.AttributeSet;
+import android.view.KeyEvent;
 import android.view.View;
-import android.graphics.Rect;
 
 /**
  * This widget is a layout that contains several specifically-named child views that
@@ -169,7 +169,7 @@
                         // Only check to see if the digit is valid if the key is a printing key
                         // in the TextKeyListener. This prevents us from hiding the digits
                         // line when keys like UP and DOWN are hit.
-                        // XXX note that KEYCODE_TAB is special-cased here for 
+                        // XXX note that KEYCODE_TAB is special-cased here for
                         // devices that share tab and 0 on a single key.
                         boolean isPrint = event.isPrintingKey();
                         if (isPrint || keyCode == KeyEvent.KEYCODE_SPACE
diff --git a/core/java/android/widget/DigitalClock.java b/core/java/android/widget/DigitalClock.java
index 1df1643..c503ef2 100644
--- a/core/java/android/widget/DigitalClock.java
+++ b/core/java/android/widget/DigitalClock.java
@@ -23,6 +23,7 @@
 import android.provider.Settings;
 import android.text.format.DateFormat;
 import android.util.AttributeSet;
+
 import java.util.Calendar;
 
 /**
diff --git a/core/java/android/widget/DropDownListView.java b/core/java/android/widget/DropDownListView.java
index 69e4218..e9c4728 100644
--- a/core/java/android/widget/DropDownListView.java
+++ b/core/java/android/widget/DropDownListView.java
@@ -17,13 +17,13 @@
 package android.widget;
 
 
-import com.android.internal.widget.AutoScrollHelper.AbsListViewAutoScroller;
-
 import android.annotation.NonNull;
 import android.content.Context;
 import android.view.MotionEvent;
 import android.view.View;
 
+import com.android.internal.widget.AutoScrollHelper.AbsListViewAutoScroller;
+
 /**
  * Wrapper class for a ListView. This wrapper can hijack the focus to
  * make sure the list uses the appropriate drawables and states when
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 9019f31..98d8a13 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -17,14 +17,13 @@
 package android.widget;
 
 import android.annotation.ColorInt;
+import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
-
-import android.content.Context;
-import android.graphics.Canvas;
 import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
@@ -103,7 +102,7 @@
     private int mState = STATE_IDLE;
 
     private float mPullDistance;
-    
+
     private final Rect mBounds = new Rect();
     private final Paint mPaint = new Paint();
     private float mRadius;
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 24d8618..a8d3984 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -17,7 +17,6 @@
 package android.widget;
 
 import android.content.Context;
-import android.os.Bundle;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.Spannable;
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index fac36c5..8d9848d 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -16,7 +16,7 @@
 
 package android.widget;
 
-import com.android.internal.R;
+import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
 
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -27,14 +27,14 @@
 import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
 import android.view.SoundEffectConstants;
 import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
 import android.widget.ExpandableListConnector.PositionMetadata;
 
-import java.util.ArrayList;
+import com.android.internal.R;
 
-import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
+import java.util.ArrayList;
 
 /**
  * A view that shows items in a vertically scrolling two-level list. This
@@ -68,7 +68,7 @@
  * wrap_content since it also can be any length. However, you can use
  * wrap_content if the ExpandableListView parent has a specific size, such as
  * 100 pixels.
- * 
+ *
  * @attr ref android.R.styleable#ExpandableListView_groupIndicator
  * @attr ref android.R.styleable#ExpandableListView_indicatorLeft
  * @attr ref android.R.styleable#ExpandableListView_indicatorRight
@@ -87,7 +87,7 @@
      * The packed position represents a group.
      */
     public static final int PACKED_POSITION_TYPE_GROUP = 0;
-    
+
     /**
      * The packed position represents a child.
      */
@@ -97,14 +97,14 @@
      * The packed position represents a neither/null/no preference.
      */
     public static final int PACKED_POSITION_TYPE_NULL = 2;
-    
+
     /**
      * The value for a packed position that represents neither/null/no
      * preference. This value is not otherwise possible since a group type
      * (first bit 0) should not have a child position filled.
      */
     public static final long PACKED_POSITION_VALUE_NULL = 0x00000000FFFFFFFFL;
-    
+
     /** The mask (in packed position representation) for the child */
     private static final long PACKED_POSITION_MASK_CHILD = 0x00000000FFFFFFFFL;
 
@@ -125,13 +125,13 @@
 
     /** The mask (in integer group position representation) for the group */
     private static final long PACKED_POSITION_INT_MASK_GROUP = 0x7FFFFFFF;
-    
+
     /** Serves as the glue/translator between a ListView and an ExpandableListView */
     private ExpandableListConnector mConnector;
-    
-    /** Gives us Views through group+child positions */ 
+
+    /** Gives us Views through group+child positions */
     private ExpandableListAdapter mAdapter;
-    
+
     /** Left bound for drawing the indicator. */
     private int mIndicatorLeft;
 
@@ -210,7 +210,7 @@
     /** State indicating the child is the last within its group. */
     private static final int[] CHILD_LAST_STATE_SET =
             {R.attr.state_last};
-    
+
     /** Drawable to be used as a divider when it is adjacent to any children */
     private Drawable mChildDivider;
 
@@ -367,16 +367,16 @@
         }
 
         final int headerViewsCount = getHeaderViewsCount();
-        
+
         final int lastChildFlPos = mItemCount - getFooterViewsCount() - headerViewsCount - 1;
 
-        final int myB = mBottom; 
-        
+        final int myB = mBottom;
+
         PositionMetadata pos;
         View item;
-        Drawable indicator; 
+        Drawable indicator;
         int t, b;
-        
+
         // Start at a value that is neither child nor group
         int lastItemType = ~(ExpandableListPosition.CHILD | ExpandableListPosition.GROUP);
 
@@ -385,7 +385,7 @@
         // The "child" mentioned in the following two lines is this
         // View's child, not referring to an expandable list's
         // notion of a child (as opposed to a group)
-        final int childCount = getChildCount(); 
+        final int childCount = getChildCount();
         for (int i = 0, childFlPos = mFirstPosition - headerViewsCount; i < childCount;
              i++, childFlPos++) {
 
@@ -396,11 +396,11 @@
                 // This child is footer, so are all subsequent children
                 break;
             }
-            
+
             item = getChildAt(i);
             t = item.getTop();
             b = item.getBottom();
-            
+
             // This item isn't on the screen
             if ((b < 0) || (t > myB)) continue;
 
@@ -435,7 +435,7 @@
                     indicatorRect.right += mPaddingLeft;
                 }
 
-                lastItemType = pos.position.type; 
+                lastItemType = pos.position.type;
             }
 
             if (indicatorRect.left != indicatorRect.right) {
@@ -448,7 +448,7 @@
                     indicatorRect.top = t;
                     indicatorRect.bottom = b;// + mDividerHeight;
                 }
-                
+
                 // Get the indicator (with its state set to the item's state)
                 indicator = getIndicator(pos);
                 if (indicator != null) {
@@ -468,24 +468,24 @@
     /**
      * Gets the indicator for the item at the given position. If the indicator
      * is stateful, the state will be given to the indicator.
-     * 
+     *
      * @param pos The flat list position of the item whose indicator
      *            should be returned.
      * @return The indicator in the proper state.
      */
     private Drawable getIndicator(PositionMetadata pos) {
         Drawable indicator;
-        
+
         if (pos.position.type == ExpandableListPosition.GROUP) {
             indicator = mGroupIndicator;
-            
+
             if (indicator != null && indicator.isStateful()) {
                 // Empty check based on availability of data.  If the groupMetadata isn't null,
                 // we do a check on it. Otherwise, the group is collapsed so we consider it
                 // empty for performance reasons.
                 boolean isEmpty = (pos.groupMetadata == null) ||
                         (pos.groupMetadata.lastChildFlPos == pos.groupMetadata.flPos);
-                
+
                 final int stateSetIndex =
                     (pos.isExpanded() ? 1 : 0) | // Expanded?
                     (isEmpty ? 2 : 0); // Empty?
@@ -493,7 +493,7 @@
             }
         } else {
             indicator = mChildIndicator;
-            
+
             if (indicator != null && indicator.isStateful()) {
                 // No need for a state sets array for the child since it only has two states
                 final int stateSet[] = pos.position.flatListPos == pos.groupMetadata.lastChildFlPos
@@ -502,15 +502,15 @@
                 indicator.setState(stateSet);
             }
         }
-        
+
         return indicator;
     }
-    
+
     /**
      * Sets the drawable that will be drawn adjacent to every child in the list. This will
      * be drawn using the same height as the normal divider ({@link #setDivider(Drawable)}) or
      * if it does not have an intrinsic height, the height set by {@link #setDividerHeight(int)}.
-     * 
+     *
      * @param childDivider The drawable to use.
      */
     public void setChildDivider(Drawable childDivider) {
@@ -520,7 +520,7 @@
     @Override
     void drawDivider(Canvas canvas, Rect bounds, int childIndex) {
         int flatListPosition = childIndex + mFirstPosition;
-        
+
         // Only proceed as possible child if the divider isn't above all items (if it is above
         // all items, then the item below it has to be a group)
         if (flatListPosition >= 0) {
@@ -538,7 +538,7 @@
             }
             pos.recycle();
         }
-        
+
         // Otherwise draw the default divider
         super.drawDivider(canvas, bounds, flatListPosition);
     }
@@ -589,18 +589,18 @@
     public void setAdapter(ExpandableListAdapter adapter) {
         // Set member variable
         mAdapter = adapter;
-        
+
         if (adapter != null) {
             // Create the connector
             mConnector = new ExpandableListConnector(adapter);
         } else {
             mConnector = null;
         }
-        
+
         // Link the ListView (superclass) to the expandable list data through the connector
         super.setAdapter(mConnector);
     }
-    
+
     /**
      * Gets the adapter that provides data to this view.
      * @return The adapter that provides data to this view.
@@ -608,7 +608,7 @@
     public ExpandableListAdapter getExpandableListAdapter() {
         return mAdapter;
     }
-    
+
     /**
      * @param position An absolute (including header and footer) flat list position.
      * @return true if the position corresponds to a header or a footer item.
@@ -621,7 +621,7 @@
     /**
      * Converts an absolute item flat position into a group/child flat position, shifting according
      * to the number of header items.
-     * 
+     *
      * @param flatListPosition The absolute flat position
      * @return A group/child flat position as expected by the connector.
      */
@@ -632,7 +632,7 @@
     /**
      * Converts a group/child flat position into an absolute flat position, that takes into account
      * the possible headers.
-     * 
+     *
      * @param flatListPosition The child/group flat position
      * @return An absolute flat position.
      */
@@ -647,25 +647,25 @@
             // Clicked on a header/footer, so ignore pass it on to super
             return super.performItemClick(v, position, id);
         }
-        
+
         // Internally handle the item click
         final int adjustedPosition = getFlatPositionForConnector(position);
         return handleItemClick(v, adjustedPosition, id);
     }
-    
+
     /**
      * This will either expand/collapse groups (if a group was clicked) or pass
      * on the click to the proper child (if a child was clicked)
-     * 
+     *
      * @param position The flat list position. This has already been factored to
      *            remove the header/footer.
      * @param id The ListAdapter ID, not the group or child ID.
      */
     boolean handleItemClick(View v, int position, long id) {
         final PositionMetadata posMetadata = mConnector.getUnflattenedPos(position);
-        
+
         id = getChildOrGroupId(posMetadata.position);
-        
+
         boolean returnValue;
         if (posMetadata.position.type == ExpandableListPosition.GROUP) {
             /* It's a group, so handle collapsing/expanding */
@@ -697,11 +697,11 @@
                 if (mOnGroupExpandListener != null) {
                     mOnGroupExpandListener.onGroupExpand(posMetadata.position.groupPos);
                 }
-                
+
                 final int groupPos = posMetadata.position.groupPos;
                 final int groupFlatPos = posMetadata.position.flatListPos;
 
-                final int shiftedGroupPosition = groupFlatPos + getHeaderViewsCount(); 
+                final int shiftedGroupPosition = groupFlatPos + getHeaderViewsCount();
                 smoothScrollToPosition(shiftedGroupPosition + mAdapter.getChildrenCount(groupPos),
                         shiftedGroupPosition);
             }
@@ -764,17 +764,17 @@
 
         return retValue;
     }
-    
+
     /**
      * Collapse a group in the grouped list view
-     * 
+     *
      * @param groupPos position of the group to collapse
      * @return True if the group was collapsed, false otherwise (if the group
      *         was already collapsed, this will return false)
      */
     public boolean collapseGroup(int groupPos) {
         boolean retValue = mConnector.collapseGroup(groupPos);
-        
+
         if (mOnGroupCollapseListener != null) {
             mOnGroupCollapseListener.onGroupCollapse(groupPos);
         }
@@ -787,14 +787,14 @@
         /**
          * Callback method to be invoked when a group in this expandable list has
          * been collapsed.
-         * 
+         *
          * @param groupPosition The group position that was collapsed
          */
         void onGroupCollapse(int groupPosition);
     }
-    
+
     private OnGroupCollapseListener mOnGroupCollapseListener;
-    
+
     public void setOnGroupCollapseListener(
             OnGroupCollapseListener onGroupCollapseListener) {
         mOnGroupCollapseListener = onGroupCollapseListener;
@@ -805,14 +805,14 @@
         /**
          * Callback method to be invoked when a group in this expandable list has
          * been expanded.
-         * 
+         *
          * @param groupPosition The group position that was expanded
          */
         void onGroupExpand(int groupPosition);
     }
-    
+
     private OnGroupExpandListener mOnGroupExpandListener;
-    
+
     public void setOnGroupExpandListener(
             OnGroupExpandListener onGroupExpandListener) {
         mOnGroupExpandListener = onGroupExpandListener;
@@ -826,7 +826,7 @@
         /**
          * Callback method to be invoked when a group in this expandable list has
          * been clicked.
-         * 
+         *
          * @param parent The ExpandableListConnector where the click happened
          * @param v The view within the expandable list/ListView that was clicked
          * @param groupPosition The group position that was clicked
@@ -836,13 +836,13 @@
         boolean onGroupClick(ExpandableListView parent, View v, int groupPosition,
                 long id);
     }
-    
+
     private OnGroupClickListener mOnGroupClickListener;
 
     public void setOnGroupClickListener(OnGroupClickListener onGroupClickListener) {
         mOnGroupClickListener = onGroupClickListener;
     }
-    
+
     /**
      * Interface definition for a callback to be invoked when a child in this
      * expandable list has been clicked.
@@ -851,7 +851,7 @@
         /**
          * Callback method to be invoked when a child in this expandable list has
          * been clicked.
-         * 
+         *
          * @param parent The ExpandableListView where the click happened
          * @param v The view within the expandable list/ListView that was clicked
          * @param groupPosition The group position that contains the child that
@@ -863,13 +863,13 @@
         boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
                 int childPosition, long id);
     }
-    
+
     private OnChildClickListener mOnChildClickListener;
 
     public void setOnChildClickListener(OnChildClickListener onChildClickListener) {
         mOnChildClickListener = onChildClickListener;
     }
-    
+
     /**
      * Converts a flat list position (the raw position of an item (child or group)
      * in the list) to a group and/or child position (represented in a
@@ -878,7 +878,7 @@
      * {@link ExpandableListView#getPackedPositionType} ,
      * {@link ExpandableListView#getPackedPositionChild},
      * {@link ExpandableListView#getPackedPositionGroup} to unpack.
-     * 
+     *
      * @param flatListPosition The flat list position to be converted.
      * @return The group and/or child position for the given flat list position
      *         in packed position representation. #PACKED_POSITION_VALUE_NULL if
@@ -895,12 +895,12 @@
         pm.recycle();
         return packedPos;
     }
-    
+
     /**
      * Converts a group and/or child position to a flat list position. This is
      * useful in situations where the caller needs to use the underlying
      * {@link ListView}'s methods.
-     * 
+     *
      * @param packedPosition The group and/or child positions to be converted in
      *            packed position representation. Use
      *            {@link #getPackedPositionForChild(int, int)} or
@@ -920,7 +920,7 @@
     /**
      * Gets the position of the currently selected group or child (along with
      * its type). Can return {@link #PACKED_POSITION_VALUE_NULL} if no selection.
-     * 
+     *
      * @return A packed position containing the currently selected group or
      *         child's position and type. #PACKED_POSITION_VALUE_NULL if no selection
      *         or if selection is on a header or a footer item.
@@ -931,11 +931,11 @@
         // The case where there is no selection (selectedPos == -1) is also handled here.
         return getExpandableListPosition(selectedPos);
     }
-    
+
     /**
      * Gets the ID of the currently selected group or child. Can return -1 if no
      * selection.
-     * 
+     *
      * @return The ID of the currently selected group or child. -1 if no
      *         selection.
      */
@@ -944,7 +944,7 @@
         if (packedPos == PACKED_POSITION_VALUE_NULL) return -1;
 
         int groupPos = getPackedPositionGroup(packedPos);
-        
+
         if (getPackedPositionType(packedPos) == PACKED_POSITION_TYPE_GROUP) {
             // It's a group
             return mAdapter.getGroupId(groupPos);
@@ -953,7 +953,7 @@
             return mAdapter.getChildId(groupPos, getPackedPositionChild(packedPos));
         }
     }
-    
+
     /**
      * Sets the selection to the specified group.
      * @param groupPosition The position of the group that should be selected.
@@ -967,12 +967,12 @@
         super.setSelection(absoluteFlatPosition);
         pm.recycle();
     }
-    
+
     /**
      * Sets the selection to the specified child. If the child is in a collapsed
      * group, the group will only be expanded and child subsequently selected if
      * shouldExpandGroup is set to true, otherwise the method will return false.
-     * 
+     *
      * @param groupPosition The position of the group that contains the child.
      * @param childPosition The position of the child within the group.
      * @param shouldExpandGroup Whether the child's group should be expanded if
@@ -981,48 +981,48 @@
      */
     public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) {
         ExpandableListPosition elChildPos = ExpandableListPosition.obtainChildPosition(
-                groupPosition, childPosition); 
+                groupPosition, childPosition);
         PositionMetadata flatChildPos = mConnector.getFlattenedPos(elChildPos);
-        
+
         if (flatChildPos == null) {
             // The child's group isn't expanded
-            
+
             // Shouldn't expand the group, so return false for we didn't set the selection
-            if (!shouldExpandGroup) return false; 
+            if (!shouldExpandGroup) return false;
 
             expandGroup(groupPosition);
-            
+
             flatChildPos = mConnector.getFlattenedPos(elChildPos);
-            
+
             // Sanity check
             if (flatChildPos == null) {
                 throw new IllegalStateException("Could not find child");
             }
         }
-        
+
         int absoluteFlatPosition = getAbsoluteFlatPosition(flatChildPos.position.flatListPos);
         super.setSelection(absoluteFlatPosition);
-        
+
         elChildPos.recycle();
         flatChildPos.recycle();
-        
+
         return true;
     }
 
     /**
      * Whether the given group is currently expanded.
-     * 
+     *
      * @param groupPosition The group to check.
      * @return Whether the group is currently expanded.
      */
     public boolean isGroupExpanded(int groupPosition) {
         return mConnector.isGroupExpanded(groupPosition);
     }
-    
+
     /**
      * Gets the type of a packed position. See
      * {@link #getPackedPositionForChild(int, int)}.
-     * 
+     *
      * @param packedPosition The packed position for which to return the type.
      * @return The type of the position contained within the packed position,
      *         either {@link #PACKED_POSITION_TYPE_CHILD}, {@link #PACKED_POSITION_TYPE_GROUP}, or
@@ -1032,7 +1032,7 @@
         if (packedPosition == PACKED_POSITION_VALUE_NULL) {
             return PACKED_POSITION_TYPE_NULL;
         }
-        
+
         return (packedPosition & PACKED_POSITION_MASK_TYPE) == PACKED_POSITION_MASK_TYPE
                 ? PACKED_POSITION_TYPE_CHILD
                 : PACKED_POSITION_TYPE_GROUP;
@@ -1041,7 +1041,7 @@
     /**
      * Gets the group position from a packed position. See
      * {@link #getPackedPositionForChild(int, int)}.
-     * 
+     *
      * @param packedPosition The packed position from which the group position
      *            will be returned.
      * @return The group position portion of the packed position. If this does
@@ -1050,7 +1050,7 @@
     public static int getPackedPositionGroup(long packedPosition) {
         // Null
         if (packedPosition == PACKED_POSITION_VALUE_NULL) return -1;
-        
+
         return (int) ((packedPosition & PACKED_POSITION_MASK_GROUP) >> PACKED_POSITION_SHIFT_GROUP);
     }
 
@@ -1060,7 +1060,7 @@
      * To get the group that this child belongs to, use
      * {@link #getPackedPositionGroup(long)}. See
      * {@link #getPackedPositionForChild(int, int)}.
-     * 
+     *
      * @param packedPosition The packed position from which the child position
      *            will be returned.
      * @return The child position portion of the packed position. If this does
@@ -1069,7 +1069,7 @@
     public static int getPackedPositionChild(long packedPosition) {
         // Null
         if (packedPosition == PACKED_POSITION_VALUE_NULL) return -1;
-        
+
         // Group since a group type clears this bit
         if ((packedPosition & PACKED_POSITION_MASK_TYPE) != PACKED_POSITION_MASK_TYPE) return -1;
 
@@ -1087,7 +1087,7 @@
      * {@link #getPackedPositionChild(long)},
      * {@link #getPackedPositionGroup(long)}, and
      * {@link #getPackedPositionType(long)}.
-     * 
+     *
      * @param groupPosition The child's parent group's position.
      * @param childPosition The child position within the group.
      * @return The packed position representation of the child (and parent group).
@@ -1096,20 +1096,20 @@
         return (((long)PACKED_POSITION_TYPE_CHILD) << PACKED_POSITION_SHIFT_TYPE)
                 | ((((long)groupPosition) & PACKED_POSITION_INT_MASK_GROUP)
                         << PACKED_POSITION_SHIFT_GROUP)
-                | (childPosition & PACKED_POSITION_INT_MASK_CHILD);  
+                | (childPosition & PACKED_POSITION_INT_MASK_CHILD);
     }
 
     /**
      * Returns the packed position representation of a group's position. See
      * {@link #getPackedPositionForChild(int, int)}.
-     * 
+     *
      * @param groupPosition The child's parent group's position.
      * @return The packed position representation of the group.
      */
     public static long getPackedPositionForGroup(int groupPosition) {
         // No need to OR a type in because PACKED_POSITION_GROUP == 0
         return ((((long)groupPosition) & PACKED_POSITION_INT_MASK_GROUP)
-                        << PACKED_POSITION_SHIFT_GROUP); 
+                        << PACKED_POSITION_SHIFT_GROUP);
     }
 
     @Override
@@ -1122,12 +1122,12 @@
         final int adjustedPosition = getFlatPositionForConnector(flatListPosition);
         PositionMetadata pm = mConnector.getUnflattenedPos(adjustedPosition);
         ExpandableListPosition pos = pm.position;
-        
+
         id = getChildOrGroupId(pos);
         long packedPosition = pos.getPackedPosition();
 
         pm.recycle();
-        
+
         return new ExpandableListContextMenuInfo(view, packedPosition, id);
     }
 
@@ -1135,7 +1135,7 @@
      * Gets the ID of the group or child at the given <code>position</code>.
      * This is useful since there is no ListAdapter ID -> ExpandableListAdapter
      * ID conversion mechanism (in some cases, it isn't possible).
-     * 
+     *
      * @param position The position of the child or group whose ID should be
      *            returned.
      */
@@ -1146,10 +1146,10 @@
             return mAdapter.getGroupId(position.groupPos);
         }
     }
-    
+
     /**
      * Sets the indicator to be drawn next to a child.
-     * 
+     *
      * @param childIndicator The drawable to be used as an indicator. If the
      *            child is the last child for a group, the state
      *            {@link android.R.attr#state_last} will be set.
@@ -1157,7 +1157,7 @@
     public void setChildIndicator(Drawable childIndicator) {
         mChildIndicator = childIndicator;
     }
-    
+
     /**
      * Sets the drawing bounds for the child indicator. For either, you can
      * specify {@link #CHILD_INDICATOR_INHERIT} to use inherit from the general
@@ -1194,7 +1194,7 @@
 
     /**
      * Sets the indicator to be drawn next to a group.
-     * 
+     *
      * @param groupIndicator The drawable to be used as an indicator. If the
      *            group is empty, the state {@link android.R.attr#state_empty} will be
      *            set. If the group is expanded, the state
@@ -1211,8 +1211,8 @@
      * Sets the drawing bounds for the indicators (at minimum, the group indicator
      * is affected by this; the child indicator is affected by this if the
      * child indicator bounds are set to inherit).
-     * 
-     * @see #setChildIndicatorBounds(int, int) 
+     *
+     * @see #setChildIndicatorBounds(int, int)
      * @param left The left position (relative to the left bounds of this View)
      *            to start drawing the indicator.
      * @param right The right position (relative to the left bounds of this
@@ -1248,13 +1248,13 @@
      * callback when a context menu is brought up for this AdapterView.
      */
     public static class ExpandableListContextMenuInfo implements ContextMenu.ContextMenuInfo {
-        
+
         public ExpandableListContextMenuInfo(View targetView, long packedPosition, long id) {
             this.targetView = targetView;
             this.packedPosition = packedPosition;
             this.id = id;
         }
-        
+
         /**
          * The view for which the context menu is being displayed. This
          * will be one of the children Views of this {@link ExpandableListView}.
@@ -1276,10 +1276,10 @@
          */
         public long id;
     }
-    
+
     static class SavedState extends BaseSavedState {
         ArrayList<ExpandableListConnector.GroupMetadata> expandedGroupMetadataList;
-        
+
         /**
          * Constructor called from {@link ExpandableListView#onSaveInstanceState()}
          */
@@ -1333,7 +1333,7 @@
 
         SavedState ss = (SavedState) state;
         super.onRestoreInstanceState(ss.getSuperState());
-        
+
         if (mConnector != null && ss.expandedGroupMetadataList != null) {
             mConnector.setExpandedGroupMetadataList(ss.expandedGroupMetadataList);
         }
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index b8c74d8..dc8ee01 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.AttrRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,6 +32,8 @@
 import android.view.ViewHierarchyEncoder;
 import android.widget.RemoteViews.RemoteView;
 
+import com.android.internal.R;
+
 import java.util.ArrayList;
 
 /**
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index af2852c..1c15c7a 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -16,6 +16,20 @@
 
 package android.widget;
 
+import static android.view.Gravity.AXIS_PULL_AFTER;
+import static android.view.Gravity.AXIS_PULL_BEFORE;
+import static android.view.Gravity.AXIS_SPECIFIED;
+import static android.view.Gravity.AXIS_X_SHIFT;
+import static android.view.Gravity.AXIS_Y_SHIFT;
+import static android.view.Gravity.HORIZONTAL_GRAVITY_MASK;
+import static android.view.Gravity.RELATIVE_LAYOUT_DIRECTION;
+import static android.view.Gravity.VERTICAL_GRAVITY_MASK;
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.makeMeasureSpec;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
 import android.annotation.IntDef;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -32,6 +46,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.RemoteViews.RemoteView;
+
 import com.android.internal.R;
 
 import java.lang.annotation.Retention;
@@ -43,12 +58,6 @@
 import java.util.List;
 import java.util.Map;
 
-import static android.view.Gravity.*;
-import static android.view.View.MeasureSpec.EXACTLY;
-import static android.view.View.MeasureSpec.makeMeasureSpec;
-import static java.lang.Math.max;
-import static java.lang.Math.min;
-
 /**
  * A layout that places its children in a rectangular <em>grid</em>.
  * <p>
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index b95aa52..20543fb 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -36,9 +36,9 @@
 import android.view.ViewRootImpl;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo;
+import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.animation.GridLayoutAnimationController;
 import android.widget.RemoteViews.RemoteView;
 
@@ -54,7 +54,7 @@
  *
  * <p>See the <a href="{@docRoot}guide/topics/ui/layout/gridview.html">Grid
  * View</a> guide.</p>
- * 
+ *
  * @attr ref android.R.styleable#GridView_horizontalSpacing
  * @attr ref android.R.styleable#GridView_verticalSpacing
  * @attr ref android.R.styleable#GridView_stretchMode
@@ -71,33 +71,33 @@
 
     /**
      * Disables stretching.
-     * 
-     * @see #setStretchMode(int) 
+     *
+     * @see #setStretchMode(int)
      */
     public static final int NO_STRETCH = 0;
     /**
      * Stretches the spacing between columns.
-     * 
-     * @see #setStretchMode(int) 
+     *
+     * @see #setStretchMode(int)
      */
     public static final int STRETCH_SPACING = 1;
     /**
      * Stretches columns.
-     * 
-     * @see #setStretchMode(int) 
+     *
+     * @see #setStretchMode(int)
      */
     public static final int STRETCH_COLUMN_WIDTH = 2;
     /**
      * Stretches the spacing between columns. The spacing is uniform.
-     * 
-     * @see #setStretchMode(int) 
+     *
+     * @see #setStretchMode(int)
      */
     public static final int STRETCH_SPACING_UNIFORM = 3;
 
     /**
      * Creates as many columns as can fit on screen.
-     * 
-     * @see #setNumColumns(int) 
+     *
+     * @see #setNumColumns(int)
      */
     public static final int AUTO_FIT = -1;
 
@@ -161,7 +161,7 @@
         if (index >= 0) {
             setGravity(index);
         }
-        
+
         a.recycle();
     }
 
@@ -192,7 +192,7 @@
         }
 
         resetList();
-        mRecycler.clear();        
+        mRecycler.clear();
         mAdapter = adapter;
 
         mOldSelectedPosition = INVALID_POSITION;
@@ -222,7 +222,7 @@
             setNextSelectedPositionInt(position);
             checkSelectionChanged();
         } else {
-            checkFocus();            
+            checkFocus();
             // Nothing selected
             checkSelectionChanged();
         }
@@ -376,7 +376,7 @@
         }
 
         mReferenceView = child;
-        
+
         if (selectedView != null) {
             mReferenceViewInSelectedRow = mReferenceView;
         }
@@ -515,7 +515,7 @@
                 offsetChildrenTopAndBottom(offset);
             }
         }
-    }    
+    }
 
     @Override
     int findMotionRow(int y) {
@@ -624,7 +624,7 @@
 
             // This is how far the bottom edge of the last view is from the bottom of the
             // drawable area
-            int bottomOffset = end - lastBottom;        
+            int bottomOffset = end - lastBottom;
 
             final View firstChild = getChildAt(0);
             final int firstTop = firstChild.getTop();
@@ -636,7 +636,7 @@
                     // Don't pull the top too far down
                     bottomOffset = Math.min(bottomOffset, mListPadding.top - firstTop);
                 }
-                
+
                 // Move everything down
                 offsetChildrenTopAndBottom(bottomOffset);
                 if (mFirstPosition > 0) {
@@ -679,7 +679,7 @@
                     // Don't pull the bottom too far up
                     topOffset = Math.min(topOffset, lastBottom - end);
                 }
-                
+
                 // Move everything up
                 offsetChildrenTopAndBottom(-topOffset);
                 if (lastPosition < mItemCount - 1) {
@@ -965,7 +965,7 @@
         final int stretchMode = mStretchMode;
         final int requestedColumnWidth = mRequestedColumnWidth;
         boolean didNotInitiallyFit = false;
-        
+
         if (mRequestedNumColumns == AUTO_FIT) {
             if (requestedColumnWidth > 0) {
                 // Client told us to pick the number of columns
@@ -979,57 +979,57 @@
             // We picked the columns
             mNumColumns = mRequestedNumColumns;
         }
-        
+
         if (mNumColumns <= 0) {
             mNumColumns = 1;
         }
 
         switch (stretchMode) {
-        case NO_STRETCH:
-            // Nobody stretches
-            mColumnWidth = requestedColumnWidth;
-            mHorizontalSpacing = requestedHorizontalSpacing;
-            break;
-
-        default:
-            int spaceLeftOver = availableSpace - (mNumColumns * requestedColumnWidth) -
-                    ((mNumColumns - 1) * requestedHorizontalSpacing);
-
-            if (spaceLeftOver < 0) {
-                didNotInitiallyFit = true;
-            }
-
-            switch (stretchMode) {
-            case STRETCH_COLUMN_WIDTH:
-                // Stretch the columns
-                mColumnWidth = requestedColumnWidth + spaceLeftOver / mNumColumns;
+            case NO_STRETCH:
+                // Nobody stretches
+                mColumnWidth = requestedColumnWidth;
                 mHorizontalSpacing = requestedHorizontalSpacing;
                 break;
 
-            case STRETCH_SPACING:
-                // Stretch the spacing between columns
-                mColumnWidth = requestedColumnWidth;
-                if (mNumColumns > 1) {
-                    mHorizontalSpacing = requestedHorizontalSpacing + 
-                        spaceLeftOver / (mNumColumns - 1);
-                } else {
-                    mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver;
-                }
-                break;
+            default:
+                int spaceLeftOver = availableSpace - (mNumColumns * requestedColumnWidth)
+                        - ((mNumColumns - 1) * requestedHorizontalSpacing);
 
-            case STRETCH_SPACING_UNIFORM:
-                // Stretch the spacing between columns
-                mColumnWidth = requestedColumnWidth;
-                if (mNumColumns > 1) {
-                    mHorizontalSpacing = requestedHorizontalSpacing + 
-                        spaceLeftOver / (mNumColumns + 1);
-                } else {
-                    mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver;
+                if (spaceLeftOver < 0) {
+                    didNotInitiallyFit = true;
                 }
-                break;
-            }
 
-            break;
+                switch (stretchMode) {
+                    case STRETCH_COLUMN_WIDTH:
+                        // Stretch the columns
+                        mColumnWidth = requestedColumnWidth + spaceLeftOver / mNumColumns;
+                        mHorizontalSpacing = requestedHorizontalSpacing;
+                        break;
+
+                    case STRETCH_SPACING:
+                        // Stretch the spacing between columns
+                        mColumnWidth = requestedColumnWidth;
+                        if (mNumColumns > 1) {
+                            mHorizontalSpacing = requestedHorizontalSpacing
+                                    + spaceLeftOver / (mNumColumns - 1);
+                        } else {
+                            mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver;
+                        }
+                        break;
+
+                    case STRETCH_SPACING_UNIFORM:
+                        // Stretch the spacing between columns
+                        mColumnWidth = requestedColumnWidth;
+                        if (mNumColumns > 1) {
+                            mHorizontalSpacing = requestedHorizontalSpacing
+                                    + spaceLeftOver / (mNumColumns + 1);
+                        } else {
+                            mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver;
+                        }
+                        break;
+                }
+
+                break;
         }
         return didNotInitiallyFit;
     }
@@ -1052,7 +1052,7 @@
             }
             widthSize += getVerticalScrollbarWidth();
         }
-        
+
         int childWidth = widthSize - mListPadding.left - mListPadding.right;
         boolean didNotInitiallyFit = determineColumns(childWidth);
 
@@ -1087,7 +1087,7 @@
                 mRecycler.addScrapView(child, -1);
             }
         }
-        
+
         if (heightMode == MeasureSpec.UNSPECIFIED) {
             heightSize = mListPadding.top + mListPadding.bottom + childHeight +
                     getVerticalFadingEdgeLength() * 2;
@@ -1095,7 +1095,7 @@
 
         if (heightMode == MeasureSpec.AT_MOST) {
             int ourSize =  mListPadding.top + mListPadding.bottom;
-           
+
             final int numColumns = mNumColumns;
             for (int i = 0; i < count; i += numColumns) {
                 ourSize += childHeight;
@@ -1574,9 +1574,9 @@
 
     /**
      * Sets the currently selected item
-     * 
+     *
      * @param position Index (starting at 0) of the data item to be selected.
-     * 
+     *
      * If in touch mode, the item will not be selected but it will still be positioned
      * appropriately.
      */
@@ -1609,8 +1609,8 @@
 
         setNextSelectedPositionInt(position);
         layoutChildren();
-        
-        final int next = mStackFromBottom ? mItemCount - 1  - mNextSelectedPosition : 
+
+        final int next = mStackFromBottom ? mItemCount - 1  - mNextSelectedPosition :
             mNextSelectedPosition;
         final int previous = mStackFromBottom ? mItemCount - 1
                 - previousSelectedPosition : previousSelectedPosition;
@@ -1802,7 +1802,7 @@
             invokeOnItemScrollListener();
             moved = true;
         }
-        
+
         if (moved) {
             awakenScrollBars();
         }
@@ -1874,7 +1874,7 @@
         if (moved) {
             awakenScrollBars();
         }
-        
+
         return moved;
     }
 
@@ -2216,17 +2216,17 @@
             requestLayoutIfNecessary();
         }
     }
-    
+
     /**
-     * Get the number of columns in the grid. 
+     * Get the number of columns in the grid.
      * Returns {@link #AUTO_FIT} if the Grid has never been laid out.
      *
      * @attr ref android.R.styleable#GridView_numColumns
-     * 
+     *
      * @see #setNumColumns(int)
      */
     @ViewDebug.ExportedProperty
-    public int getNumColumns() {  
+    public int getNumColumns() {
         return mNumColumns;
     }
 
@@ -2259,13 +2259,13 @@
                 // we are too high, slide all views down to align with bottom
                 child = getChildAt(childCount - 1);
                 delta = child.getBottom() - (getHeight() - mListPadding.bottom);
-                
+
                 if (mFirstPosition + childCount < mItemCount) {
                     // It's OK to have some space below the last item if it is
                     // part of the vertical spacing
                     delta += mVerticalSpacing;
                 }
-                
+
                 if (delta > 0) {
                     // We only are looking to see if we are too high, not too low
                     delta = 0;
@@ -2277,14 +2277,14 @@
             }
         }
     }
-    
+
     @Override
     protected int computeVerticalScrollExtent() {
         final int count = getChildCount();
         if (count > 0) {
             final int numColumns = mNumColumns;
             final int rowCount = (count + numColumns - 1) / numColumns;
-            
+
             int extent = rowCount * 100;
 
             View view = getChildAt(0);
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index d9cb269..4d405c5 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -467,6 +467,14 @@
      * {@link #setImageBitmap(android.graphics.Bitmap)} and
      * {@link android.graphics.BitmapFactory} instead.</p>
      *
+     * <p class="note">On devices running SDK < 24, this method will fail to
+     * apply correct density scaling to images loaded from
+     * {@link ContentResolver#SCHEME_CONTENT content} and
+     * {@link ContentResolver#SCHEME_FILE file} schemes. Applications running
+     * on devices with SDK >= 24 <strong>MUST</strong> specify the
+     * {@code targetSdkVersion} in their manifest as 24 or above for density
+     * scaling to be applied to images loaded from these schemes.</p>
+     *
      * @param uri the Uri of an image, or {@code null} to clear the content
      */
     @android.view.RemotableViewMethod(asyncImpl="setImageURIAsync")
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 6511de8..544e591 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,15 +32,17 @@
 import android.view.ViewHierarchyEncoder;
 import android.widget.RemoteViews.RemoteView;
 
+import com.android.internal.R;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 
 /**
- * A Layout that arranges its children in a single column or a single row. The direction of 
- * the row can be set by calling {@link #setOrientation(int) setOrientation()}. 
+ * A Layout that arranges its children in a single column or a single row. The direction of
+ * the row can be set by calling {@link #setOrientation(int) setOrientation()}.
  * You can also specify gravity, which specifies the alignment of all the child elements by
- * calling {@link #setGravity(int) setGravity()} or specify that specific children 
+ * calling {@link #setGravity(int) setGravity()} or specify that specific children
  * grow to fill up any remaining space in the layout by setting the <em>weight</em> member of
  * {@link android.widget.LinearLayout.LayoutParams LinearLayout.LayoutParams}.
  * The default orientation is horizontal.
@@ -202,7 +202,7 @@
     public LinearLayout(Context context, @Nullable AttributeSet attrs) {
         this(context, attrs, 0);
     }
-    
+
     public LinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         this(context, attrs, defStyleAttr, 0);
     }
@@ -497,7 +497,7 @@
      * When true, all children with a weight will be considered having
      * the minimum size of the largest child. If false, all children are
      * measured normally.
-     * 
+     *
      * @return True to measure children with a weight using the minimum
      *         size of the largest child, false otherwise.
      *
@@ -511,9 +511,9 @@
      * When set to true, all children with a weight will be considered having
      * the minimum size of the largest child. If false, all children are
      * measured normally.
-     * 
+     *
      * Disabled by default.
-     * 
+     *
      * @param enabled True to measure children with a weight using the
      *        minimum size of the largest child, false otherwise.
      *
@@ -589,7 +589,7 @@
     /**
      * @param i The index of the child that will be used if this layout is
      *          part of a larger layout that is baseline aligned.
-     * 
+     *
      * @attr ref android.R.styleable#LinearLayout_baselineAlignedChildIndex
      */
     @android.view.RemotableViewMethod
@@ -720,14 +720,14 @@
         float totalWeight = 0;
 
         final int count = getVirtualChildCount();
-        
+
         final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
         final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 
         boolean matchWidth = false;
         boolean skippedMeasure = false;
 
-        final int baselineChildIndex = mBaselineAlignedChildIndex;        
+        final int baselineChildIndex = mBaselineAlignedChildIndex;
         final boolean useLargestChild = mUseLargestChild;
 
         int largestChildHeight = Integer.MIN_VALUE;
@@ -886,7 +886,7 @@
 
         // Check against our minimum height
         heightSize = Math.max(heightSize, getSuggestedMinimumHeight());
-        
+
         // Reconcile our calculated size with the heightMeasureSpec
         int heightSizeAndState = resolveSizeAndState(heightSize, heightMeasureSpec, 0);
         heightSize = heightSizeAndState & MEASURED_SIZE_MASK;
@@ -991,12 +991,12 @@
         if (!allFillParent && widthMode != MeasureSpec.EXACTLY) {
             maxWidth = alternativeMaxWidth;
         }
-        
+
         maxWidth += mPaddingLeft + mPaddingRight;
 
         // Check against our minimum width
         maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
-        
+
         setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
                 heightSizeAndState);
 
@@ -1013,13 +1013,13 @@
            final View child = getVirtualChildAt(i);
            if (child != null && child.getVisibility() != GONE) {
                LinearLayout.LayoutParams lp = ((LinearLayout.LayoutParams)child.getLayoutParams());
-               
+
                if (lp.width == LayoutParams.MATCH_PARENT) {
                    // Temporarily force children to reuse their old measured height
                    // FIXME: this may not be right for something like wrapping text?
                    int oldHeight = lp.height;
                    lp.height = child.getMeasuredHeight();
-                   
+
                    // Remeasue with new dimensions
                    measureChildWithMargins(child, uniformMeasureSpec, 0, heightMeasureSpec, 0);
                    lp.height = oldHeight;
@@ -1037,7 +1037,7 @@
      *
      * @see #getOrientation()
      * @see #setOrientation(int)
-     * @see #onMeasure(int, int) 
+     * @see #onMeasure(int, int)
      */
     void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
         mTotalLength = 0;
@@ -1049,7 +1049,7 @@
         float totalWeight = 0;
 
         final int count = getVirtualChildCount();
-        
+
         final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
         final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 
@@ -1069,7 +1069,7 @@
 
         final boolean baselineAligned = mBaselineAligned;
         final boolean useLargestChild = mUseLargestChild;
-        
+
         final boolean isExactly = widthMode == MeasureSpec.EXACTLY;
 
         int largestChildWidth = Integer.MIN_VALUE;
@@ -1084,7 +1084,7 @@
                 mTotalLength += measureNullChild(i);
                 continue;
             }
-           
+
             if (child.getVisibility() == GONE) {
                 i += getChildrenSkipCount(child, i);
                 continue;
@@ -1263,16 +1263,16 @@
 
         // Add in our padding
         mTotalLength += mPaddingLeft + mPaddingRight;
-        
+
         int widthSize = mTotalLength;
-        
+
         // Check against our minimum width
         widthSize = Math.max(widthSize, getSuggestedMinimumWidth());
-        
+
         // Reconcile our calculated size with the widthMeasureSpec
         int widthSizeAndState = resolveSizeAndState(widthSize, widthMeasureSpec, 0);
         widthSize = widthSizeAndState & MEASURED_SIZE_MASK;
-        
+
         // Either expand children with weight to take up available space or
         // shrink them if they extend beyond our current bounds. If we skipped
         // measurement on any children, we need to measure them now.
@@ -1409,12 +1409,12 @@
         if (!allFillParent && heightMode != MeasureSpec.EXACTLY) {
             maxHeight = alternativeMaxHeight;
         }
-        
+
         maxHeight += mPaddingTop + mPaddingBottom;
 
         // Check against our minimum height
         maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
-        
+
         setMeasuredDimension(widthSizeAndState | (childState&MEASURED_STATE_MASK),
                 resolveSizeAndState(maxHeight, heightMeasureSpec,
                         (childState<<MEASURED_HEIGHT_STATE_SHIFT)));
@@ -1434,13 +1434,13 @@
            final View child = getVirtualChildAt(i);
            if (child != null && child.getVisibility() != GONE) {
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
-               
+
                if (lp.height == LayoutParams.MATCH_PARENT) {
                    // Temporarily force children to reuse their old measured width
                    // FIXME: this may not be right for something like wrapping text?
                    int oldWidth = lp.width;
                    lp.width = child.getMeasuredWidth();
-                   
+
                    // Remeasure with new dimensions
                    measureChildWithMargins(child, widthMeasureSpec, 0, uniformMeasureSpec, 0);
                    lp.width = oldWidth;
@@ -1541,14 +1541,14 @@
 
         int childTop;
         int childLeft;
-        
+
         // Where right end of child should go
         final int width = right - left;
         int childRight = width - mPaddingRight;
-        
+
         // Space available for child
         int childSpace = width - paddingLeft - mPaddingRight;
-        
+
         final int count = getVirtualChildCount();
 
         final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
@@ -1578,10 +1578,10 @@
             } else if (child.getVisibility() != GONE) {
                 final int childWidth = child.getMeasuredWidth();
                 final int childHeight = child.getMeasuredHeight();
-                
+
                 final LinearLayout.LayoutParams lp =
                         (LinearLayout.LayoutParams) child.getLayoutParams();
-                
+
                 int gravity = lp.gravity;
                 if (gravity < 0) {
                     gravity = minorGravity;
@@ -1647,11 +1647,11 @@
 
         int childTop;
         int childLeft;
-        
+
         // Where bottom of child should go
         final int height = bottom - top;
-        int childBottom = height - mPaddingBottom; 
-        
+        int childBottom = height - mPaddingBottom;
+
         // Space available for child
         int childSpace = height - paddingTop - mPaddingBottom;
 
@@ -1707,12 +1707,12 @@
                 if (baselineAligned && lp.height != LayoutParams.MATCH_PARENT) {
                     childBaseline = child.getBaseline();
                 }
-                
+
                 int gravity = lp.gravity;
                 if (gravity < 0) {
                     gravity = minorGravity;
                 }
-                
+
                 switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
                     case Gravity.TOP:
                         childTop = paddingTop + lp.topMargin;
@@ -1764,15 +1764,15 @@
         }
     }
 
-    private void setChildFrame(View child, int left, int top, int width, int height) {        
+    private void setChildFrame(View child, int left, int top, int width, int height) {
         child.layout(left, top, left + width, top + height);
     }
-    
+
     /**
      * Should the layout be a column or a row.
      * @param orientation Pass {@link #HORIZONTAL} or {@link #VERTICAL}. Default
      * value is {@link #HORIZONTAL}.
-     * 
+     *
      * @attr ref android.R.styleable#LinearLayout_orientation
      */
     public void setOrientation(@OrientationMode int orientation) {
@@ -1784,7 +1784,7 @@
 
     /**
      * Returns the current orientation.
-     * 
+     *
      * @return either {@link #HORIZONTAL} or {@link #VERTICAL}
      */
     @OrientationMode
@@ -1797,9 +1797,9 @@
      * this layout has a VERTICAL orientation, this controls where all the child
      * views are placed if there is extra vertical space. If this layout has a
      * HORIZONTAL orientation, this controls the alignment of the children.
-     * 
+     *
      * @param gravity See {@link android.view.Gravity}
-     * 
+     *
      * @attr ref android.R.styleable#LinearLayout_gravity
      */
     @android.view.RemotableViewMethod
@@ -1845,7 +1845,7 @@
             requestLayout();
         }
     }
-    
+
     @Override
     public LayoutParams generateLayoutParams(AttributeSet attrs) {
         return new LinearLayout.LayoutParams(getContext(), attrs);
@@ -1909,7 +1909,7 @@
 
     /**
      * Per-child layout information associated with ViewLinearLayout.
-     * 
+     *
      * @attr ref android.R.styleable#LinearLayout_Layout_layout_weight
      * @attr ref android.R.styleable#LinearLayout_Layout_layout_gravity
      */
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 6a10743..0bde983 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -16,9 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-import com.android.internal.view.menu.ShowableListMenu;
-
 import android.annotation.AttrRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -42,14 +39,17 @@
 import android.view.WindowManager;
 import android.widget.AdapterView.OnItemSelectedListener;
 
+import com.android.internal.R;
+import com.android.internal.view.menu.ShowableListMenu;
+
 /**
  * A ListPopupWindow anchors itself to a host view and displays a
  * list of choices.
- * 
+ *
  * <p>ListPopupWindow contains a number of tricky behaviors surrounding
  * positioning, scrolling parents to fit the dropdown, interacting
  * sanely with the IME if present, and others.
- * 
+ *
  * @see android.widget.AutoCompleteTextView
  * @see android.widget.Spinner
  */
@@ -116,7 +116,7 @@
 
     /**
      * The provided prompt view should appear above list content.
-     * 
+     *
      * @see #setPromptPosition(int)
      * @see #getPromptPosition()
      * @see #setPromptView(View)
@@ -125,7 +125,7 @@
 
     /**
      * The provided prompt view should appear below list content.
-     * 
+     *
      * @see #setPromptPosition(int)
      * @see #getPromptPosition()
      * @see #setPromptView(View)
@@ -138,13 +138,13 @@
      * If used to specify a popup height, the popup will fill available space.
      */
     public static final int MATCH_PARENT = ViewGroup.LayoutParams.MATCH_PARENT;
-    
+
     /**
      * Alias for {@link ViewGroup.LayoutParams#WRAP_CONTENT}.
      * If used to specify a popup width, the popup will use the width of its content.
      */
     public static final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT;
-    
+
     /**
      * Mode for {@link #setInputMethodMode(int)}: the requirements for the
      * input method should be based on the focusability of the popup.  That is
@@ -152,7 +152,7 @@
      * it doesn't.
      */
     public static final int INPUT_METHOD_FROM_FOCUSABLE = PopupWindow.INPUT_METHOD_FROM_FOCUSABLE;
-    
+
     /**
      * Mode for {@link #setInputMethodMode(int)}: this popup always needs to
      * work with an input method, regardless of whether it is focusable.  This
@@ -160,7 +160,7 @@
      * the input method while it is shown.
      */
     public static final int INPUT_METHOD_NEEDED = PopupWindow.INPUT_METHOD_NEEDED;
-    
+
     /**
      * Mode for {@link #setInputMethodMode(int)}: this popup never needs to
      * work with an input method, regardless of whether it is focusable.  This
@@ -172,7 +172,7 @@
     /**
      * Create a new, empty popup window capable of displaying items from a ListAdapter.
      * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
-     * 
+     *
      * @param context Context used for contained views.
      */
     public ListPopupWindow(@NonNull Context context) {
@@ -182,7 +182,7 @@
     /**
      * Create a new, empty popup window capable of displaying items from a ListAdapter.
      * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
-     * 
+     *
      * @param context Context used for contained views.
      * @param attrs Attributes from inflating parent views used to style the popup.
      */
@@ -193,7 +193,7 @@
     /**
      * Create a new, empty popup window capable of displaying items from a ListAdapter.
      * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
-     * 
+     *
      * @param context Context used for contained views.
      * @param attrs Attributes from inflating parent views used to style the popup.
      * @param defStyleAttr Default style attribute to use for popup content.
@@ -206,7 +206,7 @@
     /**
      * Create a new, empty popup window capable of displaying items from a ListAdapter.
      * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
-     * 
+     *
      * @param context Context used for contained views.
      * @param attrs Attributes from inflating parent views used to style the popup.
      * @param defStyleAttr Style attribute to read for default styling of popup content.
@@ -248,7 +248,7 @@
         if (mAdapter != null) {
             adapter.registerDataSetObserver(mObserver);
         }
-        
+
         if (mDropDownList != null) {
             mDropDownList.setAdapter(mAdapter);
         }
@@ -257,9 +257,9 @@
     /**
      * Set where the optional prompt view should appear. The default is
      * {@link #POSITION_PROMPT_ABOVE}.
-     * 
+     *
      * @param position A position constant declaring where the prompt should be displayed.
-     * 
+     *
      * @see #POSITION_PROMPT_ABOVE
      * @see #POSITION_PROMPT_BELOW
      */
@@ -269,7 +269,7 @@
 
     /**
      * @return Where the optional prompt view should appear.
-     * 
+     *
      * @see #POSITION_PROMPT_ABOVE
      * @see #POSITION_PROMPT_BELOW
      */
@@ -279,11 +279,11 @@
 
     /**
      * Set whether this window should be modal when shown.
-     * 
+     *
      * <p>If a popup window is modal, it will receive all touch and key input.
      * If the user touches outside the popup window's content area the popup window
      * will be dismissed.
-     * 
+     *
      * @param modal {@code true} if the popup window should be modal, {@code false} otherwise.
      */
     public void setModal(boolean modal) {
@@ -293,7 +293,7 @@
 
     /**
      * Returns whether the popup window will be modal when shown.
-     * 
+     *
      * @return {@code true} if the popup window will be modal, {@code false} otherwise.
      */
     public boolean isModal() {
@@ -304,7 +304,7 @@
      * Forces outside touches to be ignored. Normally if {@link #isDropDownAlwaysVisible()} is
      * false, we allow outside touch to dismiss the dropdown. If this is set to true, then we
      * ignore outside touch even when the drop down is not set to always visible.
-     * 
+     *
      * @hide Used only by AutoCompleteTextView to handle some internal special cases.
      */
     public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) {
@@ -361,7 +361,7 @@
 
     /**
      * Sets a drawable to use as the list item selector.
-     * 
+     *
      * @param selector List selector drawable to use in the popup.
      */
     public void setListSelector(Drawable selector) {
@@ -377,7 +377,7 @@
 
     /**
      * Sets a drawable to be the background for the popup window.
-     * 
+     *
      * @param d A drawable to set as the background.
      */
     public void setBackgroundDrawable(@Nullable Drawable d) {
@@ -386,7 +386,7 @@
 
     /**
      * Set an animation style to use when the popup window is shown or dismissed.
-     * 
+     *
      * @param animationStyle Animation style to use.
      */
     public void setAnimationStyle(@StyleRes int animationStyle) {
@@ -396,7 +396,7 @@
     /**
      * Returns the animation style that will be used when the popup window is
      * shown or dismissed.
-     * 
+     *
      * @return Animation style that will be used.
      */
     public @StyleRes int getAnimationStyle() {
@@ -405,7 +405,7 @@
 
     /**
      * Returns the view that will be used to anchor this popup.
-     * 
+     *
      * @return The popup's anchor view
      */
     public @Nullable View getAnchorView() {
@@ -415,7 +415,7 @@
     /**
      * Sets the popup's anchor view. This popup will always be positioned relative to
      * the anchor view when shown.
-     * 
+     *
      * @param anchor The view to use as an anchor.
      */
     public void setAnchorView(@Nullable View anchor) {
@@ -431,7 +431,7 @@
 
     /**
      * Set the horizontal offset of this popup from its anchor view in pixels.
-     * 
+     *
      * @param offset The horizontal offset of the popup from its anchor.
      */
     public void setHorizontalOffset(int offset) {
@@ -450,7 +450,7 @@
 
     /**
      * Set the vertical offset of this popup from its anchor view in pixels.
-     * 
+     *
      * @param offset The vertical offset of the popup from its anchor.
      */
     public void setVerticalOffset(int offset) {
@@ -489,7 +489,7 @@
     /**
      * Sets the width of the popup window in pixels. Can also be {@link #MATCH_PARENT}
      * or {@link #WRAP_CONTENT}.
-     * 
+     *
      * @param width Width of the popup window.
      */
     public void setWidth(int width) {
@@ -521,7 +521,7 @@
 
     /**
      * Sets the height of the popup window in pixels. Can also be {@link #MATCH_PARENT}.
-     * 
+     *
      * @param height Height of the popup window.
      */
     public void setHeight(int height) {
@@ -543,9 +543,9 @@
 
     /**
      * Sets a listener to receive events when a list item is clicked.
-     * 
+     *
      * @param clickListener Listener to register
-     * 
+     *
      * @see ListView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener)
      */
     public void setOnItemClickListener(@Nullable AdapterView.OnItemClickListener clickListener) {
@@ -554,9 +554,9 @@
 
     /**
      * Sets a listener to receive events when a list item is selected.
-     * 
+     *
      * @param selectedListener Listener to register.
-     * 
+     *
      * @see ListView#setOnItemSelectedListener(OnItemSelectedListener)
      */
     public void setOnItemSelectedListener(@Nullable OnItemSelectedListener selectedListener) {
@@ -566,7 +566,7 @@
     /**
      * Set a view to act as a user prompt for this popup window. Where the prompt view will appear
      * is controlled by {@link #setPromptPosition(int)}.
-     * 
+     *
      * @param prompt View to use as an informational prompt.
      */
     public void setPromptView(@Nullable View prompt) {
@@ -662,7 +662,7 @@
             mPopup.setWidth(widthSpec);
             mPopup.setHeight(heightSpec);
             mPopup.setClipToScreenEnabled(true);
-            
+
             // use outside touchable to dismiss drop down when touching outside of it, so
             // only set this if the dropdown is not always visible
             mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
@@ -671,7 +671,7 @@
             mPopup.showAsDropDown(getAnchorView(), mDropDownHorizontalOffset,
                     mDropDownVerticalOffset, mDropDownGravity);
             mDropDownList.setSelection(ListView.INVALID_POSITION);
-            
+
             if (!mModal || mDropDownList.isInTouchMode()) {
                 clearListSelection();
             }
@@ -716,11 +716,11 @@
      * Control how the popup operates with an input method: one of
      * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED},
      * or {@link #INPUT_METHOD_NOT_NEEDED}.
-     * 
+     *
      * <p>If the popup is showing, calling this method will take effect only
      * the next time the popup is shown or through a manual call to the {@link #show()}
      * method.</p>
-     * 
+     *
      * @see #getInputMethodMode()
      * @see #show()
      */
@@ -730,7 +730,7 @@
 
     /**
      * Return the current value in {@link #setInputMethodMode(int)}.
-     * 
+     *
      * @see #setInputMethodMode(int)
      */
     public int getInputMethodMode() {
@@ -740,7 +740,7 @@
     /**
      * Set the selected position of the list.
      * Only valid when {@link #isShowing()} == {@code true}.
-     * 
+     *
      * @param position List position to set as selected.
      */
     public void setSelection(int position) {
@@ -786,7 +786,7 @@
 
     /**
      * Perform an item click operation on the specified list adapter position.
-     * 
+     *
      * @param position Adapter position for performing the click
      * @return true if the click action could be performed, false if not.
      *         (e.g. if the popup was not showing, this method would return false.)
@@ -817,7 +817,7 @@
     /**
      * @return The position of the currently selected item or {@link ListView#INVALID_POSITION}
      * if {@link #isShowing()} == {@code false}.
-     * 
+     *
      * @see ListView#getSelectedItemPosition()
      */
     public int getSelectedItemPosition() {
@@ -830,7 +830,7 @@
     /**
      * @return The ID of the currently selected item or {@link ListView#INVALID_ROW_ID}
      * if {@link #isShowing()} == {@code false}.
-     * 
+     *
      * @see ListView#getSelectedItemId()
      */
     public long getSelectedItemId() {
@@ -843,7 +843,7 @@
     /**
      * @return The View for the currently selected item or null if
      * {@link #isShowing()} == {@code false}.
-     * 
+     *
      * @see ListView#getSelectedView()
      */
     public @Nullable View getSelectedView() {
@@ -904,7 +904,7 @@
                 final boolean below = !mPopup.isAboveAnchor();
 
                 final ListAdapter adapter = mAdapter;
-                
+
                 boolean allEnabled;
                 int firstItem = Integer.MAX_VALUE;
                 int lastItem = Integer.MIN_VALUE;
@@ -914,9 +914,9 @@
                     firstItem = allEnabled ? 0 :
                             mDropDownList.lookForSelectablePosition(0, true);
                     lastItem = allEnabled ? adapter.getCount() - 1 :
-                            mDropDownList.lookForSelectablePosition(adapter.getCount() - 1, false);                    
+                            mDropDownList.lookForSelectablePosition(adapter.getCount() - 1, false);
                 }
-                
+
                 if ((below && keyCode == KeyEvent.KEYCODE_DPAD_UP && curIndex <= firstItem) ||
                         (!below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN && curIndex >= lastItem)) {
                     // When the selection is at the top, we block the key
@@ -1132,18 +1132,18 @@
                 LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams(
                         ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f
                 );
-                
+
                 switch (mPromptPosition) {
                 case POSITION_PROMPT_BELOW:
                     hintContainer.addView(dropDownView, hintParams);
                     hintContainer.addView(hintView);
                     break;
-                    
+
                 case POSITION_PROMPT_ABOVE:
                     hintContainer.addView(hintView);
                     hintContainer.addView(dropDownView, hintParams);
                     break;
-                    
+
                 default:
                     Log.e(TAG, "Invalid hint position " + mPromptPosition);
                     break;
@@ -1249,7 +1249,7 @@
                 show();
             }
         }
-        
+
         @Override
         public void onInvalidated() {
             dismiss();
@@ -1278,7 +1278,7 @@
             final int action = event.getAction();
             final int x = (int) event.getX();
             final int y = (int) event.getY();
-            
+
             if (action == MotionEvent.ACTION_DOWN &&
                     mPopup != null && mPopup.isShowing() &&
                     (x >= 0 && x < mPopup.getWidth() && y >= 0 && y < mPopup.getHeight())) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index b0f19d7..e88c7ef 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -16,11 +16,6 @@
 
 package android.widget;
 
-import com.google.android.collect.Lists;
-
-import com.android.internal.R;
-import com.android.internal.util.Predicate;
-
 import android.annotation.IdRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -53,6 +48,11 @@
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.widget.RemoteViews.RemoteView;
 
+import com.android.internal.R;
+import com.android.internal.util.Predicate;
+
+import com.google.android.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -464,7 +464,7 @@
      *        data backing this list and for producing a view to represent an
      *        item in that data set.
      *
-     * @see #getAdapter() 
+     * @see #getAdapter()
      */
     @Override
     public void setAdapter(ListAdapter adapter) {
@@ -1532,7 +1532,7 @@
                         adjustViewsUpOrDown();
                     }
                 } else if (lastPosition == mItemCount - 1) {
-                    adjustViewsUpOrDown();                    
+                    adjustViewsUpOrDown();
                 }
             }
         }
@@ -1857,7 +1857,7 @@
                     && focusLayoutRestoreView.getWindowToken() != null) {
                 focusLayoutRestoreView.dispatchFinishTemporaryDetach();
             }
-            
+
             mLayoutMode = LAYOUT_NORMAL;
             mDataChanged = false;
             if (mPositionScrollAfterLayout != null) {
@@ -2109,7 +2109,7 @@
 
     /**
      * Makes the item at the supplied position selected.
-     * 
+     *
      * @param position the position of the item to select
      */
     @Override
@@ -2960,7 +2960,7 @@
             if (startPos < firstPosition) {
                 startPos = firstPosition;
             }
-            
+
             final int lastVisiblePos = getLastVisiblePosition();
             final ListAdapter adapter = getAdapter();
             for (int pos = startPos; pos <= lastVisiblePos; pos++) {
@@ -3129,7 +3129,7 @@
     /**
      * Determine the distance to the nearest edge of a view in a particular
      * direction.
-     * 
+     *
      * @param descendant A descendant of this list.
      * @return The distance, or 0 if the nearest edge is already on screen.
      */
@@ -3386,7 +3386,7 @@
             final int listBottom = mBottom - mTop - effectivePaddingBottom + mScrollY;
             if (!mStackFromBottom) {
                 int bottom = 0;
-                
+
                 // Draw top divider or header for overscroll
                 final int scrollY = mScrollY;
                 if (count > 0 && scrollY < 0) {
@@ -3483,7 +3483,7 @@
                         }
                     }
                 }
-                
+
                 if (count > 0 && scrollY > 0) {
                     if (drawOverscrollFooter) {
                         final int absListBottom = mBottom;
@@ -3567,7 +3567,7 @@
     public int getDividerHeight() {
         return mDividerHeight;
     }
-    
+
     /**
      * Sets the height of the divider that will be drawn between each item in the list. Calling
      * this will override the intrinsic height as set by {@link #setDivider(Drawable)}
@@ -3625,7 +3625,7 @@
     public boolean areFooterDividersEnabled() {
         return mFooterDividersEnabled;
     }
-    
+
     /**
      * Sets the drawable that will be drawn above all other list content.
      * This area can become visible when the user overscrolls the list.
@@ -3878,10 +3878,10 @@
     /**
      * Returns the set of checked items ids. The result is only valid if the
      * choice mode has not been set to {@link #CHOICE_MODE_NONE}.
-     * 
+     *
      * @return A new array which contains the id of each checked item in the
      *         list.
-     *         
+     *
      * @deprecated Use {@link #getCheckedItemIds()} instead.
      */
     @Deprecated
diff --git a/core/java/android/widget/MenuItemHoverListener.java b/core/java/android/widget/MenuItemHoverListener.java
index 13f0e6a..835e4cd 100644
--- a/core/java/android/widget/MenuItemHoverListener.java
+++ b/core/java/android/widget/MenuItemHoverListener.java
@@ -1,10 +1,10 @@
 package android.widget;
 
-import com.android.internal.view.menu.MenuBuilder;
-
 import android.annotation.NonNull;
 import android.view.MenuItem;
 
+import com.android.internal.view.menu.MenuBuilder;
+
 /**
  * An interface notified when a menu item is hovered. Useful for cases when hover should trigger
  * some behavior at a higher level, like managing the opening and closing of submenus.
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 72b2e31..662e640 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.TestApi;
@@ -32,12 +30,10 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.text.Editable;
 import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Spanned;
 import android.text.TextUtils;
-import android.text.TextWatcher;
 import android.text.method.NumberKeyListener;
 import android.util.AttributeSet;
 import android.util.SparseArray;
@@ -57,6 +53,10 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 
+import com.android.internal.R;
+
+import libcore.icu.LocaleData;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -64,8 +64,6 @@
 import java.util.List;
 import java.util.Locale;
 
-import libcore.icu.LocaleData;
-
 /**
  * A widget that enables the user to select a number from a predefined range.
  * There are two flavors of this widget and which one is presented to the user
diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java
index 027f874..eb27533 100644
--- a/core/java/android/widget/PopupMenu.java
+++ b/core/java/android/widget/PopupMenu.java
@@ -16,11 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuPopupHelper;
-import com.android.internal.view.menu.ShowableListMenu;
-
 import android.annotation.MenuRes;
 import android.content.Context;
 import android.view.Gravity;
@@ -30,6 +25,11 @@
 import android.view.View;
 import android.view.View.OnTouchListener;
 
+import com.android.internal.R;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuPopupHelper;
+import com.android.internal.view.menu.ShowableListMenu;
+
 /**
  * A PopupMenu displays a {@link Menu} in a modal popup window anchored to a
  * {@link View}. The popup will appear below the anchor view if there is room,
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 5e73a63..fc1520b 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -16,7 +16,11 @@
 
 package android.widget;
 
-import com.android.internal.R;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowManager.LayoutParams
+        .PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -50,12 +54,9 @@
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 
-import java.lang.ref.WeakReference;
+import com.android.internal.R;
 
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import java.lang.ref.WeakReference;
 
 /**
  * <p>
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 3c967ac..266ff75 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -23,7 +23,6 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
-import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
@@ -59,6 +58,7 @@
 import android.view.animation.LinearInterpolator;
 import android.view.animation.Transformation;
 import android.widget.RemoteViews.RemoteView;
+
 import com.android.internal.R;
 
 import java.util.ArrayList;
@@ -185,6 +185,7 @@
  * @attr ref android.R.styleable#ProgressBar_indeterminateDuration
  * @attr ref android.R.styleable#ProgressBar_indeterminateOnly
  * @attr ref android.R.styleable#ProgressBar_interpolator
+ * @attr ref android.R.styleable#ProgressBar_min
  * @attr ref android.R.styleable#ProgressBar_max
  * @attr ref android.R.styleable#ProgressBar_maxHeight
  * @attr ref android.R.styleable#ProgressBar_maxWidth
@@ -215,7 +216,10 @@
 
     private int mProgress;
     private int mSecondaryProgress;
+    private int mMin;
+    private boolean mMinInitialized;
     private int mMax;
+    private boolean mMaxInitialized;
 
     private int mBehavior;
     private int mDuration;
@@ -230,7 +234,7 @@
     private Drawable mCurrentDrawable;
     private ProgressTintInfo mProgressTintInfo;
 
-    Bitmap mSampleTile;
+    int mSampleWidth = 0;
     private boolean mNoInvalidate;
     private Interpolator mInterpolator;
     private RefreshProgressRunnable mRefreshProgressRunnable;
@@ -308,6 +312,7 @@
             setInterpolator(context, resID);
         }
 
+        setMin(a.getInt(R.styleable.ProgressBar_min, mMin));
         setMax(a.getInt(R.styleable.ProgressBar_max, mMax));
 
         setProgress(a.getInt(R.styleable.ProgressBar_progress, mProgress));
@@ -505,15 +510,14 @@
         }
 
         if (drawable instanceof BitmapDrawable) {
-            final BitmapDrawable bitmap = (BitmapDrawable) drawable;
-            final Bitmap tileBitmap = bitmap.getBitmap();
-            if (mSampleTile == null) {
-                mSampleTile = tileBitmap;
-            }
-
-            final BitmapDrawable clone = (BitmapDrawable) bitmap.getConstantState().newDrawable();
+            final Drawable.ConstantState cs = drawable.getConstantState();
+            final BitmapDrawable clone = (BitmapDrawable) cs.newDrawable(getResources());
             clone.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
 
+            if (mSampleWidth <= 0) {
+                mSampleWidth = clone.getIntrinsicWidth();
+            }
+
             if (clip) {
                 return new ClipDrawable(clone, Gravity.LEFT, ClipDrawable.HORIZONTAL);
             } else {
@@ -565,6 +569,7 @@
      * </ul>
      */
     private void initProgressBar() {
+        mMin = 0;
         mMax = 100;
         mProgress = 0;
         mSecondaryProgress = 0;
@@ -1310,7 +1315,8 @@
 
     private synchronized void doRefreshProgress(int id, int progress, boolean fromUser,
             boolean callBackToApp, boolean animate) {
-        final float scale = mMax > 0 ? progress / (float) mMax : 0;
+        int range = mMax - mMin;
+        final float scale = range > 0 ? (progress - mMin) / (float) range : 0;
         final boolean isPrimary = id == R.id.progress;
 
         if (isPrimary && animate) {
@@ -1436,7 +1442,7 @@
             return false;
         }
 
-        progress = MathUtils.constrain(progress, 0, mMax);
+        progress = MathUtils.constrain(progress, mMin, mMax);
 
         if (progress == mProgress) {
             // No change from current.
@@ -1466,8 +1472,8 @@
             return;
         }
 
-        if (secondaryProgress < 0) {
-            secondaryProgress = 0;
+        if (secondaryProgress < mMin) {
+            secondaryProgress = mMin;
         }
 
         if (secondaryProgress > mMax) {
@@ -1515,6 +1521,20 @@
     }
 
     /**
+     * <p>Return the lower limit of this progress bar's range.</p>
+     *
+     * @return a positive integer
+     *
+     * @see #setMin(int)
+     * @see #getProgress()
+     * @see #getSecondaryProgress()
+     */
+    @ViewDebug.ExportedProperty(category = "progress")
+    public synchronized int getMin() {
+        return mMin;
+    }
+
+    /**
      * <p>Return the upper limit of this progress bar's range.</p>
      *
      * @return a positive integer
@@ -1529,7 +1549,37 @@
     }
 
     /**
-     * <p>Set the range of the progress bar to 0...<tt>max</tt>.</p>
+     * <p>Set the lower range of the progress bar to <tt>min</tt>.</p>
+     *
+     * @param min the lower range of this progress bar
+     *
+     * @see #getMin()
+     * @see #setProgress(int)
+     * @see #setSecondaryProgress(int)
+     */
+    @android.view.RemotableViewMethod
+    public synchronized void setMin(int min) {
+        if (mMaxInitialized) {
+            if (min > mMax) {
+                min = mMax;
+            }
+        }
+        mMinInitialized = true;
+        if (mMaxInitialized && min != mMin) {
+            mMin = min;
+            postInvalidate();
+
+            if (mProgress < min) {
+                mProgress = min;
+            }
+            refreshProgress(R.id.progress, mProgress, false, false);
+        } else {
+            mMin = min;
+        }
+    }
+
+    /**
+     * <p>Set the upper range of the progress bar <tt>max</tt>.</p>
      *
      * @param max the upper range of this progress bar
      *
@@ -1539,10 +1589,13 @@
      */
     @android.view.RemotableViewMethod
     public synchronized void setMax(int max) {
-        if (max < 0) {
-            max = 0;
+        if (mMinInitialized) {
+            if (max < mMin) {
+                max = mMin;
+            }
         }
-        if (max != mMax) {
+        mMaxInitialized = true;
+        if (mMinInitialized && max != mMax) {
             mMax = max;
             postInvalidate();
 
@@ -1550,6 +1603,8 @@
                 mProgress = max;
             }
             refreshProgress(R.id.progress, mProgress, false, false);
+        } else {
+            mMax = max;
         }
     }
 
@@ -1959,7 +2014,7 @@
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
-        event.setItemCount(mMax);
+        event.setItemCount(mMax - mMin);
         event.setCurrentItemIndex(mProgress);
     }
 
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index 8c15cde..8f6b0d5 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.content.AsyncQueryHandler;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -38,6 +36,8 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 
+import com.android.internal.R;
+
 /**
  * Widget used to show an image with the standard QuickContact badge
  * and on-click behavior.
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 5a0e1f9..757a4ca 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -16,10 +16,6 @@
 
 package android.widget;
 
-import android.view.PointerIcon;
-import com.android.internal.R;
-import com.android.internal.widget.ExploreByTouchHelper;
-
 import android.animation.ObjectAnimator;
 import android.annotation.IntDef;
 import android.content.Context;
@@ -43,11 +39,15 @@
 import android.util.TypedValue;
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
+import android.view.PointerIcon;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
+import com.android.internal.R;
+import com.android.internal.widget.ExploreByTouchHelper;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Calendar;
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 065feb8..54b5763 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.IdRes;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -25,6 +23,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.R;
+
 
 /**
  * <p>This class is used to create a multiple-exclusion scope for a set of radio
@@ -39,14 +39,14 @@
  * in the XML layout file.</p>
  *
  * <p><strong>XML Attributes</strong></p>
- * <p>See {@link android.R.styleable#RadioGroup RadioGroup Attributes}, 
+ * <p>See {@link android.R.styleable#RadioGroup RadioGroup Attributes},
  * {@link android.R.styleable#LinearLayout LinearLayout Attributes},
  * {@link android.R.styleable#ViewGroup ViewGroup Attributes},
  * {@link android.R.styleable#View View Attributes}</p>
  * <p>Also see
  * {@link android.widget.LinearLayout.LayoutParams LinearLayout.LayoutParams}
  * for layout attributes.</p>
- * 
+ *
  * @see RadioButton
  *
  */
@@ -310,7 +310,7 @@
             } else {
                 width = WRAP_CONTENT;
             }
-            
+
             if (a.hasValue(heightAttr)) {
                 height = a.getLayoutDimension(heightAttr, "layout_height");
             } else {
diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java
index 3ad05b5..3b7fe86 100644
--- a/core/java/android/widget/RatingBar.java
+++ b/core/java/android/widget/RatingBar.java
@@ -22,6 +22,7 @@
 import android.graphics.drawable.shapes.Shape;
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityNodeInfo;
+
 import com.android.internal.R;
 
 /**
@@ -281,10 +282,8 @@
     protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
-        if (mSampleTile != null) {
-            // TODO: Once ProgressBar's TODOs are gone, this can be done more
-            // cleanly than mSampleTile
-            final int width = mSampleTile.getWidth() * mNumStars;
+        if (mSampleWidth > 0) {
+            final int width = mSampleWidth * mNumStars;
             setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),
                     getMeasuredHeight());
         }
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index a189d3c..b424101 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -16,20 +16,14 @@
 
 package android.widget;
 
+import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
+
 import android.annotation.NonNull;
-import android.util.ArrayMap;
-import com.android.internal.R;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.os.Build;
+import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Pools.SynchronizedPool;
 import android.util.SparseArray;
@@ -41,7 +35,13 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.RemoteViews.RemoteView;
 
-import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
+import com.android.internal.R;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 /**
  * A Layout where the positions of the children can be described in relation to each other or to the
@@ -209,7 +209,7 @@
     private int mIgnoreGravity;
 
     private SortedSet<View> mTopToBottomLeftToRightSet = null;
-    
+
     private boolean mDirtyHierarchy;
     private View[] mSortedHorizontalChildren;
     private View[] mSortedVerticalChildren;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2a6e01f..6543d0c 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -59,11 +59,12 @@
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.AdapterView.OnItemClickListener;
-import libcore.util.Objects;
 
 import com.android.internal.R;
 import com.android.internal.util.Preconditions;
 
+import libcore.util.Objects;
+
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 10abbab..e0f94fd 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -16,13 +16,6 @@
 
 package android.widget;
 
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-
 import android.Manifest;
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
@@ -48,6 +41,11 @@
 import com.android.internal.widget.IRemoteViewsAdapterConnection;
 import com.android.internal.widget.IRemoteViewsFactory;
 
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+
 /**
  * An adapter to a RemoteViewsService which fetches and caches RemoteViews
  * to be later inflated as child views.
diff --git a/core/java/android/widget/RemoteViewsService.java b/core/java/android/widget/RemoteViewsService.java
index 07bd918..2827f63 100644
--- a/core/java/android/widget/RemoteViewsService.java
+++ b/core/java/android/widget/RemoteViewsService.java
@@ -16,14 +16,14 @@
 
 package android.widget;
 
-import java.util.HashMap;
-
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
 
 import com.android.internal.widget.IRemoteViewsFactory;
 
+import java.util.HashMap;
+
 /**
  * The service to be connected to for a remote adapter to request RemoteViews.  Users should
  * extend the RemoteViewsService to provide the appropriate RemoteViewsFactory's used to
@@ -46,7 +46,7 @@
      * An interface for an adapter between a remote collection view (ListView, GridView, etc) and
      * the underlying data for that view.  The implementor is responsible for making a RemoteView
      * for each item in the data set. This interface is a thin wrapper around {@link Adapter}.
-     * 
+     *
      * @see android.widget.Adapter
      * @see android.appwidget.AppWidgetManager
      */
diff --git a/core/java/android/widget/ResourceCursorAdapter.java b/core/java/android/widget/ResourceCursorAdapter.java
index 100f919..9732bb1 100644
--- a/core/java/android/widget/ResourceCursorAdapter.java
+++ b/core/java/android/widget/ResourceCursorAdapter.java
@@ -20,9 +20,9 @@
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.LayoutInflater;
 
 
 /**
@@ -148,7 +148,7 @@
     public void setViewResource(int layout) {
         mLayout = layout;
     }
-    
+
     /**
      * <p>Sets the layout resource of the drop down views.</p>
      *
diff --git a/core/java/android/widget/ResourceCursorTreeAdapter.java b/core/java/android/widget/ResourceCursorTreeAdapter.java
index ddce515..0894dba 100644
--- a/core/java/android/widget/ResourceCursorTreeAdapter.java
+++ b/core/java/android/widget/ResourceCursorTreeAdapter.java
@@ -18,9 +18,9 @@
 
 import android.content.Context;
 import android.database.Cursor;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.LayoutInflater;
 
 /**
  * A fairly simple ExpandableListAdapter that creates views defined in an XML
@@ -32,10 +32,10 @@
     private int mChildLayout;
     private int mLastChildLayout;
     private LayoutInflater mInflater;
-    
+
     /**
      * Constructor.
-     * 
+     *
      * @param context The context where the ListView associated with this
      *            SimpleListItemFactory is running
      * @param cursor The database cursor
@@ -51,18 +51,18 @@
     public ResourceCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout,
             int expandedGroupLayout, int childLayout, int lastChildLayout) {
         super(cursor, context);
-        
+
         mCollapsedGroupLayout = collapsedGroupLayout;
         mExpandedGroupLayout = expandedGroupLayout;
         mChildLayout = childLayout;
         mLastChildLayout = lastChildLayout;
-        
+
         mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     }
 
     /**
      * Constructor.
-     * 
+     *
      * @param context The context where the ListView associated with this
      *            SimpleListItemFactory is running
      * @param cursor The database cursor
@@ -80,7 +80,7 @@
 
     /**
      * Constructor.
-     * 
+     *
      * @param context The context where the ListView associated with this
      *            SimpleListItemFactory is running
      * @param cursor The database cursor
@@ -93,7 +93,7 @@
             int childLayout) {
         this(context, cursor, groupLayout, groupLayout, childLayout, childLayout);
     }
-    
+
     @Override
     public View newChildView(Context context, Cursor cursor, boolean isLastChild,
             ViewGroup parent) {
diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java
index 11eab2a..2ae38c9 100644
--- a/core/java/android/widget/ScrollBarDrawable.java
+++ b/core/java/android/widget/ScrollBarDrawable.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.widget.ScrollBarUtils;
-
 import android.annotation.NonNull;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
@@ -25,6 +23,8 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 
+import com.android.internal.widget.ScrollBarUtils;
+
 /**
  * This is only used by View for displaying its scroll bars. It should probably
  * be moved in to the view package since it is used in that lower-level layer.
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index e696ff7..d8f3379 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -17,18 +17,16 @@
 package android.widget;
 
 import android.annotation.NonNull;
-import android.content.res.Configuration;
-import android.os.Build;
-import android.os.Build.VERSION_CODES;
-import android.os.Parcel;
-import android.os.Parcelable;
-import com.android.internal.R;
-
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.StrictMode;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -47,6 +45,8 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 
+import com.android.internal.R;
+
 import java.util.List;
 
 /**
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
index 5d01d8d..f9aced0 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -46,8 +46,10 @@
          * to distinguish user-initiated changes from those that occurred programmatically.
          *
          * @param seekBar The SeekBar whose progress has changed
-         * @param progress The current progress level. This will be in the range 0..max where max
-         *        was set by {@link ProgressBar#setMax(int)}. (The default value for max is 100.)
+         * @param progress The current progress level. This will be in the range min..max where min
+         *                 and max were set by {@link ProgressBar#setMin(int)} and
+         *                 {@link ProgressBar#setMax(int)}, respectively. (The default values for
+         *                 min is 0 and max is 100.)
          * @param fromUser True if the progress change was initiated by the user.
          */
         void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser);
diff --git a/core/java/android/widget/SimpleAdapter.java b/core/java/android/widget/SimpleAdapter.java
index 3bf9485..9190117 100644
--- a/core/java/android/widget/SimpleAdapter.java
+++ b/core/java/android/widget/SimpleAdapter.java
@@ -20,11 +20,11 @@
 import android.annotation.LayoutRes;
 import android.content.Context;
 import android.content.res.Resources;
+import android.net.Uri;
 import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.LayoutInflater;
-import android.net.Uri;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -40,7 +40,7 @@
  * Binding data to views occurs in two phases. First, if a
  * {@link android.widget.SimpleAdapter.ViewBinder} is available,
  * {@link ViewBinder#setViewValue(android.view.View, Object, String)}
- * is invoked. If the returned value is true, binding has occurred. 
+ * is invoked. If the returned value is true, binding has occurred.
  * If the returned value is false, the following views are then tried in order:
  * <ul>
  * <li> A view that implements Checkable (e.g. CheckBox).  The expected bind value is a boolean.
@@ -223,7 +223,7 @@
                         setViewText((TextView) v, text);
                     } else if (v instanceof ImageView) {
                         if (data instanceof Integer) {
-                            setViewImage((ImageView) v, (Integer) data);                            
+                            setViewImage((ImageView) v, (Integer) data);
                         } else {
                             setViewImage((ImageView) v, text);
                         }
@@ -291,7 +291,7 @@
      * @param v ImageView to receive an image
      * @param value the value retrieved from the data set
      *
-     * @see #setViewImage(ImageView, int) 
+     * @see #setViewImage(ImageView, int)
      */
     public void setViewImage(ImageView v, String value) {
         try {
@@ -381,18 +381,18 @@
                 for (int i = 0; i < count; i++) {
                     Map<String, ?> h = unfilteredValues.get(i);
                     if (h != null) {
-                        
+
                         int len = mTo.length;
 
                         for (int j=0; j<len; j++) {
                             String str =  (String)h.get(mFrom[j]);
-                            
+
                             String[] words = str.split(" ");
                             int wordCount = words.length;
-                            
+
                             for (int k = 0; k < wordCount; k++) {
                                 String word = words[k];
-                                
+
                                 if (word.toLowerCase().startsWith(prefixString)) {
                                     newValues.add(h);
                                     break;
diff --git a/core/java/android/widget/SimpleExpandableListAdapter.java b/core/java/android/widget/SimpleExpandableListAdapter.java
index 015c169..597502b 100644
--- a/core/java/android/widget/SimpleExpandableListAdapter.java
+++ b/core/java/android/widget/SimpleExpandableListAdapter.java
@@ -17,9 +17,9 @@
 package android.widget;
 
 import android.content.Context;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.LayoutInflater;
 
 import java.util.List;
 import java.util.Map;
@@ -42,18 +42,18 @@
     private int mCollapsedGroupLayout;
     private String[] mGroupFrom;
     private int[] mGroupTo;
-    
+
     private List<? extends List<? extends Map<String, ?>>> mChildData;
     private int mChildLayout;
     private int mLastChildLayout;
     private String[] mChildFrom;
     private int[] mChildTo;
-    
+
     private LayoutInflater mInflater;
-    
+
     /**
      * Constructor
-     * 
+     *
      * @param context The context where the {@link ExpandableListView}
      *            associated with this {@link SimpleExpandableListAdapter} is
      *            running
@@ -98,7 +98,7 @@
 
     /**
      * Constructor
-     * 
+     *
      * @param context The context where the {@link ExpandableListView}
      *            associated with this {@link SimpleExpandableListAdapter} is
      *            running
@@ -147,7 +147,7 @@
 
     /**
      * Constructor
-     * 
+     *
      * @param context The context where the {@link ExpandableListView}
      *            associated with this {@link SimpleExpandableListAdapter} is
      *            running
@@ -200,16 +200,16 @@
         mCollapsedGroupLayout = collapsedGroupLayout;
         mGroupFrom = groupFrom;
         mGroupTo = groupTo;
-        
+
         mChildData = childData;
         mChildLayout = childLayout;
         mLastChildLayout = lastChildLayout;
         mChildFrom = childFrom;
         mChildTo = childTo;
-        
+
         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     }
-    
+
     public Object getChild(int groupPosition, int childPosition) {
         return mChildData.get(groupPosition).get(childPosition);
     }
@@ -239,7 +239,7 @@
     public View newChildView(boolean isLastChild, ViewGroup parent) {
         return mInflater.inflate((isLastChild) ? mLastChildLayout : mChildLayout, parent, false);
     }
-    
+
     private void bindView(View view, Map<String, ?> data, String[] from, int[] to) {
         int len = to.length;
 
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 8c43782..855d1d2 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -16,10 +16,6 @@
 
 package android.widget;
 
-import android.view.PointerIcon;
-import com.android.internal.R;
-import com.android.internal.widget.ExploreByTouchHelper;
-
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -43,17 +39,21 @@
 import android.util.StateSet;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.PointerIcon;
 import android.view.View;
 import android.view.ViewParent;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
-import java.text.NumberFormat;
-import java.util.Locale;
+import com.android.internal.R;
+import com.android.internal.widget.ExploreByTouchHelper;
 
 import libcore.icu.LocaleData;
 
+import java.text.NumberFormat;
+import java.util.Locale;
+
 /**
  * A calendar-like view displaying a specified month and the appropriate selectable day numbers
  * within the specified month.
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index dc5e5a2..28cc693 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -16,13 +16,9 @@
 
 package android.widget;
 
-import android.annotation.TestApi;
-import android.view.PointerIcon;
-import com.android.internal.R;
-import com.android.internal.view.menu.ShowableListMenu;
-
 import android.annotation.DrawableRes;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.annotation.Widget;
 import android.app.AlertDialog;
 import android.content.Context;
@@ -42,6 +38,7 @@
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.MotionEvent;
+import android.view.PointerIcon;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
@@ -49,6 +46,9 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.PopupWindow.OnDismissListener;
 
+import com.android.internal.R;
+import com.android.internal.view.menu.ShowableListMenu;
+
 /**
  * A view that displays one child at a time and lets the user pick among them.
  * The items in the Spinner come from the {@link Adapter} associated with
@@ -123,7 +123,7 @@
      *                access the current theme, resources, etc.
      * @param mode Constant describing how the user will select choices from
      *             the spinner.
-     * 
+     *
      * @see #MODE_DIALOG
      * @see #MODE_DROPDOWN
      */
@@ -563,7 +563,7 @@
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        
+
         if (mPopup != null && mPopup.isShowing()) {
             mPopup.dismiss();
         }
@@ -772,7 +772,7 @@
     @Override
     public boolean performClick() {
         boolean handled = super.performClick();
-        
+
         if (!handled) {
             handled = true;
 
@@ -1011,7 +1011,7 @@
 
         /**
          * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call.
-         * Otherwise, return true. 
+         * Otherwise, return true.
          */
         public boolean areAllItemsEnabled() {
             final ListAdapter adapter = mListAdapter;
@@ -1042,19 +1042,19 @@
         public int getViewTypeCount() {
             return 1;
         }
-        
+
         public boolean isEmpty() {
             return getCount() == 0;
         }
     }
-    
+
     /**
      * Implements some sort of popup selection interface for selecting a spinner option.
      * Allows for different spinner modes.
      */
     private interface SpinnerPopup {
         public void setAdapter(ListAdapter adapter);
-        
+
         /**
          * Show the popup
          */
@@ -1064,12 +1064,12 @@
          * Dismiss the popup
          */
         public void dismiss();
-        
+
         /**
          * @return true if the popup is showing, false otherwise.
          */
         public boolean isShowing();
-        
+
         /**
          * Set hint text to be displayed to the user. This should provide
          * a description of the choice being made.
@@ -1129,7 +1129,7 @@
             listView.setTextAlignment(textAlignment);
             mPopup.show();
         }
-        
+
         public void onClick(DialogInterface dialog, int which) {
             setSelection(which);
             if (mOnItemClickListener != null) {
@@ -1168,7 +1168,7 @@
             return 0;
         }
     }
-    
+
     private class DropdownPopup extends ListPopupWindow implements SpinnerPopup {
         private CharSequence mHintText;
         private ListAdapter mAdapter;
@@ -1190,7 +1190,7 @@
                 }
             });
         }
-        
+
         @Override
         public void setAdapter(ListAdapter adapter) {
             super.setAdapter(adapter);
@@ -1200,7 +1200,7 @@
         public CharSequence getHintText() {
             return mHintText;
         }
-        
+
         public void setPromptText(CharSequence hintText) {
             // Hint text is ignored for dropdowns, but maintain it here.
             mHintText = hintText;
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 2bd3143..0e99c02 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -15,8 +15,6 @@
 
 package android.widget;
 
-import java.lang.ref.WeakReference;
-
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.content.Context;
@@ -45,6 +43,8 @@
 import android.view.animation.LinearInterpolator;
 import android.widget.RemoteViews.RemoteView;
 
+import java.lang.ref.WeakReference;
+
 @RemoteView
 /**
  * A view that displays its children in a stack and allows users to discretely swipe
@@ -670,12 +670,12 @@
                 activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ? 1 : 0;
             }
 
-            boolean endOfStack = mLoopViews && adapterCount == 1 && 
-                ((mStackMode == ITEMS_SLIDE_UP && swipeGestureType == GESTURE_SLIDE_UP) ||
-                 (mStackMode == ITEMS_SLIDE_DOWN && swipeGestureType == GESTURE_SLIDE_DOWN));
-            boolean beginningOfStack = mLoopViews && adapterCount == 1 && 
-                ((mStackMode == ITEMS_SLIDE_DOWN && swipeGestureType == GESTURE_SLIDE_UP) ||
-                 (mStackMode == ITEMS_SLIDE_UP && swipeGestureType == GESTURE_SLIDE_DOWN));
+            boolean endOfStack = mLoopViews && adapterCount == 1
+                    && ((mStackMode == ITEMS_SLIDE_UP && swipeGestureType == GESTURE_SLIDE_UP)
+                    || (mStackMode == ITEMS_SLIDE_DOWN && swipeGestureType == GESTURE_SLIDE_DOWN));
+            boolean beginningOfStack = mLoopViews && adapterCount == 1
+                    && ((mStackMode == ITEMS_SLIDE_DOWN && swipeGestureType == GESTURE_SLIDE_UP)
+                    || (mStackMode == ITEMS_SLIDE_UP && swipeGestureType == GESTURE_SLIDE_DOWN));
 
             int stackMode;
             if (mLoopViews && !beginningOfStack && !endOfStack) {
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index aad0625..f833d1b 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -21,8 +21,8 @@
 import android.app.SearchableInfo;
 import android.content.ComponentName;
 import android.content.ContentResolver;
-import android.content.Context;
 import android.content.ContentResolver.OpenResourceIdResult;
+import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -39,8 +39,8 @@
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.View.OnClickListener;
+import android.view.ViewGroup;
 
 import com.android.internal.R;
 
@@ -111,7 +111,7 @@
         mProviderContext = mSearchable.getProviderContext(mContext, activityContext);
 
         mOutsideDrawablesCache = outsideDrawablesCache;
-        
+
         // mStartSpinnerRunnable = new Runnable() {
         // public void run() {
         // // mSearchView.setWorking(true); // TODO:
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index d51c5be..fcc1667 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -30,8 +30,8 @@
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
-import android.graphics.Typeface;
 import android.graphics.Region.Op;
+import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.text.Layout;
 import android.text.StaticLayout;
@@ -46,8 +46,8 @@
 import android.view.MotionEvent;
 import android.view.SoundEffectConstants;
 import android.view.VelocityTracker;
-import android.view.ViewStructure;
 import android.view.ViewConfiguration;
+import android.view.ViewStructure;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 583f037..32418cd 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.LocalActivityManager;
@@ -35,6 +33,9 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.Window;
+
+import com.android.internal.R;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 1f0cb7c..05f7c0a 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -16,10 +16,6 @@
 
 package android.widget;
 
-import android.view.MotionEvent;
-import android.view.PointerIcon;
-import com.android.internal.R;
-
 import android.annotation.DrawableRes;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -29,11 +25,15 @@
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.PointerIcon;
 import android.view.View;
 import android.view.View.OnFocusChangeListener;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 
+import com.android.internal.R;
+
 /**
  *
  * Displays a list of tab labels representing each page in the parent's tab
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index eed3c2d..8bb4d16 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -16,14 +16,15 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
 import android.util.SparseBooleanArray;
 import android.view.View;
 import android.view.ViewGroup;
+
+import com.android.internal.R;
+
 import java.util.regex.Pattern;
 
 /**
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index 278ceb2..a6a9db4 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -16,6 +16,9 @@
 
 package android.widget;
 
+import static android.view.ViewDebug.ExportedProperty;
+import static android.widget.RemoteViews.RemoteView;
+
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
@@ -37,13 +40,10 @@
 
 import com.android.internal.R;
 
-import java.util.Calendar;
-import java.util.TimeZone;
-
 import libcore.icu.LocaleData;
 
-import static android.view.ViewDebug.ExportedProperty;
-import static android.widget.RemoteViews.*;
+import java.util.Calendar;
+import java.util.TimeZone;
 
 /**
  * <p><code>TextClock</code> can display the current date and/or time as
@@ -132,7 +132,7 @@
 
     private CharSequence mDescFormat;
 
-    private boolean mAttached;
+    private boolean mRegistered;
 
     private Calendar mTime;
     private String mTimeZone;
@@ -252,7 +252,7 @@
         }
 
         createTime(mTimeZone);
-        // Wait until onAttachedToWindow() to handle the ticker
+        // Wait until registering for events to handle the ticker
         chooseFormat(false);
     }
 
@@ -503,7 +503,7 @@
         boolean hadSeconds = mHasSeconds;
         mHasSeconds = DateFormat.hasSeconds(mFormat);
 
-        if (handleTicker && mAttached && hadSeconds != mHasSeconds) {
+        if (handleTicker && mRegistered && hadSeconds != mHasSeconds) {
             if (hadSeconds) getHandler().removeCallbacks(mTicker);
             else mTicker.run();
         }
@@ -517,11 +517,9 @@
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-
-        if (!mAttached) {
-            mAttached = true;
+    public void onVisibilityAggregated(boolean isVisible) {
+        if (!mRegistered && isVisible) {
+            mRegistered = true;
 
             registerReceiver();
             registerObserver();
@@ -533,20 +531,13 @@
             } else {
                 onTimeChanged();
             }
-        }
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-
-        if (mAttached) {
+        } else if (mRegistered && !isVisible) {
             unregisterReceiver();
             unregisterObserver();
 
             getHandler().removeCallbacks(mTicker);
 
-            mAttached = false;
+            mRegistered = false;
         }
     }
 
@@ -569,7 +560,7 @@
     }
 
     private void registerObserver() {
-        if (isAttachedToWindow()) {
+        if (mRegistered) {
             if (mFormatChangeObserver == null) {
                 mFormatChangeObserver = new FormatChangeObserver(getHandler());
             }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5264d5c..f1c3079 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -41,6 +41,7 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.graphics.BaseCanvas;
 import android.graphics.Canvas;
 import android.graphics.Insets;
 import android.graphics.Paint;
@@ -10222,12 +10223,14 @@
             System.arraycopy(mChars, start + mStart, buf, off, end - start);
         }
 
-        public void drawText(Canvas c, int start, int end,
+        @Override
+        public void drawText(BaseCanvas c, int start, int end,
                              float x, float y, Paint p) {
             c.drawText(mChars, start + mStart, end - start, x, y, p);
         }
 
-        public void drawTextRun(Canvas c, int start, int end,
+        @Override
+        public void drawTextRun(BaseCanvas c, int start, int end,
                 int contextStart, int contextEnd, float x, float y, boolean isRtl, Paint p) {
             int count = end - start;
             int contextCount = contextEnd - contextStart;
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 6a76c5b..e6cd798 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -32,12 +30,14 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 
+import com.android.internal.R;
+
+import libcore.icu.LocaleData;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Locale;
 
-import libcore.icu.LocaleData;
-
 /**
  * A widget for selecting the time of day, in either 24-hour or AM/PM mode.
  * <p>
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 26e1564..6a68f60 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -16,6 +16,9 @@
 
 package android.widget;
 
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
+
 import android.annotation.TestApi;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -29,14 +32,12 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
-import com.android.internal.R;
 
-import java.util.Calendar;
+import com.android.internal.R;
 
 import libcore.icu.LocaleData;
 
-import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
-import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
+import java.util.Calendar;
 
 /**
  * A delegate implementing the basic spinner-based TimePicker.
diff --git a/core/java/android/widget/TwoLineListItem.java b/core/java/android/widget/TwoLineListItem.java
index 69ff488..0445ebd 100644
--- a/core/java/android/widget/TwoLineListItem.java
+++ b/core/java/android/widget/TwoLineListItem.java
@@ -20,22 +20,21 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
-import android.widget.RelativeLayout;
 
 /**
- * <p>A view group with two children, intended for use in ListViews. This item has two 
- * {@link android.widget.TextView TextViews} elements (or subclasses) with the ID values 
+ * <p>A view group with two children, intended for use in ListViews. This item has two
+ * {@link android.widget.TextView TextViews} elements (or subclasses) with the ID values
  * {@link android.R.id#text1 text1}
- * and {@link android.R.id#text2 text2}. There is an optional third View element with the 
- * ID {@link android.R.id#selectedIcon selectedIcon}, which can be any View subclass 
+ * and {@link android.R.id#text2 text2}. There is an optional third View element with the
+ * ID {@link android.R.id#selectedIcon selectedIcon}, which can be any View subclass
  * (though it is typically a graphic View, such as {@link android.widget.ImageView ImageView})
- * that can be displayed when a TwoLineListItem has focus. Android supplies a 
- * {@link android.R.layout#two_line_list_item standard layout resource for TwoLineListView} 
+ * that can be displayed when a TwoLineListItem has focus. Android supplies a
+ * {@link android.R.layout#two_line_list_item standard layout resource for TwoLineListView}
  * (which does not include a selected item icon), but you can design your own custom XML
  * layout for this object.
- * 
+ *
  * @attr ref android.R.styleable#TwoLineListItem_mode
- * 
+ *
  * @deprecated This class can be implemented easily by apps using a {@link RelativeLayout}
  * or a {@link LinearLayout}.
  */
@@ -51,7 +50,7 @@
     }
 
     public TwoLineListItem(Context context, AttributeSet attrs) {
-        this(context, attrs, 0); 
+        this(context, attrs, 0);
     }
 
     public TwoLineListItem(Context context, AttributeSet attrs, int defStyleAttr) {
@@ -70,11 +69,11 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        
+
         mText1 = (TextView) findViewById(com.android.internal.R.id.text1);
         mText2 = (TextView) findViewById(com.android.internal.R.id.text2);
     }
-    
+
     /**
      * Returns a handle to the item with ID text1.
      * @return A handle to the item with ID text1.
@@ -82,7 +81,7 @@
     public TextView getText1() {
         return mText1;
     }
-    
+
     /**
      * Returns a handle to the item with ID text2.
      * @return A handle to the item with ID text2.
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
index 65af7aa..e769d71 100644
--- a/core/java/android/widget/ViewFlipper.java
+++ b/core/java/android/widget/ViewFlipper.java
@@ -21,7 +21,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.TypedArray;
-import android.os.*;
+import android.os.Message;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.widget.RemoteViews.RemoteView;
diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java
index a3f5a67..824fec8 100644
--- a/core/java/android/widget/YearPickerView.java
+++ b/core/java/android/widget/YearPickerView.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.icu.util.Calendar;
@@ -27,6 +25,8 @@
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 
+import com.android.internal.R;
+
 /**
  * Displays a selectable list of years.
  */
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index fb912a4..69b79971 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -30,11 +30,11 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewRootImpl;
 import android.view.WindowManager;
-import android.view.View.OnClickListener;
 import android.view.WindowManager.LayoutParams;
 
 /*
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index a5b2a91..3b6073a 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -68,6 +68,7 @@
 import android.widget.BaseAdapter;
 import android.widget.ListView;
 import com.android.internal.R;
+import com.android.internal.app.ResolverActivity.TargetInfo;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.google.android.collect.Lists;
@@ -345,6 +346,12 @@
     }
 
     @Override
+    public boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
+        return getIntent().getBooleanExtra(Intent.EXTRA_AUTO_LAUNCH_SINGLE_CHOICE,
+                super.shouldAutoLaunchSingleChoice(target));
+    }
+
+    @Override
     public void showTargetDetails(ResolveInfo ri) {
         ComponentName name = ri.activityInfo.getComponentName();
         boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 8c5df08..8c2c236 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -379,7 +379,7 @@
 
     public void setState(int state, long now) {
         ensureNotDead();
-        if (mCurState != state) {
+        if (!mDead && (mCurState != state)) {
             //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
             commitStateTime(now);
             mCurState = state;
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
new file mode 100644
index 0000000..cf1bf62
--- /dev/null
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.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 com.android.internal.hardware;
+
+import com.android.internal.R;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+public class AmbientDisplayConfiguration {
+
+    private final Context mContext;
+
+    public AmbientDisplayConfiguration(Context context) {
+        mContext = context;
+    }
+    
+    public boolean enabled(int user) {
+        return pulseOnNotificationEnabled(user)
+                || pulseOnPickupEnabled(user)
+                || pulseOnDoubleTapEnabled(user);
+    }
+    
+    public boolean available() {
+        return pulseOnNotificationAvailable() || pulseOnPickupAvailable()
+                || pulseOnDoubleTapAvailable();
+    }
+    
+    public boolean pulseOnNotificationEnabled(int user) {
+        return boolSetting(Settings.Secure.DOZE_ENABLED, user) && pulseOnNotificationAvailable();
+    }
+
+    public boolean pulseOnNotificationAvailable() {
+        return ambientDisplayAvailable();
+    }
+
+    public boolean pulseOnPickupEnabled(int user) {
+        return boolSetting(Settings.Secure.DOZE_PULSE_ON_PICK_UP, user)
+                && pulseOnPickupAvailable();
+    }
+    
+    public boolean pulseOnPickupAvailable() {
+        return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup)
+                && ambientDisplayAvailable();
+    }
+    
+    public boolean pulseOnDoubleTapEnabled(int user) {
+        return boolSetting(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, user)
+                && pulseOnDoubleTapAvailable();
+    }
+
+    public boolean pulseOnDoubleTapAvailable() {
+        return !TextUtils.isEmpty(doubleTapSensorType()) && ambientDisplayAvailable();
+    }
+
+    public String doubleTapSensorType() {
+        return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
+    }
+
+    public String ambientDisplayComponent() {
+        return mContext.getResources().getString(R.string.config_dozeComponent);
+    }
+
+    private boolean ambientDisplayAvailable() {
+        return !TextUtils.isEmpty(ambientDisplayComponent());
+    }
+
+    private boolean boolSetting(String name, int user) {
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(), name, 1, user) != 0;
+    }
+
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 0aa3a7e..b60e6b5 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -10787,7 +10787,7 @@
             }
 
             int NW = in.readInt();
-            if (NW > 100) {
+            if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
                 throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
             }
             for (int iw = 0; iw < NW; iw++) {
@@ -10796,7 +10796,7 @@
             }
 
             int NS = in.readInt();
-            if (NS > 100) {
+            if (NS > (MAX_WAKELOCKS_PER_UID+1)) {
                 throw new ParcelFormatException("File corrupt: too many syncs " + NS);
             }
             for (int is = 0; is < NS; is++) {
@@ -10805,7 +10805,7 @@
             }
 
             int NJ = in.readInt();
-            if (NJ > 100) {
+            if (NJ > (MAX_WAKELOCKS_PER_UID+1)) {
                 throw new ParcelFormatException("File corrupt: too many job timers " + NJ);
             }
             for (int ij = 0; ij < NJ; ij++) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 59a3563..12d4be3 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -476,11 +476,11 @@
      */
     private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
                                                                  int targetSdkVersion) {
-      String librarySearchPath = System.getProperty("java.library.path");
+      String libraryPath = System.getProperty("java.library.path");
 
       return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
-                                                      librarySearchPath,
-                                                      null /* libraryPermittedPath */,
+                                                      libraryPath,
+                                                      libraryPath,
                                                       ClassLoader.getSystemClassLoader(),
                                                       targetSdkVersion,
                                                       true /* isNamespaceShared */);
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 644c7e9..4f7b106 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -580,7 +580,13 @@
                         return;
                     }
                     if (grantUriPermission) {
-                        inputContentInfo.requestPermission();
+                        try {
+                            inputContentInfo.requestPermission();
+                        } catch (Exception e) {
+                            Log.e(TAG, "InputConnectionInfo.requestPermission() failed", e);
+                            args.callback.setCommitContentResult(false, args.seq);
+                            return;
+                        }
                     }
                     final boolean result =
                             ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2);
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index df9b0dd..586ece0 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -4,6 +4,7 @@
 
 import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -29,6 +30,11 @@
          * the call. Only non-0 if matched is false.
          */
         void onChecked(boolean matched, int throttleTimeoutMs);
+
+        /**
+         * Called when the underlying AsyncTask was cancelled.
+         */
+        default void onCancelled() {}
     }
 
     /**
@@ -61,11 +67,19 @@
             final OnVerifyCallback callback) {
         AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
             private int mThrottleTimeout;
+            private List<LockPatternView.Cell> patternCopy;
+
+            @Override
+            protected void onPreExecute() {
+                // Make a copy of the pattern to prevent race conditions.
+                // No need to clone the individual cells because they are immutable.
+                patternCopy = new ArrayList(pattern);
+            }
 
             @Override
             protected byte[] doInBackground(Void... args) {
                 try {
-                    return utils.verifyPattern(pattern, challenge, userId);
+                    return utils.verifyPattern(patternCopy, challenge, userId);
                 } catch (RequestThrottledException ex) {
                     mThrottleTimeout = ex.getTimeoutMs();
                     return null;
@@ -95,11 +109,19 @@
             final OnCheckCallback callback) {
         AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
             private int mThrottleTimeout;
+            private List<LockPatternView.Cell> patternCopy;
+
+            @Override
+            protected void onPreExecute() {
+                // Make a copy of the pattern to prevent race conditions.
+                // No need to clone the individual cells because they are immutable.
+                patternCopy = new ArrayList(pattern);
+            }
 
             @Override
             protected Boolean doInBackground(Void... args) {
                 try {
-                    return utils.checkPattern(pattern, userId, callback::onEarlyMatched);
+                    return utils.checkPattern(patternCopy, userId, callback::onEarlyMatched);
                 } catch (RequestThrottledException ex) {
                     mThrottleTimeout = ex.getTimeoutMs();
                     return false;
@@ -110,6 +132,11 @@
             protected void onPostExecute(Boolean result) {
                 callback.onChecked(result, mThrottleTimeout);
             }
+
+            @Override
+            protected void onCancelled() {
+                callback.onCancelled();
+            }
         };
         task.execute();
         return task;
@@ -217,6 +244,11 @@
             protected void onPostExecute(Boolean result) {
                 callback.onChecked(result, mThrottleTimeout);
             }
+
+            @Override
+            protected void onCancelled() {
+                callback.onCancelled();
+            }
         };
         task.execute();
         return task;
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 4c6350b..7950685 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -19,6 +19,14 @@
     LOCAL_CFLAGS += -DENABLE_CPUSETS
 endif
 
+# TODO: Linear blending should be enabled by default, but we are
+# TODO: making it an opt-in while it's a work in progress
+# TODO: The final test should be:
+# TODO: ifneq ($(TARGET_ENABLE_LINEAR_BLENDING),false)
+ifeq ($(TARGET_ENABLE_LINEAR_BLENDING),true)
+    LOCAL_CFLAGS += -DANDROID_ENABLE_LINEAR_BLENDING
+endif
+
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
 LOCAL_CFLAGS += -DU_USING_ICU_NAMESPACE=0
@@ -214,6 +222,7 @@
 LOCAL_SHARED_LIBRARIES := \
     libmemtrack \
     libandroidfw \
+    libbase \
     libexpat \
     libnativehelper \
     liblog \
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 6acb76d..9ed1588 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -16,8 +16,8 @@
 #include "android_util_Binder.h"
 #include "android_nio_utils.h"
 #include "CreateJavaOutputStreamAdaptor.h"
-#include <Caches.h>
 #include <hwui/Paint.h>
+#include <hwui/PixelRef.h>
 #include <renderthread/RenderProxy.h>
 
 #include "core_jni_helpers.h"
@@ -25,302 +25,103 @@
 #include <jni.h>
 #include <memory>
 #include <string>
-#include <sys/mman.h>
-#include <cutils/ashmem.h>
 
 #define DEBUG_PARCEL 0
 #define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
 
+static jclass   gBitmap_class;
+static jfieldID gBitmap_nativePtr;
+static jmethodID gBitmap_constructorMethodID;
+static jmethodID gBitmap_reinitMethodID;
+static jmethodID gBitmap_getAllocationByteCountMethodID;
+
 namespace android {
 
-class WrappedPixelRef : public SkPixelRef {
+class Bitmap {
 public:
-    WrappedPixelRef(Bitmap* wrapper, void* storage,
-            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
-            : SkPixelRef(info)
-            , mBitmap(*wrapper)
-            , mStorage(storage) {
-        reconfigure(info, rowBytes, ctable);
+    Bitmap(PixelRef* pixelRef)
+        : mPixelRef(pixelRef) { }
+
+    void freePixels() {
+        mInfo = mPixelRef->info();
+        mHasHardwareMipMap = mPixelRef->hasHardwareMipMap();
+        mAllocationSize = mPixelRef->getAllocationByteCount();
+        mRowBytes = mPixelRef->rowBytes();
+        mGenerationId = mPixelRef->getGenerationID();
+        mPixelRef.reset();
     }
 
-    ~WrappedPixelRef() {
-        // Tell SkRefCnt that everything is as it expects by forcing
-        // the refcnt to 1
-        internal_dispose_restore_refcnt_to_1();
-        SkSafeUnref(mColorTable);
+    bool valid() {
+        return !!mPixelRef;
     }
 
-    void reconfigure(const SkImageInfo& newInfo, size_t rowBytes, SkColorTable* ctable) {
-        if (kIndex_8_SkColorType != newInfo.colorType()) {
-            ctable = nullptr;
+    PixelRef* pixelRef() { return mPixelRef.get(); }
+
+    void assertValid() {
+        LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
+    }
+
+    void getSkBitmap(SkBitmap* outBitmap) {
+        assertValid();
+        mPixelRef->getSkBitmap(outBitmap);
+    }
+
+    bool hasHardwareMipMap() {
+        if (mPixelRef) {
+            return mPixelRef->hasHardwareMipMap();
         }
-        mRowBytes = rowBytes;
-        if (mColorTable != ctable) {
-            SkSafeUnref(mColorTable);
-            mColorTable = ctable;
-            SkSafeRef(mColorTable);
-        }
-
-        // Need to validate the alpha type to filter against the color type
-        // to prevent things like a non-opaque RGB565 bitmap
-        SkAlphaType alphaType;
-        LOG_ALWAYS_FATAL_IF(!SkColorTypeValidateAlphaType(
-                newInfo.colorType(), newInfo.alphaType(), &alphaType),
-                "Failed to validate alpha type!");
-
-        // Dirty hack is dirty
-        // TODO: Figure something out here, Skia's current design makes this
-        // really hard to work with. Skia really, really wants immutable objects,
-        // but with the nested-ref-count hackery going on that's just not
-        // feasible without going insane trying to figure it out
-        SkImageInfo* myInfo = const_cast<SkImageInfo*>(&this->info());
-        *myInfo = newInfo;
-        changeAlphaType(alphaType);
-
-        // Docs say to only call this in the ctor, but we're going to call
-        // it anyway even if this isn't always the ctor.
-        // TODO: Fix this too as part of the above TODO
-        setPreLocked(mStorage, mRowBytes, mColorTable);
-    }
-
-    // Can't mark as override since SkPixelRef::rowBytes isn't virtual
-    // but that's OK since we just want BitmapWrapper to be able to rely
-    // on calling rowBytes() on an unlocked pixelref, which it will be
-    // doing on a WrappedPixelRef type, not a SkPixelRef, so static
-    // dispatching will do what we want.
-    size_t rowBytes() const { return mRowBytes; }
-    SkColorTable* colorTable() const { return mColorTable; }
-
-    bool hasHardwareMipMap() const {
         return mHasHardwareMipMap;
     }
 
     void setHasHardwareMipMap(bool hasMipMap) {
-        mHasHardwareMipMap = hasMipMap;
+        assertValid();
+        mPixelRef->setHasHardwareMipMap(hasMipMap);
     }
 
-protected:
-    virtual bool onNewLockPixels(LockRec* rec) override {
-        rec->fPixels = mStorage;
-        rec->fRowBytes = mRowBytes;
-        rec->fColorTable = mColorTable;
-        return true;
+    void setAlphaType(SkAlphaType alphaType) {
+        assertValid();
+        mPixelRef->setAlphaType(alphaType);
     }
 
-    virtual void onUnlockPixels() override {
-        // nothing
+    const SkImageInfo& info() {
+        if (mPixelRef) {
+            return mPixelRef->info();
+        }
+        return mInfo;
     }
 
-    virtual size_t getAllocatedSizeInBytes() const override {
-        return info().getSafeSize(mRowBytes);
+    size_t getAllocationByteCount() const {
+        if (mPixelRef) {
+            return mPixelRef->getAllocationByteCount();
+        }
+        return mAllocationSize;
     }
 
+    size_t rowBytes() const {
+        if (mPixelRef) {
+            return mPixelRef->rowBytes();
+        }
+        return mRowBytes;
+    }
+
+    uint32_t getGenerationID() const {
+        if (mPixelRef) {
+            return mPixelRef->getGenerationID();
+        }
+        return mGenerationId;
+    }
+
+    ~Bitmap() { }
+
 private:
-    Bitmap& mBitmap;
-    void* mStorage;
-    size_t mRowBytes = 0;
-    SkColorTable* mColorTable = nullptr;
-    bool mHasHardwareMipMap = false;
-
-    virtual void internal_dispose() const override {
-        mBitmap.onStrongRefDestroyed();
-    }
+    sk_sp<PixelRef> mPixelRef;
+    SkImageInfo mInfo;
+    bool mHasHardwareMipMap;
+    size_t mAllocationSize;
+    size_t mRowBytes;
+    uint32_t mGenerationId;
 };
 
-Bitmap::Bitmap(void* address, size_t size, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
-        : mPixelStorageType(PixelStorageType::Heap) {
-    mPixelStorage.heap.address = address;
-    mPixelStorage.heap.size = size;
-    mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable));
-    // Note: this will trigger a call to onStrongRefDestroyed(), but
-    // we want the pixel ref to have a ref count of 0 at this point
-    mPixelRef->unref();
-}
-
-Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc,
-            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
-        : mPixelStorageType(PixelStorageType::External) {
-    mPixelStorage.external.address = address;
-    mPixelStorage.external.context = context;
-    mPixelStorage.external.freeFunc = freeFunc;
-    mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable));
-    // Note: this will trigger a call to onStrongRefDestroyed(), but
-    // we want the pixel ref to have a ref count of 0 at this point
-    mPixelRef->unref();
-}
-
-Bitmap::Bitmap(void* address, int fd, size_t mappedSize,
-            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
-        : mPixelStorageType(PixelStorageType::Ashmem) {
-    mPixelStorage.ashmem.address = address;
-    mPixelStorage.ashmem.fd = fd;
-    mPixelStorage.ashmem.size = mappedSize;
-    mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable));
-    // Note: this will trigger a call to onStrongRefDestroyed(), but
-    // we want the pixel ref to have a ref count of 0 at this point
-    mPixelRef->unref();
-}
-Bitmap::~Bitmap() {
-    doFreePixels();
-}
-
-void Bitmap::freePixels() {
-    AutoMutex _lock(mLock);
-    if (mPinnedRefCount == 0) {
-        doFreePixels();
-        mPixelStorageType = PixelStorageType::Invalid;
-    }
-}
-
-void Bitmap::doFreePixels() {
-    switch (mPixelStorageType) {
-    case PixelStorageType::Invalid:
-        // already free'd, nothing to do
-        break;
-    case PixelStorageType::External:
-        mPixelStorage.external.freeFunc(mPixelStorage.external.address,
-                mPixelStorage.external.context);
-        break;
-    case PixelStorageType::Ashmem:
-        munmap(mPixelStorage.ashmem.address, mPixelStorage.ashmem.size);
-        close(mPixelStorage.ashmem.fd);
-        break;
-    case PixelStorageType::Heap:
-        free(mPixelStorage.heap.address);
-        break;
-    }
-
-    if (android::uirenderer::Caches::hasInstance()) {
-        android::uirenderer::Caches::getInstance().textureCache.releaseTexture(
-                mPixelRef->getStableID());
-    }
-}
-
-bool Bitmap::hasHardwareMipMap() {
-    return mPixelRef->hasHardwareMipMap();
-}
-
-void Bitmap::setHasHardwareMipMap(bool hasMipMap) {
-    mPixelRef->setHasHardwareMipMap(hasMipMap);
-}
-
-int Bitmap::getAshmemFd() const {
-    switch (mPixelStorageType) {
-    case PixelStorageType::Ashmem:
-        return mPixelStorage.ashmem.fd;
-    default:
-        return -1;
-    }
-}
-
-size_t Bitmap::getAllocationByteCount() const {
-    switch (mPixelStorageType) {
-    case PixelStorageType::Heap:
-        return mPixelStorage.heap.size;
-    default:
-        return rowBytes() * height();
-    }
-}
-
-const SkImageInfo& Bitmap::info() const {
-    return mPixelRef->info();
-}
-
-size_t Bitmap::rowBytes() const {
-    return mPixelRef->rowBytes();
-}
-
-SkPixelRef* Bitmap::peekAtPixelRef() const {
-    assertValid();
-    return mPixelRef.get();
-}
-
-SkPixelRef* Bitmap::refPixelRef() {
-    assertValid();
-    android::AutoMutex _lock(mLock);
-    return refPixelRefLocked();
-}
-
-SkPixelRef* Bitmap::refPixelRefLocked() {
-    mPixelRef->ref();
-    if (mPixelRef->unique()) {
-        // We just restored this from 0, pin the pixels and inc the strong count
-        // Note that there *might be* an incoming onStrongRefDestroyed from whatever
-        // last unref'd
-        mPinnedRefCount++;
-    }
-    return mPixelRef.get();
-}
-
-void Bitmap::reconfigure(const SkImageInfo& info, size_t rowBytes,
-        SkColorTable* ctable) {
-    mPixelRef->reconfigure(info, rowBytes, ctable);
-}
-
-void Bitmap::reconfigure(const SkImageInfo& info) {
-    reconfigure(info, info.minRowBytes(), nullptr);
-}
-
-void Bitmap::setAlphaType(SkAlphaType alphaType) {
-    if (!SkColorTypeValidateAlphaType(info().colorType(), alphaType, &alphaType)) {
-        return;
-    }
-
-    mPixelRef->changeAlphaType(alphaType);
-}
-
-void Bitmap::detachFromJava() {
-    bool disposeSelf;
-    {
-        android::AutoMutex _lock(mLock);
-        mAttachedToJava = false;
-        disposeSelf = shouldDisposeSelfLocked();
-    }
-    if (disposeSelf) {
-        delete this;
-    }
-}
-
-bool Bitmap::shouldDisposeSelfLocked() {
-    return mPinnedRefCount == 0 && !mAttachedToJava;
-}
-
-
-void Bitmap::onStrongRefDestroyed() {
-    bool disposeSelf = false;
-    {
-        android::AutoMutex _lock(mLock);
-        if (mPinnedRefCount > 0) {
-            mPinnedRefCount--;
-            if (mPinnedRefCount == 0) {
-                disposeSelf = shouldDisposeSelfLocked();
-            }
-        }
-    }
-    if (disposeSelf) {
-        delete this;
-    }
-}
-
-void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
-    assertValid();
-    android::AutoMutex _lock(mLock);
-    // Safe because mPixelRef is a WrappedPixelRef type, otherwise rowBytes()
-    // would require locking the pixels first.
-    outBitmap->setInfo(mPixelRef->info(), mPixelRef->rowBytes());
-    outBitmap->setPixelRef(refPixelRefLocked())->unref();
-    outBitmap->setHasHardwareMipMap(hasHardwareMipMap());
-}
-
-void Bitmap::assertValid() const {
-    LOG_ALWAYS_FATAL_IF(mPixelStorageType == PixelStorageType::Invalid,
-            "Error, cannot access an invalid/free'd bitmap here!");
-}
-
-} // namespace android
-
-using namespace android;
-
 // Convenience class that does not take a global ref on the pixels, relying
 // on the caller already having a local JNI ref
 class LocalScopedBitmap {
@@ -333,7 +134,7 @@
     }
 
     void* pixels() {
-        return mBitmap->peekAtPixelRef()->pixels();
+        return mBitmap->pixelRef()->pixels();
     }
 
     bool valid() {
@@ -344,6 +145,78 @@
     Bitmap* mBitmap;
 };
 
+namespace bitmap {
+
+// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
+static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
+    // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
+    // irrelevant. This just tests to ensure that the SkAlphaType is not
+    // opposite of isPremultiplied.
+    if (isPremultiplied) {
+        SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
+    } else {
+        SkASSERT(info.alphaType() != kPremul_SkAlphaType);
+    }
+}
+
+void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
+        bool isPremultiplied)
+{
+    // The caller needs to have already set the alpha type properly, so the
+    // native SkBitmap stays in sync with the Java Bitmap.
+    assert_premultiplied(info, isPremultiplied);
+
+    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
+            info.width(), info.height(), isPremultiplied);
+}
+
+int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
+{
+    return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
+}
+
+jobject createBitmap(JNIEnv* env, PixelRef* pixelRef,
+        int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
+        int density) {
+    bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
+    bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
+    // The caller needs to have already set the alpha type properly, so the
+    // native SkBitmap stays in sync with the Java Bitmap.
+    assert_premultiplied(pixelRef->info(), isPremultiplied);
+    Bitmap* bitmap = new Bitmap(pixelRef);
+    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
+            reinterpret_cast<jlong>(bitmap), pixelRef->width(), pixelRef->height(), density, isMutable,
+            isPremultiplied, ninePatchChunk, ninePatchInsets);
+
+    if (env->ExceptionCheck() != 0) {
+        ALOGE("*** Uncaught exception returned from Java call!\n");
+        env->ExceptionDescribe();
+    }
+    return obj;
+}
+
+void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
+    LocalScopedBitmap bitmap(bitmapHandle);
+    bitmap->getSkBitmap(outBitmap);
+}
+
+PixelRef* toPixelRef(JNIEnv* env, jobject bitmap) {
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+    LocalScopedBitmap localBitmap(bitmapHandle);
+    localBitmap->assertValid();
+    return localBitmap->pixelRef();
+}
+
+} // namespace bitmap
+
+} // namespace android
+
+using namespace android;
+using namespace android::bitmap;
+
 ///////////////////////////////////////////////////////////////////////////////
 // Conversions to/from SkColor, for get/setPixels, and the create method, which
 // is basically like setPixels
@@ -649,8 +522,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 static int getPremulBitmapCreateFlags(bool isMutable) {
-    int flags = GraphicsJNI::kBitmapCreateFlag_Premultiplied;
-    if (isMutable) flags |= GraphicsJNI::kBitmapCreateFlag_Mutable;
+    int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
+    if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
     return flags;
 }
 
@@ -672,9 +545,10 @@
     }
 
     SkBitmap bitmap;
-    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType));
+    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
+            GraphicsJNI::defaultColorSpace()));
 
-    Bitmap* nativeBitmap = GraphicsJNI::allocateHeapPixelRef(&bitmap, NULL);
+    PixelRef* nativeBitmap = GraphicsJNI::allocateHeapPixelRef(&bitmap, NULL);
     if (!nativeBitmap) {
         return NULL;
     }
@@ -684,7 +558,7 @@
                 0, 0, width, height, bitmap);
     }
 
-    return GraphicsJNI::createBitmap(env, nativeBitmap,
+    return createBitmap(env, nativeBitmap,
             getPremulBitmapCreateFlags(isMutable));
 }
 
@@ -699,29 +573,28 @@
     if (!src.copyTo(&result, dstCT, &allocator)) {
         return NULL;
     }
-    Bitmap* bitmap = allocator.getStorageObjAndReset();
-    return GraphicsJNI::createBitmap(env, bitmap,
-            getPremulBitmapCreateFlags(isMutable));
+    auto pixelRef = allocator.getStorageObjAndReset();
+    return createBitmap(env, pixelRef, getPremulBitmapCreateFlags(isMutable));
 }
 
-static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
+static PixelRef* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
     SkBitmap result;
 
     AshmemPixelAllocator allocator(env);
     if (!src.copyTo(&result, dstCT, &allocator)) {
         return NULL;
     }
-    Bitmap* bitmap = allocator.getStorageObjAndReset();
-    bitmap->peekAtPixelRef()->setImmutable();
-    return bitmap;
+    auto pixelRef = allocator.getStorageObjAndReset();
+    pixelRef->setImmutable();
+    return pixelRef;
 }
 
 static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
     SkBitmap src;
     reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
     SkColorType dstCT = src.colorType();
-    Bitmap* bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
-    jobject ret = GraphicsJNI::createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
+    auto pixelRef = Bitmap_copyAshmemImpl(env, src, dstCT);
+    jobject ret = createBitmap(env, pixelRef, getPremulBitmapCreateFlags(false));
     return ret;
 }
 
@@ -729,13 +602,13 @@
     SkBitmap src;
     reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
     SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
-    Bitmap* bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
-    jobject ret = GraphicsJNI::createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
+    auto pixelRef = Bitmap_copyAshmemImpl(env, src, dstCT);
+    jobject ret = createBitmap(env, pixelRef, getPremulBitmapCreateFlags(false));
     return ret;
 }
 
 static void Bitmap_destruct(Bitmap* bitmap) {
-    bitmap->detachFromJava();
+    delete bitmap;
 }
 
 static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
@@ -751,6 +624,7 @@
 static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
         jint width, jint height, jint configHandle, jboolean requestPremul) {
     LocalScopedBitmap bitmap(bitmapHandle);
+    bitmap->assertValid();
     SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
 
     // ARGB_4444 is a deprecated format, convert automatically to 8888
@@ -773,7 +647,8 @@
         // Otherwise respect the premultiplied request.
         alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
     }
-    bitmap->reconfigure(SkImageInfo::Make(width, height, colorType, alphaType));
+    bitmap->pixelRef()->reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
+            sk_sp<SkColorSpace>(bitmap->info().colorSpace())));
 }
 
 // These must match the int values in Bitmap.java
@@ -843,7 +718,7 @@
 
 static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
     LocalScopedBitmap bitmap(bitmapHandle);
-    return static_cast<jint>(bitmap->peekAtPixelRef()->getGenerationID());
+    return static_cast<jint>(bitmap->getGenerationID());
 }
 
 static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
@@ -906,6 +781,7 @@
     const bool        isMutable = p->readInt32() != 0;
     const SkColorType colorType = (SkColorType)p->readInt32();
     const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
+    const bool        isSRGB = p->readInt32() != 0;
     const int         width = p->readInt32();
     const int         height = p->readInt32();
     const int         rowBytes = p->readInt32();
@@ -922,7 +798,8 @@
 
     std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
 
-    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType), rowBytes)) {
+    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType,
+            isSRGB ? SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named) : nullptr), rowBytes)) {
         return NULL;
     }
 
@@ -955,7 +832,7 @@
     }
 
     // Map the bitmap in place from the ashmem region if possible otherwise copy.
-    Bitmap* nativeBitmap;
+    PixelRef* nativeBitmap;
     if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
 #if DEBUG_PARCEL
         ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
@@ -1018,7 +895,7 @@
         blob.release();
     }
 
-    return GraphicsJNI::createBitmap(env, nativeBitmap,
+    return createBitmap(env, nativeBitmap,
             getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
 }
 
@@ -1034,12 +911,16 @@
     android::Parcel* p = android::parcelForJavaObject(env, parcel);
     SkBitmap bitmap;
 
-    android::Bitmap* androidBitmap = reinterpret_cast<Bitmap*>(bitmapHandle);
+    auto androidBitmap = reinterpret_cast<Bitmap*>(bitmapHandle);
     androidBitmap->getSkBitmap(&bitmap);
 
+    sk_sp<SkColorSpace> sRGB = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+    bool isSRGB = bitmap.colorSpace() == sRGB.get();
+
     p->writeInt32(isMutable);
     p->writeInt32(bitmap.colorType());
     p->writeInt32(bitmap.alphaType());
+    p->writeInt32(isSRGB); // TODO: We should write the color space (b/32072280)
     p->writeInt32(bitmap.width());
     p->writeInt32(bitmap.height());
     p->writeInt32(bitmap.rowBytes());
@@ -1061,7 +942,7 @@
 
     // Transfer the underlying ashmem region if we have one and it's immutable.
     android::status_t status;
-    int fd = androidBitmap->getAshmemFd();
+    int fd = androidBitmap->pixelRef()->getAshmemFd();
     if (fd >= 0 && !isMutable && p->allowFds()) {
 #if DEBUG_PARCEL
         ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
@@ -1131,7 +1012,7 @@
         env->ReleaseIntArrayElements(offsetXY, array, 0);
     }
 
-    return GraphicsJNI::createBitmap(env, allocator.getStorageObjAndReset(),
+    return createBitmap(env, allocator.getStorageObjAndReset(),
             getPremulBitmapCreateFlags(true));
 }
 
@@ -1252,7 +1133,9 @@
     reinterpret_cast<Bitmap*>(bm1Handle)->getSkBitmap(&bm1);
     if (bm0.width() != bm1.width() ||
         bm0.height() != bm1.height() ||
-        bm0.colorType() != bm1.colorType()) {
+        bm0.colorType() != bm1.colorType() ||
+        bm0.alphaType() != bm1.alphaType() ||
+        bm0.colorSpace() != bm1.colorSpace()) {
         return JNI_FALSE;
     }
 
@@ -1307,7 +1190,7 @@
 
 static jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) {
     LocalScopedBitmap bitmap(bitmapHandle);
-    SkPixelRef* pixelRef = bitmap.valid() ? bitmap->peekAtPixelRef() : nullptr;
+    SkPixelRef* pixelRef = bitmap->pixelRef();
     SkSafeRef(pixelRef);
     return reinterpret_cast<jlong>(pixelRef);
 }
@@ -1326,6 +1209,20 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+static jclass make_globalref(JNIEnv* env, const char classname[])
+{
+    jclass c = env->FindClass(classname);
+    SkASSERT(c);
+    return (jclass) env->NewGlobalRef(c);
+}
+
+static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
+                                const char fieldname[], const char type[])
+{
+    jfieldID id = env->GetFieldID(clazz, fieldname, type);
+    SkASSERT(id);
+    return id;
+}
 
 static const JNINativeMethod gBitmapMethods[] = {
     {   "nativeCreate",             "([IIIIIIZ)Landroid/graphics/Bitmap;",
@@ -1374,6 +1271,11 @@
 
 int register_android_graphics_Bitmap(JNIEnv* env)
 {
+    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
+    gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
+    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
+    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
+    gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
     return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
                                          NELEM(gBitmapMethods));
-}
+}
\ No newline at end of file
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
index 9ae1f3f..588a99c 100644
--- a/core/jni/android/graphics/Bitmap.h
+++ b/core/jni/android/graphics/Bitmap.h
@@ -20,98 +20,38 @@
 #include <SkBitmap.h>
 #include <SkColorTable.h>
 #include <SkImageInfo.h>
-#include <utils/Mutex.h>
-#include <memory>
+#include <SkPixelRef.h>
 
 namespace android {
 
-enum class PixelStorageType {
-    Invalid,
-    External,
-    Heap,
-    Ashmem,
+class PixelRef;
+
+namespace bitmap {
+
+enum BitmapCreateFlags {
+    kBitmapCreateFlag_None = 0x0,
+    kBitmapCreateFlag_Mutable = 0x1,
+    kBitmapCreateFlag_Premultiplied = 0x2,
 };
 
-class WrappedPixelRef;
+jobject createBitmap(JNIEnv* env, PixelRef* bitmap,
+            int bitmapCreateFlags, jbyteArray ninePatchChunk = NULL,
+            jobject ninePatchInsets = NULL, int density = -1);
 
-typedef void (*FreeFunc)(void* addr, void* context);
 
-/**
- * Glue-thingy that deals with managing the interaction between the Java
- * Bitmap object & SkBitmap along with trying to map a notion of strong/weak
- * lifecycles onto SkPixelRef which only has strong counts to avoid requiring
- * two GC passes to free the byte[] that backs a Bitmap.
- *
- * Since not all Bitmaps are byte[]-backed it also supports external allocations,
- * which currently is used by screenshots to wrap a gralloc buffer.
- */
-class Bitmap {
-public:
-    Bitmap(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes,
-            SkColorTable* ctable);
-    Bitmap(void* address, void* context, FreeFunc freeFunc,
-            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
-    Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info,
-            size_t rowBytes, SkColorTable* ctable);
+void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap);
 
-    const SkImageInfo& info() const;
+PixelRef* toPixelRef(JNIEnv* env, jobject bitmap);
 
-    int width() const { return info().width(); }
-    int height() const { return info().height(); }
-    size_t rowBytes() const;
-    SkPixelRef* peekAtPixelRef() const;
-    SkPixelRef* refPixelRef();
-    bool valid() const { return mPixelStorageType != PixelStorageType::Invalid; }
+/** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
+    sync with isPremultiplied
+*/
+void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
+        bool isPremultiplied);
 
-    void reconfigure(const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
-    void reconfigure(const SkImageInfo& info);
-    void setAlphaType(SkAlphaType alphaType);
+int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap);
 
-    void getSkBitmap(SkBitmap* outBitmap);
-    void detachFromJava();
-
-    void freePixels();
-
-    bool hasHardwareMipMap();
-    void setHasHardwareMipMap(bool hasMipMap);
-    int getAshmemFd() const;
-    size_t getAllocationByteCount() const;
-
-private:
-    friend class WrappedPixelRef;
-
-    ~Bitmap();
-    void doFreePixels();
-    void onStrongRefDestroyed();
-
-    void pinPixelsLocked();
-    bool shouldDisposeSelfLocked();
-    void assertValid() const;
-    SkPixelRef* refPixelRefLocked();
-
-    android::Mutex mLock;
-    int mPinnedRefCount = 0;
-    std::unique_ptr<WrappedPixelRef> mPixelRef;
-    PixelStorageType mPixelStorageType;
-    bool mAttachedToJava = true;
-
-    union {
-        struct {
-            void* address;
-            void* context;
-            FreeFunc freeFunc;
-        } external;
-        struct {
-            void* address;
-            int fd;
-            size_t size;
-        } ashmem;
-        struct {
-            void* address;
-            size_t size;
-        } heap;
-    } mPixelStorage;
-};
+} // namespace bitmap
 
 } // namespace android
 
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 5a540ce..ad39a57 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -162,7 +162,7 @@
 
 class RecyclingPixelAllocator : public SkBitmap::Allocator {
 public:
-    RecyclingPixelAllocator(android::Bitmap* bitmap, unsigned int size)
+    RecyclingPixelAllocator(android::PixelRef* bitmap, unsigned int size)
             : mBitmap(bitmap), mSize(size) {
     }
 
@@ -190,7 +190,8 @@
         }
 
         mBitmap->reconfigure(info, bitmap->rowBytes(), ctable);
-        bitmap->setPixelRef(mBitmap->refPixelRef())->unref();
+        mBitmap->ref();
+        bitmap->setPixelRef(mBitmap)->unref();
 
         // since we're already allocated, we lockPixels right away
         // HeapAllocator behaves this way too
@@ -199,7 +200,7 @@
     }
 
 private:
-    android::Bitmap* const mBitmap;
+    android::PixelRef* const mBitmap;
     const unsigned int mSize;
 };
 
@@ -326,16 +327,16 @@
         scaledHeight = static_cast<int>(scaledHeight * scale + 0.5f);
     }
 
-    android::Bitmap* reuseBitmap = nullptr;
+    android::PixelRef* reuseBitmap = nullptr;
     unsigned int existingBufferSize = 0;
     if (javaBitmap != NULL) {
-        reuseBitmap = GraphicsJNI::getBitmap(env, javaBitmap);
-        if (reuseBitmap->peekAtPixelRef()->isImmutable()) {
+        reuseBitmap = bitmap::toPixelRef(env, javaBitmap);
+        if (reuseBitmap->isImmutable()) {
             ALOGW("Unable to reuse an immutable bitmap as an image decoder target.");
             javaBitmap = NULL;
             reuseBitmap = nullptr;
         } else {
-            existingBufferSize = GraphicsJNI::getBitmapAllocationByteCount(env, javaBitmap);
+            existingBufferSize = bitmap::getBitmapAllocationByteCount(env, javaBitmap);
         }
     }
 
@@ -384,11 +385,8 @@
     // Set the alpha type for the decode.
     SkAlphaType alphaType = codec->computeOutputAlphaType(requireUnpremultiplied);
 
-    // Enable legacy behavior to avoid any gamma correction.  Android's assets are
-    // adjusted to expect a non-gamma correct premultiply.
-    sk_sp<SkColorSpace> colorSpace = nullptr;
-    const SkImageInfo decodeInfo = SkImageInfo::Make(size.width(), size.height(), decodeColorType,
-                                                     alphaType, colorSpace);
+    const SkImageInfo decodeInfo = SkImageInfo::Make(size.width(), size.height(),
+            decodeColorType, alphaType, GraphicsJNI::defaultColorSpace());
 
     SkImageInfo bitmapInfo = decodeInfo;
     if (decodeColorType == kGray_8_SkColorType) {
@@ -412,7 +410,7 @@
 
     // Use SkAndroidCodec to perform the decode.
     SkAndroidCodec::AndroidOptions codecOptions;
-    codecOptions.fZeroInitialized =  decodeAllocator == &defaultAllocator ?
+    codecOptions.fZeroInitialized = decodeAllocator == &defaultAllocator ?
             SkCodec::kYes_ZeroInitialized : SkCodec::kNo_ZeroInitialized;
     codecOptions.fColorPtr = colorPtr;
     codecOptions.fColorCount = colorCount;
@@ -451,8 +449,10 @@
     jobject ninePatchInsets = NULL;
     if (peeker.mHasInsets) {
         ninePatchInsets = env->NewObject(gInsetStruct_class, gInsetStruct_constructorMethodID,
-                peeker.mOpticalInsets[0], peeker.mOpticalInsets[1], peeker.mOpticalInsets[2], peeker.mOpticalInsets[3],
-                peeker.mOutlineInsets[0], peeker.mOutlineInsets[1], peeker.mOutlineInsets[2], peeker.mOutlineInsets[3],
+                peeker.mOpticalInsets[0], peeker.mOpticalInsets[1],
+                peeker.mOpticalInsets[2], peeker.mOpticalInsets[3],
+                peeker.mOutlineInsets[0], peeker.mOutlineInsets[1],
+                peeker.mOutlineInsets[2], peeker.mOutlineInsets[3],
                 peeker.mOutlineRadius, peeker.mOutlineAlpha, scale);
         if (ninePatchInsets == NULL) {
             return nullObjectReturn("nine patch insets == null");
@@ -494,11 +494,11 @@
         }
 
         SkPaint paint;
-        // kSrc_Mode instructs us to overwrite the unininitialized pixels in
+        // kSrc_Mode instructs us to overwrite the uninitialized pixels in
         // outputBitmap.  Otherwise we would blend by default, which is not
         // what we want.
-        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
-        paint.setFilterQuality(kLow_SkFilterQuality);
+        paint.setBlendMode(SkBlendMode::kSrc);
+        paint.setFilterQuality(kLow_SkFilterQuality); // bilinear filtering
 
         SkCanvas canvas(outputBitmap);
         canvas.scale(sx, sy);
@@ -529,18 +529,18 @@
 
     bool isPremultiplied = !requireUnpremultiplied;
     if (javaBitmap != nullptr) {
-        GraphicsJNI::reinitBitmap(env, javaBitmap, outputBitmap.info(), isPremultiplied);
+        bitmap::reinitBitmap(env, javaBitmap, outputBitmap.info(), isPremultiplied);
         outputBitmap.notifyPixelsChanged();
         // If a java bitmap was passed in for reuse, pass it back
         return javaBitmap;
     }
 
     int bitmapCreateFlags = 0x0;
-    if (isMutable) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Mutable;
-    if (isPremultiplied) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Premultiplied;
+    if (isMutable) bitmapCreateFlags |= android::bitmap::kBitmapCreateFlag_Mutable;
+    if (isPremultiplied) bitmapCreateFlags |= android::bitmap::kBitmapCreateFlag_Premultiplied;
 
     // now create the java bitmap
-    return GraphicsJNI::createBitmap(env, defaultAllocator.getStorageObjAndReset(),
+    return bitmap::createBitmap(env, defaultAllocator.getStorageObjAndReset(),
             bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1);
 }
 
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 21850bd..7d0915b 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -148,14 +148,14 @@
     }
 
     // Recycle a bitmap if possible.
-    android::Bitmap* recycledBitmap = nullptr;
+    android::PixelRef* recycledBitmap = nullptr;
     size_t recycledBytes = 0;
     if (javaBitmap) {
-        recycledBitmap = GraphicsJNI::getBitmap(env, javaBitmap);
-        if (recycledBitmap->peekAtPixelRef()->isImmutable()) {
+        recycledBitmap = bitmap::toPixelRef(env, javaBitmap);
+        if (recycledBitmap->isImmutable()) {
             ALOGW("Warning: Reusing an immutable bitmap as an image decoder target.");
         }
-        recycledBytes = GraphicsJNI::getBitmapAllocationByteCount(env, javaBitmap);
+        recycledBytes = bitmap::getBitmapAllocationByteCount(env, javaBitmap);
     }
 
     // Set up the pixel allocator
@@ -198,9 +198,9 @@
 
     int bitmapCreateFlags = 0;
     if (!requireUnpremul) {
-        bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Premultiplied;
+        bitmapCreateFlags |= android::bitmap::kBitmapCreateFlag_Premultiplied;
     }
-    return GraphicsJNI::createBitmap(env, heapAlloc.getStorageObjAndReset(), bitmapCreateFlags);
+    return android::bitmap::createBitmap(env, heapAlloc.getStorageObjAndReset(), bitmapCreateFlags);
 }
 
 static jint nativeGetHeight(JNIEnv* env, jobject, jlong brdHandle) {
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index 1a86e5f..79439e2 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -21,7 +21,6 @@
 
 #include "SkColorFilter.h"
 #include "SkColorMatrixFilter.h"
-#include "SkXfermode.h"
 
 #include <Caches.h>
 
@@ -33,16 +32,16 @@
 public:
     static void finalizer(JNIEnv* env, jobject clazz, jlong skFilterHandle) {
         SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(skFilterHandle);
-        if (filter) SkSafeUnref(filter);
+        SkSafeUnref(filter);
     }
 
     static jlong CreatePorterDuffFilter(JNIEnv* env, jobject, jint srcColor, jint modeHandle) {
-        SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
-        return reinterpret_cast<jlong>(SkColorFilter::CreateModeFilter(srcColor, mode));
+        SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
+        return reinterpret_cast<jlong>(SkColorFilter::MakeModeFilter(srcColor, mode).release());
     }
 
     static jlong CreateLightingFilter(JNIEnv* env, jobject, jint mul, jint add) {
-        return reinterpret_cast<jlong>(SkColorMatrixFilter::CreateLightingFilter(mul, add));
+        return reinterpret_cast<jlong>(SkColorMatrixFilter::MakeLightingFilter(mul, add).release());
     }
 
     static jlong CreateColorMatrixFilter(JNIEnv* env, jobject, jfloatArray jarray) {
@@ -50,7 +49,7 @@
         const float* src = autoArray.ptr();
 
 #ifdef SK_SCALAR_IS_FLOAT
-        return reinterpret_cast<jlong>(SkColorMatrixFilter::Create(src));
+        return reinterpret_cast<jlong>(SkColorFilter::MakeMatrixFilterRowMajor255(src).release());
 #else
         SkASSERT(false);
 #endif
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 8cee814..82b70fc 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -157,12 +157,6 @@
 static jfieldID gPointF_xFieldID;
 static jfieldID gPointF_yFieldID;
 
-static jclass   gBitmap_class;
-static jfieldID gBitmap_nativePtr;
-static jmethodID gBitmap_constructorMethodID;
-static jmethodID gBitmap_reinitMethodID;
-static jmethodID gBitmap_getAllocationByteCountMethodID;
-
 static jclass   gBitmapConfig_class;
 static jfieldID gBitmapConfig_nativeInstanceID;
 
@@ -342,24 +336,15 @@
     return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]);
 }
 
-android::Bitmap* GraphicsJNI::getBitmap(JNIEnv* env, jobject bitmap) {
-    SkASSERT(env);
-    SkASSERT(bitmap);
-    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
-    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-    android::Bitmap* b = reinterpret_cast<android::Bitmap*>(bitmapHandle);
-    SkASSERT(b);
-    return b;
-}
-
 void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) {
-    getBitmap(env, bitmap)->getSkBitmap(outBitmap);
+    android::bitmap::toPixelRef(env, bitmap)->getSkBitmap(outBitmap);
 }
 
 SkPixelRef* GraphicsJNI::refSkPixelRef(JNIEnv* env, jobject bitmap) {
-    return getBitmap(env, bitmap)->refPixelRef();
+    SkPixelRef* pixelRef = android::bitmap::toPixelRef(env, bitmap);
+    pixelRef->ref();
+    return pixelRef;
 }
-
 SkColorType GraphicsJNI::getNativeBitmapColorType(JNIEnv* env, jobject jconfig) {
     SkASSERT(env);
     if (NULL == jconfig) {
@@ -394,50 +379,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 
-// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
-static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
-    // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
-    // irrelevant. This just tests to ensure that the SkAlphaType is not
-    // opposite of isPremultiplied.
-    if (isPremultiplied) {
-        SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
-    } else {
-        SkASSERT(info.alphaType() != kPremul_SkAlphaType);
-    }
-}
-
-jobject GraphicsJNI::createBitmap(JNIEnv* env, android::Bitmap* bitmap,
-        int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
-        int density) {
-    bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
-    bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
-    // The caller needs to have already set the alpha type properly, so the
-    // native SkBitmap stays in sync with the Java Bitmap.
-    assert_premultiplied(bitmap->info(), isPremultiplied);
-
-    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
-            reinterpret_cast<jlong>(bitmap), bitmap->width(), bitmap->height(), density, isMutable,
-            isPremultiplied, ninePatchChunk, ninePatchInsets);
-    hasException(env); // For the side effect of logging.
-    return obj;
-}
-
-void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
-        bool isPremultiplied)
-{
-    // The caller needs to have already set the alpha type properly, so the
-    // native SkBitmap stays in sync with the Java Bitmap.
-    assert_premultiplied(info, isPremultiplied);
-
-    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
-            info.width(), info.height(), isPremultiplied);
-}
-
-int GraphicsJNI::getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
-{
-    return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
-}
-
 jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap)
 {
     SkASSERT(bitmap != NULL);
@@ -482,7 +423,7 @@
     return true;
 }
 
-android::Bitmap* GraphicsJNI::allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
+android::PixelRef* GraphicsJNI::allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
     const SkImageInfo& info = bitmap->info();
     if (info.colorType() == kUnknown_SkColorType) {
         LOG_ALWAYS_FATAL("unknown bitmap configuration");
@@ -503,7 +444,7 @@
         return nullptr;
     }
 
-    android::Bitmap* wrapper = new android::Bitmap(addr, size, info, rowBytes, ctable);
+    auto wrapper = new android::PixelRef(addr, size, info, rowBytes, ctable);
     wrapper->getSkBitmap(bitmap);
     // since we're already allocated, we lockPixels right away
     // HeapAllocator behaves this way too
@@ -566,7 +507,7 @@
     return true;
 }
 
-android::Bitmap* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
+android::PixelRef* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
                                                      SkColorTable* ctable) {
     int fd;
 
@@ -603,7 +544,7 @@
         return nullptr;
     }
 
-    android::Bitmap* wrapper = new android::Bitmap(addr, fd, size, info, rowBytes, ctable);
+    auto wrapper = new android::PixelRef(addr, fd, size, info, rowBytes, ctable);
     wrapper->getSkBitmap(bitmap);
     // since we're already allocated, we lockPixels right away
     // HeapAllocator behaves this way too
@@ -612,7 +553,7 @@
     return wrapper;
 }
 
-android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
+android::PixelRef* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
         SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly) {
     const SkImageInfo& info = bitmap->info();
     if (info.colorType() == kUnknown_SkColorType) {
@@ -634,7 +575,7 @@
     // attempting to compute our own.
     const size_t rowBytes = bitmap->rowBytes();
 
-    android::Bitmap* wrapper = new android::Bitmap(addr, fd, size, info, rowBytes, ctable);
+    auto wrapper = new android::PixelRef(addr, fd, size, info, rowBytes, ctable);
     wrapper->getSkBitmap(bitmap);
     if (readOnly) {
         bitmap->pixelRef()->setImmutable();
@@ -646,25 +587,24 @@
     return wrapper;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
-HeapAllocator::HeapAllocator() {}
-
-HeapAllocator::~HeapAllocator() {
-    if (mStorage) {
-        mStorage->detachFromJava();
-    }
+sk_sp<SkColorSpace> GraphicsJNI::defaultColorSpace() {
+#ifdef ANDROID_ENABLE_LINEAR_BLENDING
+    return SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+#else
+    return nullptr;
+#endif
 }
 
+///////////////////////////////////////////////////////////////////////////////
 bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
-    mStorage = GraphicsJNI::allocateHeapPixelRef(bitmap, ctable);
-    return mStorage != nullptr;
+    mStorage.reset(GraphicsJNI::allocateHeapPixelRef(bitmap, ctable));
+    return !!mStorage;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 RecyclingClippingPixelAllocator::RecyclingClippingPixelAllocator(
-        android::Bitmap* recycledBitmap, size_t recycledBytes)
+        android::PixelRef* recycledBitmap, size_t recycledBytes)
     : mRecycledBitmap(recycledBitmap)
     , mRecycledBytes(recycledBytes)
     , mSkiaBitmap(nullptr)
@@ -707,7 +647,8 @@
         // skbug.com/4538: We also need to make sure that the rowBytes on the pixel ref
         //                 match the rowBytes on the bitmap.
         bitmap->setInfo(bitmap->info(), rowBytes);
-        bitmap->setPixelRef(mRecycledBitmap->refPixelRef())->unref();
+        mRecycledBitmap->ref();
+        bitmap->setPixelRef(mRecycledBitmap)->unref();
 
         // Make sure that the recycled bitmap has the correct alpha type.
         mRecycledBitmap->setAlphaType(bitmap->alphaType());
@@ -734,7 +675,8 @@
 
 void RecyclingClippingPixelAllocator::copyIfNecessary() {
     if (mNeedsCopy) {
-        SkPixelRef* recycledPixels = mRecycledBitmap->refPixelRef();
+        mRecycledBitmap->ref();
+        SkPixelRef* recycledPixels = mRecycledBitmap;
         void* dst = recycledPixels->pixels();
         const size_t dstRowBytes = mRecycledBitmap->rowBytes();
         const size_t bytesToCopy = std::min(mRecycledBitmap->info().minRowBytes(),
@@ -759,16 +701,10 @@
             "env->GetJavaVM failed");
 }
 
-AshmemPixelAllocator::~AshmemPixelAllocator() {
-    if (mStorage) {
-        mStorage->detachFromJava();
-    }
-}
-
 bool AshmemPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
     JNIEnv* env = vm2env(mJavaVM);
-    mStorage = GraphicsJNI::allocateAshmemPixelRef(env, bitmap, ctable);
-    return mStorage != nullptr;
+    mStorage.reset(GraphicsJNI::allocateAshmemPixelRef(env, bitmap, ctable));
+    return !!mStorage;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -813,11 +749,6 @@
     gPointF_xFieldID = getFieldIDCheck(env, gPointF_class, "x", "F");
     gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F");
 
-    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
-    gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
-    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
-    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
-    gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
     gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder");
     gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(J)V");
 
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 738ad54..cf617bd 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -10,8 +10,10 @@
 #include "SkMallocPixelRef.h"
 #include "SkPoint.h"
 #include "SkRect.h"
+#include "SkColorSpace.h"
 #include <jni.h>
 #include <hwui/Canvas.h>
+#include <hwui/PixelRef.h>
 
 class SkBitmapRegionDecoder;
 class SkCanvas;
@@ -23,12 +25,6 @@
 
 class GraphicsJNI {
 public:
-    enum BitmapCreateFlags {
-        kBitmapCreateFlag_None = 0x0,
-        kBitmapCreateFlag_Mutable = 0x1,
-        kBitmapCreateFlag_Premultiplied = 0x2,
-    };
-
     // returns true if an exception is set (and dumps it out to the Log)
     static bool hasException(JNIEnv*);
 
@@ -51,14 +47,13 @@
     static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
 
     static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
-    static android::Bitmap* getBitmap(JNIEnv*, jobject bitmap);
     static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
     static SkPixelRef* refSkPixelRef(JNIEnv*, jobject bitmap);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
 
     // Given the 'native' long held by the Rasterizer.java object, return a
     // ref to its SkRasterizer* (or NULL).
-    static SkRasterizer* refNativeRasterizer(jlong rasterizerHandle);
+    static sk_sp<SkRasterizer> refNativeRasterizer(jlong rasterizerHandle);
 
     /*
      *  LegacyBitmapConfig is the old enum in Skia that matched the enum int values
@@ -73,32 +68,16 @@
     */
     static SkColorType getNativeBitmapColorType(JNIEnv*, jobject jconfig);
 
-    /*
-     * Create a java Bitmap object given the native bitmap
-     * bitmap's SkAlphaType must already be in sync with bitmapCreateFlags.
-    */
-    static jobject createBitmap(JNIEnv* env, android::Bitmap* bitmap,
-            int bitmapCreateFlags, jbyteArray ninePatchChunk = NULL,
-            jobject ninePatchInsets = NULL, int density = -1);
-
-    /** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
-        sync with isPremultiplied
-    */
-    static void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
-            bool isPremultiplied);
-
-    static int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap);
-
     static jobject createRegion(JNIEnv* env, SkRegion* region);
 
     static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap);
 
-    static android::Bitmap* allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
+    static android::PixelRef* allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
 
-    static android::Bitmap* allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
+    static android::PixelRef* allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
             SkColorTable* ctable);
 
-    static android::Bitmap* mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
+    static android::PixelRef* mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
             SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly);
 
     /**
@@ -116,27 +95,27 @@
     static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
             int srcStride, int x, int y, int width, int height,
             const SkBitmap& dstBitmap);
+
+    static sk_sp<SkColorSpace> defaultColorSpace();
 };
 
 class HeapAllocator : public SkBRDAllocator {
 public:
-   HeapAllocator();
-    ~HeapAllocator();
+   HeapAllocator() { };
+    ~HeapAllocator() { };
 
     virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) override;
 
     /**
      * Fetches the backing allocation object. Must be called!
      */
-    android::Bitmap* getStorageObjAndReset() {
-        android::Bitmap* result = mStorage;
-        mStorage = NULL;
-        return result;
+    android::PixelRef* getStorageObjAndReset() {
+        return mStorage.release();
     };
 
     SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kYes_ZeroInitialized; }
 private:
-    android::Bitmap* mStorage = nullptr;
+    sk_sp<android::PixelRef> mStorage;
 };
 
 /**
@@ -169,7 +148,7 @@
 class RecyclingClippingPixelAllocator : public SkBRDAllocator {
 public:
 
-    RecyclingClippingPixelAllocator(android::Bitmap* recycledBitmap,
+    RecyclingClippingPixelAllocator(android::PixelRef* recycledBitmap,
             size_t recycledBytes);
 
     ~RecyclingClippingPixelAllocator();
@@ -194,7 +173,7 @@
     SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kNo_ZeroInitialized; }
 
 private:
-    android::Bitmap* mRecycledBitmap;
+    android::PixelRef* mRecycledBitmap;
     const size_t     mRecycledBytes;
     SkBitmap*        mSkiaBitmap;
     bool             mNeedsCopy;
@@ -203,17 +182,15 @@
 class AshmemPixelAllocator : public SkBitmap::Allocator {
 public:
     explicit AshmemPixelAllocator(JNIEnv* env);
-    ~AshmemPixelAllocator();
+    ~AshmemPixelAllocator() { };
     virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
-    android::Bitmap* getStorageObjAndReset() {
-        android::Bitmap* result = mStorage;
-        mStorage = NULL;
-        return result;
+    android::PixelRef* getStorageObjAndReset() {
+        return mStorage.release();
     };
 
 private:
     JavaVM* mJavaVM;
-    android::Bitmap* mStorage = nullptr;
+    sk_sp<android::PixelRef> mStorage;
 };
 
 
diff --git a/core/jni/android/graphics/MaskFilter.cpp b/core/jni/android/graphics/MaskFilter.cpp
index 2b4a1ab..3e3de5a 100644
--- a/core/jni/android/graphics/MaskFilter.cpp
+++ b/core/jni/android/graphics/MaskFilter.cpp
@@ -23,7 +23,7 @@
 
     static jlong createBlur(JNIEnv* env, jobject, jfloat radius, jint blurStyle) {
         SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
-        SkMaskFilter* filter = SkBlurMaskFilter::Create((SkBlurStyle)blurStyle, sigma);
+        SkMaskFilter* filter = SkBlurMaskFilter::Make((SkBlurStyle)blurStyle, sigma).release();
         ThrowIAE_IfNull(env, filter);
         return reinterpret_cast<jlong>(filter);
     }
@@ -38,8 +38,8 @@
         }
 
         SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
-        SkMaskFilter* filter =  SkBlurMaskFilter::CreateEmboss(sigma,
-                direction, ambient, specular);
+        SkMaskFilter* filter =  SkBlurMaskFilter::MakeEmboss(sigma,
+                direction, ambient, specular).release();
         ThrowIAE_IfNull(env, filter);
         return reinterpret_cast<jlong>(filter);
     }
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 4b1530a..38452bb 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -29,6 +29,7 @@
 #include "SkColorFilter.h"
 #include "SkMaskFilter.h"
 #include "SkPath.h"
+#include "SkPathEffect.h"
 #include "SkRasterizer.h"
 #include "SkShader.h"
 #include "SkXfermode.h"
@@ -791,51 +792,55 @@
     static jlong setShader(jlong objHandle, jlong shaderHandle) {
         Paint* obj = reinterpret_cast<Paint*>(objHandle);
         SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
-        return reinterpret_cast<jlong>(obj->setShader(shader));
+        obj->setShader(sk_ref_sp(shader));
+        return reinterpret_cast<jlong>(obj->getShader());
     }
 
     static jlong setColorFilter(jlong objHandle, jlong filterHandle) {
         Paint* obj = reinterpret_cast<Paint *>(objHandle);
         SkColorFilter* filter  = reinterpret_cast<SkColorFilter *>(filterHandle);
-        return reinterpret_cast<jlong>(obj->setColorFilter(filter));
+        obj->setColorFilter(sk_ref_sp(filter));
+        return reinterpret_cast<jlong>(obj->getColorFilter());
     }
 
     static void setXfermode(jlong paintHandle, jint xfermodeHandle) {
         // validate that the Java enum values match our expectations
-        static_assert(0 == SkXfermode::kClear_Mode, "xfermode_mismatch");
-        static_assert(1 == SkXfermode::kSrc_Mode, "xfermode_mismatch");
-        static_assert(2 == SkXfermode::kDst_Mode, "xfermode_mismatch");
-        static_assert(3 == SkXfermode::kSrcOver_Mode, "xfermode_mismatch");
-        static_assert(4 == SkXfermode::kDstOver_Mode, "xfermode_mismatch");
-        static_assert(5 == SkXfermode::kSrcIn_Mode, "xfermode_mismatch");
-        static_assert(6 == SkXfermode::kDstIn_Mode, "xfermode_mismatch");
-        static_assert(7 == SkXfermode::kSrcOut_Mode, "xfermode_mismatch");
-        static_assert(8 == SkXfermode::kDstOut_Mode, "xfermode_mismatch");
-        static_assert(9 == SkXfermode::kSrcATop_Mode, "xfermode_mismatch");
-        static_assert(10 == SkXfermode::kDstATop_Mode, "xfermode_mismatch");
-        static_assert(11 == SkXfermode::kXor_Mode, "xfermode_mismatch");
-        static_assert(16 == SkXfermode::kDarken_Mode, "xfermode_mismatch");
-        static_assert(17 == SkXfermode::kLighten_Mode, "xfermode_mismatch");
-        static_assert(13 == SkXfermode::kModulate_Mode, "xfermode_mismatch");
-        static_assert(14 == SkXfermode::kScreen_Mode, "xfermode_mismatch");
-        static_assert(12 == SkXfermode::kPlus_Mode, "xfermode_mismatch");
-        static_assert(15 == SkXfermode::kOverlay_Mode, "xfermode_mismatch");
+        static_assert(0 == static_cast<int>(SkBlendMode::kClear), "xfermode_mismatch");
+        static_assert(1 == static_cast<int>(SkBlendMode::kSrc), "xfermode_mismatch");
+        static_assert(2 == static_cast<int>(SkBlendMode::kDst), "xfermode_mismatch");
+        static_assert(3 == static_cast<int>(SkBlendMode::kSrcOver), "xfermode_mismatch");
+        static_assert(4 == static_cast<int>(SkBlendMode::kDstOver), "xfermode_mismatch");
+        static_assert(5 == static_cast<int>(SkBlendMode::kSrcIn), "xfermode_mismatch");
+        static_assert(6 == static_cast<int>(SkBlendMode::kDstIn), "xfermode_mismatch");
+        static_assert(7 == static_cast<int>(SkBlendMode::kSrcOut), "xfermode_mismatch");
+        static_assert(8 == static_cast<int>(SkBlendMode::kDstOut), "xfermode_mismatch");
+        static_assert(9 == static_cast<int>(SkBlendMode::kSrcATop), "xfermode_mismatch");
+        static_assert(10 == static_cast<int>(SkBlendMode::kDstATop), "xfermode_mismatch");
+        static_assert(11 == static_cast<int>(SkBlendMode::kXor), "xfermode_mismatch");
+        static_assert(16 == static_cast<int>(SkBlendMode::kDarken), "xfermode_mismatch");
+        static_assert(17 == static_cast<int>(SkBlendMode::kLighten), "xfermode_mismatch");
+        static_assert(13 == static_cast<int>(SkBlendMode::kModulate), "xfermode_mismatch");
+        static_assert(14 == static_cast<int>(SkBlendMode::kScreen), "xfermode_mismatch");
+        static_assert(12 == static_cast<int>(SkBlendMode::kPlus), "xfermode_mismatch");
+        static_assert(15 == static_cast<int>(SkBlendMode::kOverlay), "xfermode_mismatch");
 
-        SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(xfermodeHandle);
+        SkBlendMode mode = static_cast<SkBlendMode>(xfermodeHandle);
         Paint* paint = reinterpret_cast<Paint*>(paintHandle);
-        paint->setXfermodeMode(mode);
+        paint->setBlendMode(mode);
     }
 
     static jlong setPathEffect(jlong objHandle, jlong effectHandle) {
         Paint* obj = reinterpret_cast<Paint*>(objHandle);
         SkPathEffect* effect  = reinterpret_cast<SkPathEffect*>(effectHandle);
-        return reinterpret_cast<jlong>(obj->setPathEffect(effect));
+        obj->setPathEffect(sk_ref_sp(effect));
+        return reinterpret_cast<jlong>(obj->getPathEffect());
     }
 
     static jlong setMaskFilter(jlong objHandle, jlong maskfilterHandle) {
         Paint* obj = reinterpret_cast<Paint*>(objHandle);
         SkMaskFilter* maskfilter  = reinterpret_cast<SkMaskFilter*>(maskfilterHandle);
-        return reinterpret_cast<jlong>(obj->setMaskFilter(maskfilter));
+        obj->setMaskFilter(sk_ref_sp(maskfilter));
+        return reinterpret_cast<jlong>(obj->getMaskFilter());
     }
 
     static jlong setTypeface(jlong objHandle, jlong typefaceHandle) {
@@ -845,8 +850,8 @@
 
     static jlong setRasterizer(jlong objHandle, jlong rasterizerHandle) {
         Paint* obj = reinterpret_cast<Paint*>(objHandle);
-        SkAutoTUnref<SkRasterizer> rasterizer(GraphicsJNI::refNativeRasterizer(rasterizerHandle));
-        return reinterpret_cast<jlong>(obj->setRasterizer(rasterizer));
+        obj->setRasterizer(GraphicsJNI::refNativeRasterizer(rasterizerHandle));
+        return reinterpret_cast<jlong>(obj->getRasterizer());
     }
 
     static jint getTextAlign(jlong objHandle) {
@@ -940,7 +945,7 @@
         }
         else {
             SkScalar sigma = android::uirenderer::Blur::convertRadiusToSigma(radius);
-            paint->setLooper(SkBlurDrawLooper::Create((SkColor)color, sigma, dx, dy))->unref();
+            paint->setLooper(SkBlurDrawLooper::Make((SkColor)color, sigma, dx, dy));
         }
     }
 
diff --git a/core/jni/android/graphics/PathEffect.cpp b/core/jni/android/graphics/PathEffect.cpp
index b289b21..e801da3 100644
--- a/core/jni/android/graphics/PathEffect.cpp
+++ b/core/jni/android/graphics/PathEffect.cpp
@@ -20,7 +20,8 @@
                                      jlong outerHandle, jlong innerHandle) {
         SkPathEffect* outer = reinterpret_cast<SkPathEffect*>(outerHandle);
         SkPathEffect* inner = reinterpret_cast<SkPathEffect*>(innerHandle);
-        SkPathEffect* effect = SkComposePathEffect::Create(outer, inner);
+        SkPathEffect* effect = SkComposePathEffect::Make(sk_ref_sp(outer),
+                sk_ref_sp(inner)).release();
         return reinterpret_cast<jlong>(effect);
     }
 
@@ -28,7 +29,8 @@
                                  jlong firstHandle, jlong secondHandle) {
         SkPathEffect* first = reinterpret_cast<SkPathEffect*>(firstHandle);
         SkPathEffect* second = reinterpret_cast<SkPathEffect*>(secondHandle);
-        SkPathEffect* effect = SkSumPathEffect::Create(first, second);
+        SkPathEffect* effect = SkSumPathEffect::Make(sk_ref_sp(first),
+                sk_ref_sp(second)).release();
         return reinterpret_cast<jlong>(effect);
     }
 
@@ -41,7 +43,7 @@
 #else
         #error Need to convert float array to SkScalar array before calling the following function.
 #endif
-        SkPathEffect* effect = SkDashPathEffect::Create(intervals, count, phase);
+        SkPathEffect* effect = SkDashPathEffect::Make(intervals, count, phase).release();
         return reinterpret_cast<jlong>(effect);
     }
 
@@ -49,19 +51,19 @@
                   jlong shapeHandle, jfloat advance, jfloat phase, jint style) {
         const SkPath* shape = reinterpret_cast<SkPath*>(shapeHandle);
         SkASSERT(shape != NULL);
-        SkPathEffect* effect = SkPath1DPathEffect::Create(*shape, advance, phase,
-                (SkPath1DPathEffect::Style)style);
+        SkPathEffect* effect = SkPath1DPathEffect::Make(*shape, advance, phase,
+                (SkPath1DPathEffect::Style)style).release();
         return reinterpret_cast<jlong>(effect);
     }
 
     static jlong Corner_constructor(JNIEnv* env, jobject, jfloat radius){
-        SkPathEffect* effect = SkCornerPathEffect::Create(radius);
+        SkPathEffect* effect = SkCornerPathEffect::Make(radius).release();
         return reinterpret_cast<jlong>(effect);
     }
 
     static jlong Discrete_constructor(JNIEnv* env, jobject,
                                       jfloat length, jfloat deviation) {
-        SkPathEffect* effect = SkDiscretePathEffect::Create(length, deviation);
+        SkPathEffect* effect = SkDiscretePathEffect::Make(length, deviation).release();
         return reinterpret_cast<jlong>(effect);
     }
 
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index 07e14a2..d1ddfab 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -27,9 +27,9 @@
         mWidth = src->width();
         mHeight = src->height();
         if (NULL != src->mPicture.get()) {
-            mPicture.reset(SkRef(src->mPicture.get()));
+            mPicture = src->mPicture;
         } else if (NULL != src->mRecorder.get()) {
-            mPicture.reset(src->makePartialCopy());
+            mPicture = src->makePartialCopy();
         }
         validate();
     } else {
@@ -49,7 +49,7 @@
 
 void Picture::endRecording() {
     if (NULL != mRecorder.get()) {
-        mPicture.reset(mRecorder->endRecording());
+        mPicture = mRecorder->finishRecordingAsPicture();
         validate();
         mRecorder.reset(NULL);
     }
@@ -68,9 +68,9 @@
 Picture* Picture::CreateFromStream(SkStream* stream) {
     Picture* newPict = new Picture;
 
-    SkPicture* skPicture = SkPicture::CreateFromStream(stream);
+    sk_sp<SkPicture> skPicture = SkPicture::MakeFromStream(stream);
     if (NULL != skPicture) {
-        newPict->mPicture.reset(skPicture);
+        newPict->mPicture = skPicture;
 
         const SkIRect cullRect = skPicture->cullRect().roundOut();
         newPict->mWidth = cullRect.width();
@@ -82,16 +82,15 @@
 
 void Picture::serialize(SkWStream* stream) const {
     if (NULL != mRecorder.get()) {
-        std::unique_ptr<SkPicture> tempPict(this->makePartialCopy());
-        tempPict->serialize(stream);
+        this->makePartialCopy()->serialize(stream);
     } else if (NULL != mPicture.get()) {
         validate();
         mPicture->serialize(stream);
     } else {
+        // serialize "empty" picture
         SkPictureRecorder recorder;
         recorder.beginRecording(0, 0);
-        std::unique_ptr<SkPicture> empty(recorder.endRecording());
-        empty->serialize(stream);
+        recorder.finishRecordingAsPicture()->serialize(stream);
     }
 }
 
@@ -102,18 +101,18 @@
     }
     validate();
     if (NULL != mPicture.get()) {
-        mPicture.get()->playback(canvas->asSkCanvas());
+        mPicture->playback(canvas->asSkCanvas());
     }
 }
 
-SkPicture* Picture::makePartialCopy() const {
+sk_sp<SkPicture> Picture::makePartialCopy() const {
     SkASSERT(NULL != mRecorder.get());
 
     SkPictureRecorder reRecorder;
 
     SkCanvas* canvas = reRecorder.beginRecording(mWidth, mHeight, NULL, 0);
     mRecorder->partialReplay(canvas);
-    return reRecorder.endRecording();
+    return reRecorder.finishRecordingAsPicture();
 }
 
 void Picture::validate() const {
diff --git a/core/jni/android/graphics/Picture.h b/core/jni/android/graphics/Picture.h
index 26a4f6a..b73b375 100644
--- a/core/jni/android/graphics/Picture.h
+++ b/core/jni/android/graphics/Picture.h
@@ -55,12 +55,12 @@
 private:
     int mWidth;
     int mHeight;
-    SkAutoTUnref<const SkPicture> mPicture;
+    sk_sp<SkPicture> mPicture;
     std::unique_ptr<SkPictureRecorder> mRecorder;
 
     // Make a copy of a picture that is in the midst of being recorded. The
     // resulting picture will have balanced saves and restores.
-    SkPicture* makePartialCopy() const;
+    sk_sp<SkPicture> makePartialCopy() const;
 
     void validate() const;
 };
diff --git a/core/jni/android/graphics/Rasterizer.cpp b/core/jni/android/graphics/Rasterizer.cpp
index 3784f0d..f409498 100644
--- a/core/jni/android/graphics/Rasterizer.cpp
+++ b/core/jni/android/graphics/Rasterizer.cpp
@@ -34,19 +34,19 @@
     virtual ~NativeRasterizer() {}
 
     // Can return NULL, or a ref to the skia rasterizer.
-    virtual SkRasterizer* refRasterizer() { return NULL; }
+    virtual sk_sp<SkRasterizer> refRasterizer() { return NULL; }
 };
 
 class NativeLayerRasterizer : public NativeRasterizer {
 public:
     SkLayerRasterizer::Builder fBuilder;
 
-    virtual SkRasterizer* refRasterizer() {
-        return fBuilder.snapshotRasterizer();
+    virtual sk_sp<SkRasterizer> refRasterizer() {
+        return fBuilder.snapshot();
     }
 };
 
-SkRasterizer* GraphicsJNI::refNativeRasterizer(jlong rasterizerHandle) {
+sk_sp<SkRasterizer> GraphicsJNI::refNativeRasterizer(jlong rasterizerHandle) {
     NativeRasterizer* nr = reinterpret_cast<NativeRasterizer*>(rasterizerHandle);
     return nr ? nr->refRasterizer() : NULL;
 }
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 03462a6..a2416df 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -79,9 +79,9 @@
         if (proxyMatrix == *matrix) {
             return reinterpret_cast<jlong>(currentShader.detach());
         }
-        return reinterpret_cast<jlong>(baseShader->newWithLocalMatrix(*matrix));
+        return reinterpret_cast<jlong>(baseShader->makeWithLocalMatrix(*matrix).release());
     }
-    return reinterpret_cast<jlong>(currentShader->newWithLocalMatrix(*matrix));
+    return reinterpret_cast<jlong>(currentShader->makeWithLocalMatrix(*matrix).release());
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
@@ -126,9 +126,9 @@
     #error Need to convert float array to SkScalar array before calling the following function.
 #endif
 
-    SkShader* shader = SkGradientShader::CreateLinear(pts,
+    SkShader* shader = SkGradientShader::MakeLinear(pts,
             reinterpret_cast<const SkColor*>(colorValues), pos, count,
-            static_cast<SkShader::TileMode>(tileMode));
+            static_cast<SkShader::TileMode>(tileMode)).release();
 
     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
     ThrowIAE_IfNull(env, shader);
@@ -147,7 +147,7 @@
     colors[0] = color0;
     colors[1] = color1;
 
-    SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode);
+    SkShader* s = SkGradientShader::MakeLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode).release();
 
     ThrowIAE_IfNull(env, s);
     return reinterpret_cast<jlong>(s);
@@ -170,9 +170,9 @@
     #error Need to convert float array to SkScalar array before calling the following function.
 #endif
 
-    SkShader* shader = SkGradientShader::CreateRadial(center, radius,
+    SkShader* shader = SkGradientShader::MakeRadial(center, radius,
             reinterpret_cast<const SkColor*>(colorValues), pos, count,
-            static_cast<SkShader::TileMode>(tileMode));
+            static_cast<SkShader::TileMode>(tileMode)).release();
     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
                                  JNI_ABORT);
 
@@ -189,8 +189,8 @@
     colors[0] = color0;
     colors[1] = color1;
 
-    SkShader* s = SkGradientShader::CreateRadial(center, radius, colors, NULL, 2,
-            (SkShader::TileMode)tileMode);
+    SkShader* s = SkGradientShader::MakeRadial(center, radius, colors, NULL, 2,
+            (SkShader::TileMode)tileMode).release();
     ThrowIAE_IfNull(env, s);
     return reinterpret_cast<jlong>(s);
 }
@@ -209,8 +209,8 @@
     #error Need to convert float array to SkScalar array before calling the following function.
 #endif
 
-    SkShader* shader = SkGradientShader::CreateSweep(x, y,
-            reinterpret_cast<const SkColor*>(colors), pos, count);
+    SkShader* shader = SkGradientShader::MakeSweep(x, y,
+            reinterpret_cast<const SkColor*>(colors), pos, count).release();
     env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
                                  JNI_ABORT);
     ThrowIAE_IfNull(env, shader);
@@ -222,7 +222,7 @@
     SkColor colors[2];
     colors[0] = color0;
     colors[1] = color1;
-    SkShader* s = SkGradientShader::CreateSweep(x, y, colors, NULL, 2);
+    SkShader* s = SkGradientShader::MakeSweep(x, y, colors, NULL, 2).release();
     ThrowIAE_IfNull(env, s);
     return reinterpret_cast<jlong>(s);
 }
@@ -234,8 +234,10 @@
 {
     SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle);
     SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle);
-    SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(xfermodeHandle);
-    SkShader* shader = SkShader::CreateComposeShader(shaderA, shaderB, mode);
+    SkBlendMode mode = static_cast<SkBlendMode>(xfermodeHandle);
+    SkShader* shader = SkShader::MakeComposeShader(sk_ref_sp(shaderA),
+                                                   sk_ref_sp(shaderB),
+                                                   (SkXfermode::Mode)mode).release();
     return reinterpret_cast<jlong>(shader);
 }
 
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index acf9996..d233f7b 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -81,7 +81,7 @@
         assert(mCurrentPage != NULL);
         assert(mCurrentPage->mPictureRecorder != NULL);
         assert(mCurrentPage->mPicture == NULL);
-        mCurrentPage->mPicture = mCurrentPage->mPictureRecorder->endRecording();
+        mCurrentPage->mPicture = mCurrentPage->mPictureRecorder->finishRecordingAsPicture().release();
         delete mCurrentPage->mPictureRecorder;
         mCurrentPage->mPictureRecorder = NULL;
         mCurrentPage = NULL;
diff --git a/core/jni/android_app_admin_SecurityLog.cpp b/core/jni/android_app_admin_SecurityLog.cpp
index da47c4c..e8ca793 100644
--- a/core/jni/android_app_admin_SecurityLog.cpp
+++ b/core/jni/android_app_admin_SecurityLog.cpp
@@ -19,7 +19,7 @@
 #include "JNIHelp.h"
 #include "core_jni_helpers.h"
 #include "jni.h"
-#include "log/logger.h"
+#include <private/android_logger.h>
 
 // The size of the tag number comes out of the payload size.
 #define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index d5a7a90..776175f 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -207,7 +207,7 @@
 }
 
 static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
-    SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
+    SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
     get_canvas(canvasHandle)->drawColor(color, mode);
 }
 
@@ -341,9 +341,8 @@
         jlong paintHandle, jint dstDensity, jint srcDensity) {
 
     Canvas* canvas = get_canvas(canvasHandle);
-    Bitmap* bitmap = reinterpret_cast<Bitmap*>(bitmapHandle);
     SkBitmap skiaBitmap;
-    bitmap->getSkBitmap(&skiaBitmap);
+    bitmap::toSkBitmap(bitmapHandle, &skiaBitmap);
     const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle);
     const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
 
@@ -369,7 +368,7 @@
     }
 }
 
-static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap,
+static void drawBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
                        jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
                        jint screenDensity, jint bitmapDensity) {
     Canvas* canvas = get_canvas(canvasHandle);
@@ -443,9 +442,8 @@
                             jboolean hasAlpha, jlong paintHandle) {
     // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
     // correct the alphaType to kOpaque_SkAlphaType.
-    SkImageInfo info = SkImageInfo::Make(width, height,
-                           hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
-                           kPremul_SkAlphaType);
+    SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType,
+            GraphicsJNI::defaultColorSpace());
     SkBitmap bitmap;
     bitmap.setInfo(info);
     if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) {
@@ -573,65 +571,77 @@
 }; // namespace CanvasJNI
 
 static const JNINativeMethod gMethods[] = {
-    {"getNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
-    {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
-    {"native_setBitmap", "!(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
-    {"native_isOpaque","!(J)Z", (void*) CanvasJNI::isOpaque},
-    {"native_getWidth","!(J)I", (void*) CanvasJNI::getWidth},
-    {"native_getHeight","!(J)I", (void*) CanvasJNI::getHeight},
-    {"native_setHighContrastText","!(JZ)V", (void*) CanvasJNI::setHighContrastText},
-    {"native_save","!(JI)I", (void*) CanvasJNI::save},
-    {"native_saveLayer","!(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
-    {"native_saveLayerAlpha","!(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
-    {"native_getSaveCount","!(J)I", (void*) CanvasJNI::getSaveCount},
-    {"native_restore","!(JZ)V", (void*) CanvasJNI::restore},
-    {"native_restoreToCount","!(JIZ)V", (void*) CanvasJNI::restoreToCount},
-    {"native_getCTM", "!(JJ)V", (void*)CanvasJNI::getCTM},
-    {"native_setMatrix","!(JJ)V", (void*) CanvasJNI::setMatrix},
-    {"native_concat","!(JJ)V", (void*) CanvasJNI::concat},
-    {"native_rotate","!(JF)V", (void*) CanvasJNI::rotate},
-    {"native_scale","!(JFF)V", (void*) CanvasJNI::scale},
-    {"native_skew","!(JFF)V", (void*) CanvasJNI::skew},
-    {"native_translate","!(JFF)V", (void*) CanvasJNI::translate},
-    {"native_getClipBounds","!(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
-    {"native_quickReject","!(JJ)Z", (void*) CanvasJNI::quickRejectPath},
-    {"native_quickReject","!(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
-    {"native_clipRect","!(JFFFFI)Z", (void*) CanvasJNI::clipRect},
-    {"native_clipPath","!(JJI)Z", (void*) CanvasJNI::clipPath},
-    {"native_clipRegion","!(JJI)Z", (void*) CanvasJNI::clipRegion},
-    {"native_drawColor","!(JII)V", (void*) CanvasJNI::drawColor},
-    {"native_drawPaint","!(JJ)V", (void*) CanvasJNI::drawPaint},
-    {"native_drawPoint", "!(JFFJ)V", (void*) CanvasJNI::drawPoint},
-    {"native_drawPoints", "!(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
-    {"native_drawLine", "!(JFFFFJ)V", (void*) CanvasJNI::drawLine},
-    {"native_drawLines", "!(J[FIIJ)V", (void*) CanvasJNI::drawLines},
-    {"native_drawRect","!(JFFFFJ)V", (void*) CanvasJNI::drawRect},
-    {"native_drawRegion", "!(JJJ)V", (void*) CanvasJNI::drawRegion },
-    {"native_drawRoundRect","!(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
-    {"native_drawCircle","!(JFFFJ)V", (void*) CanvasJNI::drawCircle},
-    {"native_drawOval","!(JFFFFJ)V", (void*) CanvasJNI::drawOval},
-    {"native_drawArc","!(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
-    {"native_drawPath","!(JJJ)V", (void*) CanvasJNI::drawPath},
-    {"nativeDrawVertices", "!(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
-    {"native_drawNinePatch", "!(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
-    {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
-    {"nativeDrawBitmapMatrix", "!(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
-    {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
-    {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
-    {"nativeDrawBitmapMesh", "!(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
-    {"native_drawText","!(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
-    {"native_drawText","!(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
-    {"native_drawTextRun","!(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
-    {"native_drawTextRun","!(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
-    {"native_drawTextOnPath","!(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
-    {"native_drawTextOnPath","!(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
-    {"nativeSetDrawFilter", "!(JJ)V", (void*) CanvasJNI::setDrawFilter},
-    {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
-    {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
+    {"nGetNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
+    {"nInitRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
+    {"nFreeCaches", "()V", (void*) CanvasJNI::freeCaches},
+    {"nFreeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches},
+
+    // ------------ @FastNative ----------------
+    {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
+    {"nIsOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
+    {"nGetWidth","(J)I", (void*) CanvasJNI::getWidth},
+    {"nGetHeight","(J)I", (void*) CanvasJNI::getHeight},
+    {"nSetHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText},
+    {"nSave","(JI)I", (void*) CanvasJNI::save},
+    {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
+    {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
+    {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
+    {"nRestore","(JZ)V", (void*) CanvasJNI::restore},
+    {"nRestoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount},
+    {"nGetCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
+    {"nSetMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
+    {"nConcat","(JJ)V", (void*) CanvasJNI::concat},
+    {"nRotate","(JF)V", (void*) CanvasJNI::rotate},
+    {"nScale","(JFF)V", (void*) CanvasJNI::scale},
+    {"nSkew","(JFF)V", (void*) CanvasJNI::skew},
+    {"nTranslate","(JFF)V", (void*) CanvasJNI::translate},
+    {"nGetClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
+    {"nQuickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
+    {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
+    {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
+    {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
+    {"nClipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
+    {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
+};
+
+// If called from Canvas these are regular JNI
+// If called from DisplayListCanvas they are @FastNative
+static const JNINativeMethod gDrawMethods[] = {
+    {"nDrawColor","(JII)V", (void*) CanvasJNI::drawColor},
+    {"nDrawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
+    {"nDrawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
+    {"nDrawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
+    {"nDrawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
+    {"nDrawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
+    {"nDrawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
+    {"nDrawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
+    {"nDrawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
+    {"nDrawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
+    {"nDrawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
+    {"nDrawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
+    {"nDrawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
+    {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
+    {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
+    {"nDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
+    {"nDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
+    {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
+    {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
+    {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
+    {"nDrawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
+    {"nDrawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
+    {"nDrawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
+    {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
+    {"nDrawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
+    {"nDrawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
 };
 
 int register_android_graphics_Canvas(JNIEnv* env) {
-    return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
+    int ret = 0;
+    ret |= RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
+    ret |= RegisterMethodsOrDie(env, "android/graphics/BaseCanvas", gDrawMethods, NELEM(gDrawMethods));
+    ret |= RegisterMethodsOrDie(env, "android/view/RecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
+    return ret;
+
 }
 
 }; // namespace android
diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
index ade718b..99a5fc7 100644
--- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
@@ -188,17 +188,20 @@
     {"nCreateAnimatorSet", "()J", (void*)createAnimatorSet},
     {"nSetVectorDrawableTarget", "(JJ)V", (void*)setVectorDrawableTarget},
     {"nAddAnimator", "(JJJJJII)V", (void*)addAnimator},
-    {"nCreateGroupPropertyHolder", "!(JIFF)J", (void*)createGroupPropertyHolder},
-    {"nCreatePathDataPropertyHolder", "!(JJJ)J", (void*)createPathDataPropertyHolder},
-    {"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder},
-    {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder},
-    {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder},
     {"nSetPropertyHolderData", "(J[FI)V", (void*)setFloatPropertyHolderData},
     {"nSetPropertyHolderData", "(J[II)V", (void*)setIntPropertyHolderData},
     {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)start},
     {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)reverse},
-    {"nEnd", "!(J)V", (void*)end},
-    {"nReset", "!(J)V", (void*)reset},
+
+    // ------------- @FastNative -------------------
+
+    {"nCreateGroupPropertyHolder", "(JIFF)J", (void*)createGroupPropertyHolder},
+    {"nCreatePathDataPropertyHolder", "(JJJ)J", (void*)createPathDataPropertyHolder},
+    {"nCreatePathColorPropertyHolder", "(JIII)J", (void*)createPathColorPropertyHolder},
+    {"nCreatePathPropertyHolder", "(JIFF)J", (void*)createPathPropertyHolder},
+    {"nCreateRootAlphaPropertyHolder", "(JFF)J", (void*)createRootAlphaPropertyHolder},
+    {"nEnd", "(J)V", (void*)end},
+    {"nReset", "(J)V", (void*)reset},
 };
 
 const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT";
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index 045f127..e9ea702 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -350,64 +350,66 @@
 }
 
 static const JNINativeMethod gMethods[] = {
-        {"nCreateTree", "!(J)J", (void*)createTree},
-        {"nCreateTreeFromCopy", "!(JJ)J", (void*)createTreeFromCopy},
-        {"nSetRendererViewportSize", "!(JFF)V", (void*)setTreeViewportSize},
-        {"nSetRootAlpha", "!(JF)Z", (void*)setRootAlpha},
-        {"nGetRootAlpha", "!(J)F", (void*)getRootAlpha},
-        {"nSetAllowCaching", "!(JZ)V", (void*)setAllowCaching},
-
         {"nDraw", "(JJJLandroid/graphics/Rect;ZZ)I", (void*)draw},
-        {"nCreateFullPath", "!()J", (void*)createEmptyFullPath},
-        {"nCreateFullPath", "!(J)J", (void*)createFullPath},
-        {"nUpdateFullPathProperties", "!(JFIFIFFFFFIII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
-        {"nUpdateFullPathFillGradient", "!(JJ)V", (void*)updateFullPathFillGradient},
-        {"nUpdateFullPathStrokeGradient", "!(JJ)V", (void*)updateFullPathStrokeGradient},
         {"nGetFullPathProperties", "(J[BI)Z", (void*)getFullPathProperties},
         {"nGetGroupProperties", "(J[FI)Z", (void*)getGroupProperties},
-
-        {"nCreateClipPath", "!()J", (void*)createEmptyClipPath},
-        {"nCreateClipPath", "!(J)J", (void*)createClipPath},
-        {"nCreateGroup", "!()J", (void*)createEmptyGroup},
-        {"nCreateGroup", "!(J)J", (void*)createGroup},
-        {"nSetName", "(JLjava/lang/String;)V", (void*)setNodeName},
-        {"nUpdateGroupProperties", "!(JFFFFFFF)V", (void*)updateGroupProperties},
-
-        {"nAddChild", "!(JJ)V", (void*)addChild},
         {"nSetPathString", "(JLjava/lang/String;I)V", (void*)setPathString},
+        {"nSetName", "(JLjava/lang/String;)V", (void*)setNodeName},
 
-        {"nGetRotation", "!(J)F", (void*)getRotation},
-        {"nSetRotation", "!(JF)V", (void*)setRotation},
-        {"nGetPivotX", "!(J)F", (void*)getPivotX},
-        {"nSetPivotX", "!(JF)V", (void*)setPivotX},
-        {"nGetPivotY", "!(J)F", (void*)getPivotY},
-        {"nSetPivotY", "!(JF)V", (void*)setPivotY},
-        {"nGetScaleX", "!(J)F", (void*)getScaleX},
-        {"nSetScaleX", "!(JF)V", (void*)setScaleX},
-        {"nGetScaleY", "!(J)F", (void*)getScaleY},
-        {"nSetScaleY", "!(JF)V", (void*)setScaleY},
-        {"nGetTranslateX", "!(J)F", (void*)getTranslateX},
-        {"nSetTranslateX", "!(JF)V", (void*)setTranslateX},
-        {"nGetTranslateY", "!(J)F", (void*)getTranslateY},
-        {"nSetTranslateY", "!(JF)V", (void*)setTranslateY},
+        // ------------- @FastNative ----------------
 
-        {"nSetPathData", "!(JJ)V", (void*)setPathData},
-        {"nGetStrokeWidth", "!(J)F", (void*)getStrokeWidth},
-        {"nSetStrokeWidth", "!(JF)V", (void*)setStrokeWidth},
-        {"nGetStrokeColor", "!(J)I", (void*)getStrokeColor},
-        {"nSetStrokeColor", "!(JI)V", (void*)setStrokeColor},
-        {"nGetStrokeAlpha", "!(J)F", (void*)getStrokeAlpha},
-        {"nSetStrokeAlpha", "!(JF)V", (void*)setStrokeAlpha},
-        {"nGetFillColor", "!(J)I", (void*)getFillColor},
-        {"nSetFillColor", "!(JI)V", (void*)setFillColor},
-        {"nGetFillAlpha", "!(J)F", (void*)getFillAlpha},
-        {"nSetFillAlpha", "!(JF)V", (void*)setFillAlpha},
-        {"nGetTrimPathStart", "!(J)F", (void*)getTrimPathStart},
-        {"nSetTrimPathStart", "!(JF)V", (void*)setTrimPathStart},
-        {"nGetTrimPathEnd", "!(J)F", (void*)getTrimPathEnd},
-        {"nSetTrimPathEnd", "!(JF)V", (void*)setTrimPathEnd},
-        {"nGetTrimPathOffset", "!(J)F", (void*)getTrimPathOffset},
-        {"nSetTrimPathOffset", "!(JF)V", (void*)setTrimPathOffset},
+        {"nCreateTree", "(J)J", (void*)createTree},
+        {"nCreateTreeFromCopy", "(JJ)J", (void*)createTreeFromCopy},
+        {"nSetRendererViewportSize", "(JFF)V", (void*)setTreeViewportSize},
+        {"nSetRootAlpha", "(JF)Z", (void*)setRootAlpha},
+        {"nGetRootAlpha", "(J)F", (void*)getRootAlpha},
+        {"nSetAllowCaching", "(JZ)V", (void*)setAllowCaching},
+
+        {"nCreateFullPath", "()J", (void*)createEmptyFullPath},
+        {"nCreateFullPath", "(J)J", (void*)createFullPath},
+        {"nUpdateFullPathProperties", "(JFIFIFFFFFIII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
+        {"nUpdateFullPathFillGradient", "(JJ)V", (void*)updateFullPathFillGradient},
+        {"nUpdateFullPathStrokeGradient", "(JJ)V", (void*)updateFullPathStrokeGradient},
+
+        {"nCreateClipPath", "()J", (void*)createEmptyClipPath},
+        {"nCreateClipPath", "(J)J", (void*)createClipPath},
+        {"nCreateGroup", "()J", (void*)createEmptyGroup},
+        {"nCreateGroup", "(J)J", (void*)createGroup},
+        {"nUpdateGroupProperties", "(JFFFFFFF)V", (void*)updateGroupProperties},
+
+        {"nAddChild", "(JJ)V", (void*)addChild},
+        {"nGetRotation", "(J)F", (void*)getRotation},
+        {"nSetRotation", "(JF)V", (void*)setRotation},
+        {"nGetPivotX", "(J)F", (void*)getPivotX},
+        {"nSetPivotX", "(JF)V", (void*)setPivotX},
+        {"nGetPivotY", "(J)F", (void*)getPivotY},
+        {"nSetPivotY", "(JF)V", (void*)setPivotY},
+        {"nGetScaleX", "(J)F", (void*)getScaleX},
+        {"nSetScaleX", "(JF)V", (void*)setScaleX},
+        {"nGetScaleY", "(J)F", (void*)getScaleY},
+        {"nSetScaleY", "(JF)V", (void*)setScaleY},
+        {"nGetTranslateX", "(J)F", (void*)getTranslateX},
+        {"nSetTranslateX", "(JF)V", (void*)setTranslateX},
+        {"nGetTranslateY", "(J)F", (void*)getTranslateY},
+        {"nSetTranslateY", "(JF)V", (void*)setTranslateY},
+
+        {"nSetPathData", "(JJ)V", (void*)setPathData},
+        {"nGetStrokeWidth", "(J)F", (void*)getStrokeWidth},
+        {"nSetStrokeWidth", "(JF)V", (void*)setStrokeWidth},
+        {"nGetStrokeColor", "(J)I", (void*)getStrokeColor},
+        {"nSetStrokeColor", "(JI)V", (void*)setStrokeColor},
+        {"nGetStrokeAlpha", "(J)F", (void*)getStrokeAlpha},
+        {"nSetStrokeAlpha", "(JF)V", (void*)setStrokeAlpha},
+        {"nGetFillColor", "(J)I", (void*)getFillColor},
+        {"nSetFillColor", "(JI)V", (void*)setFillColor},
+        {"nGetFillAlpha", "(J)F", (void*)getFillAlpha},
+        {"nSetFillAlpha", "(JF)V", (void*)setFillAlpha},
+        {"nGetTrimPathStart", "(J)F", (void*)getTrimPathStart},
+        {"nSetTrimPathStart", "(JF)V", (void*)setTrimPathStart},
+        {"nGetTrimPathEnd", "(J)F", (void*)getTrimPathEnd},
+        {"nSetTrimPathEnd", "(JF)V", (void*)setTrimPathEnd},
+        {"nGetTrimPathOffset", "(J)F", (void*)getTrimPathOffset},
+        {"nSetTrimPathOffset", "(JF)V", (void*)setTrimPathOffset},
 };
 
 int register_android_graphics_drawable_VectorDrawable(JNIEnv* env) {
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 97c7f04..06f22dd 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -15,15 +15,7 @@
  */
 
 #define LOG_TAG "android.os.Debug"
-#include "JNIHelp.h"
-#include "jni.h"
-#include <utils/String8.h>
-#include "utils/misc.h"
-#include "cutils/debugger.h"
-#include <memtrack/memtrack.h>
-#include <memunreachable/memunreachable.h>
 
-#include <cutils/log.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <stdio.h>
@@ -40,9 +32,26 @@
 #include <iomanip>
 #include <string>
 
+#include "jni.h"
+
+#include "android-base/stringprintf.h"
+#include "cutils/debugger.h"
+#include "cutils/log.h"
+#include "JNIHelp.h"
+#include "memtrack/memtrack.h"
+#include "memunreachable/memunreachable.h"
+#include "utils/misc.h"
+#include "utils/String8.h"
+
 namespace android
 {
 
+using UniqueFile = std::unique_ptr<FILE, decltype(&fclose)>;
+
+static inline UniqueFile MakeUniqueFile(const char* path, const char* mode) {
+    return UniqueFile(fopen(path, mode), fclose);
+}
+
 enum {
     HEAP_UNKNOWN,
     HEAP_DALVIK,
@@ -116,8 +125,6 @@
 jfieldID otherStats_field;
 jfieldID hasSwappedOutPss_field;
 
-static bool memtrackLoaded;
-
 struct stats_t {
     int pss;
     int swappablePss;
@@ -199,10 +206,6 @@
  */
 static int read_memtrack_memory(int pid, struct graphics_memory_pss* graphics_mem)
 {
-    if (!memtrackLoaded) {
-        return -1;
-    }
-
     struct memtrack_proc* p = memtrack_proc_new();
     if (p == NULL) {
         ALOGW("failed to create memtrack_proc");
@@ -427,15 +430,13 @@
 
 static void load_maps(int pid, stats_t* stats, bool* foundSwapPss)
 {
-    char tmp[128];
-    FILE *fp;
+    *foundSwapPss = false;
 
-    sprintf(tmp, "/proc/%d/smaps", pid);
-    fp = fopen(tmp, "r");
-    if (fp == 0) return;
+    std::string smaps_path = base::StringPrintf("/proc/%d/smaps", pid);
+    UniqueFile fp = MakeUniqueFile(smaps_path.c_str(), "re");
+    if (fp == nullptr) return;
 
-    read_mapinfo(fp, stats, foundSwapPss);
-    fclose(fp);
+    read_mapinfo(fp.get(), stats, foundSwapPss);
 }
 
 static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
@@ -517,51 +518,48 @@
     jlong uss = 0;
     jlong memtrack = 0;
 
-    char tmp[128];
-    FILE *fp;
-
     struct graphics_memory_pss graphics_mem;
     if (read_memtrack_memory(pid, &graphics_mem) == 0) {
         pss = uss = memtrack = graphics_mem.graphics + graphics_mem.gl + graphics_mem.other;
     }
 
-    sprintf(tmp, "/proc/%d/smaps", pid);
-    fp = fopen(tmp, "r");
+    {
+        std::string smaps_path = base::StringPrintf("/proc/%d/smaps", pid);
+        UniqueFile fp = MakeUniqueFile(smaps_path.c_str(), "re");
 
-    if (fp != 0) {
-        while (true) {
-            if (fgets(line, 1024, fp) == NULL) {
-                break;
-            }
+        if (fp != nullptr) {
+            while (true) {
+                if (fgets(line, 1024, fp.get()) == NULL) {
+                    break;
+                }
 
-            if (line[0] == 'P') {
-                if (strncmp(line, "Pss:", 4) == 0) {
-                    char* c = line + 4;
+                if (line[0] == 'P') {
+                    if (strncmp(line, "Pss:", 4) == 0) {
+                        char* c = line + 4;
+                        while (*c != 0 && (*c < '0' || *c > '9')) {
+                            c++;
+                        }
+                        pss += atoi(c);
+                    } else if (strncmp(line, "Private_Clean:", 14) == 0
+                                || strncmp(line, "Private_Dirty:", 14) == 0) {
+                        char* c = line + 14;
+                        while (*c != 0 && (*c < '0' || *c > '9')) {
+                            c++;
+                        }
+                        uss += atoi(c);
+                    }
+                } else if (line[0] == 'S' && strncmp(line, "SwapPss:", 8) == 0) {
+                    char* c = line + 8;
+                    jlong lSwapPss;
                     while (*c != 0 && (*c < '0' || *c > '9')) {
                         c++;
                     }
-                    pss += atoi(c);
-                } else if (strncmp(line, "Private_Clean:", 14) == 0
-                        || strncmp(line, "Private_Dirty:", 14) == 0) {
-                    char* c = line + 14;
-                    while (*c != 0 && (*c < '0' || *c > '9')) {
-                        c++;
-                    }
-                    uss += atoi(c);
+                    lSwapPss = atoi(c);
+                    swapPss += lSwapPss;
+                    pss += lSwapPss; // Also in swap, those pages would be accounted as Pss without SWAP
                 }
-            } else if (line[0] == 'S' && strncmp(line, "SwapPss:", 8) == 0) {
-                char* c = line + 8;
-                jlong lSwapPss;
-                while (*c != 0 && (*c < '0' || *c > '9')) {
-                    c++;
-                }
-                lSwapPss = atoi(c);
-                swapPss += lSwapPss;
-                pss += lSwapPss; // Also in swap, those pages would be accounted as Pss without SWAP
             }
         }
-
-        fclose(fp);
     }
 
     if (outUssSwapPss != NULL) {
@@ -605,12 +603,14 @@
             NULL
     };
     long size, vmalloc_allocated_size = 0;
-    FILE* fp = fopen("/proc/vmallocinfo", "r");
-    if (fp == NULL) {
+
+    UniqueFile fp = MakeUniqueFile("/proc/vmallocinfo", "re");
+    if (fp == nullptr) {
         return 0;
     }
+
     while (true) {
-        if (fgets(line, 1024, fp) == NULL) {
+        if (fgets(line, 1024, fp.get()) == NULL) {
             break;
         }
         bool valid_line = true;
@@ -626,7 +626,6 @@
             vmalloc_allocated_size += size;
         }
     }
-    fclose(fp);
     return vmalloc_allocated_size;
 }
 
@@ -650,27 +649,25 @@
 static long long get_zram_mem_used()
 {
 #define ZRAM_SYSFS "/sys/block/zram0/"
-    FILE *f = fopen(ZRAM_SYSFS "mm_stat", "r");
-    if (f) {
+    UniqueFile mm_stat_file = MakeUniqueFile(ZRAM_SYSFS "mm_stat", "re");
+    if (mm_stat_file) {
         long long mem_used_total = 0;
 
-        int matched = fscanf(f, "%*d %*d %lld %*d %*d %*d %*d", &mem_used_total);
+        int matched = fscanf(mm_stat_file.get(), "%*d %*d %lld %*d %*d %*d %*d", &mem_used_total);
         if (matched != 1)
             ALOGW("failed to parse " ZRAM_SYSFS "mm_stat");
 
-        fclose(f);
         return mem_used_total;
     }
 
-    f = fopen(ZRAM_SYSFS "mem_used_total", "r");
-    if (f) {
+    UniqueFile mem_used_total_file = MakeUniqueFile(ZRAM_SYSFS "mem_used_total", "re");
+    if (mem_used_total_file) {
         long long mem_used_total = 0;
 
-        int matched = fscanf(f, "%lld", &mem_used_total);
+        int matched = fscanf(mem_used_total_file.get(), "%lld", &mem_used_total);
         if (matched != 1)
             ALOGW("failed to parse " ZRAM_SYSFS "mem_used_total");
 
-        fclose(f);
         return mem_used_total;
     }
 
@@ -783,8 +780,8 @@
 
 static jint read_binder_stat(const char* stat)
 {
-    FILE* fp = fopen(BINDER_STATS, "r");
-    if (fp == NULL) {
+    UniqueFile fp = MakeUniqueFile(BINDER_STATS, "re");
+    if (fp == nullptr) {
         return -1;
     }
 
@@ -795,8 +792,7 @@
 
     // loop until we have the block that represents this process
     do {
-        if (fgets(line, 1024, fp) == 0) {
-            fclose(fp);
+        if (fgets(line, 1024, fp.get()) == 0) {
             return -1;
         }
     } while (strncmp(compare, line, len));
@@ -805,8 +801,7 @@
     len = snprintf(compare, 128, "  %s: ", stat);
 
     do {
-        if (fgets(line, 1024, fp) == 0) {
-            fclose(fp);
+        if (fgets(line, 1024, fp.get()) == 0) {
             return -1;
         }
     } while (strncmp(compare, line, len));
@@ -814,7 +809,6 @@
     // we have the line, now increment the line ptr to the value
     char* ptr = line + len;
     jint result = atoi(ptr);
-    fclose(fp);
     return result;
 }
 
@@ -960,16 +954,15 @@
 
     fprintf(fp, "MAPS\n");
     const char* maps = "/proc/self/maps";
-    FILE* in = fopen(maps, "r");
-    if (in == NULL) {
+    UniqueFile in = MakeUniqueFile(maps, "re");
+    if (in == nullptr) {
         fprintf(fp, "Could not open %s\n", maps);
         return;
     }
     char buf[BUFSIZ];
-    while (size_t n = fread(buf, sizeof(char), BUFSIZ, in)) {
+    while (size_t n = fread(buf, sizeof(char), BUFSIZ, in.get())) {
         fwrite(buf, sizeof(char), n, fp);
     }
-    fclose(in);
 
     fprintf(fp, "END\n");
 }
@@ -999,8 +992,8 @@
         return;
     }
 
-    FILE* fp = fdopen(fd, "w");
-    if (fp == NULL) {
+    UniqueFile fp(fdopen(fd, "w"), fclose);
+    if (fp == nullptr) {
         ALOGW("fdopen(%d) failed: %s\n", fd, strerror(errno));
         close(fd);
         jniThrowRuntimeException(env, "fdopen() failed");
@@ -1008,10 +1001,8 @@
     }
 
     ALOGD("Native heap dump starting...\n");
-    dumpNativeHeap(fp);
+    dumpNativeHeap(fp.get());
     ALOGD("Native heap dump complete.\n");
-
-    fclose(fp);
 }
 
 
@@ -1093,14 +1084,6 @@
 
 int register_android_os_Debug(JNIEnv *env)
 {
-    int err = memtrack_init();
-    if (err != 0) {
-        memtrackLoaded = false;
-        ALOGE("failed to load memtrack module: %d", err);
-    } else {
-        memtrackLoaded = true;
-    }
-
     jclass clazz = env->FindClass("android/os/Debug$MemoryInfo");
 
     // Sanity check the number of other statistics expected in Java matches here.
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 7da0314..13e3f0d 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -266,6 +266,9 @@
         return NULL;
     }
 
+    LOG(INFO) << "Starting thread pool.";
+    ::android::hardware::ProcessState::self()->startThreadPool();
+
     return JHwRemoteBinder::NewObject(env, service);
 }
 
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 428159a..6dd7a6a 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -31,7 +31,7 @@
 
 #include "androidfw/Asset.h"
 #include "androidfw/AssetManager.h"
-#include "androidfw/AttributeFinder.h"
+#include "androidfw/AttributeResolution.h"
 #include "androidfw/ResourceTypes.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_util_Binder.h"
@@ -51,7 +51,6 @@
 namespace android {
 
 static const bool kThrowOnBadId = false;
-static const bool kDebugStyles = false;
 
 // ----------------------------------------------------------------------------
 
@@ -187,18 +186,17 @@
                 argv[argc++] = AssetManager::IDMAP_DIR;
 
                 // Directories to scan for overlays: if OVERLAY_SKU_DIR_PROPERTY is defined,
-                // use OVERLAY_DIR/<value of OVERLAY_SKU_DIR_PROPERTY> if exists, otherwise
-                // use OVERLAY_DIR if exists.
+                // use OVERLAY_DIR/<value of OVERLAY_SKU_DIR_PROPERTY> in addition to OVERLAY_DIR.
                 char subdir[PROP_VALUE_MAX];
                 int len = __system_property_get(AssetManager::OVERLAY_SKU_DIR_PROPERTY, subdir);
-                String8 overlayPath;
                 if (len > 0) {
-                    overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
-                } else {
-                    overlayPath = String8(AssetManager::OVERLAY_DIR);
+                    String8 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
+                    if (stat(overlayPath.string(), &st) == 0) {
+                        argv[argc++] = overlayPath.string();
+                    }
                 }
-                if (stat(overlayPath.string(), &st) == 0) {
-                    argv[argc++] = overlayPath.string();
+                if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
+                    argv[argc++] = AssetManager::OVERLAY_DIR;
                 }
 
                 // Finally, invoke idmap (if any overlay directory exists)
@@ -1121,30 +1119,6 @@
     theme->dumpToLog();
 }
 
-class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
-public:
-    explicit XmlAttributeFinder(const ResXMLParser* parser)
-        : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
-        , mParser(parser) {}
-
-    inline uint32_t getAttribute(jsize index) const {
-        return mParser->getAttributeNameResID(index);
-    }
-
-private:
-    const ResXMLParser* mParser;
-};
-
-class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
-public:
-    BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
-        : BackTrackingAttributeFinder(start, end) {}
-
-    inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
-        return entry->map.name.ident;
-    }
-};
-
 static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
                                                           jlong themeToken,
                                                           jint defStyleAttr,
@@ -1167,16 +1141,6 @@
         return JNI_FALSE;
     }
 
-    if (kDebugStyles) {
-        ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
-              "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
-    }
-
-    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
-    const ResTable& res = theme->getResTable();
-    ResTable_config config;
-    Res_value value;
-
     const jsize NI = env->GetArrayLength(attrs);
     const jsize NV = env->GetArrayLength(outValues);
     if (NV < (NI*STYLE_NUM_ENTRIES)) {
@@ -1193,159 +1157,32 @@
     const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
 
     jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
-    jint* dest = baseDest;
-    if (dest == NULL) {
+    if (baseDest == NULL) {
         env->ReleasePrimitiveArrayCritical(attrs, src, 0);
         return JNI_FALSE;
     }
 
     jint* indices = NULL;
-    int indicesIdx = 0;
     if (outIndices != NULL) {
         if (env->GetArrayLength(outIndices) > NI) {
             indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
         }
     }
 
-    // Load default style from attribute, if specified...
-    uint32_t defStyleBagTypeSetFlags = 0;
-    if (defStyleAttr != 0) {
-        Res_value value;
-        if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
-            if (value.dataType == Res_value::TYPE_REFERENCE) {
-                defStyleRes = value.data;
-            }
-        }
-    }
-
-    // Now lock down the resource object and start pulling stuff from it.
-    res.lock();
-
-    // Retrieve the default style bag, if requested.
-    const ResTable::bag_entry* defStyleStart = NULL;
-    uint32_t defStyleTypeSetFlags = 0;
-    ssize_t bagOff = defStyleRes != 0
-            ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
-    defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
-    const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
-    BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
-
-    // Now iterate through all of the attributes that the client has requested,
-    // filling in each with whatever data we can find.
-    ssize_t block = 0;
-    uint32_t typeSetFlags;
-    for (jsize ii=0; ii<NI; ii++) {
-        const uint32_t curIdent = (uint32_t)src[ii];
-
-        if (kDebugStyles) {
-            ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
-        }
-
-        // Try to find a value for this attribute...  we prioritize values
-        // coming from, first XML attributes, then XML style, then default
-        // style, and finally the theme.
-        value.dataType = Res_value::TYPE_NULL;
-        value.data = Res_value::DATA_NULL_UNDEFINED;
-        typeSetFlags = 0;
-        config.density = 0;
-
-        // Retrieve the current input value if available.
-        if (NSV > 0 && srcValues[ii] != 0) {
-            block = -1;
-            value.dataType = Res_value::TYPE_ATTRIBUTE;
-            value.data = srcValues[ii];
-            if (kDebugStyles) {
-                ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
-            }
-        }
-
-        if (value.dataType == Res_value::TYPE_NULL) {
-            const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
-            if (defStyleEntry != defStyleEnd) {
-                block = defStyleEntry->stringBlock;
-                typeSetFlags = defStyleTypeSetFlags;
-                value = defStyleEntry->map.value;
-                if (kDebugStyles) {
-                    ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
-                }
-            }
-        }
-
-        uint32_t resid = 0;
-        if (value.dataType != Res_value::TYPE_NULL) {
-            // Take care of resolving the found resource to its final value.
-            ssize_t newBlock = theme->resolveAttributeReference(&value, block,
-                    &resid, &typeSetFlags, &config);
-            if (newBlock >= 0) block = newBlock;
-            if (kDebugStyles) {
-                ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
-            }
-        } else {
-            // If we still don't have a value for this attribute, try to find
-            // it in the theme!
-            ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
-            if (newBlock >= 0) {
-                if (kDebugStyles) {
-                    ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
-                }
-                newBlock = res.resolveReference(&value, block, &resid,
-                        &typeSetFlags, &config);
-                if (kThrowOnBadId) {
-                    if (newBlock == BAD_INDEX) {
-                        jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-                        return JNI_FALSE;
-                    }
-                }
-                if (newBlock >= 0) block = newBlock;
-                if (kDebugStyles) {
-                    ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
-                }
-            }
-        }
-
-        // Deal with the special @null value -- it turns back to TYPE_NULL.
-        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
-            if (kDebugStyles) {
-                ALOGI("-> Setting to @null!");
-            }
-            value.dataType = Res_value::TYPE_NULL;
-            value.data = Res_value::DATA_NULL_UNDEFINED;
-            block = -1;
-        }
-
-        if (kDebugStyles) {
-            ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
-                  value.data);
-        }
-
-        // Write the final value back to Java.
-        dest[STYLE_TYPE] = value.dataType;
-        dest[STYLE_DATA] = value.data;
-        dest[STYLE_ASSET_COOKIE] =
-            block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
-        dest[STYLE_RESOURCE_ID] = resid;
-        dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
-        dest[STYLE_DENSITY] = config.density;
-
-        if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
-            indicesIdx++;
-            indices[indicesIdx] = ii;
-        }
-
-        dest += STYLE_NUM_ENTRIES;
-    }
-
-    res.unlock();
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
+    bool result = resolveAttrs(theme, defStyleAttr, defStyleRes,
+                               (uint32_t*) srcValues, NSV,
+                               (uint32_t*) src, NI,
+                               (uint32_t*) baseDest,
+                               (uint32_t*) indices);
 
     if (indices != NULL) {
-        indices[0] = indicesIdx;
         env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
     }
     env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
     env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
     env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-
-    return JNI_TRUE;
+    return result ? JNI_TRUE : JNI_FALSE;
 }
 
 static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
@@ -1370,18 +1207,6 @@
         return JNI_FALSE;
     }
 
-    if (kDebugStyles) {
-    ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
-          "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
-          xmlParserToken);
-    }
-
-    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
-    const ResTable& res = theme->getResTable();
-    ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
-    ResTable_config config;
-    Res_value value;
-
     const jsize NI = env->GetArrayLength(attrs);
     const jsize NV = env->GetArrayLength(outValues);
     if (NV < (NI*STYLE_NUM_ENTRIES)) {
@@ -1395,211 +1220,32 @@
     }
 
     jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
-    jint* dest = baseDest;
-    if (dest == NULL) {
+    if (baseDest == NULL) {
         env->ReleasePrimitiveArrayCritical(attrs, src, 0);
         return JNI_FALSE;
     }
 
     jint* indices = NULL;
-    int indicesIdx = 0;
     if (outIndices != NULL) {
         if (env->GetArrayLength(outIndices) > NI) {
             indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
         }
     }
 
-    // Load default style from attribute, if specified...
-    uint32_t defStyleBagTypeSetFlags = 0;
-    if (defStyleAttr != 0) {
-        Res_value value;
-        if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
-            if (value.dataType == Res_value::TYPE_REFERENCE) {
-                defStyleRes = value.data;
-            }
-        }
-    }
-
-    // Retrieve the style class associated with the current XML tag.
-    int style = 0;
-    uint32_t styleBagTypeSetFlags = 0;
-    if (xmlParser != NULL) {
-        ssize_t idx = xmlParser->indexOfStyle();
-        if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
-            if (value.dataType == value.TYPE_ATTRIBUTE) {
-                if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
-                    value.dataType = Res_value::TYPE_NULL;
-                }
-            }
-            if (value.dataType == value.TYPE_REFERENCE) {
-                style = value.data;
-            }
-        }
-    }
-
-    // Now lock down the resource object and start pulling stuff from it.
-    res.lock();
-
-    // Retrieve the default style bag, if requested.
-    const ResTable::bag_entry* defStyleAttrStart = NULL;
-    uint32_t defStyleTypeSetFlags = 0;
-    ssize_t bagOff = defStyleRes != 0
-            ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
-    defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
-    const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
-    BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
-
-    // Retrieve the style class bag, if requested.
-    const ResTable::bag_entry* styleAttrStart = NULL;
-    uint32_t styleTypeSetFlags = 0;
-    bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
-    styleTypeSetFlags |= styleBagTypeSetFlags;
-    const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
-    BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
-
-    // Retrieve the XML attributes, if requested.
-    static const ssize_t kXmlBlock = 0x10000000;
-    XmlAttributeFinder xmlAttrFinder(xmlParser);
-    const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
-
-    // Now iterate through all of the attributes that the client has requested,
-    // filling in each with whatever data we can find.
-    ssize_t block = 0;
-    uint32_t typeSetFlags;
-    for (jsize ii = 0; ii < NI; ii++) {
-        const uint32_t curIdent = (uint32_t)src[ii];
-
-        if (kDebugStyles) {
-            ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
-        }
-
-        // Try to find a value for this attribute...  we prioritize values
-        // coming from, first XML attributes, then XML style, then default
-        // style, and finally the theme.
-        value.dataType = Res_value::TYPE_NULL;
-        value.data = Res_value::DATA_NULL_UNDEFINED;
-        typeSetFlags = 0;
-        config.density = 0;
-
-        // Walk through the xml attributes looking for the requested attribute.
-        const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
-        if (xmlAttrIdx != xmlAttrEnd) {
-            // We found the attribute we were looking for.
-            block = kXmlBlock;
-            xmlParser->getAttributeValue(xmlAttrIdx, &value);
-            if (kDebugStyles) {
-                ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
-            }
-        }
-
-        if (value.dataType == Res_value::TYPE_NULL) {
-            // Walk through the style class values looking for the requested attribute.
-            const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
-            if (styleAttrEntry != styleAttrEnd) {
-                // We found the attribute we were looking for.
-                block = styleAttrEntry->stringBlock;
-                typeSetFlags = styleTypeSetFlags;
-                value = styleAttrEntry->map.value;
-                if (kDebugStyles) {
-                    ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
-                }
-            }
-        }
-
-        if (value.dataType == Res_value::TYPE_NULL) {
-            // Walk through the default style values looking for the requested attribute.
-            const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
-            if (defStyleAttrEntry != defStyleAttrEnd) {
-                // We found the attribute we were looking for.
-                block = defStyleAttrEntry->stringBlock;
-                typeSetFlags = styleTypeSetFlags;
-                value = defStyleAttrEntry->map.value;
-                if (kDebugStyles) {
-                    ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
-                }
-            }
-        }
-
-        uint32_t resid = 0;
-        if (value.dataType != Res_value::TYPE_NULL) {
-            // Take care of resolving the found resource to its final value.
-            ssize_t newBlock = theme->resolveAttributeReference(&value, block,
-                    &resid, &typeSetFlags, &config);
-            if (newBlock >= 0) {
-                block = newBlock;
-            }
-
-            if (kDebugStyles) {
-                ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
-            }
-        } else {
-            // If we still don't have a value for this attribute, try to find
-            // it in the theme!
-            ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
-            if (newBlock >= 0) {
-                if (kDebugStyles) {
-                    ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
-                }
-                newBlock = res.resolveReference(&value, block, &resid,
-                        &typeSetFlags, &config);
-                if (kThrowOnBadId) {
-                    if (newBlock == BAD_INDEX) {
-                        jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-                        return JNI_FALSE;
-                    }
-                }
-
-                if (newBlock >= 0) {
-                    block = newBlock;
-                }
-
-                if (kDebugStyles) {
-                    ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
-                }
-            }
-        }
-
-        // Deal with the special @null value -- it turns back to TYPE_NULL.
-        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
-            if (kDebugStyles) {
-                ALOGI("-> Setting to @null!");
-            }
-            value.dataType = Res_value::TYPE_NULL;
-            value.data = Res_value::DATA_NULL_UNDEFINED;
-            block = kXmlBlock;
-        }
-
-        if (kDebugStyles) {
-            ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
-        }
-
-        // Write the final value back to Java.
-        dest[STYLE_TYPE] = value.dataType;
-        dest[STYLE_DATA] = value.data;
-        dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
-            static_cast<jint>(res.getTableCookie(block)) : -1;
-        dest[STYLE_RESOURCE_ID] = resid;
-        dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
-        dest[STYLE_DENSITY] = config.density;
-
-        if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
-            indicesIdx++;
-            indices[indicesIdx] = ii;
-        }
-
-        dest += STYLE_NUM_ENTRIES;
-    }
-
-    res.unlock();
+    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
+    ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
+    bool result = applyStyle(theme, xmlParser,
+                             defStyleAttr, defStyleRes,
+                             (uint32_t*) src, NI,
+                             (uint32_t*) baseDest,
+                             (uint32_t*) indices);
 
     if (indices != NULL) {
-        indices[0] = indicesIdx;
         env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
     }
     env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
     env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-
-    return JNI_TRUE;
+    return result ? JNI_TRUE : JNI_FALSE;
 }
 
 static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
@@ -1627,8 +1273,6 @@
     }
     const ResTable& res(am->getResources());
     ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
-    ResTable_config config;
-    Res_value value;
 
     const jsize NI = env->GetArrayLength(attrs);
     const jsize NV = env->GetArrayLength(outValues);
@@ -1643,108 +1287,29 @@
     }
 
     jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
-    jint* dest = baseDest;
-    if (dest == NULL) {
+    if (baseDest == NULL) {
         env->ReleasePrimitiveArrayCritical(attrs, src, 0);
         return JNI_FALSE;
     }
 
     jint* indices = NULL;
-    int indicesIdx = 0;
     if (outIndices != NULL) {
         if (env->GetArrayLength(outIndices) > NI) {
             indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
         }
     }
 
-    // Now lock down the resource object and start pulling stuff from it.
-    res.lock();
-
-    // Retrieve the XML attributes, if requested.
-    const jsize NX = xmlParser->getAttributeCount();
-    jsize ix=0;
-    uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
-
-    static const ssize_t kXmlBlock = 0x10000000;
-
-    // Now iterate through all of the attributes that the client has requested,
-    // filling in each with whatever data we can find.
-    ssize_t block = 0;
-    uint32_t typeSetFlags;
-    for (jsize ii=0; ii<NI; ii++) {
-        const uint32_t curIdent = (uint32_t)src[ii];
-
-        // Try to find a value for this attribute...
-        value.dataType = Res_value::TYPE_NULL;
-        value.data = Res_value::DATA_NULL_UNDEFINED;
-        typeSetFlags = 0;
-        config.density = 0;
-
-        // Skip through XML attributes until the end or the next possible match.
-        while (ix < NX && curIdent > curXmlAttr) {
-            ix++;
-            curXmlAttr = xmlParser->getAttributeNameResID(ix);
-        }
-        // Retrieve the current XML attribute if it matches, and step to next.
-        if (ix < NX && curIdent == curXmlAttr) {
-            block = kXmlBlock;
-            xmlParser->getAttributeValue(ix, &value);
-            ix++;
-            curXmlAttr = xmlParser->getAttributeNameResID(ix);
-        }
-
-        //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
-        uint32_t resid = 0;
-        if (value.dataType != Res_value::TYPE_NULL) {
-            // Take care of resolving the found resource to its final value.
-            //printf("Resolving attribute reference\n");
-            ssize_t newBlock = res.resolveReference(&value, block, &resid,
-                    &typeSetFlags, &config);
-            if (kThrowOnBadId) {
-                if (newBlock == BAD_INDEX) {
-                    jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
-                    return JNI_FALSE;
-                }
-            }
-            if (newBlock >= 0) block = newBlock;
-        }
-
-        // Deal with the special @null value -- it turns back to TYPE_NULL.
-        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
-            value.dataType = Res_value::TYPE_NULL;
-            value.data = Res_value::DATA_NULL_UNDEFINED;
-        }
-
-        //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
-
-        // Write the final value back to Java.
-        dest[STYLE_TYPE] = value.dataType;
-        dest[STYLE_DATA] = value.data;
-        dest[STYLE_ASSET_COOKIE] =
-            block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
-        dest[STYLE_RESOURCE_ID] = resid;
-        dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
-        dest[STYLE_DENSITY] = config.density;
-
-        if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
-            indicesIdx++;
-            indices[indicesIdx] = ii;
-        }
-
-        dest += STYLE_NUM_ENTRIES;
-    }
-
-    res.unlock();
+    bool result = retrieveAttributes(&res, xmlParser,
+                                     (uint32_t*) src, NI,
+                                     (uint32_t*) baseDest,
+                                     (uint32_t*) indices);
 
     if (indices != NULL) {
-        indices[0] = indicesIdx;
         env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
     }
-
     env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
     env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-
-    return JNI_TRUE;
+    return result ? JNI_TRUE : JNI_FALSE;
 }
 
 static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
@@ -2161,9 +1726,11 @@
         (void*) android_content_AssetManager_readAsset },
     { "seekAsset",      "(JJI)J",
         (void*) android_content_AssetManager_seekAsset },
-    { "getAssetLength", "!(J)J",
+    // @FastNative
+    { "getAssetLength", "(J)J",
         (void*) android_content_AssetManager_getAssetLength },
-    { "getAssetRemainingLength", "!(J)J",
+    // @FastNative
+    { "getAssetRemainingLength", "(J)J",
         (void*) android_content_AssetManager_getAssetRemainingLength },
     { "addAssetPathNative", "(Ljava/lang/String;Z)I",
         (void*) android_content_AssetManager_addAssetPath },
@@ -2179,25 +1746,35 @@
         (void*) android_content_AssetManager_getNonSystemLocales },
     { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
         (void*) android_content_AssetManager_getSizeConfigurations },
-    { "setConfiguration", "!(IILjava/lang/String;IIIIIIIIIIIIII)V",
+    // @FastNative
+    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
         (void*) android_content_AssetManager_setConfiguration },
-    { "getResourceIdentifier","!(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+    // @FastNative
+    { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
         (void*) android_content_AssetManager_getResourceIdentifier },
-    { "getResourceName","!(I)Ljava/lang/String;",
+    // @FastNative
+    { "getResourceName","(I)Ljava/lang/String;",
         (void*) android_content_AssetManager_getResourceName },
-    { "getResourcePackageName","!(I)Ljava/lang/String;",
+    // @FastNative
+    { "getResourcePackageName","(I)Ljava/lang/String;",
         (void*) android_content_AssetManager_getResourcePackageName },
-    { "getResourceTypeName","!(I)Ljava/lang/String;",
+    // @FastNative
+    { "getResourceTypeName","(I)Ljava/lang/String;",
         (void*) android_content_AssetManager_getResourceTypeName },
-    { "getResourceEntryName","!(I)Ljava/lang/String;",
+    // @FastNative
+    { "getResourceEntryName","(I)Ljava/lang/String;",
         (void*) android_content_AssetManager_getResourceEntryName },
-    { "loadResourceValue","!(ISLandroid/util/TypedValue;Z)I",
+    // @FastNative
+    { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
         (void*) android_content_AssetManager_loadResourceValue },
-    { "loadResourceBagValue","!(IILandroid/util/TypedValue;Z)I",
+    // @FastNative
+    { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
         (void*) android_content_AssetManager_loadResourceBagValue },
-    { "getStringBlockCount","!()I",
+    // @FastNative
+    { "getStringBlockCount","()I",
         (void*) android_content_AssetManager_getStringBlockCount },
-    { "getNativeStringBlock","!(I)J",
+    // @FastNative
+    { "getNativeStringBlock","(I)J",
         (void*) android_content_AssetManager_getNativeStringBlock },
     { "getCookieName","(I)Ljava/lang/String;",
         (void*) android_content_AssetManager_getCookieName },
@@ -2215,21 +1792,28 @@
         (void*) android_content_AssetManager_copyTheme },
     { "clearTheme", "(J)V",
         (void*) android_content_AssetManager_clearTheme },
-    { "loadThemeAttributeValue", "!(JILandroid/util/TypedValue;Z)I",
+    // @FastNative
+    { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
         (void*) android_content_AssetManager_loadThemeAttributeValue },
-    { "getThemeChangingConfigurations", "!(J)I",
+    // @FastNative
+    { "getThemeChangingConfigurations", "(J)I",
         (void*) android_content_AssetManager_getThemeChangingConfigurations },
     { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
         (void*) android_content_AssetManager_dumpTheme },
-    { "applyStyle","!(JIIJ[I[I[I)Z",
+    // @FastNative
+    { "applyStyle","(JIIJ[I[I[I)Z",
         (void*) android_content_AssetManager_applyStyle },
-    { "resolveAttrs","!(JII[I[I[I[I)Z",
+    // @FastNative
+    { "resolveAttrs","(JII[I[I[I[I)Z",
         (void*) android_content_AssetManager_resolveAttrs },
-    { "retrieveAttributes","!(J[I[I[I)Z",
+    // @FastNative
+    { "retrieveAttributes","(J[I[I[I)Z",
         (void*) android_content_AssetManager_retrieveAttributes },
-    { "getArraySize","!(I)I",
+    // @FastNative
+    { "getArraySize","(I)I",
         (void*) android_content_AssetManager_getArraySize },
-    { "retrieveArray","!(I[I)I",
+    // @FastNative
+    { "retrieveArray","(I[I)I",
         (void*) android_content_AssetManager_retrieveArray },
 
     // XML files.
@@ -2239,11 +1823,14 @@
     // Arrays.
     { "getArrayStringResource","(I)[Ljava/lang/String;",
         (void*) android_content_AssetManager_getArrayStringResource },
-    { "getArrayStringInfo","!(I)[I",
+    // @FastNative
+    { "getArrayStringInfo","(I)[I",
         (void*) android_content_AssetManager_getArrayStringInfo },
-    { "getArrayIntResource","!(I)[I",
+    // @FastNative
+    { "getArrayIntResource","(I)[I",
         (void*) android_content_AssetManager_getArrayIntResource },
-    { "getStyleAttributes","!(I)[I",
+    // @FastNative
+    { "getStyleAttributes","(I)[I",
         (void*) android_content_AssetManager_getStyleAttributes },
 
     // Bookkeeping.
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 4f8a2cb..173afd8 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -19,7 +19,7 @@
 #include "JNIHelp.h"
 #include "core_jni_helpers.h"
 #include "jni.h"
-#include "log/logger.h"
+#include <log/logger.h>
 
 #define UNUSED  __attribute__((__unused__))
 
diff --git a/core/jni/android_util_PathParser.cpp b/core/jni/android_util_PathParser.cpp
index 53669a8..10efb95 100644
--- a/core/jni/android_util_PathParser.cpp
+++ b/core/jni/android_util_PathParser.cpp
@@ -101,14 +101,17 @@
 
 static const JNINativeMethod gMethods[] = {
     {"nParseStringForPath", "(JLjava/lang/String;I)V", (void*)parseStringForPath},
-    {"nCreateEmptyPathData", "!()J", (void*)createEmptyPathData},
-    {"nCreatePathData", "!(J)J", (void*)createPathData},
     {"nCreatePathDataFromString", "(Ljava/lang/String;I)J", (void*)createPathDataFromStringPath},
-    {"nInterpolatePathData", "!(JJJF)Z", (void*)interpolatePathData},
-    {"nFinalize", "!(J)V", (void*)deletePathData},
-    {"nCanMorph", "!(JJ)Z", (void*)canMorphPathData},
-    {"nSetPathData", "!(JJ)V", (void*)setPathData},
-    {"nCreatePathFromPathData", "!(JJ)V", (void*)setSkPathFromPathData},
+
+    // ---------------- @FastNative -----------------
+
+    {"nCreateEmptyPathData", "()J", (void*)createEmptyPathData},
+    {"nCreatePathData", "(J)J", (void*)createPathData},
+    {"nInterpolatePathData", "(JJJF)Z", (void*)interpolatePathData},
+    {"nFinalize", "(J)V", (void*)deletePathData},
+    {"nCanMorph", "(JJ)Z", (void*)canMorphPathData},
+    {"nSetPathData", "(JJ)V", (void*)setPathData},
+    {"nCreatePathFromPathData", "(JJ)V", (void*)setSkPathFromPathData},
 };
 
 int register_android_util_PathParser(JNIEnv* env) {
diff --git a/core/jni/android_util_XmlBlock.cpp b/core/jni/android_util_XmlBlock.cpp
index a15c23c..99882cc 100644
--- a/core/jni/android_util_XmlBlock.cpp
+++ b/core/jni/android_util_XmlBlock.cpp
@@ -372,42 +372,45 @@
             (void*) android_content_XmlBlock_nativeGetStringBlock },
     { "nativeCreateParseState",     "(J)J",
             (void*) android_content_XmlBlock_nativeCreateParseState },
-    { "nativeNext",                 "!(J)I",
-            (void*) android_content_XmlBlock_nativeNext },
-    { "nativeGetNamespace",         "!(J)I",
-            (void*) android_content_XmlBlock_nativeGetNamespace },
-    { "nativeGetName",              "!(J)I",
-            (void*) android_content_XmlBlock_nativeGetName },
-    { "nativeGetText",              "!(J)I",
-            (void*) android_content_XmlBlock_nativeGetText },
-    { "nativeGetLineNumber",        "!(J)I",
-            (void*) android_content_XmlBlock_nativeGetLineNumber },
-    { "nativeGetAttributeCount",    "!(J)I",
-            (void*) android_content_XmlBlock_nativeGetAttributeCount },
-    { "nativeGetAttributeNamespace","!(JI)I",
-            (void*) android_content_XmlBlock_nativeGetAttributeNamespace },
-    { "nativeGetAttributeName",     "!(JI)I",
-            (void*) android_content_XmlBlock_nativeGetAttributeName },
-    { "nativeGetAttributeResource", "!(JI)I",
-            (void*) android_content_XmlBlock_nativeGetAttributeResource },
-    { "nativeGetAttributeDataType", "!(JI)I",
-            (void*) android_content_XmlBlock_nativeGetAttributeDataType },
-    { "nativeGetAttributeData",    "!(JI)I",
-            (void*) android_content_XmlBlock_nativeGetAttributeData },
-    { "nativeGetAttributeStringValue", "!(JI)I",
-            (void*) android_content_XmlBlock_nativeGetAttributeStringValue },
-    { "nativeGetAttributeIndex",    "!(JLjava/lang/String;Ljava/lang/String;)I",
-            (void*) android_content_XmlBlock_nativeGetAttributeIndex },
-    { "nativeGetIdAttribute",      "!(J)I",
-            (void*) android_content_XmlBlock_nativeGetIdAttribute },
-    { "nativeGetClassAttribute",   "!(J)I",
-            (void*) android_content_XmlBlock_nativeGetClassAttribute },
-    { "nativeGetStyleAttribute",   "!(J)I",
-            (void*) android_content_XmlBlock_nativeGetStyleAttribute },
     { "nativeDestroyParseState",    "(J)V",
             (void*) android_content_XmlBlock_nativeDestroyParseState },
     { "nativeDestroy",              "(J)V",
             (void*) android_content_XmlBlock_nativeDestroy },
+
+    // ------------------- @FastNative ----------------------
+
+    { "nativeNext",                 "(J)I",
+            (void*) android_content_XmlBlock_nativeNext },
+    { "nativeGetNamespace",         "(J)I",
+            (void*) android_content_XmlBlock_nativeGetNamespace },
+    { "nativeGetName",              "(J)I",
+            (void*) android_content_XmlBlock_nativeGetName },
+    { "nativeGetText",              "(J)I",
+            (void*) android_content_XmlBlock_nativeGetText },
+    { "nativeGetLineNumber",        "(J)I",
+            (void*) android_content_XmlBlock_nativeGetLineNumber },
+    { "nativeGetAttributeCount",    "(J)I",
+            (void*) android_content_XmlBlock_nativeGetAttributeCount },
+    { "nativeGetAttributeNamespace","(JI)I",
+            (void*) android_content_XmlBlock_nativeGetAttributeNamespace },
+    { "nativeGetAttributeName",     "(JI)I",
+            (void*) android_content_XmlBlock_nativeGetAttributeName },
+    { "nativeGetAttributeResource", "(JI)I",
+            (void*) android_content_XmlBlock_nativeGetAttributeResource },
+    { "nativeGetAttributeDataType", "(JI)I",
+            (void*) android_content_XmlBlock_nativeGetAttributeDataType },
+    { "nativeGetAttributeData",    "(JI)I",
+            (void*) android_content_XmlBlock_nativeGetAttributeData },
+    { "nativeGetAttributeStringValue", "(JI)I",
+            (void*) android_content_XmlBlock_nativeGetAttributeStringValue },
+    { "nativeGetAttributeIndex",    "(JLjava/lang/String;Ljava/lang/String;)I",
+            (void*) android_content_XmlBlock_nativeGetAttributeIndex },
+    { "nativeGetIdAttribute",      "(J)I",
+            (void*) android_content_XmlBlock_nativeGetIdAttribute },
+    { "nativeGetClassAttribute",   "(J)I",
+            (void*) android_content_XmlBlock_nativeGetClassAttribute },
+    { "nativeGetStyleAttribute",   "(J)I",
+            (void*) android_content_XmlBlock_nativeGetStyleAttribute },
 };
 
 int register_android_content_XmlBlock(JNIEnv* env)
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index edc0da3..8d2a058 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -215,24 +215,27 @@
 const char* const kClassPathName = "android/view/DisplayListCanvas";
 
 static JNINativeMethod gMethods[] = {
-    { "nInsertReorderBarrier","!(JZ)V",         (void*) android_view_DisplayListCanvas_insertReorderBarrier },
 
-    { "nCallDrawGLFunction", "!(JJLjava/lang/Runnable;)V",
+    // ------------ @FastNative ------------------
+
+    { "nInsertReorderBarrier","(JZ)V",         (void*) android_view_DisplayListCanvas_insertReorderBarrier },
+
+    { "nCallDrawGLFunction", "(JJLjava/lang/Runnable;)V",
             (void*) android_view_DisplayListCanvas_callDrawGLFunction },
 
-    { "nDrawRoundRect",     "!(JJJJJJJJ)V",     (void*) android_view_DisplayListCanvas_drawRoundRectProps },
-    { "nDrawCircle",        "!(JJJJJ)V",        (void*) android_view_DisplayListCanvas_drawCircleProps },
+    { "nDrawRoundRect",     "(JJJJJJJJ)V",     (void*) android_view_DisplayListCanvas_drawRoundRectProps },
+    { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_DisplayListCanvas_drawCircleProps },
 
-    { "nFinishRecording",   "!(J)J",            (void*) android_view_DisplayListCanvas_finishRecording },
-    { "nDrawRenderNode",    "!(JJ)V",           (void*) android_view_DisplayListCanvas_drawRenderNode },
+    { "nFinishRecording",   "(J)J",            (void*) android_view_DisplayListCanvas_finishRecording },
+    { "nDrawRenderNode",    "(JJ)V",           (void*) android_view_DisplayListCanvas_drawRenderNode },
 
-    { "nCreateDisplayListCanvas", "!(II)J",     (void*) android_view_DisplayListCanvas_createDisplayListCanvas },
-    { "nResetDisplayListCanvas", "!(JII)V",     (void*) android_view_DisplayListCanvas_resetDisplayListCanvas },
+    { "nCreateDisplayListCanvas", "(II)J",     (void*) android_view_DisplayListCanvas_createDisplayListCanvas },
+    { "nResetDisplayListCanvas", "(JII)V",     (void*) android_view_DisplayListCanvas_resetDisplayListCanvas },
 
-    { "nDrawLayer",               "!(JJ)V",     (void*) android_view_DisplayListCanvas_drawLayer },
+    { "nDrawLayer",               "(JJ)V",     (void*) android_view_DisplayListCanvas_drawLayer },
 
-    { "nGetMaximumTextureWidth",  "!()I",       (void*) android_view_DisplayListCanvas_getMaxTextureWidth },
-    { "nGetMaximumTextureHeight", "!()I",       (void*) android_view_DisplayListCanvas_getMaxTextureHeight },
+    { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_DisplayListCanvas_getMaxTextureWidth },
+    { "nGetMaximumTextureHeight", "()I",       (void*) android_view_DisplayListCanvas_getMaxTextureHeight },
 };
 
 static JNINativeMethod gActivityThreadMethods[] = {
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index 59c337b..1743731 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -182,7 +182,8 @@
     SkBitmap bitmap;
     bitmap.setInfo(SkImageInfo::Make(buffer->getWidth(), buffer->getHeight(),
                                      convertPixelFormat(buffer->getPixelFormat()),
-                                     kPremul_SkAlphaType),
+                                     kPremul_SkAlphaType,
+                                     GraphicsJNI::defaultColorSpace()),
                    bytesCount);
 
     if (buffer->getWidth() > 0 && buffer->getHeight() > 0) {
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 3f2b924..b6c81cf8 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -318,11 +318,11 @@
         return 0;
     }
 
-
     SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
                                          convertPixelFormat(outBuffer.format),
-                                         outBuffer.format == PIXEL_FORMAT_RGBX_8888 ?
-                                         kOpaque_SkAlphaType : kPremul_SkAlphaType);
+                                         outBuffer.format == PIXEL_FORMAT_RGBX_8888
+                                                 ? kOpaque_SkAlphaType : kPremul_SkAlphaType,
+                                         GraphicsJNI::defaultColorSpace());
 
     SkBitmap bitmap;
     ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 73b3f52..65f12ac 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -175,7 +175,9 @@
     }
     SkImageInfo screenshotInfo = SkImageInfo::Make(screenshot->getWidth(),
                                                    screenshot->getHeight(),
-                                                   colorType, alphaType);
+                                                   colorType,
+                                                   alphaType,
+                                                   GraphicsJNI::defaultColorSpace());
 
     const size_t rowBytes =
             screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
@@ -184,14 +186,14 @@
         return NULL;
     }
 
-    Bitmap* bitmap = new Bitmap(
+    auto pixelRef = new PixelRef(
             (void*) screenshot->getPixels(), (void*) screenshot.get(), DeleteScreenshot,
             screenshotInfo, rowBytes, nullptr);
     screenshot.release();
-    bitmap->peekAtPixelRef()->setImmutable();
+    pixelRef->setImmutable();
 
-    return GraphicsJNI::createBitmap(env, bitmap,
-            GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
+    return bitmap::createBitmap(env, pixelRef,
+            bitmap::kBitmapCreateFlag_Premultiplied, NULL);
 }
 
 static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index e185281..268aec5 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -90,7 +90,8 @@
         default:
             break;
     }
-    return SkImageInfo::Make(buffer.width, buffer.height, colorType, alphaType);
+    return SkImageInfo::Make(buffer.width, buffer.height, colorType, alphaType,
+            GraphicsJNI::defaultColorSpace());
 }
 
 /**
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 309bb2f..14dcb3f 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -613,21 +613,6 @@
     return atoi(prop) > 0 ? JNI_TRUE : JNI_FALSE;
 }
 
-static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
-    sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
-    jsize len = env->GetArrayLength(atlasMapArray);
-    if (len <= 0) {
-        ALOGW("Failed to initialize atlas, invalid map length: %d", len);
-        return;
-    }
-    int64_t* map = new int64_t[len];
-    env->GetLongArrayRegion(atlasMapArray, 0, len, map);
-
-    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->setTextureAtlas(buffer, map, len);
-}
-
 static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jint fd) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -955,7 +940,6 @@
 
 static const JNINativeMethod gMethods[] = {
     { "nSupportsOpenGL", "()Z", (void*) android_view_ThreadedRenderer_supportsOpenGL },
-    { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
     { "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
     { "nGetRenderThreadTid", "(J)I", (void*) android_view_ThreadedRenderer_getRenderThreadTid },
     { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a08c63e..c346849 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -149,6 +149,8 @@
     <protected-broadcast
         android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
     <protected-broadcast
+        android:name="android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED" />
+    <protected-broadcast
         android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
         android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
@@ -434,6 +436,7 @@
 
     <protected-broadcast android:name="ScheduleConditionProvider.EVALUATE" />
     <protected-broadcast android:name="EventConditionProvider.EVALUATE" />
+    <protected-broadcast android:name="SnoozeHelper.EVALUATE" />
     <protected-broadcast android:name="wifi_scan_available" />
 
     <protected-broadcast android:name="action.cne.started" />
@@ -496,6 +499,8 @@
 
     <protected-broadcast android:name="com.android.server.retaildemo.ACTION_RESET_DEMO" />
 
+    <protected-broadcast android:name="android.intent.action.DEVICE_LOCKED_CHANGED" />
+
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
     <!-- ====================================================================== -->
@@ -3040,7 +3045,7 @@
     <!-- @SystemApi Allows access to MAC addresses of WiFi and Bluetooth peer devices.
         @hide -->
     <permission android:name="android.permission.PEERS_MAC_ADDRESS"
-                android:protectionLevel="signature" />
+                android:protectionLevel="signature|setup" />
 
     <!-- Allows the Nfc stack to dispatch Nfc messages to applications. Applications
         can use this permission to ensure incoming Nfc messages are from the Nfc stack
diff --git a/core/res/res/color/background_cache_hint_selector_device_default.xml b/core/res/res/color/background_cache_hint_selector_device_default.xml
index 3cb4bbc..4470754 100644
--- a/core/res/res/color/background_cache_hint_selector_device_default.xml
+++ b/core/res/res/color/background_cache_hint_selector_device_default.xml
@@ -18,3 +18,4 @@
     <item android:state_accelerated="false" android:color="?attr/colorBackground" />
     <item android:color="@android:color/transparent" />
 </selector>
+
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 307c6db..0ab56f9 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
@@ -22,6 +22,7 @@
         android:gravity="top|center_horizontal"
         android:minHeight="@dimen/alert_dialog_title_height">
     <ImageView android:id="@+id/icon"
+            android:adjustViewBounds="true"
             android:maxHeight="24dp"
             android:maxWidth="24dp"
             android:layout_marginTop="8dp"
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 0279911..e543c9b 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
@@ -21,9 +21,11 @@
         android:gravity="top|center_horizontal"
         android:minHeight="@dimen/alert_dialog_title_height">
     <ImageView android:id="@+id/icon"
+            android:adjustViewBounds="true"
             android:maxHeight="24dp"
             android:maxWidth="24dp"
             android:layout_marginTop="12dp"
+            android:layout_gravity="center_horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:src="@null" />
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 3469f97..2509eae 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -152,7 +152,7 @@
     <string name="httpErrorAuth" msgid="1435065629438044534">"Nije moguće potvrditi autentičnost."</string>
     <string name="httpErrorProxyAuth" msgid="1788207010559081331">"Potvrda identiteta preko proksi servera nije uspela."</string>
     <string name="httpErrorConnect" msgid="8714273236364640549">"Nije moguće povezati se sa serverom."</string>
-    <string name="httpErrorIO" msgid="2340558197489302188">"Nije moguće komunicirati sa serverom. Pokušajte ponovo kasnije."</string>
+    <string name="httpErrorIO" msgid="2340558197489302188">"Nije moguće komunicirati sa serverom. Probajte ponovo kasnije."</string>
     <string name="httpErrorTimeout" msgid="4743403703762883954">"Veza sa serverom je istekla."</string>
     <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"Stranica sadrži previše veza za preusmeravanje sa servera."</string>
     <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"Protokol nije podržan."</string>
@@ -160,7 +160,7 @@
     <string name="httpErrorBadUrl" msgid="3636929722728881972">"Stranicu nije moguće otvoriti zato što je URL adresa nevažeća."</string>
     <string name="httpErrorFile" msgid="2170788515052558676">"Nije moguće pristupiti datoteci."</string>
     <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Nije moguće pronaći traženu datoteku."</string>
-    <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Previše zahteva se obrađuje. Pokušajte ponovo kasnije."</string>
+    <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Previše zahteva se obrađuje. Probajte ponovo kasnije."</string>
     <string name="notification_title" msgid="8967710025036163822">"Greška pri prijavljivanju za <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
     <string name="contentServiceSync" msgid="8353523060269335667">"Sinhronizacija"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinhronizacija"</string>
@@ -440,19 +440,19 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Dozvoljava aplikaciji da aktivira metode za dodavanje i brisanje šablona otisaka prstiju koji će se koristiti."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"koristi hardver za otiske prstiju"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Dozvoljava aplikaciji da koristi hardver za otiske prstiju radi potvrde autentičnosti"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Otkriven je delimični otisak prsta. Pokušajte ponovo."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nije uspela obrada otiska prsta. Pokušajte ponovo."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Otkriven je delimični otisak prsta. Probajte ponovo."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nije uspela obrada otiska prsta. Probajte ponovo."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Senzor za otiske prstiju je prljav. Očistite ga i pokušajte ponovo."</string>
-    <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Prebrzo ste pomerili prst. Pokušajte ponovo."</string>
-    <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Previše sporo ste pomerili prst. Pokušajte ponovo."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Prebrzo ste pomerili prst. Probajte ponovo."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Previše sporo ste pomerili prst. Probajte ponovo."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otiske prstiju nije dostupan."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Nije moguće sačuvati otisak prsta. Uklonite neki od postojećih otisaka prstiju."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Pokušajte ponovo."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Probajte ponovo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
-    <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
-    <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Pokušajte ponovo."</string>
+    <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Probajte ponovo kasnije."</string>
+    <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probajte ponovo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -680,8 +680,8 @@
     <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Hitne službe"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Nazad na poziv"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Tačno!"</string>
-    <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Pokušajte ponovo"</string>
-    <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Pokušajte ponovo"</string>
+    <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Probajte ponovo"</string>
+    <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Probajte ponovo"</string>
     <string name="lockscreen_storage_locked" msgid="9167551160010625200">"Otključaj za sve funkcije i podatke"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Premašen je najveći dozvoljeni broj pokušaja Otključavanja licem"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Nema SIM kartice"</string>
@@ -705,19 +705,19 @@
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Pogledajte Korisnički vodič ili kontaktirajte Korisničku podršku."</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM kartica je zaključana."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Otključavanje SIM kartice…"</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste nepravilno nacrtali šablon za otključavanje. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste pogrešno uneli lozinku. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste pogrešno uneli PIN. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste netačno uneli šablon za otključavanje. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> nesupešna(ih) pokušaja, od vas će biti zatraženo da otključate tablet pomoću podataka za prijavljivanje na Google.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Neispravno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja od vas će biti zatraženo da otključate TV pomoću podataka za prijavljivanje na Google.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste netačno uneli šablon za otključavanje. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> nesupešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću podataka za prijavljivanje na Google.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste nepravilno nacrtali šablon za otključavanje. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste pogrešno uneli lozinku. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste pogrešno uneli PIN. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste netačno uneli šablon za otključavanje. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> nesupešna(ih) pokušaja, od vas će biti zatraženo da otključate tablet pomoću podataka za prijavljivanje na Google.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Neispravno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja od vas će biti zatraženo da otključate TV pomoću podataka za prijavljivanje na Google.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste netačno uneli šablon za otključavanje. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> nesupešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću podataka za prijavljivanje na Google.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Nepravilno ste pokušali da otključate tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još neuspešnih pokušaja (<xliff:g id="NUMBER_1">%2$d</xliff:g>) tablet će biti resetovan na fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Pokušali ste da otključate TV netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja TV će biti resetovan na podrazumevana fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Neispravno ste pokušali da otključate telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još neuspešnih pokušaja (<xliff:g id="NUMBER_1">%2$d</xliff:g>) telefon će biti resetovan na fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Neispravno ste pokušali da otključate tablet <xliff:g id="NUMBER">%d</xliff:g> puta. Tablet će sada biti vraćen na podrazumevana fabrička podešavanja."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Pokušali ste da otključate TV netačno <xliff:g id="NUMBER">%d</xliff:g> puta. TV će sada biti resetovan na podrazumevana fabrička podešavanja."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Neispravno ste pokušali da otključate telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Telefon će sada biti vraćen na podrazumevana fabrička podešavanja."</string>
-    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekunde(i)."</string>
+    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Probajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekunde(i)."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Zaboravili ste šablon?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Otključavanje naloga"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Previše pokušaja unosa šablona"</string>
@@ -1421,7 +1421,7 @@
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Pogrešan šablon"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"Pogrešna lozinka"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Pogrešan PIN"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Pokušajte ponovo za <xliff:g id="NUMBER">%1$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Probajte ponovo za <xliff:g id="NUMBER">%1$d</xliff:g> sekunde(i)."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Nacrtajte šablon"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Unesite PIN SIM kartice"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"Unesite PIN"</string>
@@ -1443,18 +1443,18 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nevažeće korisničko ime ili lozinka."</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Zaboravili ste korisničko ime ili lozinku?\nPosetite adresu "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"Provera naloga…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Uneli ste netačni PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Uneli ste netačnu lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Uneli ste netačni PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Uneli ste netačnu lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Pokušali ste da otključate tablet netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja tablet će biti resetovan na fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"Pokušali ste da otključate TV netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja TV će biti resetovan na podrazumevana fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Pokušali ste da otključate telefon netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja telefon će biti resetovan na fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Pokušali ste da otključate tablet netačno <xliff:g id="NUMBER">%d</xliff:g> puta. Tablet će sada biti vraćen na podrazumevana fabrička podešavanja."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Pokušali ste da otključate TV netačno <xliff:g id="NUMBER">%d</xliff:g> puta. TV će sada biti resetovan na podrazumevana fabrička podešavanja."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Pokušali ste da otključate telefon netačno <xliff:g id="NUMBER">%d</xliff:g> puta. Telefon će sada biti vraćen na podrazumevana fabrička podešavanja."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate tablet pomoću naloga e-pošte.\n\nPokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Neispravno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate TV pomoću naloga e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću naloga e-pošte.\n\nPokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate tablet pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Neispravno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate TV pomoću naloga e-pošte.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Ukloni"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Želite da pojačate zvuk iznad preporučenog nivoa?\n\nSlušanje glasne muzike duže vreme može da vam ošteti sluh."</string>
@@ -1565,14 +1565,14 @@
     <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"Novi PIN"</string>
     <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"Potvrdite novi PIN"</string>
     <string name="restr_pin_create_pin" msgid="8017600000263450337">"Napravite PIN za izmenu ograničenja"</string>
-    <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN-ovi se ne podudaraju. Pokušajte ponovo."</string>
+    <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN-ovi se ne podudaraju. Probajte ponovo."</string>
     <string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN je prekratak. Mora da sadrži najmanje 4 cifre."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
-      <item quantity="one">Pokušajte ponovo za <xliff:g id="COUNT">%d</xliff:g> sekundu</item>
-      <item quantity="few">Pokušajte ponovo za <xliff:g id="COUNT">%d</xliff:g> sekunde</item>
-      <item quantity="other">Pokušajte ponovo za <xliff:g id="COUNT">%d</xliff:g> sekundi</item>
+      <item quantity="one">Probajte ponovo za <xliff:g id="COUNT">%d</xliff:g> sekundu</item>
+      <item quantity="few">Probajte ponovo za <xliff:g id="COUNT">%d</xliff:g> sekunde</item>
+      <item quantity="other">Probajte ponovo za <xliff:g id="COUNT">%d</xliff:g> sekundi</item>
     </plurals>
-    <string name="restr_pin_try_later" msgid="973144472490532377">"Pokušajte ponovo kasnije"</string>
+    <string name="restr_pin_try_later" msgid="973144472490532377">"Probajte ponovo kasnije"</string>
     <string name="immersive_cling_title" msgid="8394201622932303336">"Prikazuje se ceo ekran"</string>
     <string name="immersive_cling_description" msgid="3482371193207536040">"Da biste izašli, prevucite nadole odozgo."</string>
     <string name="immersive_cling_positive" msgid="5016839404568297683">"Važi"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f453024..05155ca 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -417,7 +417,7 @@
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Ermöglicht der App, Pakete zu empfangen, die mithilfe von Multicast-Adressen an sämtliche Geräte in einem WLAN versendet wurden, nicht nur an dein Telefon. Dies nimmt mehr Leistung in Anspruch als der Nicht-Multicast-Modus."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Auf Bluetooth-Einstellungen zugreifen"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Ermöglicht der App, das lokale Bluetooth-Tablet zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen"</string>
-    <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"Ermöglicht der App, den lokalen Bluetooth-Fernseher zu konfigurieren, Remote-Geräte zu erkennen und ein Pairing mit diesen durchzuführen"</string>
+    <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"Ermöglicht der App, den lokalen Bluetooth-Fernseher zu konfigurieren, Remote-Geräte zu erkennen und eine Kopplung mit ihnen durchzuführen"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Ermöglicht der App, das lokale Bluetooth-Telefon zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen"</string>
     <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX-Verbindungen herstellen und trennen"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Ermöglicht der App festzustellen, ob WiMAX aktiviert ist. Zudem kann sie Informationen zu verbundenen WiMAX-Netzwerken abrufen."</string>
@@ -425,9 +425,9 @@
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Ermöglicht der App, eine Verbindung zwischen dem Tablet und WiMAX-Netzwerken herzustellen und solche zu trennen."</string>
     <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"Ermöglicht der App, eine Verbindung zwischen dem Fernseher und WiMAX-Netzwerken herzustellen und diese zu trennen"</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Ermöglicht der App, eine Verbindung zwischen dem Telefon und WiMAX-Netzwerken herzustellen und solche zu trennen."</string>
-    <string name="permlab_bluetooth" msgid="6127769336339276828">"Pairing mit Bluetooth-Geräten durchführen"</string>
+    <string name="permlab_bluetooth" msgid="6127769336339276828">"Kopplung mit Bluetooth-Geräten durchführen"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Ermöglicht der App, die Bluetooth-Konfiguration eines Tablets einzusehen und Verbindungen zu gekoppelten Geräten herzustellen und zu akzeptieren."</string>
-    <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"Ermöglicht der App, die Bluetooth-Konfiguration des Fernsehers einzusehen und Verbindungen zu Pairing-Geräten herzustellen und zu akzeptieren"</string>
+    <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"Ermöglicht der App, die Bluetooth-Konfiguration des Fernsehers abzurufen und Verbindungen zu gekoppelten Geräten herzustellen und zu akzeptieren"</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Ermöglicht der App, die Bluetooth-Konfiguration des Telefons einzusehen und Verbindungen mit gekoppelten Geräten herzustellen und zu akzeptieren."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"Nahfeldkommunikation steuern"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Ermöglicht der App die Kommunikation mit Tags für die Nahfeldkommunikation, Karten und Readern"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 5f148e3..4283827 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -250,7 +250,7 @@
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"Ημερολόγιο"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"έχει πρόσβαση στο ημερολόγιό σας"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
-    <string name="permgroupdesc_sms" msgid="4656988620100940350">"αποστολή και προβολή μηνυμάτων SMS"</string>
+    <string name="permgroupdesc_sms" msgid="4656988620100940350">"στέλνει και να διαβάζει μηνύματα SMS"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Αποθηκευτικός χώρος"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"έχει πρόσβαση στις φωτογραφίες/πολυμέσα/αρχεία στη συσκευή σας"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Μικρόφωνο"</string>
@@ -273,149 +273,149 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ελέγξτε το επίπεδο ζουμ και τη θέση της οθόνης."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Εκτέλεση κινήσεων"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Επιτρέπει το πάτημα, την ολίσθηση, το πλησίασμα και άλλες κινήσεις."</string>
-    <string name="permlab_statusBar" msgid="7417192629601890791">"απενεργοποίηση ή τροποποίηση γραμμής κατάστασης"</string>
+    <string name="permlab_statusBar" msgid="7417192629601890791">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
-    <string name="permlab_statusBarService" msgid="4826835508226139688">"ορισμός ως γραμμής κατάστασης"</string>
+    <string name="permlab_statusBarService" msgid="4826835508226139688">"ορίζεται ως γραμμή κατάστασης"</string>
     <string name="permdesc_statusBarService" msgid="716113660795976060">"Επιτρέπει στην εφαρμογή να αποτελεί τη γραμμή κατάστασης."</string>
-    <string name="permlab_expandStatusBar" msgid="1148198785937489264">"ανάπτυξη/σύμπτυξη γραμμής κατάστασης"</string>
+    <string name="permlab_expandStatusBar" msgid="1148198785937489264">"αναπτύσσει/συμπτύσσει τη γραμμή κατάστασης"</string>
     <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Επιτρέπει στην εφαρμογή να αναπτύξει ή να συμπτύξει τη γραμμή κατάστασης."</string>
-    <string name="permlab_install_shortcut" msgid="4279070216371564234">"εγκατάσταση συντομεύσεων"</string>
+    <string name="permlab_install_shortcut" msgid="4279070216371564234">"εγκαθιστά συντομεύσεις"</string>
     <string name="permdesc_install_shortcut" msgid="8341295916286736996">"Επιτρέπει σε μια εφαρμογή την προσθήκη συντομεύσεων στην Αρχική οθόνη χωρίς την παρέμβαση του χρήστη."</string>
-    <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"κατάργηση εγκατάστασης συντομεύσεων"</string>
+    <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"καταργεί την εγκατάσταση συντομεύσεων"</string>
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Επιτρέπει στην εφαρμογή την κατάργηση συντομεύσεων από την Αρχική οθόνη χωρίς την παρέμβαση του χρήστη."</string>
-    <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"αναδρομολόγηση εξερχόμενων κλήσεων"</string>
+    <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"αναδρομολογεί τις εξερχόμενες κλήσεις"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Επιτρέπει στην εφαρμογή να βλέπει τον αριθμό που καλέσατε κατά τη διάρκεια μιας εξερχόμενης κλήσης με επιλογή ανακατεύθυνσης της κλήσης σε έναν διαφορετικό αριθμό ή διακοπής της κλήσης."</string>
-    <string name="permlab_receiveSms" msgid="8673471768947895082">"λήψη μηνυμάτων κειμένου (SMS)"</string>
+    <string name="permlab_receiveSms" msgid="8673471768947895082">"λαμβάνει μηνύματα κειμένου (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων SMS. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
-    <string name="permlab_receiveMms" msgid="1821317344668257098">"λήψη μηνυμάτων κειμένου (MMS)"</string>
+    <string name="permlab_receiveMms" msgid="1821317344668257098">"λαμβάνει μηνύματα κειμένου (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων MMS. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
-    <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ανάγνωση μηνυμάτων που έχουν μεταδοθεί μέσω κινητού τηλεφώνου"</string>
+    <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"διαβάζει μηνύματα που έχουν μεταδοθεί μέσω κινητού τηλεφώνου"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Επιτρέπει στην εφαρμογή την ανάγνωση μηνυμάτων που έχουν μεταδοθεί μέσω κινητού τηλεφώνου και έχουν ληφθεί από τη συσκευή σας. Ειδοποιήσεις που μεταδίδονται μέσω κινητού παραδίδονται σε ορισμένες τοποθεσίες για να σας προειδοποιήσουν για καταστάσεις έκτακτης ανάγκης. Κακόβουλες εφαρμογές ενδέχεται να παρεμποδίσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μετάδοσης μέσω κινητού σχετικά με μια επείγουσα κατάσταση."</string>
-    <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ανάγνωση ροών δεδομένων στις οποίες έχετε εγγραφεί"</string>
+    <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"διαβάζει ροές δεδομένων στις οποίες έχετε εγγραφεί"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Επιτρέπει στην εφαρμογή τη λήψη λεπτομερειών σχετικά με τις τρέχουσες συγχρονισμένες ροές δεδομένων."</string>
-    <string name="permlab_sendSms" msgid="7544599214260982981">"πραγματοποιεί αποστολή και προβολή μηνυμάτων SMS"</string>
+    <string name="permlab_sendSms" msgid="7544599214260982981">"στέλνει και να διαβάζει μηνύματα SMS"</string>
     <string name="permdesc_sendSms" msgid="7094729298204937667">"Επιτρέπει στην εφαρμογή των αποστολή μηνυμάτων SMS. Αυτό μπορεί να προκαλέσει μη αναμενόμενες χρεώσεις. Οι κακόβουλες εφαρμογές ενδέχεται να σας κοστίσουν χρήματα, αποστέλλοντας μηνύματα χωρίς την έγκρισή σας."</string>
-    <string name="permlab_readSms" msgid="8745086572213270480">"ανάγνωση των μηνυμάτων κειμένου σας (SMS ή MMS)"</string>
+    <string name="permlab_readSms" msgid="8745086572213270480">"διαβάζει τα μηνύματα κειμένου (SMS ή MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Επιτρέπει στην εφαρμογή την ανάγνωση μηνυμάτων SMS που είναι αποθηκευμένα στο tablet σας ή στην κάρτα σας SIM. Αυτό δίνει τη δυνατότητα στην εφαρμογή να διαβάζει όλα τα μηνύματα SMS, ανεξάρτητα από το περιεχόμενο ή το επίπεδο εμπιστευτικότητάς τους."</string>
     <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"Επιτρέπει στην εφαρμογή να διαβάζει μηνύματα SMS που έχουν αποθηκευτεί στην τηλεόραση ή στην κάρτα SIM. Έτσι, η εφαρμογή μπορεί να διαβάζει όλα τα μηνύματα SMS, ανεξαρτήτως περιεχομένου ή εμπιστευτικότητας."</string>
     <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Επιτρέπει στην εφαρμογή την ανάγνωση μηνυμάτων SMS που είναι αποθηκευμένα στο τηλέφωνό σας ή στην κάρτα σας SIM. Αυτό δίνει τη δυνατότητα στην εφαρμογή να διαβάζει όλα τα μηνύματα SMS, ανεξάρτητα από το περιεχόμενο ή το επίπεδο εμπιστευτικότητάς τους."</string>
-    <string name="permlab_receiveWapPush" msgid="5991398711936590410">"λήψη μηνυμάτων κειμένου (WAP)"</string>
+    <string name="permlab_receiveWapPush" msgid="5991398711936590410">"λαμβάνει μηνύματα κειμένου (WAP)"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων WAP. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
-    <string name="permlab_getTasks" msgid="6466095396623933906">"ανάκτηση εκτελούμενων εφαρμογών"</string>
+    <string name="permlab_getTasks" msgid="6466095396623933906">"ανακτά εκτελούμενες εφαρμογές"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Επιτρέπει στην εφαρμογή την ανάκτηση πληροφοριών σχετικά με τρέχουσες και πρόσφατα εκτελούμενες εργασίες. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να ανακαλύπτει πληροφορίες σχετικά με το ποιες εφαρμογές χρησιμοποιούνται στη συσκευή."</string>
-    <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"διαχείριση προφίλ και κατόχων συσκευής"</string>
+    <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"διαχειρίζεται το προφίλ και τους κατόχους συσκευής"</string>
     <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"Επιτρέπει σε εφαρμογές να ορίζουν τους κατόχους προφίλ και τον κάτοχο της συσκευής."</string>
-    <string name="permlab_reorderTasks" msgid="2018575526934422779">"αναδιάταξη εκτελούμενων εφαρμογών"</string>
+    <string name="permlab_reorderTasks" msgid="2018575526934422779">"αναδιατάσσει τις εκτελούμενες εφαρμογές"</string>
     <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Επιτρέπει στην εφαρμογή τη μετακίνηση εργασιών στο προσκήνιο και το παρασκήνιο. Η εφαρμογή μπορεί να το κάνει αυτό χωρίς να καταχωρίσετε δεδομένα εισόδου."</string>
-    <string name="permlab_enableCarMode" msgid="5684504058192921098">"ενεργοποίηση λειτουργίας αυτοκινήτου"</string>
+    <string name="permlab_enableCarMode" msgid="5684504058192921098">"ενεργοποιεί την λειτουργία αυτοκινήτου"</string>
     <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Επιτρέπει στην εφαρμογή την ενεργοποίηση της λειτουργίας αυτοκινήτου."</string>
-    <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"κλείσιμο των άλλων εφαρμογών"</string>
+    <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"κλείνει άλλες εφαρμογές"</string>
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Επιτρέπει στην εφαρμογή τον τερματισμό των διεργασιών παρασκηνίου άλλων εφαρμογών. Αυτό μπορεί να προκαλεί τη διακοπή λειτουργίας άλλων εφαρμογών."</string>
-    <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"σχεδίαση πάνω σε άλλες εφαρμογές"</string>
+    <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"σχεδιάζει πάνω από άλλες εφαρμογές"</string>
     <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Επιτρέπει στην εφαρμογή το σχεδιασμό πάνω σε άλλες εφαρμογές ή τμήματα του περιβάλλοντος χρήστη. Ενδέχεται να παρεμβαίνουν στη χρήση του περιβάλλοντος σε άλλες εφαρμογές ή να αλλάζουν τα στοιχεία που βλέπετε σε άλλες εφαρμογές."</string>
-    <string name="permlab_persistentActivity" msgid="8841113627955563938">"να εκτελείται συνεχώς η εφαρμογή"</string>
+    <string name="permlab_persistentActivity" msgid="8841113627955563938">"επιτρέπει στην εφαρμογή να εκτελείται συνεχώς"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Επιτρέπει στην εφαρμογή να δημιουργεί μόνιμα τμήματα του εαυτού της στη μνήμη. Αυτό μπορεί να περιορίζει τη μνήμη που διατίθεται σε άλλες εφαρμογές, καθυστερώντας τη λειτουργία του tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Επιτρέπει στην εφαρμογή να καθιστά τμήματά της μόνιμα στη μνήμη. Αυτό μπορεί να περιορίσει τη μνήμη που διατίθεται σε άλλες εφαρμογές, επιβραδύνοντας τη λειτουργία της τηλεόρασης."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Επιτρέπει στην εφαρμογή να δημιουργεί μόνιμα τμήματα του εαυτού της στη μνήμη. Αυτό μπορεί να περιορίζει τη μνήμη που διατίθεται σε άλλες εφαρμογές, καθυστερώντας τη λειτουργία του τηλεφώνου."</string>
-    <string name="permlab_getPackageSize" msgid="7472921768357981986">"μέτρηση αποθηκευτικού χώρου εφαρμογής"</string>
+    <string name="permlab_getPackageSize" msgid="7472921768357981986">"υπολογίζει τον αποθηκευτικό χώρο εφαρμογής"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Επιτρέπει στην εφαρμογή να ανακτήσει τα μεγέθη κώδικα, δεδομένων και προσωρινής μνήμης"</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"τροποποίηση ρυθμίσεων συστήματος"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"Επιτρέπει στην εφαρμογή την τροποποίηση των δεδομένων των ρυθμίσεων του συστήματος. Τυχόν κακόβουλες εφαρμογές ενδέχεται να καταστρέψουν τη διαμόρφωση του συστήματός σας."</string>
-    <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"εκτέλεση κατά την έναρξη"</string>
+    <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"εκτελείται κατά την έναρξη"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Επιτρέπει στην εφαρμογή να εκκινηθεί αμέσως μόλις ολοκληρωθεί η εκκίνηση του συστήματος. Αυτό ενδέχεται να καθυστερήσει την εκκίνηση του tablet και να προκαλέσει γενική μείωση της ταχύτητας λειτουργίας του tablet, καθώς η εφαρμογή θα εκτελείται συνεχώς."</string>
     <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"Επιτρέπει στην εφαρμογή να ξεκινάει μόλις ολοκληρώνεται η εκκίνηση του συστήματος. Αυτό μπορεί να καθυστερεί την εκκίνηση της τηλεόρασης και επιτρέπει στην εφαρμογή να επιβραδύνει τη συνολική λειτουργία του tablet, λόγω της συνεχούς προβολής."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Επιτρέπει στην εφαρμογή να εκκινηθεί αμέσως μόλις ολοκληρωθεί η εκκίνηση του συστήματος. Αυτό ενδέχεται να καθυστερήσει την εκκίνηση του τηλεφώνου και να προκαλέσει γενική μείωση της ταχύτητας λειτουργίας του τηλεφώνου, καθώς η εφαρμογή θα εκτελείται συνεχώς."</string>
-    <string name="permlab_broadcastSticky" msgid="7919126372606881614">"αποστολή εκπομπής sticky"</string>
+    <string name="permlab_broadcastSticky" msgid="7919126372606881614">"στέλνει εκπομπή sticky"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Επιτρέπει στην εφαρμογή την αποστολή εκπομπών sticky, οι οποίες παραμένουν μετά το τέλος της εκπομπής. Η υπερβολική χρήση ενδέχεται να καταστήσει τη λειτουργία του tablet αργή ή ασταθή, προκαλώντας τη χρήση μεγάλου τμήματος της μνήμης."</string>
     <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"Επιτρέπει στην εφαρμογή να στέλνει εκπομπές που παραμένουν μετά το τέλος της μετάδοσης. Η υπερβολική χρήση μπορεί να καταστήσει αργή ή ασταθή τη λειτουργία της τηλεόρασης, προκαλώντας τη χρήση υπερβολικά μεγάλου μέρους της μνήμης."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Επιτρέπει στην εφαρμογή την αποστολή εκπομπών sticky, οι οποίες παραμένουν μετά το τέλος της εκπομπής. Η υπερβολική χρήση ενδέχεται να καταστήσει τη λειτουργία του τηλεφώνου αργή ή ασταθή, προκαλώντας τη χρήση μεγάλου τμήματος της μνήμης."</string>
-    <string name="permlab_readContacts" msgid="8348481131899886131">"ανάγνωση των επαφών σας"</string>
+    <string name="permlab_readContacts" msgid="8348481131899886131">"διαβάζει τις επαφές σας"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Επιτρέπει στην εφαρμογή την ανάγνωση δεδομένων σχετικά με τις επαφές σας που είναι αποθηκευμένες στο tablet σας, συμπεριλαμβανομένης της συχνότητας με την οποία έχετε καλέσει συγκεκριμένα άτομα ή έχετε επικοινωνήσει μαζί τους μέσω ηλεκτρονικού ταχυδρομείου ή άλλου τρόπου. Αυτή η άδεια δίνει τη δυνατότητα σε εφαρμογές να αποθηκεύουν τα δεδομένα των επαφών σας και οι κακόβουλες εφαρμογές ενδέχεται να μοιράζονται δεδομένα επαφών χωρίς να το γνωρίζετε."</string>
     <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"Επιτρέπει στην εφαρμογή να διαβάζει δεδομένα σχετικά με τις επαφές σας που είναι αποθηκευμένες στην τηλεόρασή σας, συμπεριλαμβανομένης της συχνότητας με την οποία έχετε καλέσει συγκεκριμένα άτομα ή έχετε επικοινωνήσει μαζί τους μέσω ηλεκτρονικού ταχυδρομείου ή άλλου τρόπου. Αυτό το δικαίωμα επιτρέπει στις εφαρμογές να αποθηκεύουν τα δεδομένα των επαφών σας. Επίσης, κακόβουλες εφαρμογές μπορεί να μοιραστούν δεδομένα επαφών χωρίς να το γνωρίζετε."</string>
     <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Επιτρέπει στην εφαρμογή την ανάγνωση δεδομένων σχετικά με τις επαφές σας που είναι αποθηκευμένες στο τηλέφωνό σας, συμπεριλαμβανομένης της συχνότητας με την οποία έχετε καλέσει συγκεκριμένα άτομα ή έχετε επικοινωνήσει μαζί τους μέσω ηλεκτρονικού ταχυδρομείου ή άλλου τρόπου. Αυτή η άδεια δίνει τη δυνατότητα σε εφαρμογές να αποθηκεύουν τα δεδομένα των επαφών σας και οι κακόβουλες εφαρμογές ενδέχεται να μοιράζονται δεδομένα επαφών χωρίς να το γνωρίζετε."</string>
-    <string name="permlab_writeContacts" msgid="5107492086416793544">"τροποποίηση των επαφών σας"</string>
+    <string name="permlab_writeContacts" msgid="5107492086416793544">"τροποποιεί τις επαφές σας"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Επιτρέπει στην εφαρμογή την τροποποίηση των δεδομένων σχετικά με τις επαφές σας που είναι αποθηκευμένες στο tablet σας, συμπεριλαμβανομένης της συχνότητας με την οποία έχετε καλέσει συγκεκριμένες επαφές ή έχετε επικοινωνήσει μαζί τους μέσω ηλεκτρονικού ταχυδρομείου ή άλλου τρόπου. Αυτή η άδεια δίνει τη δυνατότητα σε εφαρμογές να διαγράφουν δεδομένα επαφών."</string>
     <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Επιτρέπει στην εφαρμογή να τροποποιεί τα δεδομένα σχετικά με τις επαφές που είναι αποθηκευμένες στην τηλεόρασή σας, συμπεριλαμβανομένης της συχνότητας με την οποία έχετε καλέσει συγκεκριμένες επαφές ή έχετε επικοινωνήσει μαζί τους μέσω ηλεκτρονικού ταχυδρομείου ή άλλου τρόπου. Αυτό το δικαίωμα δίνει τη δυνατότητα σε εφαρμογές να διαγράφουν δεδομένα επαφών."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Επιτρέπει στην εφαρμογή την τροποποίηση των δεδομένων σχετικά με τις επαφές σας που είναι αποθηκευμένες στο τηλέφωνό σας, συμπεριλαμβανομένης της συχνότητας με την οποία έχετε καλέσει συγκεκριμένες επαφές ή έχετε επικοινωνήσει μαζί τους μέσω ηλεκτρονικού ταχυδρομείου ή άλλου τρόπου. Αυτή η άδεια δίνει τη δυνατότητα σε εφαρμογές να διαγράφουν δεδομένα επαφών."</string>
-    <string name="permlab_readCallLog" msgid="3478133184624102739">"ανάγνωση αρχείου καταγραφής κλήσεων"</string>
+    <string name="permlab_readCallLog" msgid="3478133184624102739">"διαβάζει το αρχείο καταγραφής κλήσεων"</string>
     <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Επιτρέπει στην εφαρμογή την ανάγνωση του αρχείου καταγραφής κλήσεων του tablet σας, συμπεριλαμβανομένων των δεδομένων σχετικά με τις εισερχόμενες και τις εξερχόμενες κλήσεις. Αυτή η άδεια δίνει τη δυνατότητα στις εφαρμογές να αποθηκεύει τα δεδομένα του αρχείου καταγραφής κλήσεων και οι κακόβουλες εφαρμογές ενδέχεται να μοιράζονται δεδομένα του αρχείου καταγραφής κλήσεων χωρίς να το γνωρίζετε."</string>
     <string name="permdesc_readCallLog" product="tv" msgid="5611770887047387926">"Επιτρέπει στην εφαρμογή να διαβάζει το αρχείο καταγραφής κλήσεων της τηλεόρασής σας, συμπεριλαμβανομένων δεδομένων σχετικά με τις εισερχόμενες και τις εξερχόμενες κλήσεις. Αυτό το δικαίωμα επιτρέπει στις εφαρμογές να αποθηκεύουν τα δεδομένα του αρχείου καταγραφής κλήσεων. Επίσης, κακόβουλες εφαρμογές μπορεί να μοιραστούν δεδομένα αρχείου καταγραφής κλήσεων χωρίς να το γνωρίζετε."</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Επιτρέπει στην εφαρμογή την ανάγνωση του αρχείου καταγραφής κλήσεων του τηλεφώνου σας, συμπεριλαμβανομένων των δεδομένων σχετικά με τις εισερχόμενες και τις εξερχόμενες κλήσεις. Αυτή η άδεια δίνει τη δυνατότητα στις εφαρμογές να αποθηκεύει τα δεδομένα του αρχείου καταγραφής κλήσεων και οι κακόβουλες εφαρμογές ενδέχεται να μοιράζονται δεδομένα του αρχείου καταγραφής κλήσεων χωρίς να το γνωρίζετε."</string>
-    <string name="permlab_writeCallLog" msgid="8552045664743499354">"εγγραφή αρχείου καταγραφής κλήσεων"</string>
+    <string name="permlab_writeCallLog" msgid="8552045664743499354">"εγγράφει αρχείο καταγραφής κλήσεων"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Επιτρέπει στην εφαρμογή να τροποποιεί το αρχείο καταγραφής κλήσεων του tablet σας, συμπεριλαμβανομένων των δεδομένων σχετικά με τις εισερχόμενες και τις εξερχόμενες κλήσεις. Οι κακόβουλες εφαρμογές μπορεί να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν το αρχείο καταγραφής κλήσεων."</string>
     <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Επιτρέπει στην εφαρμογή να τροποποιεί το αρχείο καταγραφής κλήσεων της τηλεόρασής σας, συμπεριλαμβανομένων των δεδομένων σχετικά με τις εισερχόμενες και τις εξερχόμενες κλήσεις. Κακόβουλες εφαρμογές μπορεί να χρησιμοποιήσουν αυτήν τη δυνατότητα, για να διαγράψουν ή να τροποποιήσουν το αρχείο καταγραφής κλήσεων."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Επιτρέπει στην εφαρμογή να τροποποιεί το αρχείο καταγραφής κλήσεων του τηλεφώνου σας, συμπεριλαμβανομένων των δεδομένων σχετικά με τις εισερχόμενες και τις εξερχόμενες κλήσεις. Οι κακόβουλες εφαρμογές μπορεί να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν το αρχείο καταγραφής κλήσεων."</string>
     <string name="permlab_bodySensors" msgid="4683341291818520277">"πρόσβαση στους αισθητήρες λειτουργιών (π.χ. παρακολούθηση καρδιακού παλμού)"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Επιτρέπει στην εφαρμογή να αποκτήσει πρόσβαση στα δεδομένα των αισθητήρων που παρακολουθούν τη φυσική σας κατάσταση, όπως τον καρδιακό ρυθμό σας."</string>
-    <string name="permlab_readCalendar" msgid="5972727560257612398">"ανάγνωση συμβάντων ημερολογίου και εμπιστευτικών πληροφοριών"</string>
+    <string name="permlab_readCalendar" msgid="5972727560257612398">"διαβάζει συμβάντα ημερολογίου και εμπιστευτικές πληροφορίες"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Επιτρέπει στην εφαρμογή την ανάγνωση όλων των συμβάντων ημερολογίου που είναι αποθηκευμένα στο tablet σας, συμπεριλαμβανομένων εκείνων των φίλων ή των συναδέλφων σας. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να μοιράζεται ή να αποθηκεύει τα δεδομένα του ημερολογίου σας, ανεξάρτητα από το βαθμό εμπιστευτικότητας ή ευαισθησίας τους."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="3191352452242394196">"Επιτρέπει στην εφαρμογή να διαβάζει όλα τα συμβάντα ημερολογίου που είναι αποθηκευμένα στην τηλεόρασή σας, συμπεριλαμβανομένων εκείνων από τους φίλους ή τους συναδέλφους σας. Αυτό μπορεί να επιτρέψει στην εφαρμογή να μοιράζεται ή να αποθηκεύει τα δεδομένα ημερολογίου, ανεξαρτήτως εμπιστευτικότητας ή ευαισθησίας."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Επιτρέπει στην εφαρμογή την ανάγνωση όλων των συμβάντων ημερολογίου που είναι αποθηκευμένα στο τηλέφωνό σας, συμπεριλαμβανομένων εκείνων των φίλων ή των συναδέλφων σας. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να μοιράζεται ή να αποθηκεύει τα δεδομένα του ημερολογίου σας, ανεξάρτητα από το βαθμό εμπιστευτικότητας ή ευαισθησίας τους."</string>
-    <string name="permlab_writeCalendar" msgid="8438874755193825647">"προσθήκη ή τροποποίηση συμβάντων ημερολογίου και αποστολή μηνυμάτων ηλεκτρονικού ταχυδρομείου σε προσκεκλημένους χωρίς να το γνωρίζουν οι κάτοχοι"</string>
+    <string name="permlab_writeCalendar" msgid="8438874755193825647">"προσθέτει ή τροποποιεί συμβάντα ημερολογίου και να στέλνει μηνύματα ηλ. ταχυδρομείου σε προσκεκλημένους χωρίς να το γνωρίζουν οι κάτοχοι"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Επιτρέπει στην εφαρμογή την προσθήκη, την κατάργηση και την αλλαγή συμβάντων που μπορείτε να τροποποιήσετε στο tablet σας, συμπεριλαμβανομένων εκείνων των φίλων ή των συναδέλφων σας. Αυτό μπορεί να επιτρέπει στην εφαρμογή να αποστέλλει μηνύματα που φαίνεται ότι προέρχονται από κατόχους ημερολογίων ή να τροποποιεί συμβάντα χωρίς να το γνωρίζουν οι κάτοχοι."</string>
     <string name="permdesc_writeCalendar" product="tv" msgid="1273290605500902507">"Επιτρέπει στην εφαρμογή να προσθέτει, να καταργεί και να αλλάζει συμβάντα που μπορείτε να τροποποιείτε στην τηλεόρασή σας, συμπεριλαμβανομένων όσων ανήκουν σε φίλους ή συναδέλφους. Αυτό ενδέχεται να επιτρέπει στην εφαρμογή να αποστέλλει μηνύματα τα οποία φαίνεται ότι προέρχονται από κατόχους ημερολογίου ή να τροποποιεί συμβάντα χωρίς να το γνωρίζουν οι κάτοχοί τους."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Επιτρέπει στην εφαρμογή την προσθήκη, την κατάργηση και την αλλαγή συμβάντων που μπορείτε να τροποποιήσετε στο τηλέφωνό σας, συμπεριλαμβανομένων εκείνων των φίλων ή των συναδέλφων σας. Αυτό μπορεί να επιτρέπει στην εφαρμογή να αποστέλλει μηνύματα που φαίνεται ότι προέρχονται από κατόχους ημερολογίων ή να τροποποιεί συμβάντα χωρίς να το γνωρίζουν οι κάτοχοι."</string>
-    <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας"</string>
+    <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"έχει πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Επιτρέπει στην εφαρμογή την πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας. Αυτό μπορεί να δώσει τη δυνατότητα στην εφαρμογή να παρέμβει στη λειτουργία του GPS ή άλλων πηγών τοποθεσίας."</string>
-    <string name="permlab_accessFineLocation" msgid="251034415460950944">"πρόσβαση στην ακριβή τοποθεσία (με βάση το GPS και το δίκτυο)"</string>
+    <string name="permlab_accessFineLocation" msgid="251034415460950944">"έχει πρόσβαση στην ακριβή τοποθεσία (με βάση το GPS και το δίκτυο)"</string>
     <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Επιτρέπει στην εφαρμογή να λαμβάνει την ακριβή θέση σας με τη χρήση του Παγκόσμιου Συστήματος Εντοπισμού (GPS) ή πηγών τοποθεσίας δικτύου, όπως κεραίες κινητής τηλεφωνίας και Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας πρέπει να είναι ενεργοποιημένες και διαθέσιμες στην συσκευή σας, ώστε να μπορούν να χρησιμοποιηθούν από την εφαρμογή. Οι εφαρμογές ενδέχεται να τις χρησιμοποιήσουν για να προσδιορίσουν τη θέση σας και ενδέχεται να καταναλώσουν επιπλέον ισχύ μπαταρίας."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"πρόσβαση στην τοποθεσία κατά προσέγγιση (με βάση το δίκτυο)"</string>
+    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"έχει πρόσβαση στην τοποθεσία κατά προσέγγιση (με βάση το δίκτυο)"</string>
     <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Επιτρέπει στην εφαρμογή τη λήψη της κατά προσέγγιση τοποθεσίας σας. Αυτή η τοποθεσία προκύπτει από τις υπηρεσίες τοποθεσίας με τη χρήση πηγών τοποθεσίας δικτύου, όπως κεραίες κινητής τηλεφωνίας και Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας πρέπει να είναι ενεργοποιημένες και διαθέσιμες στην συσκευή σας, ώστε να μπορούν να χρησιμοποιηθούν από την εφαρμογή. Οι εφαρμογές ενδέχεται να τις χρησιμοποιήσουν για να προσδιορίσουν κατά προσέγγιση τη θέση σας."</string>
-    <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"αλλαγή των ρυθμίσεων ήχου"</string>
+    <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"αλλάζει τις ρυθμίσεις ήχου"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Επιτρέπει στην εφαρμογή την τροποποίηση καθολικών ρυθμίσεων ήχου, όπως η ένταση και ποιο ηχείο χρησιμοποιείται για έξοδο."</string>
-    <string name="permlab_recordAudio" msgid="3876049771427466323">"εγγραφή ήχου"</string>
+    <string name="permlab_recordAudio" msgid="3876049771427466323">"εγγράφει ήχο"</string>
     <string name="permdesc_recordAudio" msgid="4906839301087980680">"Επιτρέπει στην εφαρμογή την εγγραφή ήχου με το μικρόφωνο. Αυτή η άδεια δίνει τη δυνατότητα στην εφαρμογή να εγγράφει ήχο ανά πάσα στιγμή χωρίς την έγκρισή σας."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"στέλνει εντολές στην κάρτα SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Επιτρέπει στην εφαρμογή την αποστολή εντολών στην κάρτα SIM. Αυτό είναι εξαιρετικά επικίνδυνο."</string>
-    <string name="permlab_camera" msgid="3616391919559751192">"λήψη φωτογραφιών και βίντεο"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"κάνει λήψη φωτογραφιών και βίντεο"</string>
     <string name="permdesc_camera" msgid="8497216524735535009">"Επιτρέπει στην εφαρμογή τη λήψη φωτογραφιών και βίντεο με τη φωτογραφική μηχανή. Αυτή η άδεια δίνει τη δυνατότητα στην εφαρμογή να χρησιμοποιεί τη φωτογραφική μηχανή ανά πάσα στιγμή χωρίς την έγκρισή σας."</string>
-    <string name="permlab_vibrate" msgid="7696427026057705834">"έλεγχος δόνησης"</string>
+    <string name="permlab_vibrate" msgid="7696427026057705834">"ελέγχει τη δόνηση"</string>
     <string name="permdesc_vibrate" msgid="6284989245902300945">"Επιτρέπει στην εφαρμογή τον έλεγχο της δόνησης."</string>
-    <string name="permlab_callPhone" msgid="3925836347681847954">"απευθείας κλήση τηλεφωνικών αριθμών"</string>
+    <string name="permlab_callPhone" msgid="3925836347681847954">"πραγματοποιεί απευθείας κλήση τηλεφωνικών αριθμών"</string>
     <string name="permdesc_callPhone" msgid="3740797576113760827">"Επιτρέπει στην εφαρμογή την κλήση αριθμών τηλεφώνου χωρίς δική σας παρέμβαση. Αυτό μπορεί να προκαλέσει μη αναμενόμενες χρεώσεις ή κλήσεις. Έχετε υπόψη ότι δεν επιτρέπεται στην εφαρμογή η κλήση αριθμών έκτακτης ανάγκης. Οι κακόβουλες εφαρμογές ενδέχεται να σας κοστίσουν χρήματα, πραγματοποιώντας κλήσεις χωρίς την έγκρισή σας."</string>
-    <string name="permlab_accessImsCallService" msgid="3574943847181793918">"πρόσβαση στην υπηρεσία κλήσεων της IMS"</string>
+    <string name="permlab_accessImsCallService" msgid="3574943847181793918">"έχει πρόσβαση στην υπηρεσία κλήσεων της IMS"</string>
     <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Επιτρέπει στην εφαρμογή τη χρήση της υπηρεσίας IMS για την πραγματοποίηση κλήσεων χωρίς τη δική σας παρέμβαση."</string>
-    <string name="permlab_readPhoneState" msgid="9178228524507610486">"ανάγνωση κατάστασης και ταυτότητας τηλεφώνου"</string>
+    <string name="permlab_readPhoneState" msgid="9178228524507610486">"διαβάζει την κατάσταση και ταυτότητα τηλεφώνου"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Επιτρέπει στην εφαρμογή την πρόσβαση στις λειτουργίες τηλεφώνου της συσκευής. Αυτή η άδεια δίνει τη δυνατότητα στην εφαρμογή να καθορίζει τον αριθμό τηλεφώνου και τα αναγνωριστικά συσκευών, εάν μια κλήση είναι ενεργή, καθώς και τον απομακρυσμένο αριθμό που συνδέεται από μια κλήση."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"παρεμπόδιση μετάβασης του tablet σε κατάσταση αδράνειας"</string>
-    <string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"αποτροπή μετάβασης της τηλεόρασης στην κατάσταση αδράνειας"</string>
-    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"παρεμπόδιση μετάβασης του τηλεφώνου σε κατάσταση αδράνειας"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"αποτρέπει την μετάβαση του tablet σε κατάσταση αδράνειας"</string>
+    <string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"αποτρέπει την μετάβαση της τηλεόρασης σε κατάσταση αδράνειας"</string>
+    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"αποτρέπει το τηλεφώνο να μεταβεί σε κατάσταση αδράνειας"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Επιτρέπει στην εφαρμογή την παρεμπόδιση της μετάβασης του tablet σε κατάσταση αδράνειας."</string>
     <string name="permdesc_wakeLock" product="tv" msgid="3208534859208996974">"Επιτρέπει στην εφαρμογή να εμποδίζει τη μετάβαση της τηλεόρασης στην κατάσταση αδράνειας."</string>
     <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Επιτρέπει στην εφαρμογή την παρεμπόδιση της μετάβασης του τηλεφώνου σε κατάσταση αδράνειας."</string>
-    <string name="permlab_transmitIr" msgid="7545858504238530105">"μετάδοση υπερύθρων"</string>
+    <string name="permlab_transmitIr" msgid="7545858504238530105">"μεταδίδει με υπερύθρες"</string>
     <string name="permdesc_transmitIr" product="tablet" msgid="5358308854306529170">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί τον πομπό υπερύθρων του tablet."</string>
     <string name="permdesc_transmitIr" product="tv" msgid="3926790828514867101">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί τον πομπό υπερύθρων της τηλεόρασης."</string>
     <string name="permdesc_transmitIr" product="default" msgid="7957763745020300725">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί τον πομπό υπερύθρων του τηλεφώνου."</string>
-    <string name="permlab_setWallpaper" msgid="6627192333373465143">"ορισμός ταπετσαρίας"</string>
+    <string name="permlab_setWallpaper" msgid="6627192333373465143">"ορίζει ταπετσαρία"</string>
     <string name="permdesc_setWallpaper" msgid="7373447920977624745">"Επιτρέπει στην εφαρμογή τον ορισμό της ταπετσαρίας συστήματος."</string>
-    <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"ρύθμιση του μεγέθους της ταπετσαρίας σας"</string>
+    <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"ρυθμίζει το μέγεθος της ταπετσαρίας"</string>
     <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Επιτρέπει στην εφαρμογή τον ορισμό συμβουλών μεγέθους ταπετσαρίας συστήματος."</string>
-    <string name="permlab_setTimeZone" msgid="2945079801013077340">"ορισμός ζώνης ώρας"</string>
+    <string name="permlab_setTimeZone" msgid="2945079801013077340">"ορίζει τη ζώνης ώρας"</string>
     <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"Επιτρέπει στην εφαρμογή την αλλαγή της ζώνης ώρας του tablet."</string>
     <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"Επιτρέπει στην εφαρμογή να αλλάζει τη ζώνη ώρας της τηλεόρασης."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Επιτρέπει στην εφαρμογή την αλλαγή της ζώνης ώρας του τηλεφώνου."</string>
-    <string name="permlab_getAccounts" msgid="1086795467760122114">"εύρεση λογαριασμών στη συσκευή"</string>
+    <string name="permlab_getAccounts" msgid="1086795467760122114">"βρίσκει λογαριασμούς στη συσκευή"</string>
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Επιτρέπει στην εφαρμογή τη λήψη της λίστας λογαριασμών που υπάρχουν στο tablet. Μπορεί να περιλαμβάνονται τυχόν λογαριασμοί που δημιουργήθηκαν από εφαρμογές που έχετε εγκαταστήσει."</string>
     <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Επιτρέπει στην εφαρμογή να λαμβάνει τη λίστα λογαριασμών που γνωρίζει η τηλεόραση. Αυτό μπορεί να περιλαμβάνει λογαριασμούς που δημιουργούνται από λογαριασμούς που έχετε εγκαταστήσει."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Επιτρέπει στην εφαρμογή τη λήψη της λίστας λογαριασμών που υπάρχουν στο τηλέφωνο. Μπορεί να περιλαμβάνονται τυχόν λογαριασμοί που δημιουργήθηκαν από εφαρμογές που έχετε εγκαταστήσει."</string>
-    <string name="permlab_accessNetworkState" msgid="4951027964348974773">"προβολή συνδέσεων δικτύου"</string>
+    <string name="permlab_accessNetworkState" msgid="4951027964348974773">"βλέπει τις συνδέσεις δικτύου"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Επιτρέπει στην εφαρμογή την προβολή πληροφοριών σχετικά με συνδέσεις δικτύου, όπως ποια δίκτυα υπάρχουν και είναι συνδεδεμένα."</string>
-    <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"πλήρης πρόσβαση στο δίκτυο"</string>
+    <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"έχει πλήρη πρόσβαση στο δίκτυο"</string>
     <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Επιτρέπει στην εφαρμογή τη δημιουργία θέσεων δικτύου και τη χρήση προσαρμοσμένων πρωτοκόλλων δικτύου. Το πρόγραμμα περιήγησης και άλλες εφαρμογές παρέχουν μέσα για την αποστολή δεδομένων στο διαδίκτυο, επομένως η συγκεκριμένη άδεια δεν είναι απαραίτητη για την αποστολή δεδομένων στο διαδίκτυο."</string>
-    <string name="permlab_changeNetworkState" msgid="958884291454327309">"αλλαγή συνδεσιμότητας δικτύου"</string>
+    <string name="permlab_changeNetworkState" msgid="958884291454327309">"αλλάζει την συνδεσιμότητα δικτύου"</string>
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Επιτρέπει στην εφαρμογή την αλλαγή της κατάστασης συνδεσιμότητας δικτύου."</string>
-    <string name="permlab_changeTetherState" msgid="5952584964373017960">"αλλαγή συνδεσιμότητας μέσω σύνδεσης με κινητή συσκευή"</string>
+    <string name="permlab_changeTetherState" msgid="5952584964373017960">"αλλάζει συνδεσιμότητα μέσω σύνδεσης με κινητή συσκευή"</string>
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Επιτρέπει στην εφαρμογή την αλλαγή της κατάστασης συνδεσιμότητας δικτύου."</string>
-    <string name="permlab_accessWifiState" msgid="5202012949247040011">"προβολή συνδέσεων Wi-Fi"</string>
+    <string name="permlab_accessWifiState" msgid="5202012949247040011">"βλέπει τις συνδέσεις Wi-Fi"</string>
     <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Επιτρέπει στην εφαρμογή την προβολή πληροφοριών σχετικά με τη δικτύωση Wi-Fi, όπως εάν το Wi-Fi είναι ενεργοποιημένο και τα ονόματα των συνδεδεμένων συσκευών Wi-Fi."</string>
-    <string name="permlab_changeWifiState" msgid="6550641188749128035">"σύνδεση και αποσύνδεση από το Wi-Fi"</string>
+    <string name="permlab_changeWifiState" msgid="6550641188749128035">"συνδέεται/αποσυνδέεται από το Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Επιτρέπει στην εφαρμογή τη σύνδεση σε σημεία πρόσβασης Wi-Fi και την αποσύνδεση από αυτά, καθώς και την πραγματοποίηση αλλαγών σε διαμόρφωση συσκευών για δίκτυα Wi-Fi."</string>
-    <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"να επιτρέπεται η λήψη πολλαπλής διανομής Wi-Fi"</string>
+    <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"επιτρέπει την λήψη πολλαπλής διανομής Wi-Fi"</string>
     <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Επιτρέπει στην εφαρμογή τη λήψη πακέτων που αποστέλλονται σε όλες τις συσκευές σε ένα δίκτυο Wi-Fi, με χρήση διευθύνσεων πολλαπλής διανομής και όχι απλώς στο tablet σας. Χρησιμοποιεί περισσότερη ενέργεια σε σχέση με τη λειτουργία χωρίς πολλαπλή διανομή."</string>
     <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Επιτρέπει στην εφαρμογή να λαμβάνει πακέτα που αποστέλλονται σε όλες τις συσκευές σε ένα δίκτυο Wi-Fi, χρησιμοποιώντας διευθύνσεις multicast και όχι μόνο την τηλεόρασή σας. Χρησιμοποιεί περισσότερη ενέργεια από τη λειτουργία χωρίς multicast."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Επιτρέπει στην εφαρμογή τη λήψη πακέτων που αποστέλλονται σε όλες τις συσκευές σε ένα δίκτυο Wi-Fi, με χρήση διευθύνσεων πολλαπλής διανομής και όχι απλώς στο τηλέφωνό σας. Χρησιμοποιεί περισσότερη ενέργεια σε σχέση με τη λειτουργία χωρίς πολλαπλή διανομή."</string>
-    <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"πρόσβαση στις ρυθμίσεις Bluetooth"</string>
+    <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"διαβάζει τις ρυθμίσεις Bluetooth"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Επιτρέπει στην εφαρμογή τη διαμόρφωση του τοπικού tablet Bluetooth, τον εντοπισμό και τη σύζευξη με απομακρυσμένες συσκευές."</string>
     <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"Επιτρέπει στην εφαρμογή να διαμορφώνει το τοπικό Bluetooth στην τηλεόραση, καθώς και να ανακαλύπτει απομακρυσμένες συσκευές και να συνδέεται μαζί τους."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Επιτρέπει στην εφαρμογή τη διαμόρφωση του τοπικού tablet Bluetooth, τον εντοπισμό και τη σύζευξη με απομακρυσμένες συσκευές."</string>
@@ -425,17 +425,17 @@
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Επιτρέπει στην εφαρμογή τη σύνδεση στο tablet και την αποσύνδεση από αυτό, από δίκτυα WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"Επιτρέπει στην εφαρμογή να συνδέει και να αποσυνδέει την τηλεόραση από δίκτυα WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Επιτρέπει στην εφαρμογή τη σύνδεση στο τηλέφωνο και την αποσύνδεση από αυτό, από δίκτυα WiMAX."</string>
-    <string name="permlab_bluetooth" msgid="6127769336339276828">"σύζευξη με συσκευές Bluetooth"</string>
+    <string name="permlab_bluetooth" msgid="6127769336339276828">"πραγματοποιεί σύζευξη με συσκευές Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στο tablet, καθώς και να πραγματοποιεί και να αποδέχεται συνδέσεις με συνδεδεμένες συσκευές."</string>
     <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στην τηλεόραση, καθώς και να δημιουργεί και να αποδέχεται συνδέσεις με συσκευές σε σύζευξη."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στο τηλέφωνο, καθώς και να πραγματοποιεί και να αποδέχεται συνδέσεις με συνδεδεμένες συσκευές."</string>
-    <string name="permlab_nfc" msgid="4423351274757876953">"έλεγχος Επικοινωνίας κοντινού πεδίου (Near Field Communication)"</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"ελέγχει την Επικοινωνία κοντινού πεδίου (FNC)"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Επιτρέπει στην εφαρμογή την επικοινωνία με ετικέτες, κάρτες και αναγνώστες της Επικοινωνίας κοντινού πεδίου (NFC)."</string>
-    <string name="permlab_disableKeyguard" msgid="3598496301486439258">"απενεργοποίηση κλειδώματος οθόνης"</string>
+    <string name="permlab_disableKeyguard" msgid="3598496301486439258">"απενεργοποιεί το κλείδωμα οθόνης"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Επιτρέπει στην εφαρμογή την απενεργοποίηση του κλειδώματος πληκτρολογίου και άλλης σχετικής ασφάλειας με κωδικό πρόσβασης. Για παράδειγμα, το κλείδωμα πληκτρολογίου στο τηλέφωνο απενεργοποιείται όταν λαμβάνεται εισερχόμενη τηλεφωνική κλήση και ενεργοποιείται ξανά όταν η κλήση τερματιστεί."</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"διαχείριση εξοπλισμού μοναδικού χαρακτηριστικού"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"διαχειρίζεται τον εξοπλισμό δακτυλικού αποτυπώματος"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Επιτρέπει στην εφαρμογή να επικαλείται μεθόδους για την προσθήκη και τη διαγραφή προτύπων μοναδικού χαρακτηριστικού για χρήση."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"χρήση εξοπλισμού μοναδικού χαρακτηριστικού"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"χρησιμοποιεί τον εξοπλισμό δακτυλικού αποτυπώματος"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί εξοπλισμό μοναδικού χαρακτηριστικού για έλεγχο ταυτότητας"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Εντοπίστηκε μερικό μοναδικό χαρακτηριστικό. Δοκιμάστε ξανά."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Δεν ήταν δυνατή η επεξεργασία του μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
@@ -454,65 +454,65 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string>
-    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ανάγνωση ρυθμίσεων συγχρονισμού"</string>
+    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"διαβάζει τις ρυθμίσεις συγχρονισμού"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Επιτρέπει στην εφαρμογή την ανάγνωση των ρυθμίσεων συγχρονισμού για έναν λογαριασμό. Για παράδειγμα, αυτό μπορεί να καθορίσει εάν η εφαρμογή \"Άτομα\" είναι συγχρονισμένη με έναν λογαριασμό."</string>
-    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"εναλλαγή ενεργοποίησης και απενεργοποίησης συγχρονισμού"</string>
+    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ενεργοποιεί/απενεργοποιεί τον συγχρονισμό"</string>
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Επιτρέπει σε μια εφαρμογή την τροποποίηση των ρυθμίσεων συγχρονισμού για έναν λογαριασμό. Για παράδειγμα, αυτό μπορεί να χρησιμοποιηθεί για να ενεργοποιηθεί ο συγχρονισμός της εφαρμογής \"Άτομα\" με έναν λογαριασμό."</string>
-    <string name="permlab_readSyncStats" msgid="7396577451360202448">"ανάγνωση στατιστικών συγχρονισμού"</string>
+    <string name="permlab_readSyncStats" msgid="7396577451360202448">"διαβάζει στατιστικά στοιχεία συγχρονισμού"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Επιτρέπει σε μια εφαρμογή την ανάγνωση των στατιστικών στοιχείων συγχρονισμού για έναν λογαριασμό, συμπεριλαμβανομένων του ιστορικού των συμβάντων συγχρονισμού και του όγκου των δεδομένων που συγχρονίζονται."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"ανάγν. περιεχ. αποθηκ. χώρ.USB"</string>
-    <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"ανάγνωση του περιεχομένου της κάρτας SD"</string>
+    <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"διαβάζει το περιεχομένο της κάρτας SD"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"Επιτρέπει στην εφαρμογή την ανάγνωση του περιεχομένου του αποθηκευτικού σας χώρου USB."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"Επιτρέπει στην εφαρμογή την ανάγνωση του περιεχομένου της κάρτας SD."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"τροποποίηση ή διαγραφή του USB"</string>
-    <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"τροποποίηση ή διαγραφή των περιεχομένων της κάρτας SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"τροποποιεί/διαγράφει το USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"τροποποιεί ή διαγράφει τα περιεχόμενα της κάρτας SD"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Επιτρέπει στην εφαρμογή την εγγραφή στον αποθηκευτικό χώρο USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Επιτρέπει στην εφαρμογή την εγγραφή στην κάρτα SD."</string>
-    <string name="permlab_use_sip" msgid="2052499390128979920">"πραγματοποίηση/λήψη κλήσεων SIP"</string>
+    <string name="permlab_use_sip" msgid="2052499390128979920">"πραγματοποιεί/λαμβάνει κλήσεις SIP"</string>
     <string name="permdesc_use_sip" msgid="2297804849860225257">"Επιτρέπει στην εφαρμογή να πραγματοποιεί και να λαμβάνει κλήσεις SIP."</string>
-    <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"εγγραφή νέων συνδέσεων SIM τηλεπικοινωνιών"</string>
+    <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"πραγματοποιεί εγγραφή νέων συνδέσεων SIM τηλεπικοινωνιών"</string>
     <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"Επιτρέπει στην εφαρμογή την εγγραφή νέων συνδέσεων SIM τηλεπικοινωνιών."</string>
-    <string name="permlab_register_call_provider" msgid="108102120289029841">"εγγραφή νέων συνδέσεων τηλεπικοινωνιών"</string>
+    <string name="permlab_register_call_provider" msgid="108102120289029841">"πραγματοποιεί εγγραφή των νέων συνδέσεων τηλεπικοινωνιών"</string>
     <string name="permdesc_register_call_provider" msgid="7034310263521081388">"Επιτρέπει στην εφαρμογή την εγγραφή νέων συνδέσεων τηλεπικοινωνιών."</string>
-    <string name="permlab_connection_manager" msgid="1116193254522105375">"διαχείριση των συνδέσεων τηλεπικοινωνιών"</string>
+    <string name="permlab_connection_manager" msgid="1116193254522105375">"διαχειρίζεται τις συνδέσεις τηλεπικοινωνιών"</string>
     <string name="permdesc_connection_manager" msgid="5925480810356483565">"Επιτρέπει στην εφαρμογή να διαχειρίζεται τις συνδέσεις τηλεπικοινωνιών."</string>
-    <string name="permlab_bind_incall_service" msgid="6773648341975287125">"αλληλεπίδραση με την οθόνη κατά τη διάρκεια κλήσης"</string>
+    <string name="permlab_bind_incall_service" msgid="6773648341975287125">"αλληλεπιδρά με την οθόνη κατά τη διάρκεια κλήσης"</string>
     <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Επιτρέπει στην εφαρμογή να ελέγχει πότε και πώς βλέπει ο χρήστης την οθόνη κατά τη διάρκεια κλήσης."</string>
-    <string name="permlab_bind_connection_service" msgid="3557341439297014940">"αλληλεπίδραση με υπηρεσίες τηλεφωνίας"</string>
+    <string name="permlab_bind_connection_service" msgid="3557341439297014940">"αλληλεπιδρά με υπηρεσίες τηλεφωνίας"</string>
     <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Επιτρέπει στην εφαρμογή να αλληλεπιδρά με υπηρεσίες τηλεφωνίας για την πραγματοποίηση/λήψη κλήσεων."</string>
-    <string name="permlab_control_incall_experience" msgid="9061024437607777619">"παροχή εμπειρίας χρήστη κατά τη διάρκεια κλήσης"</string>
+    <string name="permlab_control_incall_experience" msgid="9061024437607777619">"παρέχει εμπειρία χρήστη κατά τη διάρκεια κλήσης"</string>
     <string name="permdesc_control_incall_experience" msgid="915159066039828124">"Επιτρέπει στην εφαρμογή να παρέχει μια εμπειρία στο χρήστη κατά τη διάρκεια κλήσης."</string>
-    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ανάγνωση ιστορικών δεδομένων χρήσης δικτύου"</string>
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"διαβάζει ιστορικά στοιχεία δεδομένων χρήσης δικτύου"</string>
     <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Επιτρέπει στην εφαρμογή την ανάγνωση ιστορικών στοιχείων χρήσης δικτύου για συγκεκριμένα δίκτυα και εφαρμογές."</string>
-    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"διαχείριση πολιτικής δικτύου"</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"διαχειρίζεται την πολιτική δικτύου"</string>
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Επιτρέπει στην εφαρμογή τη διαχείριση των πολιτικών δικτύου και τον ορισμό κανόνων για ορισμένες εφαρμογές."</string>
-    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"τροποποίηση υπολογισμού χρήσης δικτύου"</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"τροποποιεί τον υπολογισμό χρήσης δικτύου"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Επιτρέπει στην εφαρμογή την τροποποίηση του τρόπου υπολογισμού της χρήσης δικτύου έναντι των εφαρμογών. Δεν προορίζεται για χρήση από συνήθεις εφαρμογές."</string>
-    <string name="permlab_accessNotifications" msgid="7673416487873432268">"πρόσβαση στις ειδοποιήσεις"</string>
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"έχει πρόσβαση στις ειδοποιήσεις"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Επιτρέπει στην εφαρμογή να ανακτά, να εξετάζει και να απαλείφει ειδοποιήσεις, συμπεριλαμβανομένων εκείνων που δημοσιεύονται από άλλες εφαρμογές."</string>
-    <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"δέσμευση σε υπηρεσία ακρόασης ειδοποίησης"</string>
+    <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"συνδέεται σε υπηρεσία ακρόασης ειδοποίησης"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας ακρόασης ειδοποιήσεων. Δεν απαιτείται σε κανονικές εφαρμογές."</string>
-    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"σύνδεση σε μια υπηρεσία παρόχου συνθηκών"</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"δεσμεύεται σε μια υπηρεσία παρόχου συνθηκών"</string>
     <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Επιτρέπει στον κάτοχο τη σύνδεση στη διεπαφή ανωτάτου επιπέδου ενός παρόχου συνθηκών. Δεν απαιτείται για κανονικές εφαρμογές."</string>
-    <string name="permlab_bindDreamService" msgid="4153646965978563462">"δέσμευση σε υπηρεσία dream"</string>
+    <string name="permlab_bindDreamService" msgid="4153646965978563462">"δεσμεύεται σε υπηρεσία dream"</string>
     <string name="permdesc_bindDreamService" msgid="7325825272223347863">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας dream. Δεν απαιτείται σε κανονικές εφαρμογές."</string>
-    <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"κλήση της εφαρμογής διαμόρφωσης που παρέχεται από την εταιρεία κινητής τηλεφωνίας"</string>
+    <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"καλέι την εφαρμογή διαμόρφωσης του παρόχου κινητής τηλεφωνίας"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Επιτρέπει στον κάτοχο την κλήση της εφαρμογής διαμόρφωσης που παρέχεται από την εταιρεία κινητής τηλεφωνίας. Δεν απαιτείται για κανονικές εφαρμογές."</string>
-    <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"λήψη παρατηρήσεων σχετικά με την κατάσταση δικτύου"</string>
+    <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ανιχνεύει παρατηρήσεις σχετικά με την κατάσταση δικτύου"</string>
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Επιτρέπει σε μια εφαρμογή να λαμβάνει παρατηρήσεις σχετικά με την κατάσταση δικτύου. Δεν θα πρέπει να απαιτείται ποτέ για κανονικές εφαρμογές."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"αλλαγή βαθμονόμησης της συσκευής εισόδου"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Επιτρέπει στην εφαρμογή να τροποποιεί τις παραμέτρους βαθμονόμησης της οθόνης αφής. Δεν απαιτείται για τις κανονικές εφαρμογές."</string>
-    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"πρόσβαση σε πιστοποιητικά DRM"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"έχει πρόσβαση σε πιστοποιητικά DRM"</string>
     <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Επιτρέπει σε μια εφαρμογή να παρέχει και να χρησιμοποιεί πιστοποιητικά DRM. Δεν θα χρειαστεί ποτέ για κανονικές εφαρμογές."</string>
     <string name="permlab_handoverStatus" msgid="7820353257219300883">"λήψη κατάστασης μεταφοράς Android Beam"</string>
     <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Επιτρέπει σε αυτήν την εφαρμογή να λαμβάνει πληροφορίες σχετικά με τις τρέχουσες μεταφορές Android Beam"</string>
-    <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"κατάργηση πιστοποιητικών DRM"</string>
+    <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"καταργεί πιστοποιητικά DRM"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Επιτρέπει σε μια εφαρμογή την κατάργηση πιστοποιητικών DRM. Δεν χρειάζεται ποτέ για κανονικές εφαρμογές."</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"δέσμευση σε υπηρεσία ανταλλαγής μηνυμάτων εταιρείας κινητής τηλεφωνίας"</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"δεσμεύεται σε υπηρεσία ανταλλαγής μηνυμάτων παρόχου κινητής τηλεφωνίας"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας ανταλλαγής μηνυμάτων εταιρείας κινητής τηλεφωνίας. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
-    <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"δέσμευση σε υπηρεσίες εταιρείας κινητής τηλεφωνίας"</string>
+    <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"δεσμεύεται σε υπηρεσίες του παρόχου κινητής τηλεφωνίας"</string>
     <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"Δίνει στον κάτοχο τη δυνατότητα δέσμευσης σε υπηρεσίες εταιρείας κινητής τηλεφωνίας. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string>
-    <string name="permlab_access_notification_policy" msgid="4247510821662059671">"πρόσβαση στη λειτουργία \"Μην ενοχλείτε\""</string>
+    <string name="permlab_access_notification_policy" msgid="4247510821662059671">"έχει πρόσβαση στη λειτουργία \"Μην ενοχλείτε\""</string>
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Επιτρέπει στην εφαρμογή την εγγραφή και τη σύνταξη διαμόρφωσης για τη λειτουργία \"Μην ενοχλείτε\"."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ελέγξτε την έκταση και τους επιτρεπόμενους χαρακτήρες σε κωδικούς πρόσβασης κλειδώματος οθόνης και PIN."</string>
@@ -792,17 +792,17 @@
     <string name="autofill_parish" msgid="8202206105468820057">"Ενορία"</string>
     <string name="autofill_area" msgid="3547409050889952423">"Περιοχή"</string>
     <string name="autofill_emirate" msgid="2893880978835698818">"Εμιράτο"</string>
-    <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"ανάγνωση των σελιδοδεικτών και του ιστορικού ιστού σας"</string>
+    <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"διαβάζει τους σελιδοδείκτες και το ιστορικού ιστού"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Επιτρέπει στην εφαρμογή την ανάγνωση του ιστορικού όλων των διευθύνσεων URL που έχει επισκεφτεί το πρόγραμμα περιήγησης, καθώς και όλων των σελιδοδεικτών του προγράμματος περιήγησης. Σημείωση: αυτή η άδεια ίσως να μην μπορεί να εφαρμοστεί από τρίτα προγράμματα περιήγησης ή άλλες εφαρμογές με δυνατότητες περιήγησης ιστού."</string>
-    <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"εγγραφή σελιδοδεικτών και ιστορικού ιστού"</string>
+    <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"εγγράφει σελιδοδείκτες και ιστορικό ιστού"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Επιτρέπει στην εφαρμογή την τροποποίηση του ιστορικού του προγράμματος περιήγησης ή των σελιδοδεικτών που έχουν αποθηκευτεί στο tablet σας. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να διαγράφει ή να τροποποιεί δεδομένα του προγράμματος περιήγησης. Σημείωση: αυτή η άδεια ίσως να μην μπορεί να εφαρμοστεί από τρίτα προγράμματα περιήγησης ή άλλες εφαρμογές με δυνατότητες περιήγησης ιστού."</string>
     <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"Επιτρέπει στην εφαρμογή να τροποποιεί το ιστορικό του προγράμματος περιήγησης ή τους σελιδοδείκτες που είναι αποθηκευμένοι στην τηλεόρασή σας. Σημείωση: Αυτό το δικαίωμα δεν πρέπει να εφαρμόζεται από τρίτα προγράμματα περιήγησης ή άλλες εφαρμογές με δυνατότητες περιήγησης στον ιστό."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Επιτρέπει στην εφαρμογή την τροποποίηση του ιστορικού του προγράμματος περιήγησης ή των σελιδοδεικτών που έχουν αποθηκευτεί στο τηλέφωνό σας. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να διαγράφει ή να τροποποιεί δεδομένα του προγράμματος περιήγησης. Σημείωση: αυτή η άδεια ίσως να μην μπορεί να εφαρμοστεί από τρίτα προγράμματα περιήγησης ή άλλες εφαρμογές με δυνατότητες περιήγησης ιστού."</string>
-    <string name="permlab_setAlarm" msgid="1379294556362091814">"ρύθμιση ξυπνητηριού"</string>
+    <string name="permlab_setAlarm" msgid="1379294556362091814">"ρυθμίζει το ξυπνητήρι"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Επιτρέπει στην εφαρμογή τη ρύθμιση μιας ειδοποίησης σε μια εγκατεστημένη εφαρμογή ξυπνητηριού. Ορισμένες εφαρμογές ξυπνητηριού ενδέχεται να μην μπορούν να ενσωματώσουν αυτήν τη λειτουργία."</string>
-    <string name="permlab_addVoicemail" msgid="5525660026090959044">"προσθήκη τηλεφωνητή"</string>
+    <string name="permlab_addVoicemail" msgid="5525660026090959044">"προσθέτει τηλεφωνητή"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Επιτρέπει στην εφαρμογή να προσθέτει μηνύματα στα εισερχόμενα του αυτόματου τηλεφωνητή σας."</string>
-    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"τροποποίηση δικαιωμάτων γεωγραφικής θέσης του Προγράμματος περιήγησης"</string>
+    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"τροποποιεί δικαιώματα γεωγραφικής θέσης του Προγράμματος περιήγησης"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Επιτρέπει στην εφαρμογή την τροποποίηση των αδειών γεωτοποθεσίας του Προγράμματος περιήγησης. Τυχόν κακόβουλες εφαρμογές ενδέχεται να το χρησιμοποιήσουν για να επιτρέψουν την αποστολή πληροφοριών τοποθεσίας σε αυθαίρετους ιστότοπους."</string>
     <string name="save_password_message" msgid="767344687139195790">"Θέλετε το πρόγραμμα περιήγησης να διατηρήσει αυτόν τον κωδικό πρόσβασης;"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Να μην γίνει τώρα"</string>
@@ -1202,11 +1202,11 @@
     <string name="ext_media_status_formatting" msgid="1085079556538644861">"Διαμόρφωση…"</string>
     <string name="ext_media_status_missing" msgid="5638633895221670766">"Δεν έχει εισαχθεί"</string>
     <string name="activity_list_empty" msgid="1675388330786841066">"Δεν βρέθηκαν δραστηριότητες που να συμφωνούν με τα κριτήρια."</string>
-    <string name="permlab_route_media_output" msgid="6243022988998972085">"δρομολόγηση εξόδου μέσων"</string>
+    <string name="permlab_route_media_output" msgid="6243022988998972085">"δρομολογεί την έξοδο μέσων"</string>
     <string name="permdesc_route_media_output" msgid="4932818749547244346">"Επιτρέπει σε μια εφαρμογή τη διαγραφή διαδρομής δεδομένων εξόδου μέσων σε άλλες εξωτερικές συσκευές."</string>
-    <string name="permlab_readInstallSessions" msgid="3713753067455750349">"ανάγνωση περιόδων σύνδεσης εγκατάστασης"</string>
+    <string name="permlab_readInstallSessions" msgid="3713753067455750349">"διαβάζει τις περιόδους σύνδεσης εγκατάστασης"</string>
     <string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Επιτρέπει σε μια εφαρμογή την ανάγνωση των περιόδων σύνδεσης εγκατάστασης. Αυτό της επιτρέπει να βλέπει λεπτομέρειες σχετικά με τις εγκαταστάσεις του ενεργού πακέτου."</string>
-    <string name="permlab_requestInstallPackages" msgid="5782013576218172577">"αίτημα εγκατάστασης πακέτων"</string>
+    <string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ζητά πακέτα εγκατάστασης"</string>
     <string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Επιτρέπει σε μια εφαρμογή να ζητά εγκατάσταση πακέτων."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Πατήστε δύο φορές για έλεγχο εστίασης"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Δεν ήταν δυνατή η προσθήκη του γραφικού στοιχείου."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 7cd4ad5..77b43b1 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1569,7 +1569,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por tu administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado por tu administrador"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Para ayudar a mejorar la duración de la batería, la función de ahorro de energía reduce el rendimiento del dispositivo y limita la vibración, los servicios de ubicación y la mayor parte de la transmisión de datos en segundo plano. Es posible que las aplicaciones que se sincronizan, como las de correo y mensajes, no se actualicen a menos que las abras.\n\nLa función de ahorro de energía se desactiva automáticamente cuando el dispositivo se está cargando."</string>
-    <string name="data_saver_description" msgid="6015391409098303235">"El Economizador de Datos evita que algunas aplicaciones envíen o reciban datos en segundo plano, lo que permite reducir el uso de datos. Una aplicación activa podrá acceder a los datos, aunque con menos frecuencia. Esto significa que, por ejemplo, algunas imágenes no se muestren hasta que no las toques."</string>
+    <string name="data_saver_description" msgid="6015391409098303235">"El ahorro de datos evita que algunas aplicaciones envíen o reciban datos en segundo plano, lo que permite reducir el uso de datos. Una aplicación activa podrá acceder a los datos, aunque con menos frecuencia. Esto significa que, por ejemplo, algunas imágenes no se muestren hasta que no las toques."</string>
     <string name="data_saver_enable_title" msgid="4674073932722787417">"¿Activar ahorro de datos?"</string>
     <string name="data_saver_enable_button" msgid="7147735965247211818">"Activar"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index d1a3215..d7ee50c 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -252,7 +252,7 @@
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="4656988620100940350">"saata ja vaadata SMS-sõnumeid"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Mäluruum"</string>
-    <string name="permgroupdesc_storage" msgid="637758554581589203">"juurde pääseda seadmesse salvestatud fotodele, meediale ja failidele"</string>
+    <string name="permgroupdesc_storage" msgid="637758554581589203">"juurde pääseda seadmesse salvestatud fotodele, meediasisule ja failidele"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"heli salvestamine"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kaamera"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index da65093..e7f3f02 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -743,7 +743,7 @@
     <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Erabiltzaile-hautatzailea"</string>
     <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Egoera"</string>
     <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string>
-    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Multimedia-kontrolak"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Multimedia kontrolatzeko aukerak"</string>
     <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Widgetak berrantolatzen hasi da."</string>
     <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Widgetak berrantolatu dira."</string>
     <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> widgeta ezabatu da."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 6dfa504..09b55d9 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -994,7 +994,7 @@
     <string name="noApplications" msgid="2991814273936504689">"Aucune application ne peut effectuer cette action."</string>
     <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> a cessé de fonctionner."</string>
     <string name="aerr_process" msgid="6201597323218674729">"Le processus <xliff:g id="PROCESS">%1$s</xliff:g> a cessé de fonctionner."</string>
-    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> ne cesse de s\'arrêter."</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> s\'arrête systématiquement"</string>
     <string name="aerr_process_repeated" msgid="6235302956890402259">"Le processus \"<xliff:g id="PROCESS">%1$s</xliff:g>\" ne cesse de s\'arrêter."</string>
     <string name="aerr_restart" msgid="7581308074153624475">"Rouvrir l\'application"</string>
     <string name="aerr_report" msgid="5371800241488400617">"Envoyer des commentaires"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index a5c3c6e..704667a 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -214,7 +214,7 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcións de teléfono"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Bloqueo da pantalla"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Apagar"</string>
-    <string name="global_action_emergency" msgid="7112311161137421166">"Emerxencia"</string>
+    <string name="global_action_emergency" msgid="7112311161137421166">"Emerxencias"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Informe de erros"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Crear informe de erros"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Este informe recompilará información acerca do estado actual do teu dispositivo para enviala en forma de mensaxe de correo electrónico. O informe de erros tardará un pouco en completarse desde o seu inicio ata que estea preparado para enviarse, polo que che recomendamos que teñas paciencia."</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 83f8995..7cdc9bb 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1058,8 +1058,8 @@
     <string name="volume_icon_description_incall" msgid="8890073218154543397">"Զանգի ձայնի բարձրություն"</string>
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Մեդիա ձայնի բարձրություն"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Ծանուցումների ձայնի ուժգնությունը"</string>
-    <string name="ringtone_default" msgid="3789758980357696936">"Լռելյայն զանգերանգ"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Լռելյայն զանգերանգ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <string name="ringtone_default" msgid="3789758980357696936">"Կանխադրված զանգերանգ"</string>
+    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Կանխադրված զանգերանգ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
     <string name="ringtone_silent" msgid="7937634392408977062">"Ոչ մեկը"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Զանգերանգներ"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Անհայտ զանգերանգ"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 4eaadfe..2491f82 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1331,7 +1331,7 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"ឧបករណ៍ផ្ទុក USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb" msgid="3017954059538517278">"ឧបករណ៍​ផ្ទុក​យូអេសប៊ី"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"កែសម្រួល​"</string>
-    <string name="data_usage_warning_title" msgid="3620440638180218181">"ការដាស់តឿនពីការប្រើទិន្នន័យ"</string>
+    <string name="data_usage_warning_title" msgid="3620440638180218181">"ការព្រមានអំពីការប្រើទិន្នន័យ"</string>
     <string name="data_usage_warning_body" msgid="6660692274311972007">"ប៉ះដើម្បីមើលការប្រើប្រាស់ និងការកំណត់"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"បាន​ដល់​ដែន​កំណត់​ទិន្នន័យ 2G-3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"បាន​ដល់​ដែន​កំណត់​ទិន្នន័យ 4G"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 0a9a511..b8c90d7 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -815,9 +815,9 @@
     <string name="menu_space_shortcut_label" msgid="2410328639272162537">"space"</string>
     <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"enter"</string>
     <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"ಅಳಿಸು"</string>
-    <string name="search_go" msgid="8298016669822141719">"ಹುಡುಕು"</string>
+    <string name="search_go" msgid="8298016669822141719">"ಹುಡುಕಿ"</string>
     <string name="search_hint" msgid="1733947260773056054">"ಹುಡುಕಿ…"</string>
-    <string name="searchview_description_search" msgid="6749826639098512120">"ಹುಡುಕು"</string>
+    <string name="searchview_description_search" msgid="6749826639098512120">"ಹುಡುಕಿ"</string>
     <string name="searchview_description_query" msgid="5911778593125355124">"ಪ್ರಶ್ನೆಯನ್ನು ಹುಡುಕಿ"</string>
     <string name="searchview_description_clear" msgid="1330281990951833033">"ಪ್ರಶ್ನೆಯನ್ನು ತೆರವುಗೊಳಿಸು"</string>
     <string name="searchview_description_submit" msgid="2688450133297983542">"ಪ್ರಶ್ನೆಯನ್ನು ಸಲ್ಲಿಸು"</string>
@@ -1211,7 +1211,7 @@
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ಝೂಮ್‌ ನಿಯಂತ್ರಿಸಲು ಎರಡು ಬಾರಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"ವಿಜೆಟ್ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"ಹೋಗು"</string>
-    <string name="ime_action_search" msgid="658110271822807811">"ಹುಡುಕು"</string>
+    <string name="ime_action_search" msgid="658110271822807811">"ಹುಡುಕಿ"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"ಕಳುಹಿಸು"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"ಮುಂದೆ"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"ಮುಗಿದಿದೆ"</string>
@@ -1269,8 +1269,8 @@
     <string name="share" msgid="1778686618230011964">"ಹಂಚು"</string>
     <string name="find" msgid="4808270900322985960">"ಹುಡುಕಿ"</string>
     <string name="websearch" msgid="4337157977400211589">"ವೆಬ್ ಹುಡುಕಾಟ"</string>
-    <string name="find_next" msgid="5742124618942193978">"ಮುಂದಿನದನ್ನು ಹುಡುಕು"</string>
-    <string name="find_previous" msgid="2196723669388360506">"ಹಿಂದಿನದನ್ನು ಹುಡುಕು"</string>
+    <string name="find_next" msgid="5742124618942193978">"ಮುಂದಿನದನ್ನು ಹುಡುಕಿ"</string>
+    <string name="find_previous" msgid="2196723669388360506">"ಹಿಂದಿನದನ್ನು ಹುಡುಕಿ"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> ಅವರಿಂದ ಸ್ಥಾನ ವಿನಂತಿ"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"ಸ್ಥಾನ ವಿನಂತಿ"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>) ಅವರಿಂದ ವಿನಂತಿಸಲಾಗಿದೆ"</string>
@@ -1650,7 +1650,7 @@
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"ಸೂಚಿತ ಭಾಷೆ"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"ಎಲ್ಲಾ ಭಾಷೆಗಳು"</string>
     <string name="region_picker_section_all" msgid="8966316787153001779">"ಎಲ್ಲಾ ಪ್ರದೇಶಗಳು"</string>
-    <string name="locale_search_menu" msgid="2560710726687249178">"ಹುಡುಕು"</string>
+    <string name="locale_search_menu" msgid="2560710726687249178">"ಹುಡುಕಿ"</string>
     <string name="work_mode_off_title" msgid="8954725060677558855">"ಕೆಲಸದ ಮೋಡ್ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಹಿನ್ನೆಲೆ ಸಿಂಕ್ ಮತ್ತು ಇತರ ಸಂಬಂಧಿತ ವೈಶಿಷ್ಟ್ಯಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌‌ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಅನುಮತಿಸಿ."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ಆನ್ ಮಾಡು"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 1a5f348..7a48ae5 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1329,7 +1329,7 @@
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB түзмөгү"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB эстутуму"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Өзгөртүү"</string>
-    <string name="data_usage_warning_title" msgid="3620440638180218181">"Дайындарды колдонуу айгайы"</string>
+    <string name="data_usage_warning_title" msgid="3620440638180218181">"Дайындарды колдонууну чектөө"</string>
     <string name="data_usage_warning_body" msgid="6660692274311972007">"Колдонулушун жана жөндөөлөрүн көрүү үчүн таптаңыз."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G дайындар чегине жетти"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G дайындар чегине жетти"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index a2f5eb8..c7806f2 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1105,7 +1105,7 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Medijos garsumas"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Pranešimo apimtis"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Numatytasis skambėjimo tonas"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Numatytasis skambėjimo tonas (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Numatytasis skambėjimo tonas („<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>“)"</string>
     <string name="ringtone_silent" msgid="7937634392408977062">"Nėra"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Skambėjimo tonai"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Nežinomas skambėjimo tonas"</string>
diff --git a/core/res/res/values-mcc259-mnc05/config.xml b/core/res/res/values-mcc259-mnc05/config.xml
deleted file mode 100644
index 065668c..0000000
--- a/core/res/res/values-mcc259-mnc05/config.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2013, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- The list of ril radio technologies (see ServiceState.java) which only support
-         a single data connection at one time.  This may change by carrier via
-         overlays (some don't support multiple pdp on UMTS).  All unlisted radio
-         tech types support unlimited types (practically only 2-4 used). -->
-    <integer-array name="config_onlySingleDcAllowed">
-        <item>1</item>  <!-- GPRS -->
-        <item>2</item>  <!-- EDGE -->
-        <item>3</item>  <!-- UMTS -->
-        <item>9</item>  <!-- HSDPA -->
-        <item>10</item> <!-- HSUPA -->
-        <item>11</item> <!-- HSPA -->
-        <item>14</item> <!-- LTE -->
-        <item>15</item> <!-- HSPAP -->
-    </integer-array>
-</resources>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index d638b89..422f7c9 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -21,14 +21,6 @@
      for different hardware and product builds. -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
-        <item>302370</item>
-        <item>302610</item>
-        <item>302660</item>
-        <item>302720</item>
-        <item>302780</item>
-    </string-array>
-
     <integer name="config_mobile_mtu">1410</integer>
 
     <!-- String containing the apn value for tethering.  May be overriden by secure settings
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 1301c4d..a0a361b 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -48,9 +48,6 @@
          provisioning, availability etc -->
     <bool name="config_carrier_vt_available">true</bool>
 
-    <!-- Flag specifying whether VoLTE availability is based on provisioning -->
-    <bool name="config_carrier_volte_provisioned">true</bool>
-
     <bool name="config_auto_attach_data_on_creation">false</bool>
 
     <!-- Flag indicating whether strict threshold is used, or lenient threshold is used,
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index f0e437a..758b21b 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1075,7 +1075,7 @@
     <string name="network_available_sign_in" msgid="1848877297365446605">"नेटवर्कवर साइन इन करा"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
-    <string name="wifi_no_internet" msgid="8451173622563841546">"वाय-फाय मध्‍ये इंटरनेट प्रवेश नाही"</string>
+    <string name="wifi_no_internet" msgid="8451173622563841546">"वाय-फायवरून इंटरनेटवर प्रवेश नाही"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"पर्यायांसाठी टॅप करा"</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> वर स्विच केले"</string>
     <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> कडे इंटरनेट प्रवेश नसताना डिव्हाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> वापरतो. शुल्क लागू शकतील."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8e42bbc..13218b7 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -237,7 +237,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Spraakassistent"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Nu vergrendelen"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
-    <string name="notification_hidden_text" msgid="1135169301897151909">"Inhoud verborgen"</string>
+    <string name="notification_hidden_text" msgid="1135169301897151909">"Content verborgen"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Content verborgen op basis van beleid"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
@@ -261,12 +261,12 @@
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"bellen en telefoontjes beheren"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Lichaamssensoren"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"toegang krijgen tot sensorgegevens over je vitale functies"</string>
-    <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Inhoud van vensters ophalen"</string>
-    <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"De inhoud inspecteren van een venster waarmee je interactie hebt."</string>
+    <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Content van vensters ophalen"</string>
+    <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"De content inspecteren van een venster waarmee je interactie hebt."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"\'Verkennen via aanraking\' inschakelen"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Aangetikte items worden hardop benoemd en het scherm kan worden verkend door middel van gebaren."</string>
     <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Verbeterde internettoegankelijkheid inschakelen"</string>
-    <string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Er kunnen scripts worden geïnstalleerd om app-inhoud toegankelijker te maken."</string>
+    <string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Er kunnen scripts worden geïnstalleerd om app-content toegankelijker te maken."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Tekst observeren die u typt"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Omvat persoonlijke gegevens zoals creditcardnummers en wachtwoorden."</string>
     <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Schermvergroting bedienen"</string>
@@ -296,9 +296,9 @@
     <string name="permlab_sendSms" msgid="7544599214260982981">"sms\'jes verzenden en bekijken"</string>
     <string name="permdesc_sendSms" msgid="7094729298204937667">"Hiermee kan de app sms-berichten verzenden. Dit kan tot onverwachte kosten leiden. Schadelijke apps kunnen u geld kosten doordat ze zonder je bevestiging berichten kunnen verzenden."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"je tekstberichten (SMS of MMS) lezen"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Hiermee kan de app sms-berichten lezen die zijn opgeslagen op je tablet of simkaart. De app kan alle sms-berichten lezen, ongeacht inhoud of vertrouwelijkheid."</string>
-    <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"Hiermee kan de app sms-berichten lezen die zijn opgeslagen op je tv of simkaart. De app kan alle sms-berichten lezen, ongeacht inhoud of vertrouwelijkheid."</string>
-    <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Hiermee kan de app sms-berichten lezen die zijn opgeslagen op je telefoon of simkaart. De app kan alle sms-berichten lezen, ongeacht inhoud of vertrouwelijkheid."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Hiermee kan de app sms-berichten lezen die zijn opgeslagen op je tablet of simkaart. De app kan alle sms-berichten lezen, ongeacht content of vertrouwelijkheid."</string>
+    <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"Hiermee kan de app sms-berichten lezen die zijn opgeslagen op je tv of simkaart. De app kan alle sms-berichten lezen, ongeacht content of vertrouwelijkheid."</string>
+    <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Hiermee kan de app sms-berichten lezen die zijn opgeslagen op je telefoon of simkaart. De app kan alle sms-berichten lezen, ongeacht content of vertrouwelijkheid."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"tekstberichten (WAP) ontvangen"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Hiermee kan de app WAP-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar je apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"actieve apps ophalen"</string>
@@ -460,12 +460,12 @@
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Hiermee kan een app de synchronisatie-instellingen aanpassen voor een account. Deze toestemming kan bijvoorbeeld worden gebruikt om synchronisatie van de app Personen in te schakelen voor een account."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"synchronisatiestatistieken lezen"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Hiermee kan een app de synchronisatiestatistieken voor een account lezen, inclusief de geschiedenis van synchronisatie-activiteiten en hoeveel gegevens zijn gesynchroniseerd."</string>
-    <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"de inhoud van je USB-opslag lezen"</string>
-    <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"de inhoud van je SD-kaart lezen"</string>
-    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"De app toestaan de inhoud van je USB-opslag te lezen."</string>
-    <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"De app toestaan de inhoud van je SD-kaart te lezen."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"de inhoud van je USB-opslag aanpassen of verwijderen"</string>
-    <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"de inhoud van je SD-kaart aanpassen of verwijderen"</string>
+    <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"de content van je USB-opslag lezen"</string>
+    <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"de content van je SD-kaart lezen"</string>
+    <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"De app toestaan de content van je USB-opslag te lezen."</string>
+    <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"De app toestaan de content van je SD-kaart te lezen."</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"de content van je USB-opslag aanpassen of verwijderen"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"de content van je SD-kaart aanpassen of verwijderen"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Hiermee kan de app schrijven naar de USB-opslag."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Hiermee kan de app schrijven naar de SD-kaart."</string>
     <string name="permlab_use_sip" msgid="2052499390128979920">"SIP-oproepen plaatsen/ontvangen"</string>
@@ -1527,7 +1527,7 @@
     <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"Onbekend portret"</string>
     <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"Onbekend landschap"</string>
     <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"Geannuleerd"</string>
-    <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"Fout bij schrijven van inhoud"</string>
+    <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"Fout bij schrijven van content"</string>
     <string name="reason_unknown" msgid="6048913880184628119">"onbekend"</string>
     <string name="reason_service_unavailable" msgid="7824008732243903268">"Afdrukservice niet ingeschakeld"</string>
     <string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g>-service geïnstalleerd"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 6e99a9b..fdf8a6d 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -152,7 +152,7 @@
     <string name="httpErrorAuth" msgid="1435065629438044534">"Није могуће потврдити аутентичност."</string>
     <string name="httpErrorProxyAuth" msgid="1788207010559081331">"Потврда идентитета преко прокси сервера није успела."</string>
     <string name="httpErrorConnect" msgid="8714273236364640549">"Није могуће повезати се са сервером."</string>
-    <string name="httpErrorIO" msgid="2340558197489302188">"Није могуће комуницирати са сервером. Покушајте поново касније."</string>
+    <string name="httpErrorIO" msgid="2340558197489302188">"Није могуће комуницирати са сервером. Пробајте поново касније."</string>
     <string name="httpErrorTimeout" msgid="4743403703762883954">"Веза са сервером је истекла."</string>
     <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"Страница садржи превише веза за преусмеравање са сервера."</string>
     <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"Протокол није подржан."</string>
@@ -160,7 +160,7 @@
     <string name="httpErrorBadUrl" msgid="3636929722728881972">"Страницу није могуће отворити зато што је URL адреса неважећа."</string>
     <string name="httpErrorFile" msgid="2170788515052558676">"Није могуће приступити датотеци."</string>
     <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Није могуће пронаћи тражену датотеку."</string>
-    <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Превише захтева се обрађује. Покушајте поново касније."</string>
+    <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Превише захтева се обрађује. Пробајте поново касније."</string>
     <string name="notification_title" msgid="8967710025036163822">"Грешка при пријављивању за <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
     <string name="contentServiceSync" msgid="8353523060269335667">"Синхронизација"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синхронизација"</string>
@@ -440,19 +440,19 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Дозвољава апликацији да активира методе за додавање и брисање шаблона отисака прстију који ће се користити."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"користи хардвер за отиске прстију"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозвољава апликацији да користи хардвер за отиске прстију ради потврде аутентичности"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Откривен је делимични отисак прста. Покушајте поново."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Није успела обрада отиска прста. Покушајте поново."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Откривен је делимични отисак прста. Пробајте поново."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Није успела обрада отиска прста. Пробајте поново."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Сензор за отиске прстију је прљав. Очистите га и покушајте поново."</string>
-    <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Пребрзо сте померили прст. Покушајте поново."</string>
-    <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Превише споро сте померили прст. Покушајте поново."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Пребрзо сте померили прст. Пробајте поново."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Превише споро сте померили прст. Пробајте поново."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардвер за отиске прстију није доступан."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Није могуће сачувати отисак прста. Уклоните неки од постојећих отисака прстију."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Временско ограничење за отисак прста је истекло. Покушајте поново."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Временско ограничење за отисак прста је истекло. Пробајте поново."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Радња са отиском прста је отказана."</string>
-    <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Превише покушаја. Покушајте поново касније."</string>
-    <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Покушајте поново."</string>
+    <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Превише покушаја. Пробајте поново касније."</string>
+    <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Пробајте поново."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -680,8 +680,8 @@
     <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Хитне службе"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Назад на позив"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Тачно!"</string>
-    <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Покушајте поново"</string>
-    <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Покушајте поново"</string>
+    <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Пробајте поново"</string>
+    <string name="lockscreen_password_wrong" msgid="5737815393253165301">"Пробајте поново"</string>
     <string name="lockscreen_storage_locked" msgid="9167551160010625200">"Откључај за све функције и податке"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Премашен је највећи дозвољени број покушаја Откључавања лицем"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Нема SIM картице"</string>
@@ -705,19 +705,19 @@
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Погледајте Кориснички водич или контактирајте Корисничку подршку."</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM картица је закључана."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Откључавање SIM картице…"</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте неправилно нацртали шаблон за откључавање. \n\nПокушајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте погрешно унели лозинку. \n\nПокушајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте погрешно унели PIN. \n\nПокушајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте нетачно унели шаблон за откључавање. Након још <xliff:g id="NUMBER_1">%2$d</xliff:g> несупешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу података за пријављивање на Google.\n\n Покушајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Неисправно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја од вас ће бити затражено да откључате ТВ помоћу података за пријављивање на Google.\n\n Покушајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте нетачно унели шаблон за откључавање. Након још <xliff:g id="NUMBER_1">%2$d</xliff:g> несупешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу података за пријављивање на Google.\n\n Покушајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте неправилно нацртали шаблон за откључавање. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте погрешно унели лозинку. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте погрешно унели PIN. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте нетачно унели шаблон за откључавање. Након још <xliff:g id="NUMBER_1">%2$d</xliff:g> несупешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу података за пријављивање на Google.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Неисправно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја од вас ће бити затражено да откључате ТВ помоћу података за пријављивање на Google.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте нетачно унели шаблон за откључавање. Након још <xliff:g id="NUMBER_1">%2$d</xliff:g> несупешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу података за пријављивање на Google.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Неправилно сте покушали да откључате таблет <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Након још неуспешних покушаја (<xliff:g id="NUMBER_1">%2$d</xliff:g>) таблет ће бити ресетован на фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Покушали сте да откључате ТВ нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја ТВ ће бити ресетован на подразумевана фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Неисправно сте покушали да откључате телефон <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Након још неуспешних покушаја (<xliff:g id="NUMBER_1">%2$d</xliff:g>) телефон ће бити ресетован на фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Неисправно сте покушали да откључате таблет <xliff:g id="NUMBER">%d</xliff:g> пута. Таблет ће сада бити враћен на подразумевана фабричка подешавања."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Покушали сте да откључате ТВ нетачно <xliff:g id="NUMBER">%d</xliff:g> пута. ТВ ће сада бити ресетован на подразумевана фабричка подешавања."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Неисправно сте покушали да откључате телефон <xliff:g id="NUMBER">%d</xliff:g> пута. Телефон ће сада бити враћен на подразумевана фабричка подешавања."</string>
-    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Покушајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунде(и)."</string>
+    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Пробајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунде(и)."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Заборавили сте шаблон?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Откључавање налога"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Превише покушаја уноса шаблона"</string>
@@ -1421,7 +1421,7 @@
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Погрешан шаблон"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"Погрешна лозинка"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Погрешан PIN"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Покушајте поново за <xliff:g id="NUMBER">%1$d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Пробајте поново за <xliff:g id="NUMBER">%1$d</xliff:g> секунде(и)."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Нацртајте шаблон"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Унесите PIN SIM картице"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"Унесите PIN"</string>
@@ -1443,18 +1443,18 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"Неважеће корисничко име или лозинка."</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Заборавили сте корисничко име или лозинку?\nПосетите адресу "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"Провера налога…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Унели сте нетачни PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПокушајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Унели сте нетачну лозинку <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПокушајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПокушајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Унели сте нетачни PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Унели сте нетачну лозинку <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Покушали сте да откључате таблет нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Након још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја таблет ће бити ресетован на фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"Покушали сте да откључате ТВ нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја ТВ ће бити ресетован на подразумевана фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Покушали сте да откључате телефон нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја телефон ће бити ресетован на фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Покушали сте да откључате таблет нетачно <xliff:g id="NUMBER">%d</xliff:g> пута. Таблет ће сада бити враћен на подразумевана фабричка подешавања."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Покушали сте да откључате ТВ нетачно <xliff:g id="NUMBER">%d</xliff:g> пута. ТВ ће сада бити ресетован на подразумевана фабричка подешавања."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Покушали сте да откључате телефон нетачно <xliff:g id="NUMBER">%d</xliff:g> пута. Телефон ће сада бити враћен на подразумевана фабричка подешавања."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште.\n\nПокушајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Неисправно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате ТВ помоћу налога е-поште.\n\n Покушајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПокушајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Неисправно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате ТВ помоћу налога е-поште.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
     <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>
@@ -1565,14 +1565,14 @@
     <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"Нови PIN"</string>
     <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"Потврдите нови PIN"</string>
     <string name="restr_pin_create_pin" msgid="8017600000263450337">"Направите PIN за измену ограничења"</string>
-    <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN-ови се не подударају. Покушајте поново."</string>
+    <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN-ови се не подударају. Пробајте поново."</string>
     <string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN је прекратак. Мора да садржи најмање 4 цифре."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
-      <item quantity="one">Покушајте поново за <xliff:g id="COUNT">%d</xliff:g> секунду</item>
-      <item quantity="few">Покушајте поново за <xliff:g id="COUNT">%d</xliff:g> секунде</item>
-      <item quantity="other">Покушајте поново за <xliff:g id="COUNT">%d</xliff:g> секунди</item>
+      <item quantity="one">Пробајте поново за <xliff:g id="COUNT">%d</xliff:g> секунду</item>
+      <item quantity="few">Пробајте поново за <xliff:g id="COUNT">%d</xliff:g> секунде</item>
+      <item quantity="other">Пробајте поново за <xliff:g id="COUNT">%d</xliff:g> секунди</item>
     </plurals>
-    <string name="restr_pin_try_later" msgid="973144472490532377">"Покушајте поново касније"</string>
+    <string name="restr_pin_try_later" msgid="973144472490532377">"Пробајте поново касније"</string>
     <string name="immersive_cling_title" msgid="8394201622932303336">"Приказује се цео екран"</string>
     <string name="immersive_cling_description" msgid="3482371193207536040">"Да бисте изашли, превуците надоле одозго."</string>
     <string name="immersive_cling_positive" msgid="5016839404568297683">"Важи"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 4c135ab..fb0fda8 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1104,8 +1104,8 @@
     <string name="volume_icon_description_incall" msgid="8890073218154543397">"Гучність сигналу виклику"</string>
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Гучність медіа"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Гучність сповіщення"</string>
-    <string name="ringtone_default" msgid="3789758980357696936">"Мелодія за умовч."</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Мелодія за умовч. (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <string name="ringtone_default" msgid="3789758980357696936">"Мелодія за умовчанням"</string>
+    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Мелодія за умовчанням (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
     <string name="ringtone_silent" msgid="7937634392408977062">"Немає"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодії"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Невідома мелодія"</string>
diff --git a/core/res/res/values-watch/colors_device_defaults.xml b/core/res/res/values-watch/colors_device_defaults.xml
new file mode 100644
index 0000000..9150cc4
--- /dev/null
+++ b/core/res/res/values-watch/colors_device_defaults.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.
+-->
+
+<!-- Colors specific to DeviceDefault themes. These are mostly pass-throughs to enable
+     overlaying new theme colors. -->
+<resources>
+    <color name="button_normal_device_default_dark">@color/btn_default_material_dark</color>
+</resources>
diff --git a/core/res/res/values-watch/colors_material.xml b/core/res/res/values-watch/colors_material.xml
index 54eece4..18bfd4d 100644
--- a/core/res/res/values-watch/colors_material.xml
+++ b/core/res/res/values-watch/colors_material.xml
@@ -17,8 +17,10 @@
     <color name="background_material_dark">#ff232e33</color>
     <color name="background_floating_material_dark">#ff3e5059</color>
 
-    <color name="accent_material_dark">#ff5e97f6</color>
+    <color name="accent_material_700">#ff2e4978</color>
     <color name="accent_material_light">#ff4285f4</color>
+    <color name="accent_material_dark">#ff5e97f6</color>
+    <color name="accent_material_50">#ffd0def7</color>
 
     <color name="primary_material_dark">#4D4D4D</color>
 
diff --git a/core/res/res/values-watch/styles_material.xml b/core/res/res/values-watch/styles_material.xml
index 8a080d9c..af4207e 100644
--- a/core/res/res/values-watch/styles_material.xml
+++ b/core/res/res/values-watch/styles_material.xml
@@ -95,7 +95,7 @@
     </style>
 
     <style name="DialogWindowTitle.Material">
-        <item name="maxLines">3</item>
+        <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>
diff --git a/core/res/res/values-watch/themes_device_defaults.xml b/core/res/res/values-watch/themes_device_defaults.xml
index 0471444..aa1594d 100644
--- a/core/res/res/values-watch/themes_device_defaults.xml
+++ b/core/res/res/values-watch/themes_device_defaults.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2011 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.
@@ -18,21 +18,88 @@
 ===============================================================
                         PLEASE READ
 ===============================================================
-This file contains the themes that are the Device Defaults.
-If you want to edit themes to skin your device, do it here.
-We recommend that you do not edit themes.xml and instead edit
-this file.
-
-Editing this file instead of themes.xml will greatly simplify
+This file contains the themes that are the Device Defaults on
+Watch. If you want to edit themes to skin your device, do it
+here. Editing this file instead of themes.xml will greatly simplify
 merges for future platform versions and CTS compliance will be
 easier.
+
+You should also have a look at themes.xml, to
+understand why we define Dialogs and Settings with color
+palette Dark. It's because themes.xml modify Material in
+a similar way.
 ===============================================================
                         PLEASE READ
 ===============================================================
  -->
 <resources>
+    <style name="Theme.DeviceDefault" parent="Theme.DeviceDefaultBase">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- Variant of {@link #Theme_DeviceDefault} with no action bar -->
+    <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Material.NoActionBar">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar.  This theme
+         sets {@link android.R.attr#windowFullscreen} to true.  -->
+    <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Material.NoActionBar.Fullscreen">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar and
+    extending in to overscan region.  This theme
+    sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
+    to true. -->
+    <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Material.NoActionBar.Overscan">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- Variant of {@link #Theme_DeviceDefault} that has no title bar and translucent
+         system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
+         {@link android.R.attr#windowTranslucentNavigation} to true. -->
+    <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Material.NoActionBar.TranslucentDecor">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
     <!-- Theme used for the intent picker activity. -->
-    <style name="Theme.DeviceDefault.Resolver" parent="Theme.DeviceDefault">
+    <style name="Theme.DeviceDefault.Resolver">
         <item name="colorControlActivated">?attr/colorControlHighlight</item>
         <item name="listPreferredItemPaddingStart">?attr/dialogPreferredPadding</item>
         <item name="listPreferredItemPaddingEnd">?attr/dialogPreferredPadding</item>
@@ -40,4 +107,239 @@
 
     <!-- Use a dark theme for watches. -->
     <style name="Theme.DeviceDefault.System" />
+
+    <!-- DeviceDefault style for input methods, which is used by the
+         {@link android.inputmethodservice.InputMethodService} class.-->
+    <style name="Theme.DeviceDefault.InputMethod" parent="Theme.DeviceDefault.Panel">
+        <item name="windowAnimationStyle">@style/Animation.InputMethod</item>
+        <item name="imeFullscreenBackground">?colorBackground</item>
+        <item name="imeExtractEnterAnimation">@anim/input_method_extract_enter</item>
+    </style>
+
+    <!-- DeviceDefault theme for dialog windows and activities. In contrast to Material, the
+    watch theme is not floating. You can set this theme on an activity if you would like to make
+    an activity that looks like a Dialog.-->
+    <style name="Theme.DeviceDefault.Dialog" parent="Theme.Material.Dialog" >
+        <item name="windowIsFloating">false</item>
+        <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
+        <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
+        <item name="buttonBarStyle">@style/DeviceDefault.ButtonBar.AlertDialog</item>
+        <item name="borderlessButtonStyle">@style/Widget.DeviceDefault.Button.Borderless.Small</item>
+
+        <item name="textAppearance">@style/TextAppearance.DeviceDefault</item>
+        <item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>
+
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- DeviceDefault theme for a window that should look like the Settings app.  -->
+    <style name="Theme.DeviceDefault.Settings" parent="Theme.DeviceDefault"/>
+    <style name="Theme.DeviceDefault.Settings.NoActionBar" parent="Theme.DeviceDefault"/>
+    <style name="Theme.DeviceDefault.Settings.BaseDialog" parent="Theme.DeviceDefault.Dialog"/>
+    <style name="Theme.DeviceDefault.Settings.Dialog" parent="Theme.DeviceDefault.Settings.BaseDialog"/>
+    <style name="Theme.DeviceDefault.Settings.DialogWhenLarge" parent="Theme.DeviceDefault.DialogWhenLarge"/>
+    <style name="Theme.DeviceDefault.Settings.DialogWhenLarge.NoActionBar" parent="Theme.DeviceDefault.DialogWhenLarge.NoActionBar"/>
+    <style name="Theme.DeviceDefault.Settings.Dialog.Presentation" parent="Theme.DeviceDefault.Dialog.Presentation"/>
+    <style name="Theme.DeviceDefault.Settings.SearchBar" parent="Theme.DeviceDefault.SearchBar"/>
+
+    <style name="Theme.DeviceDefault.Settings.Dialog.Alert" parent="Theme.Material.Dialog.Alert">
+        <item name="windowIsFloating">false</item>
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <style name="Theme.DeviceDefault.Settings.CompactMenu" parent="Theme.Material.CompactMenu">
+        <item name="windowIsFloating">false</item>
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- Variant of {@link #Theme_DeviceDefault_Dialog} that has a nice minimum width for a
+    regular dialog. -->
+    <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth">
+        <item name="windowIsFloating">false</item>
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar">
+        <item name="windowIsFloating">false</item>
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- Variant of {@link #Theme_DeviceDefault_Dialog_NoActionBar} that has a nice minimum width
+    for a regular dialog. -->
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth">
+        <item name="windowIsFloating">false</item>
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+   <!-- DeviceDefault theme for a window that will be displayed either full-screen on smaller
+    screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
+    <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Material.DialogWhenLarge">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- DeviceDefault theme for a window without an action bar that will be displayed either
+    full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
+    xlarge). -->
+    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Material.DialogWhenLarge.NoActionBar">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- DeviceDefault theme for a presentation window on a secondary display. -->
+    <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Material.Dialog.Presentation">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- DeviceDefault theme for panel windows. This removes all extraneous window
+    decorations, so you basically have an empty rectangle in which to place your content. It makes
+    the window floating, with a transparent background, and turns off dimming behind the window. -->
+    <style name="Theme.DeviceDefault.Panel" parent="Theme.Material.Panel">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
+    behind them. -->
+    <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Material.Wallpaper">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
+    behind them and without an action bar. -->
+    <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Material.Wallpaper.NoTitleBar">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <!-- DeviceDefault style for input methods, which is used by the
+         {@link android.service.voice.VoiceInteractionSession} class.-->
+    <style name="Theme.DeviceDefault.VoiceInteractionSession" parent="Theme.Material.VoiceInteractionSession">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Material.Dialog.Alert">
+        <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
+
+        <!-- Color palette Dialog -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">?attr/colorBackgroundFloating</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar">
+        <!-- Color palette Dark -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
+
+    <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame">
+        <item name="windowIsFloating">false</item>
+        <!-- Color palette Dialog -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+        <item name="colorBackground">?attr/colorBackgroundFloating</item>
+        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
+        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+    </style>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f0a25aa..c3967e4 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3965,6 +3965,7 @@
     </declare-styleable>
 
     <declare-styleable name="ProgressBar">
+        <attr name="min" format="integer" />
         <!-- Defines the maximum value the progress can take. -->
         <attr name="max" format="integer" />
         <!-- Defines the default progress value, between 0 and max. -->
@@ -7941,6 +7942,14 @@
 
     <declare-styleable name="SeekBarPreference">
         <attr name="layout" />
+        <!-- Attribute indicating whether the slider within this preference can be adjusted, that is
+        pressing left/right keys when this preference is focused will move the slider accordingly (e.g.
+        inline adjustable preferences). False, if the slider within the preference is read-only and
+        cannot be adjusted. By default, the seekbar is adjustable. -->
+        <attr name="adjustable" format="boolean" />
+        <!-- Flag indicating whether the TextView next to the seekbar that shows the current seekbar value will be
+        displayed. If true, the view is VISIBLE; if false, the view will be GONE. By default, this view is VISIBLE. -->
+        <attr name="showSeekBarValue" format="boolean" />
     </declare-styleable>
 
     <!-- Base attributes available to PreferenceFragment. -->
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index 171f5cb..89691e9 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -37,6 +37,4 @@
     <color name="background_device_default_light">@color/background_material_light</color>
     <color name="background_floating_device_default_dark">@color/background_floating_material_dark</color>
     <color name="background_floating_device_default_light">@color/background_floating_material_light</color>
-    <color name="button_normal_device_default_dark">@color/btn_default_material_dark</color>
-    <color name="button_normal_device_default_light">@color/btn_default_material_light</color>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3d507b5..092109b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1715,6 +1715,12 @@
          turned off and the screen off animation has been performed. -->
     <bool name="config_dozeAfterScreenOff">false</bool>
 
+    <!-- Doze: should the TYPE_PICK_UP_GESTURE sensor be used as a pulse signal. -->
+    <bool name="config_dozePulsePickup">false</bool>
+
+    <!-- Type of the double tap sensor. Empty if double tap is not supported. -->
+    <string name="config_dozeDoubleTapSensorType" translatable="false"></string>
+
     <!-- Power Management: Specifies whether to decouple the auto-suspend state of the
          device from the display on/off state.
 
@@ -1934,19 +1940,6 @@
          where if the preferred is used we don't try the others. -->
     <bool name="config_dontPreferApn">false</bool>
 
-    <!-- The list of ril radio technologies (see ServiceState.java) which only support
-         a single data connection at one time.  This may change by carrier via
-         overlays (some don't support multiple pdp on UMTS).  All unlisted radio
-         tech types support unlimited types (practically only 2-4 used). -->
-    <integer-array name="config_onlySingleDcAllowed">
-        <item>4</item>  <!-- IS95A -->
-        <item>5</item>  <!-- IS95B -->
-        <item>6</item>  <!-- 1xRTT -->
-        <item>7</item>  <!-- EVDO_0 -->
-        <item>8</item>  <!-- EVDO_A -->
-        <item>12</item> <!-- EVDO_B -->
-    </integer-array>
-
     <!-- Set to true if after a provisioning apn the radio should be restarted -->
     <bool name="config_restartRadioAfterProvisioning">false</bool>
 
@@ -2212,9 +2205,6 @@
          provisioning, availability etc -->
     <bool name="config_carrier_volte_available">false</bool>
 
-    <!-- Flag specifying whether VoLTE availability is based on provisioning -->
-    <bool name="config_carrier_volte_provisioned">false</bool>
-
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">true</bool>
 
@@ -2274,6 +2264,21 @@
     <!-- Sprint need a 70 ms delay for 3way call -->
     <integer name="config_cdma_3waycall_flash_delay">0</integer>
 
+    <!-- If there is no preload VM number in the sim card, carriers such as
+         Verizon require to load a default vm number from the configurantion.
+         Define config_default_vm_number for this purpose. And there are two
+         optional formats for this configuration as below:
+         (1)<item>voicemail number</item>
+         (2)<item>voicemail number;gid</item>
+         The logic to pick up the correct voicemail number:
+         (1) If the config_default_vm_number array has no gid special item, the last one will be
+         picked
+         (2) If the config_default_vm_number array has gid special item and  it matches the current
+         sim's gid, it will be picked.
+         (3) If the config_default_vm_number array has gid special item but it doesn't match the
+         current sim's gid, the last one without gid will be picked -->
+    <string-array translatable="false" name="config_default_vm_number" />
+
     <!--SIM does not save, but the voice mail number to be changed. -->
     <bool name="editable_voicemailnumber">false</bool>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7bce379..7999e7e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2764,4 +2764,5 @@
     <public-group type="id" first-id="0x01020041">
     </public-group>
 
+    <public type="attr" name="min" />
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 76946db..ad3e204 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1665,7 +1665,6 @@
   <java-symbol type="array" name="config_testLocationProviders" />
   <java-symbol type="array" name="config_defaultNotificationVibePattern" />
   <java-symbol type="array" name="config_notificationFallbackVibePattern" />
-  <java-symbol type="array" name="config_onlySingleDcAllowed" />
   <java-symbol type="bool" name="config_useAttentionLight" />
   <java-symbol type="bool" name="config_animateScreenLights" />
   <java-symbol type="bool" name="config_automatic_brightness_available" />
@@ -2219,7 +2218,6 @@
   <java-symbol type="bool" name="imsServiceAllowTurnOff" />
   <java-symbol type="bool" name="config_device_volte_available" />
   <java-symbol type="bool" name="config_carrier_volte_available" />
-  <java-symbol type="bool" name="config_carrier_volte_provisioned" />
   <java-symbol type="bool" name="config_carrier_volte_tty_supported" />
   <java-symbol type="bool" name="config_device_vt_available" />
   <java-symbol type="bool" name="config_device_respects_hold_carrier_config" />
@@ -2266,6 +2264,7 @@
   <java-symbol type="attr" name="closeItemLayout" />
   <java-symbol type="layout" name="resolver_different_item_header" />
   <java-symbol type="integer" name="config_cdma_3waycall_flash_delay"/>
+  <java-symbol type="array" name="config_default_vm_number" />
   <java-symbol type="attr" name="windowBackgroundFallback" />
   <java-symbol type="id" name="textSpacerNoButtons" />
   <java-symbol type="array" name="dial_string_replace" />
@@ -2678,6 +2677,9 @@
   <java-symbol type="string" name="config_emergency_call_number" />
   <java-symbol type="array" name="config_emergency_mcc_codes" />
 
+  <java-symbol type="string" name="config_dozeDoubleTapSensorType" />
+  <java-symbol type="bool" name="config_dozePulsePickup" />
+
   <!-- Used for MimeIconUtils. -->
   <java-symbol type="drawable" name="ic_doc_apk" />
   <java-symbol type="drawable" name="ic_doc_audio" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index abb0c8f..b19858e 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -49,7 +49,7 @@
          Type.DeviceDefault.Etc (for example, {@code Widget.DeviceDefault.Button} and
          {@code TextAppearance.DeviceDefault.Widget.PopupMenu.Large}).</p>
           -->
-    <style name="Theme.DeviceDefault" parent="Theme.Material" >
+    <style name="Theme.DeviceDefaultBase" parent="Theme.Material" >
         <!-- Text styles -->
         <item name="textAppearance">@style/TextAppearance.DeviceDefault</item>
         <item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>
@@ -203,42 +203,47 @@
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
-        <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
+
     </style>
 
+    <style name="Theme.DeviceDefault" parent="Theme.DeviceDefaultBase" />
+
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar -->
-    <style name="Theme.DeviceDefault.NoActionBar">
-        <item name="windowActionBar">false</item>
-        <item name="windowNoTitle">true</item>
+    <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Material.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar.  This theme
          sets {@link android.R.attr#windowFullscreen} to true.  -->
-    <style name="Theme.DeviceDefault.NoActionBar.Fullscreen">
-        <item name="windowFullscreen">true</item>
-        <item name="windowContentOverlay">@null</item>
+    <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Material.NoActionBar.Fullscreen">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar and
     extending in to overscan region.  This theme
     sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
     to true. -->
-    <style name="Theme.DeviceDefault.NoActionBar.Overscan">
-        <item name="windowFullscreen">true</item>
-        <item name="windowOverscan">true</item>
-        <item name="windowContentOverlay">@null</item>
+    <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Material.NoActionBar.Overscan">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} that has no title bar and translucent
          system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
          {@link android.R.attr#windowTranslucentNavigation} to true. -->
-    <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor">
-        <item name="windowTranslucentStatus">true</item>
-        <item name="windowTranslucentNavigation">true</item>
-        <item name="windowContentOverlay">@null</item>
+    <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Material.NoActionBar.TranslucentDecor">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- DeviceDefault theme for dialog windows and activities. This changes the window to be
@@ -258,29 +263,32 @@
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorBackground">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog} that has a nice minimum width for a
     regular dialog. -->
-    <style name="Theme.DeviceDefault.Dialog.MinWidth">
-        <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
-        <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
+    <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
-    <style name="Theme.DeviceDefault.Dialog.NoActionBar">
-        <item name="windowActionBar">false</item>
-        <item name="windowNoTitle">true</item>
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog_NoActionBar} that has a nice minimum width
     for a regular dialog. -->
-    <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth">
-        <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
-        <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
@@ -301,52 +309,66 @@
 
     <!-- DeviceDefault theme for a window that will be displayed either full-screen on smaller
     screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
-    <style name="Theme.DeviceDefault.DialogWhenLarge" parent="@style/Theme.DeviceDefault" />
+    <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Material.DialogWhenLarge">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- DeviceDefault theme for a window without an action bar that will be displayed either
     full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
     xlarge). -->
-    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="@style/Theme.DeviceDefault.NoActionBar" />
+    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Material.DialogWhenLarge.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- DeviceDefault theme for a presentation window on a secondary display. -->
-    <style name="Theme.DeviceDefault.Dialog.Presentation" parent="@style/Theme.DeviceDefault.NoActionBar.Fullscreen" />
+    <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Material.Dialog.Presentation">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- DeviceDefault theme for panel windows. This removes all extraneous window
     decorations, so you basically have an empty rectangle in which to place your content. It makes
     the window floating, with a transparent background, and turns off dimming behind the window. -->
-    <style name="Theme.DeviceDefault.Panel">
-        <item name="windowBackground">@color/transparent</item>
-        <item name="colorBackgroundCacheHint">@null</item>
-        <item name="windowFrame">@null</item>
-        <item name="windowContentOverlay">@null</item>
-        <item name="windowAnimationStyle">@null</item>
-        <item name="windowIsFloating">true</item>
-        <item name="backgroundDimEnabled">false</item>
-        <item name="windowIsTranslucent">true</item>
-        <item name="windowNoTitle">true</item>
+    <style name="Theme.DeviceDefault.Panel" parent="Theme.Material.Panel">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
     behind them. -->
-    <style name="Theme.DeviceDefault.Wallpaper">
-        <item name="windowBackground">@color/transparent</item>
-        <item name="colorBackgroundCacheHint">@null</item>
-        <item name="windowShowWallpaper">true</item>
+    <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Material.Wallpaper">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
     behind them and without an action bar. -->
-    <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar">
-        <item name="windowNoTitle">true</item>
+    <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Material.Wallpaper.NoTitleBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- DeviceDefault style for input methods, which is used by the
          {@link android.inputmethodservice.InputMethodService} class.-->
-    <style name="Theme.DeviceDefault.InputMethod">
-        <item name="windowAnimationStyle">@style/Animation.InputMethod</item>
-        <item name="imeFullscreenBackground">@drawable/screen_background_selector_light</item>
-        <item name="imeExtractEnterAnimation">@anim/input_method_extract_enter</item>
-        <item name="imeExtractExitAnimation">@anim/input_method_extract_exit</item>
+    <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Material.InputMethod">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- DeviceDefault style for input methods, which is used by the
@@ -531,58 +553,53 @@
         <item name="colorPrimary">@color/primary_device_default_light</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
-        <item name="colorButtonNormal">@color/button_normal_device_default_light</item>
     </style>
 
     <!-- Variant of the DeviceDefault (light) theme that has a solid (opaque) action bar with an
     inverse color profile. -->
-    <style name="Theme.DeviceDefault.Light.DarkActionBar">
-        <item name="actionBarWidgetTheme">@null</item>
-        <item name="actionBarTheme">@style/ThemeOverlay.Material.Dark.ActionBar</item>
-        <item name="popupTheme">@style/ThemeOverlay.Material.Light</item>
-
+    <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Material.Light.DarkActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar">
-        <item name="windowActionBar">false</item>
-        <item name="windowNoTitle">true</item>
+    <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Material.Light.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar.
          This theme sets {@link android.R.attr#windowFullscreen} to true.  -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen">
-        <item name="windowFullscreen">true</item>
-        <item name="windowContentOverlay">@null</item>
+    <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Material.Light.NoActionBar.Fullscreen">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar
     and extending in to overscan region.  This theme
     sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
     to true. -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar.Overscan">
-        <item name="windowFullscreen">true</item>
-        <item name="windowOverscan">true</item>
-        <item name="windowContentOverlay">@null</item>
+    <style name="Theme.DeviceDefault.Light.NoActionBar.Overscan" parent="Theme.Material.Light.NoActionBar.Overscan">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light} that has no title bar and translucent
          system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
          {@link android.R.attr#windowTranslucentNavigation} to true. -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor">
-        <item name="windowTranslucentStatus">true</item>
-        <item name="windowTranslucentNavigation">true</item>
-        <item name="windowContentOverlay">@null</item>
+    <style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor" parent="Theme.Material.Light.NoActionBar.TranslucentDecor">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- DeviceDefault light theme for dialog windows and activities. This changes the window to be
@@ -602,29 +619,32 @@
         <item name="colorPrimary">@color/primary_device_default_light</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} that has a nice minimum width for a
     regular dialog. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.MinWidth">
-        <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
-        <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
+    <style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Material.Light.Dialog.MinWidth">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
      <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} without an action bar -->
-    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar">
-        <item name="windowActionBar">false</item>
-        <item name="windowNoTitle">true</item>
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Material.Light.Dialog.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog_NoActionBar} that has a nice minimum
     width for a regular dialog. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth">
-        <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
-        <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Light.Dialog.NoActionBar.MinWidth">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
@@ -633,6 +653,11 @@
         <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
         <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
         <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- Variant of Theme.DeviceDefault.Dialog.NoActionBar that has a fixed size. -->
@@ -641,19 +666,39 @@
         <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
         <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
         <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- DeviceDefault light theme for a window that will be displayed either full-screen on smaller
     screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
-    <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="@style/Theme.DeviceDefault.Light" />
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Material.Light.DialogWhenLarge">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- DeviceDefault light theme for a window without an action bar that will be displayed either
     full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
     xlarge). -->
-    <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="@style/Theme.DeviceDefault.Light.NoActionBar" />
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Material.Light.DialogWhenLarge.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- DeviceDefault light theme for a presentation window on a secondary display. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="@style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen" />
+    <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- DeviceDefault light theme for panel windows. This removes all extraneous window
     decorations, so you basically have an empty rectangle in which to place your content. It makes
@@ -663,9 +708,6 @@
         <item name="colorPrimary">@color/primary_device_default_light</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.Alert">
@@ -675,9 +717,6 @@
         <item name="colorPrimary">@color/primary_device_default_light</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Material.Light.SearchBar">
@@ -685,9 +724,6 @@
         <item name="colorPrimary">@color/primary_device_default_light</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <style name="Theme.DeviceDefault.Light.Voice" parent="Theme.Material.Light.Voice">
@@ -695,9 +731,6 @@
         <item name="colorPrimary">@color/primary_device_default_light</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <!-- DeviceDefault theme for a window that should look like the Settings app.  -->
@@ -707,9 +740,6 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <!-- DeviceDefault theme for a window that should use Settings theme colors but has
@@ -721,9 +751,6 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Settings_Dark} with no action bar -->
@@ -733,9 +760,6 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <style name="Theme.DeviceDefault.Settings.Dialog" parent="Theme.Material.Settings.Dialog">
@@ -744,9 +768,6 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <style name="Theme.DeviceDefault.Settings.DialogWhenLarge" parent="Theme.Material.Settings.DialogWhenLarge">
@@ -755,9 +776,6 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <style name="Theme.DeviceDefault.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.Alert">
@@ -766,9 +784,6 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <!-- Theme used for the intent picker activity. -->
@@ -787,9 +802,6 @@
         <item name="colorPrimary">@color/primary_device_default_light</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
-        <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
     </style>
 
     <!-- DeviceDefault theme for the default system theme.  -->
diff --git a/core/res/res/xml/preferred_time_zones.xml b/core/res/res/xml/preferred_time_zones.xml
deleted file mode 100644
index da8553f..0000000
--- a/core/res/res/xml/preferred_time_zones.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/default/default/data/preferred_time_zones.xml
-**
-** Copyright 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.
-*/
--->
-<timezones>
-	<timezone offset="-18000000">America/New_York</timezone>
-	<timezone offset="-21600000">America/Chicago</timezone>
-	<timezone offset="-25200000">America/Denver</timezone>
-	<timezone offset="-28800000">America/Los_Angeles</timezone>
-</timezones>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index a9fa5e0..29c6b79 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -57,6 +57,12 @@
     <!-- Bulgaria: 4-5 digits, plus EU -->
     <shortcode country="bg" pattern="\\d{4,5}" premium="18(?:16|423)|19(?:1[56]|35)" free="116\\d{3}" />
 
+    <!-- Bahrain: 1-5 digits (standard system default, not country specific) -->
+    <shortcode country="bh" pattern="\\d{1,5}" free="81181" />
+
+    <!-- Brazil: 1-5 digits (standard system default, not country specific) -->
+    <shortcode country="br" pattern="\\d{1,5}" free="6000[012]\\d" />
+
     <!-- Belarus: 4 digits -->
     <shortcode country="by" pattern="\\d{4}" premium="3336|4161|444[4689]|501[34]|7781" />
 
@@ -129,7 +135,7 @@
 
     <!-- Italy: 5 digits (premium=4xxxx), plus EU:
          http://clients.txtnation.com/attachments/token/di5kfblvubttvlw/?name=Italy_CASP_EN.pdf -->
-    <shortcode country="it" pattern="\\d{5}" premium="4\\d{4}" free="116\\d{3}|4112503" />
+    <shortcode country="it" pattern="\\d{5}" premium="4\\d{4}" free="116\\d{3}|4112503" standard="43\\d{3}" />
 
     <!-- Japan: 8083 used by SOFTBANK_DCB_2 -->
     <shortcode country="jp" free="8083" />
@@ -204,7 +210,7 @@
     <shortcode country="si" pattern="\\d{4}" premium="[368]\\d{3}" free="116\\d{3}" />
 
     <!-- Slovakia: 4 digits (premium), plus EU: http://www.cmtelecom.com/premium-sms/slovakia -->
-    <shortcode country="sk" premium="\\d{4}" free="116\\d{3}" />
+    <shortcode country="sk" premium="\\d{4}" free="116\\d{3}|8000" />
 
     <!-- Thailand: 4186001 used by AIS_TH_DCB -->
     <shortcode country="th" free="4186001" />
@@ -220,9 +226,9 @@
 
     <!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm),
          visual voicemail code for T-Mobile: 122 -->
-    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567" free="122|87902" />
+    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245" />
 
     <!-- Vietnam: 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="vn" pattern="\\d{1,5}" free="5001" />
+    <shortcode country="vn" pattern="\\d{1,5}" free="5001|9055" />
 
 </shortcodes>
diff --git a/core/res/res/xml/time_zones_by_country.xml b/core/res/res/xml/time_zones_by_country.xml
index 9b2bd50..a685e2b 100644
--- a/core/res/res/xml/time_zones_by_country.xml
+++ b/core/res/res/xml/time_zones_by_country.xml
@@ -31,11 +31,11 @@
 
     <!-- ANTIGUA AND BARBUDA, -4:00 -->
 
-    <timezone code="ag">America/Antigua</timezone>
+    <timezone code="ag">America/Port_of_Spain</timezone>
 
     <!-- ANGUILLA, -4:00 -->
 
-    <timezone code="ai">America/Anguilla</timezone>
+    <timezone code="ai">America/Port_of_Spain</timezone>
 
     <!-- ALBANIA, 1:00 -->
 
@@ -45,18 +45,13 @@
 
     <timezone code="am">Asia/Yerevan</timezone>
 
-    <!-- NETHERLANDS ANTILLES, -4:00 -->
-
-    <timezone code="an">America/Curacao</timezone>
-
     <!-- ANGOLA, 1:00 -->
 
-    <timezone code="ao">Africa/Luanda</timezone>
+    <timezone code="ao">Africa/Lagos</timezone>
 
     <!-- ANTARCTICA, 12:00 -->
 
-    <timezone code="aq">Antarctica/McMurdo</timezone>
-    <timezone code="aq">Antarctica/South_Pole</timezone>
+    <timezone code="aq">Pacific/Auckland</timezone>
 
     <!-- ANTARCTICA, 10:00 -->
 
@@ -70,15 +65,22 @@
 
     <timezone code="aq">Antarctica/Davis</timezone>
 
-    <!-- ANTARCTICA, 6:00 -->
+    <!-- ANTARCTICA, 5:00 -->
 
     <timezone code="aq">Antarctica/Mawson</timezone>
+
+    <!-- ANTARCTICA, 6:00 -->
+
     <timezone code="aq">Antarctica/Vostok</timezone>
 
     <!-- ANTARCTICA, 3:00 -->
 
     <timezone code="aq">Antarctica/Syowa</timezone>
 
+    <!-- ANTARCTICA, 0:00 -->
+
+    <timezone code="aq">Antarctica/Troll</timezone>
+
     <!-- ANTARCTICA, -3:00 -->
 
     <timezone code="aq">Antarctica/Rothera</timezone>
@@ -91,12 +93,14 @@
 
     <timezone code="ar">America/Argentina/Buenos_Aires</timezone>
     <timezone code="ar">America/Argentina/Cordoba</timezone>
+    <timezone code="ar">America/Argentina/Salta</timezone>
     <timezone code="ar">America/Argentina/Jujuy</timezone>
     <timezone code="ar">America/Argentina/Tucuman</timezone>
     <timezone code="ar">America/Argentina/Catamarca</timezone>
     <timezone code="ar">America/Argentina/La_Rioja</timezone>
     <timezone code="ar">America/Argentina/San_Juan</timezone>
     <timezone code="ar">America/Argentina/Mendoza</timezone>
+    <timezone code="ar">America/Argentina/San_Luis</timezone>
     <timezone code="ar">America/Argentina/Rio_Gallegos</timezone>
     <timezone code="ar">America/Argentina/Ushuaia</timezone>
 
@@ -117,6 +121,9 @@
     <timezone code="au">Australia/Currie</timezone>
     <timezone code="au">Australia/Lindeman</timezone>
 
+    <!-- AUSTRALIA, 11:00 -->
+    <timezone code="au">Antarctica/Macquarie</timezone>
+
     <!-- AUSTRALIA, 10:30 -->
 
     <timezone code="au">Australia/Lord_Howe</timezone>
@@ -137,11 +144,11 @@
 
     <!-- ARUBA, -4:00 -->
 
-    <timezone code="aw">America/Aruba</timezone>
+    <timezone code="aw">America/Curacao</timezone>
 
     <!-- ALAND ISLANDS, 2:00 -->
 
-    <timezone code="ax">Europe/Mariehamn</timezone>
+    <timezone code="ax">Europe/Helsinki</timezone>
 
     <!-- AZERBAIJAN, 4:00 -->
 
@@ -149,7 +156,7 @@
 
     <!-- BOSNIA AND HERZEGOVINA, 1:00 -->
 
-    <timezone code="ba">Europe/Sarajevo</timezone>
+    <timezone code="ba">Europe/Belgrade</timezone>
 
     <!-- BARBADOS, -4:00 -->
 
@@ -165,7 +172,7 @@
 
     <!-- BURKINA FASO, 0:00 -->
 
-    <timezone code="bf">Africa/Ouagadougou</timezone>
+    <timezone code="bf">Africa/Abidjan</timezone>
 
     <!-- BULGARIA, 2:00 -->
 
@@ -173,15 +180,19 @@
 
     <!-- BAHRAIN, 3:00 -->
 
-    <timezone code="bh">Asia/Bahrain</timezone>
+    <timezone code="bh">Asia/Qatar</timezone>
 
     <!-- BURUNDI, 2:00 -->
 
-    <timezone code="bi">Africa/Bujumbura</timezone>
+    <timezone code="bi">Africa/Maputo</timezone>
 
     <!-- BENIN, 1:00 -->
 
-    <timezone code="bj">Africa/Porto-Novo</timezone>
+    <timezone code="bj">Africa/Lagos</timezone>
+
+    <!-- Saint Barthélemy, -4:00 -->
+
+    <timezone code="bl">America/Port_of_Spain</timezone>
 
     <!-- BERMUDA, -4:00 -->
 
@@ -195,6 +206,10 @@
 
     <timezone code="bo">America/La_Paz</timezone>
 
+    <!-- Caribbean Netherlands, -4:00 -->
+
+    <timezone code="bq">America/Curacao</timezone>
+
     <!-- BRAZIL, -2:00 -->
 
     <timezone code="br">America/Noronha</timezone>
@@ -208,6 +223,7 @@
     <timezone code="br">America/Araguaina</timezone>
     <timezone code="br">America/Maceio</timezone>
     <timezone code="br">America/Bahia</timezone>
+    <timezone code="br">America/Santarem</timezone>
 
     <!-- BRAZIL, -4:00 -->
 
@@ -216,6 +232,9 @@
     <timezone code="br">America/Cuiaba</timezone>
     <timezone code="br">America/Porto_Velho</timezone>
     <timezone code="br">America/Boa_Vista</timezone>
+
+    <!-- BRAZIL, -5:00 -->
+
     <timezone code="br">America/Eirunepe</timezone>
     <timezone code="br">America/Rio_Branco</timezone>
 
@@ -229,9 +248,9 @@
 
     <!-- BOTSWANA, 2:00 -->
 
-    <timezone code="bw">Africa/Gaborone</timezone>
+    <timezone code="bw">Africa/Maputo</timezone>
 
-    <!-- BELARUS, 2:00 -->
+    <!-- BELARUS, 3:00 -->
 
     <timezone code="by">Europe/Minsk</timezone>
 
@@ -254,12 +273,10 @@
     <!-- CANADA, -5:00 -->
 
     <timezone code="ca">America/Toronto</timezone>
-    <timezone code="ca">America/Montreal</timezone>
     <timezone code="ca">America/Nipigon</timezone>
     <timezone code="ca">America/Thunder_Bay</timezone>
     <timezone code="ca">America/Iqaluit</timezone>
     <timezone code="ca">America/Pangnirtung</timezone>
-    <timezone code="ca">America/Resolute</timezone>
     <timezone code="ca">America/Atikokan</timezone>
 
     <!-- CANADA, -6:00 -->
@@ -269,6 +286,7 @@
     <timezone code="ca">America/Rankin_Inlet</timezone>
     <timezone code="ca">America/Rainy_River</timezone>
     <timezone code="ca">America/Swift_Current</timezone>
+    <timezone code="ca">America/Resolute</timezone>
 
     <!-- CANADA, -7:00 -->
 
@@ -277,6 +295,8 @@
     <timezone code="ca">America/Yellowknife</timezone>
     <timezone code="ca">America/Inuvik</timezone>
     <timezone code="ca">America/Dawson_Creek</timezone>
+    <timezone code="ca">America/Creston</timezone>
+    <timezone code="ca">America/Fort_Nelson</timezone>
 
     <!-- CANADA, -8:00 -->
 
@@ -290,19 +310,19 @@
 
     <!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE, 2:00 -->
 
-    <timezone code="cd">Africa/Lubumbashi</timezone>
+    <timezone code="cd">Africa/Maputo</timezone>
 
     <!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE, 1:00 -->
 
-    <timezone code="cd">Africa/Kinshasa</timezone>
+    <timezone code="cd">Africa/Lagos</timezone>
 
     <!-- CENTRAL AFRICAN REPUBLIC, 1:00 -->
 
-    <timezone code="cf">Africa/Bangui</timezone>
+    <timezone code="cf">Africa/Lagos</timezone>
 
     <!-- CONGO, 1:00 -->
 
-    <timezone code="cg">Africa/Brazzaville</timezone>
+    <timezone code="cg">Africa/Lagos</timezone>
 
     <!-- SWITZERLAND, 1:00 -->
 
@@ -326,15 +346,15 @@
 
     <!-- CAMEROON, 1:00 -->
 
-    <timezone code="cm">Africa/Douala</timezone>
+    <timezone code="cm">Africa/Lagos</timezone>
 
     <!-- CHINA, 8:00 -->
 
     <timezone code="cn">Asia/Shanghai</timezone>
-    <timezone code="cn">Asia/Harbin</timezone>
-    <timezone code="cn">Asia/Chongqing</timezone>
+
+    <!-- CHINA, 6:00 -->
+
     <timezone code="cn">Asia/Urumqi</timezone>
-    <timezone code="cn">Asia/Kashgar</timezone>
 
     <!-- COLOMBIA, -5:00 -->
 
@@ -352,6 +372,10 @@
 
     <timezone code="cv">Atlantic/Cape_Verde</timezone>
 
+    <!-- Curaçao, -4:00 -->
+
+    <timezone code="cw">America/Curacao</timezone>
+
     <!-- CHRISTMAS ISLAND, 7:00 -->
 
     <timezone code="cx">Indian/Christmas</timezone>
@@ -367,10 +391,11 @@
     <!-- GERMANY, 1:00 -->
 
     <timezone code="de">Europe/Berlin</timezone>
+    <timezone code="de">Europe/Zurich</timezone>
 
     <!-- DJIBOUTI, 3:00 -->
 
-    <timezone code="dj">Africa/Djibouti</timezone>
+    <timezone code="dj">Africa/Nairobi</timezone>
 
     <!-- DENMARK, 1:00 -->
 
@@ -378,7 +403,7 @@
 
     <!-- DOMINICA, -4:00 -->
 
-    <timezone code="dm">America/Dominica</timezone>
+    <timezone code="dm">America/Port_of_Spain</timezone>
 
     <!-- DOMINICAN REPUBLIC, -4:00 -->
 
@@ -410,7 +435,7 @@
 
     <!-- ERITREA, 3:00 -->
 
-    <timezone code="er">Africa/Asmara</timezone>
+    <timezone code="er">Africa/Nairobi</timezone>
 
     <!-- SPAIN, 1:00 -->
 
@@ -423,7 +448,7 @@
 
     <!-- ETHIOPIA, 3:00 -->
 
-    <timezone code="et">Africa/Addis_Ababa</timezone>
+    <timezone code="et">Africa/Nairobi</timezone>
 
     <!-- FINLAND, 2:00 -->
 
@@ -433,7 +458,7 @@
 
     <timezone code="fj">Pacific/Fiji</timezone>
 
-    <!-- FALKLAND ISLANDS (MALVINAS), -4:00 -->
+    <!-- FALKLAND ISLANDS (MALVINAS), -3:00 -->
 
     <timezone code="fk">Atlantic/Stanley</timezone>
 
@@ -444,7 +469,7 @@
 
     <!-- MICRONESIA, FEDERATED STATES OF, 10:00 -->
 
-    <timezone code="fm">Pacific/Truk</timezone>
+    <timezone code="fm">Pacific/Chuuk</timezone>
 
     <!-- FAROE ISLANDS, 0:00 -->
 
@@ -456,7 +481,7 @@
 
     <!-- GABON, 1:00 -->
 
-    <timezone code="ga">Africa/Libreville</timezone>
+    <timezone code="ga">Africa/Lagos</timezone>
 
     <!-- UNITED KINGDOM, 0:00 -->
 
@@ -464,7 +489,7 @@
 
     <!-- GRENADA, -4:00 -->
 
-    <timezone code="gd">America/Grenada</timezone>
+    <timezone code="gd">America/Port_of_Spain</timezone>
 
     <!-- GEORGIA, 4:00 -->
 
@@ -476,7 +501,7 @@
 
     <!-- GUERNSEY, 0:00 -->
 
-    <timezone code="gg">Europe/Guernsey</timezone>
+    <timezone code="gg">Europe/London</timezone>
 
     <!-- GHANA, 0:00 -->
 
@@ -504,19 +529,19 @@
 
     <!-- GAMBIA, 0:00 -->
 
-    <timezone code="gm">Africa/Banjul</timezone>
+    <timezone code="gm">Africa/Abidjan</timezone>
 
     <!-- GUINEA, 0:00 -->
 
-    <timezone code="gn">Africa/Conakry</timezone>
+    <timezone code="gn">Africa/Abidjan</timezone>
 
     <!-- GUADELOUPE, -4:00 -->
 
-    <timezone code="gp">America/Guadeloupe</timezone>
+    <timezone code="gp">America/Port_of_Spain</timezone>
 
     <!-- EQUATORIAL GUINEA, 1:00 -->
 
-    <timezone code="gq">Africa/Malabo</timezone>
+    <timezone code="gq">Africa/Lagos</timezone>
 
     <!-- GREECE, 2:00 -->
 
@@ -552,7 +577,7 @@
 
     <!-- CROATIA, 1:00 -->
 
-    <timezone code="hr">Europe/Zagreb</timezone>
+    <timezone code="hr">Europe/Belgrade</timezone>
 
     <!-- HAITI, -5:00 -->
 
@@ -585,11 +610,11 @@
 
     <!-- ISLE OF MAN, 0:00 -->
 
-    <timezone code="im">Europe/Isle_of_Man</timezone>
+    <timezone code="im">Europe/London</timezone>
 
     <!-- INDIA, 5:30 -->
 
-    <timezone code="in">Asia/Calcutta</timezone>
+    <timezone code="in">Asia/Kolkata</timezone>
 
     <!-- BRITISH INDIAN OCEAN TERRITORY, 6:00 -->
 
@@ -613,7 +638,7 @@
 
     <!-- JERSEY, 0:00 -->
 
-    <timezone code="je">Europe/Jersey</timezone>
+    <timezone code="je">Europe/London</timezone>
 
     <!-- JAMAICA, -5:00 -->
 
@@ -637,7 +662,7 @@
 
     <!-- CAMBODIA, 7:00 -->
 
-    <timezone code="kh">Asia/Phnom_Penh</timezone>
+    <timezone code="kh">Asia/Bangkok</timezone>
 
     <!-- KIRIBATI, 14:00 -->
 
@@ -653,13 +678,13 @@
 
     <!-- COMOROS, 3:00 -->
 
-    <timezone code="km">Indian/Comoro</timezone>
+    <timezone code="km">Africa/Nairobi</timezone>
 
     <!-- SAINT KITTS AND NEVIS, -4:00 -->
 
-    <timezone code="kn">America/St_Kitts</timezone>
+    <timezone code="kn">America/Port_of_Spain</timezone>
 
-    <!-- KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF, 9:00 -->
+    <!-- KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF, 8:30 -->
 
     <timezone code="kp">Asia/Pyongyang</timezone>
 
@@ -669,11 +694,11 @@
 
     <!-- KUWAIT, 3:00 -->
 
-    <timezone code="kw">Asia/Kuwait</timezone>
+    <timezone code="kw">Asia/Riyadh</timezone>
 
     <!-- CAYMAN ISLANDS, -5:00 -->
 
-    <timezone code="ky">America/Cayman</timezone>
+    <timezone code="ky">America/Panama</timezone>
 
     <!-- KAZAKHSTAN, 6:00 -->
 
@@ -688,7 +713,7 @@
 
     <!-- LAO PEOPLE'S DEMOCRATIC REPUBLIC, 7:00 -->
 
-    <timezone code="la">Asia/Vientiane</timezone>
+    <timezone code="la">Asia/Bangkok</timezone>
 
     <!-- LEBANON, 2:00 -->
 
@@ -696,11 +721,11 @@
 
     <!-- SAINT LUCIA, -4:00 -->
 
-    <timezone code="lc">America/St_Lucia</timezone>
+    <timezone code="lc">America/Port_of_Spain</timezone>
 
     <!-- LIECHTENSTEIN, 1:00 -->
 
-    <timezone code="li">Europe/Vaduz</timezone>
+    <timezone code="li">Europe/Zurich</timezone>
 
     <!-- SRI LANKA, 5:30 -->
 
@@ -712,7 +737,7 @@
 
     <!-- LESOTHO, 2:00 -->
 
-    <timezone code="ls">Africa/Maseru</timezone>
+    <timezone code="ls">Africa/Johannesburg</timezone>
 
     <!-- LITHUANIA, 2:00 -->
 
@@ -744,11 +769,15 @@
 
     <!-- MONTENEGRO, 1:00 -->
 
-    <timezone code="me">Europe/Podgorica</timezone>
+    <timezone code="me">Europe/Belgrade</timezone>
+
+    <!-- Collectivity of Saint Martin, -4:00 -->
+
+    <timezone code="mf">America/Port_of_Spain</timezone>
 
     <!-- MADAGASCAR, 3:00 -->
 
-    <timezone code="mg">Indian/Antananarivo</timezone>
+    <timezone code="mg">Africa/Nairobi</timezone>
 
     <!-- MARSHALL ISLANDS, 12:00 -->
 
@@ -757,15 +786,15 @@
 
     <!-- MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF, 1:00 -->
 
-    <timezone code="mk">Europe/Skopje</timezone>
+    <timezone code="mk">Europe/Belgrade</timezone>
 
     <!-- MALI, 0:00 -->
 
-    <timezone code="ml">Africa/Bamako</timezone>
+    <timezone code="ml">Africa/Abidjan</timezone>
 
     <!-- MYANMAR, 6:30 -->
 
-    <timezone code="mm">Asia/Rangoon</timezone>
+    <timezone code="mm">Asia/Yangon</timezone>
 
     <!-- MONGOLIA, 8:00 -->
 
@@ -782,7 +811,7 @@
 
     <!-- NORTHERN MARIANA ISLANDS, 10:00 -->
 
-    <timezone code="mp">Pacific/Saipan</timezone>
+    <timezone code="mp">Pacific/Guam</timezone>
 
     <!-- MARTINIQUE, -4:00 -->
 
@@ -790,11 +819,11 @@
 
     <!-- MAURITANIA, 0:00 -->
 
-    <timezone code="mr">Africa/Nouakchott</timezone>
+    <timezone code="mr">Africa/Abidjan</timezone>
 
     <!-- MONTSERRAT, -4:00 -->
 
-    <timezone code="ms">America/Montserrat</timezone>
+    <timezone code="ms">America/Port_of_Spain</timezone>
 
     <!-- MALTA, 1:00 -->
 
@@ -810,20 +839,26 @@
 
     <!-- MALAWI, 2:00 -->
 
-    <timezone code="mw">Africa/Blantyre</timezone>
+    <timezone code="mw">Africa/Maputo</timezone>
 
     <!-- MEXICO, -6:00 -->
 
     <timezone code="mx">America/Mexico_City</timezone>
-    <timezone code="mx">America/Cancun</timezone>
     <timezone code="mx">America/Merida</timezone>
     <timezone code="mx">America/Monterrey</timezone>
+    <timezone code="mx">America/Matamoros</timezone>
+    <timezone code="mx">America/Bahia_Banderas</timezone>
+
+    <!-- MEXICO, -5:00 -->
+
+    <timezone code="mx">America/Cancun</timezone>
 
     <!-- MEXICO, -7:00 -->
 
     <timezone code="mx">America/Chihuahua</timezone>
     <timezone code="mx">America/Hermosillo</timezone>
     <timezone code="mx">America/Mazatlan</timezone>
+    <timezone code="mx">America/Ojinaga</timezone>
 
     <!-- MEXICO, -8:00 -->
 
@@ -848,7 +883,7 @@
 
     <!-- NIGER, 1:00 -->
 
-    <timezone code="ne">Africa/Niamey</timezone>
+    <timezone code="ne">Africa/Lagos</timezone>
 
     <!-- NORFOLK ISLAND, 11:30 -->
 
@@ -892,7 +927,7 @@
 
     <!-- OMAN, 4:00 -->
 
-    <timezone code="om">Asia/Muscat</timezone>
+    <timezone code="om">Asia/Dubai</timezone>
 
     <!-- PANAMA, -5:00 -->
 
@@ -918,6 +953,10 @@
 
     <timezone code="pg">Pacific/Port_Moresby</timezone>
 
+    <!-- PAPUA NEW GUINEA, 11:00 -->
+
+    <timezone code="pg">Pacific/Bougainville</timezone>
+
     <!-- PHILIPPINES, 8:00 -->
 
     <timezone code="ph">Asia/Manila</timezone>
@@ -945,6 +984,7 @@
     <!-- PALESTINE, 2:00 -->
 
     <timezone code="ps">Asia/Gaza</timezone>
+    <timezone code="ps">Asia/Hebron</timezone>
 
     <!-- PORTUGAL, 0:00 -->
 
@@ -987,15 +1027,19 @@
     <!-- RUSSIAN FEDERATION, 11:00 -->
 
     <timezone code="ru">Asia/Magadan</timezone>
+    <timezone code="ru">Asia/Sakhalin</timezone>
+    <timezone code="ru">Asia/Srednekolymsk</timezone>
 
     <!-- RUSSIAN FEDERATION, 10:00 -->
 
     <timezone code="ru">Asia/Vladivostok</timezone>
-    <timezone code="ru">Asia/Sakhalin</timezone>
+    <timezone code="ru">Asia/Ust-Nera</timezone>
 
     <!-- RUSSIAN FEDERATION, 9:00 -->
 
     <timezone code="ru">Asia/Yakutsk</timezone>
+    <timezone code="ru">Asia/Chita</timezone>
+    <timezone code="ru">Asia/Khandyga</timezone>
 
     <!-- RUSSIAN FEDERATION, 8:00 -->
 
@@ -1004,10 +1048,13 @@
     <!-- RUSSIAN FEDERATION, 7:00 -->
 
     <timezone code="ru">Asia/Krasnoyarsk</timezone>
+    <timezone code="ru">Asia/Novosibirsk</timezone>
+    <timezone code="ru">Asia/Barnaul</timezone>
+    <timezone code="ru">Asia/Novokuznetsk</timezone>
+    <timezone code="ru">Asia/Tomsk</timezone>
 
     <!-- RUSSIAN FEDERATION, 6:00 -->
 
-    <timezone code="ru">Asia/Novosibirsk</timezone>
     <timezone code="ru">Asia/Omsk</timezone>
 
     <!-- RUSSIAN FEDERATION, 5:00 -->
@@ -1017,11 +1064,15 @@
     <!-- RUSSIAN FEDERATION, 4:00 -->
 
     <timezone code="ru">Europe/Samara</timezone>
+    <timezone code="ru">Europe/Astrakhan</timezone>
+    <timezone code="ru">Europe/Ulyanovsk</timezone>
 
     <!-- RUSSIAN FEDERATION, 3:00 -->
 
     <timezone code="ru">Europe/Moscow</timezone>
     <timezone code="ru">Europe/Volgograd</timezone>
+    <timezone code="ru">Europe/Kirov</timezone>
+    <timezone code="ru">Europe/Simferopol</timezone>
 
     <!-- RUSSIAN FEDERATION, 2:00 -->
 
@@ -1029,7 +1080,7 @@
 
     <!-- RWANDA, 2:00 -->
 
-    <timezone code="rw">Africa/Kigali</timezone>
+    <timezone code="rw">Africa/Maputo</timezone>
 
     <!-- SAUDI ARABIA, 3:00 -->
 
@@ -1057,57 +1108,65 @@
 
     <!-- SAINT HELENA, 0:00 -->
 
-    <timezone code="sh">Atlantic/St_Helena</timezone>
+    <timezone code="sh">Africa/Abidjan</timezone>
 
     <!-- SLOVENIA, 1:00 -->
 
-    <timezone code="si">Europe/Ljubljana</timezone>
+    <timezone code="si">Europe/Belgrade</timezone>
 
     <!-- SVALBARD AND JAN MAYEN, 1:00 -->
 
-    <timezone code="sj">Arctic/Longyearbyen</timezone>
+    <timezone code="sj">Europe/Oslo</timezone>
 
     <!-- SLOVAKIA, 1:00 -->
 
-    <timezone code="sk">Europe/Bratislava</timezone>
+    <timezone code="sk">Europe/Prague</timezone>
 
     <!-- SIERRA LEONE, 0:00 -->
 
-    <timezone code="sl">Africa/Freetown</timezone>
+    <timezone code="sl">Africa/Abidjan</timezone>
 
     <!-- SAN MARINO, 1:00 -->
 
-    <timezone code="sm">Europe/San_Marino</timezone>
+    <timezone code="sm">Europe/Rome</timezone>
 
     <!-- SENEGAL, 0:00 -->
 
-    <timezone code="sn">Africa/Dakar</timezone>
+    <timezone code="sn">Africa/Abidjan</timezone>
 
     <!-- SOMALIA, 3:00 -->
 
-    <timezone code="so">Africa/Mogadishu</timezone>
+    <timezone code="so">Africa/Nairobi</timezone>
 
     <!-- SURINAME, -3:00 -->
 
     <timezone code="sr">America/Paramaribo</timezone>
 
+    <!-- South Sudan, 3:00 -->
+
+    <timezone code="ss">Africa/Khartoum</timezone>
+
     <!-- SAO TOME AND PRINCIPE, 0:00 -->
 
-    <timezone code="st">Africa/Sao_Tome</timezone>
+    <timezone code="st">Africa/Abidjan</timezone>
 
     <!-- EL SALVADOR, -6:00 -->
 
     <timezone code="sv">America/El_Salvador</timezone>
 
+    <!-- Sint Maarten, -4:00 -->
+
+    <timezone code="sx">America/Curacao</timezone>
+
     <!-- SYRIAN ARAB REPUBLIC, 2:00 -->
 
     <timezone code="sy">Asia/Damascus</timezone>
 
     <!-- SWAZILAND, 2:00 -->
 
-    <timezone code="sz">Africa/Mbabane</timezone>
+    <timezone code="sz">Africa/Johannesburg</timezone>
 
-    <!-- TURKS AND CAICOS ISLANDS, -5:00 -->
+    <!-- TURKS AND CAICOS ISLANDS, -4:00 -->
 
     <timezone code="tc">America/Grand_Turk</timezone>
 
@@ -1119,9 +1178,13 @@
 
     <timezone code="tf">Indian/Kerguelen</timezone>
 
+    <!-- FRENCH SOUTHERN TERRITORIES, 4:00 -->
+
+    <timezone code="tf">Indian/Reunion</timezone>
+
     <!-- TOGO, 0:00 -->
 
-    <timezone code="tg">Africa/Lome</timezone>
+    <timezone code="tg">Africa/Abidjan</timezone>
 
     <!-- THAILAND, 7:00 -->
 
@@ -1131,7 +1194,7 @@
 
     <timezone code="tj">Asia/Dushanbe</timezone>
 
-    <!-- TOKELAU, -10:00 -->
+    <!-- TOKELAU, +13:00 -->
 
     <timezone code="tk">Pacific/Fakaofo</timezone>
 
@@ -1151,7 +1214,7 @@
 
     <timezone code="to">Pacific/Tongatapu</timezone>
 
-    <!-- TURKEY, 2:00 -->
+    <!-- TURKEY, 3:00 -->
 
     <timezone code="tr">Europe/Istanbul</timezone>
 
@@ -1169,18 +1232,17 @@
 
     <!-- TANZANIA, UNITED REPUBLIC OF, 3:00 -->
 
-    <timezone code="tz">Africa/Dar_es_Salaam</timezone>
+    <timezone code="tz">Africa/Nairobi</timezone>
 
     <!-- UKRAINE, 2:00 -->
 
     <timezone code="ua">Europe/Kiev</timezone>
     <timezone code="ua">Europe/Uzhgorod</timezone>
     <timezone code="ua">Europe/Zaporozhye</timezone>
-    <timezone code="ua">Europe/Simferopol</timezone>
 
     <!-- UGANDA, 3:00 -->
 
-    <timezone code="ug">Africa/Kampala</timezone>
+    <timezone code="ug">Africa/Nairobi</timezone>
 
     <!-- UNITED STATES MINOR OUTLYING ISLANDS, 12:00 -->
 
@@ -1188,11 +1250,11 @@
 
     <!-- UNITED STATES MINOR OUTLYING ISLANDS, -10:00 -->
 
-    <timezone code="um">Pacific/Johnston</timezone>
+    <timezone code="um">Pacific/Honolulu</timezone>
 
     <!-- UNITED STATES MINOR OUTLYING ISLANDS, -11:00 -->
 
-    <timezone code="um">Pacific/Midway</timezone>
+    <timezone code="um">Pacific/Pago_Pago</timezone>
 
     <!-- UNITED STATES, -5:00 -->
 
@@ -1214,12 +1276,13 @@
     <timezone code="us">America/Menominee</timezone>
     <timezone code="us">America/North_Dakota/Center</timezone>
     <timezone code="us">America/North_Dakota/New_Salem</timezone>
+    <timezone code="us">America/Indiana/Tell_City</timezone>
+    <timezone code="us">America/North_Dakota/Beulah</timezone>
 
     <!-- UNITED STATES, -7:00 -->
 
     <timezone code="us">America/Denver</timezone>
     <timezone code="us">America/Boise</timezone>
-    <timezone code="us">America/Shiprock</timezone>
     <timezone code="us">America/Phoenix</timezone>
 
     <!-- UNITED STATES, -8:00 -->
@@ -1232,6 +1295,8 @@
     <timezone code="us">America/Juneau</timezone>
     <timezone code="us">America/Yakutat</timezone>
     <timezone code="us">America/Nome</timezone>
+    <timezone code="us">America/Metlakatla</timezone>
+    <timezone code="us">America/Sitka</timezone>
 
     <!-- UNITED STATES, -10:00 -->
 
@@ -1249,27 +1314,28 @@
 
     <!-- HOLY SEE (VATICAN CITY STATE), 1:00 -->
 
-    <timezone code="va">Europe/Vatican</timezone>
+    <timezone code="va">Europe/Rome</timezone>
 
     <!-- SAINT VINCENT AND THE GRENADINES, -4:00 -->
 
-    <timezone code="vc">America/St_Vincent</timezone>
+    <timezone code="vc">America/Port_of_Spain</timezone>
 
-    <!-- VENEZUELA, -4:30 -->
+    <!-- VENEZUELA, -4:00 -->
 
     <timezone code="ve">America/Caracas</timezone>
 
     <!-- VIRGIN ISLANDS, BRITISH, -4:00 -->
 
-    <timezone code="vg">America/Tortola</timezone>
+    <timezone code="vg">America/Port_of_Spain</timezone>
 
     <!-- VIRGIN ISLANDS, U.S., -4:00 -->
 
-    <timezone code="vi">America/St_Thomas</timezone>
+    <timezone code="vi">America/Port_of_Spain</timezone>
 
     <!-- VIET NAM, 7:00 -->
 
-    <timezone code="vn">Asia/Saigon</timezone>
+    <timezone code="vn">Asia/Ho_Chi_Minh</timezone>
+    <timezone code="vn">Asia/Bangkok</timezone>
 
     <!-- VANUATU, 11:00 -->
 
@@ -1279,17 +1345,17 @@
 
     <timezone code="wf">Pacific/Wallis</timezone>
 
-    <!-- SAMOA, -11:00 -->
+    <!-- SAMOA, 13:00 -->
 
     <timezone code="ws">Pacific/Apia</timezone>
 
     <!-- YEMEN, 3:00 -->
 
-    <timezone code="ye">Asia/Aden</timezone>
+    <timezone code="ye">Asia/Riyadh</timezone>
 
     <!-- MAYOTTE, 3:00 -->
 
-    <timezone code="yt">Indian/Mayotte</timezone>
+    <timezone code="yt">Africa/Nairobi</timezone>
 
     <!-- SOUTH AFRICA, 2:00 -->
 
@@ -1297,9 +1363,9 @@
 
     <!-- ZAMBIA, 2:00 -->
 
-    <timezone code="zm">Africa/Lusaka</timezone>
+    <timezone code="zm">Africa/Maputo</timezone>
 
     <!-- ZIMBABWE, 2:00 -->
 
-    <timezone code="zw">Africa/Harare</timezone>
+    <timezone code="zw">Africa/Maputo</timezone>
 </timezones>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index ee78613..ba1a55d 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1323,17 +1323,6 @@
             </meta-data>
         </service>
 
-        <activity
-            android:name="android.print.mockservice.SettingsActivity"
-            android:permission="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY"
-            android:exported="true">
-        </activity>
-
-        <activity
-                android:name="android.print.mockservice.AddPrintersActivity"
-                android:exported="true">
-        </activity>
-
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/core/tests/coretests/res/xml/printservice.xml b/core/tests/coretests/res/xml/printservice.xml
index b105a0f..3bd2b04 100644
--- a/core/tests/coretests/res/xml/printservice.xml
+++ b/core/tests/coretests/res/xml/printservice.xml
@@ -16,6 +16,4 @@
     limitations under the License.
 -->
 
-<print-service  xmlns:android="http://schemas.android.com/apk/res/android"
-     android:settingsActivity="android.print.mockservice.SettingsActivity"
-     android:addPrintersActivity="android.print.mockservice.AddPrintersActivity" />
+<print-service  xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/core/tests/coretests/src/android/print/WorkflowTest.java b/core/tests/coretests/src/android/print/WorkflowTest.java
deleted file mode 100644
index 35cfe22..0000000
--- a/core/tests/coretests/src/android/print/WorkflowTest.java
+++ /dev/null
@@ -1,391 +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.print;
-
-import android.graphics.pdf.PdfDocument;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.os.ParcelFileDescriptor;
-import android.print.mockservice.AddPrintersActivity;
-import android.print.mockservice.MockPrintService;
-
-import android.print.mockservice.PrinterDiscoverySessionCallbacks;
-import android.print.mockservice.StubbablePrinterDiscoverySession;
-import android.print.pdf.PrintedPdfDocument;
-import android.support.test.filters.LargeTest;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiSelector;
-import android.util.Log;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-import java.util.function.Supplier;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Tests for the basic printing workflows
- */
-public class WorkflowTest extends BasePrintTest {
-    private static final String LOG_TAG = WorkflowTest.class.getSimpleName();
-
-    private static float sWindowAnimationScaleBefore;
-    private static float sTransitionAnimationScaleBefore;
-    private static float sAnimatiorDurationScaleBefore;
-
-    interface InterruptableConsumer<T> {
-        void accept(T t) throws InterruptedException;
-    }
-
-    /**
-     * Execute {@code waiter} until {@code condition} is met.
-     *
-     * @param condition Conditions to wait for
-     * @param waiter    Code to execute while waiting
-     */
-    private void waitWithTimeout(Supplier<Boolean> condition, InterruptableConsumer<Long> waiter)
-            throws TimeoutException, InterruptedException {
-        long startTime = System.currentTimeMillis();
-        while (condition.get()) {
-            long timeLeft = OPERATION_TIMEOUT - (System.currentTimeMillis() - startTime);
-            if (timeLeft < 0) {
-                throw new TimeoutException();
-            }
-
-            waiter.accept(timeLeft);
-        }
-    }
-
-    /**
-     * Executes a shell command using shell user identity, and return the standard output in
-     * string.
-     *
-     * @param cmd the command to run
-     *
-     * @return the standard output of the command
-     */
-    private static String runShellCommand(String cmd) throws IOException {
-        try (FileInputStream is = new ParcelFileDescriptor.AutoCloseInputStream(
-                getInstrumentation().getUiAutomation().executeShellCommand(cmd))) {
-            byte[] buf = new byte[64];
-            int bytesRead;
-
-            StringBuilder stdout = new StringBuilder();
-            while ((bytesRead = is.read(buf)) != -1) {
-                stdout.append(new String(buf, 0, bytesRead));
-            }
-
-            return stdout.toString();
-        }
-    }
-
-    @BeforeClass
-    public static void disableAnimations() throws Exception {
-        try {
-            sWindowAnimationScaleBefore = Float.parseFloat(runShellCommand(
-                    "settings get global window_animation_scale"));
-
-            runShellCommand("settings put global window_animation_scale 0");
-        } catch (NumberFormatException e) {
-            sWindowAnimationScaleBefore = Float.NaN;
-        }
-        try {
-            sTransitionAnimationScaleBefore = Float.parseFloat(runShellCommand(
-                    "settings get global transition_animation_scale"));
-
-            runShellCommand("settings put global transition_animation_scale 0");
-        } catch (NumberFormatException e) {
-            sTransitionAnimationScaleBefore = Float.NaN;
-        }
-        try {
-            sAnimatiorDurationScaleBefore = Float.parseFloat(runShellCommand(
-                    "settings get global animator_duration_scale"));
-
-            runShellCommand("settings put global animator_duration_scale 0");
-        } catch (NumberFormatException e) {
-            sAnimatiorDurationScaleBefore = Float.NaN;
-        }
-    }
-
-    @AfterClass
-    public static void enableAnimations() throws Exception {
-        if (sWindowAnimationScaleBefore != Float.NaN) {
-            runShellCommand(
-                    "settings put global window_animation_scale " + sWindowAnimationScaleBefore);
-        }
-        if (sTransitionAnimationScaleBefore != Float.NaN) {
-            runShellCommand(
-                    "settings put global transition_animation_scale " +
-                            sTransitionAnimationScaleBefore);
-        }
-        if (sAnimatiorDurationScaleBefore != Float.NaN) {
-            runShellCommand(
-                    "settings put global animator_duration_scale " + sAnimatiorDurationScaleBefore);
-        }
-    }
-
-    /** Add a printer with a given name and supported mediasize to a session */
-    private void addPrinter(StubbablePrinterDiscoverySession session,
-            String name, PrintAttributes.MediaSize mediaSize) {
-        PrinterId printerId = session.getService().generatePrinterId(name);
-        List<PrinterInfo> printers = new ArrayList<>(1);
-
-        PrinterCapabilitiesInfo.Builder builder =
-                new PrinterCapabilitiesInfo.Builder(printerId);
-
-        builder.setMinMargins(new PrintAttributes.Margins(0, 0, 0, 0))
-                .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
-                        PrintAttributes.COLOR_MODE_COLOR)
-                .addMediaSize(mediaSize, true)
-                .addResolution(new PrintAttributes.Resolution("300x300", "300x300", 300, 300),
-                        true);
-
-        printers.add(new PrinterInfo.Builder(printerId, name,
-                PrinterInfo.STATUS_IDLE).setCapabilities(builder.build()).build());
-
-        session.addPrinters(printers);
-    }
-
-    /** Find a certain element in the UI and click on it */
-    private void clickOn(UiSelector selector) throws UiObjectNotFoundException {
-        Log.i(LOG_TAG, "Click on " + selector);
-        UiObject view = getUiDevice().findObject(selector);
-        view.click();
-        getUiDevice().waitForIdle();
-    }
-
-    /** Find a certain text in the UI and click on it */
-    private void clickOnText(String text) throws UiObjectNotFoundException {
-        clickOn(new UiSelector().text(text));
-    }
-
-    /** Set the printer in the print activity */
-    private void setPrinter(String printerName) throws UiObjectNotFoundException {
-        clickOn(new UiSelector().resourceId("com.android.printspooler:id/destination_spinner"));
-
-        clickOnText(printerName);
-    }
-
-    /**
-     * Init mock print servic that returns a single printer by default.
-     *
-     * @param sessionRef Where to store the reference to the session once started
-     */
-    private void setMockPrintServiceCallbacks(StubbablePrinterDiscoverySession[] sessionRef) {
-        MockPrintService.setCallbacks(createMockPrintServiceCallbacks(
-                inv -> createMockPrinterDiscoverySessionCallbacks(inv2 -> {
-                            synchronized (sessionRef) {
-                                sessionRef[0] = ((PrinterDiscoverySessionCallbacks) inv2.getMock())
-                                        .getSession();
-
-                                addPrinter(sessionRef[0], "1st printer",
-                                        PrintAttributes.MediaSize.ISO_A0);
-
-                                sessionRef.notifyAll();
-                            }
-                            return null;
-                        },
-                        null, null, null, null, null, inv2 -> {
-                            synchronized (sessionRef) {
-                                sessionRef[0] = null;
-                                sessionRef.notifyAll();
-                            }
-                            return null;
-                        }
-        ), null, null));
-    }
-
-    /**
-     * Start print operation that just prints a single empty page
-     *
-     * @param printAttributesRef Where to store the reference to the print attributes once started
-     */
-    private void print(PrintAttributes[] printAttributesRef) {
-        print(new PrintDocumentAdapter() {
-            @Override
-            public void onStart() {
-            }
-
-            @Override
-            public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
-                    CancellationSignal cancellationSignal, LayoutResultCallback callback,
-                    Bundle extras) {
-                callback.onLayoutFinished((new PrintDocumentInfo.Builder("doc")).build(),
-                        !newAttributes.equals(printAttributesRef[0]));
-
-                synchronized (printAttributesRef) {
-                    printAttributesRef[0] = newAttributes;
-                    printAttributesRef.notifyAll();
-                }
-            }
-
-            @Override
-            public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
-                    CancellationSignal cancellationSignal, WriteResultCallback callback) {
-                try {
-                    try {
-                        PrintedPdfDocument document = new PrintedPdfDocument(getActivity(),
-                                printAttributesRef[0]);
-                        try {
-                            PdfDocument.Page page = document.startPage(0);
-                            document.finishPage(page);
-                            try (FileOutputStream os = new FileOutputStream(
-                                    destination.getFileDescriptor())) {
-                                document.writeTo(os);
-                                os.flush();
-                            }
-                        } finally {
-                            document.close();
-                        }
-                    } finally {
-                        destination.close();
-                    }
-
-                    callback.onWriteFinished(pages);
-                } catch (IOException e) {
-                    callback.onWriteFailed(e.getMessage());
-                }
-            }
-        }, null);
-    }
-
-    @Test
-    @LargeTest
-    public void addAndSelectPrinter() throws Exception {
-        final StubbablePrinterDiscoverySession session[] = new StubbablePrinterDiscoverySession[1];
-        final PrintAttributes printAttributes[] = new PrintAttributes[1];
-
-        setMockPrintServiceCallbacks(session);
-        print(printAttributes);
-
-        // We are now in the PrintActivity
-        Log.i(LOG_TAG, "Waiting for session");
-        synchronized (session) {
-            waitWithTimeout(() -> session[0] == null, session::wait);
-        }
-
-        setPrinter("1st printer");
-
-        Log.i(LOG_TAG, "Waiting for print attributes to change");
-        synchronized (printAttributes) {
-            waitWithTimeout(
-                    () -> printAttributes[0] == null || !printAttributes[0].getMediaSize().equals(
-                            PrintAttributes.MediaSize.ISO_A0), printAttributes::wait);
-        }
-
-        setPrinter("All printers\u2026");
-
-        // We are now in the SelectPrinterActivity
-        clickOnText("Add printer");
-
-        // We are now in the AddPrinterActivity
-        AddPrintersActivity.addObserver(
-                () -> addPrinter(session[0], "2nd printer", PrintAttributes.MediaSize.ISO_A1));
-
-        // This executes the observer registered above
-        clickOn(new UiSelector().text(MockPrintService.class.getCanonicalName())
-                        .resourceId("com.android.printspooler:id/title"));
-
-        getUiDevice().pressBack();
-        AddPrintersActivity.clearObservers();
-
-        // We are now in the SelectPrinterActivity
-        clickOnText("2nd printer");
-
-        // We are now in the PrintActivity
-        Log.i(LOG_TAG, "Waiting for print attributes to change");
-        synchronized (printAttributes) {
-            waitWithTimeout(
-                    () -> printAttributes[0] == null || !printAttributes[0].getMediaSize().equals(
-                            PrintAttributes.MediaSize.ISO_A1), printAttributes::wait);
-        }
-
-        getUiDevice().pressBack();
-
-        // We are back in the test activity
-        Log.i(LOG_TAG, "Waiting for session to end");
-        synchronized (session) {
-            waitWithTimeout(() -> session[0] != null, session::wait);
-        }
-    }
-
-    @Test
-    @LargeTest
-    public void abortSelectingPrinter() throws Exception {
-        final StubbablePrinterDiscoverySession session[] = new StubbablePrinterDiscoverySession[1];
-        final PrintAttributes printAttributes[] = new PrintAttributes[1];
-
-        setMockPrintServiceCallbacks(session);
-        print(printAttributes);
-
-        // We are now in the PrintActivity
-        Log.i(LOG_TAG, "Waiting for session");
-        synchronized (session) {
-            waitWithTimeout(() -> session[0] == null, session::wait);
-        }
-
-        setPrinter("1st printer");
-
-        Log.i(LOG_TAG, "Waiting for print attributes to change");
-        synchronized (printAttributes) {
-            waitWithTimeout(
-                    () -> printAttributes[0] == null || !printAttributes[0].getMediaSize().equals(
-                            PrintAttributes.MediaSize.ISO_A0), printAttributes::wait);
-        }
-
-        setPrinter("All printers\u2026");
-
-        // We are now in the SelectPrinterActivity
-        clickOnText("Add printer");
-
-        // We are now in the AddPrinterActivity
-        AddPrintersActivity.addObserver(
-                () -> addPrinter(session[0], "2nd printer", PrintAttributes.MediaSize.ISO_A1));
-
-        // This executes the observer registered above
-        clickOn(new UiSelector().text(MockPrintService.class.getCanonicalName())
-                .resourceId("com.android.printspooler:id/title"));
-
-        getUiDevice().pressBack();
-        AddPrintersActivity.clearObservers();
-
-        // Do not select a new printer, just press back
-        getUiDevice().pressBack();
-
-        // We are now in the PrintActivity
-        // The media size should not change
-        Log.i(LOG_TAG, "Make sure print attributes did not change");
-        Thread.sleep(100);
-        assertEquals(PrintAttributes.MediaSize.ISO_A0, printAttributes[0].getMediaSize());
-
-        getUiDevice().pressBack();
-
-        // We are back in the test activity
-        Log.i(LOG_TAG, "Waiting for session to end");
-        synchronized (session) {
-            waitWithTimeout(() -> session[0] != null, session::wait);
-        }
-    }
-}
diff --git a/core/tests/coretests/src/android/provider/DocumentsProviderTest.java b/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
new file mode 100644
index 0000000..0b4675c
--- /dev/null
+++ b/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.provider;
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.provider.DocumentsContract.Path;
+import android.support.test.filters.SmallTest;
+import android.test.ProviderTestCase2;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Unit tests for {@link DocumentsProvider}.
+ */
+@SmallTest
+public class DocumentsProviderTest extends ProviderTestCase2<TestDocumentsProvider> {
+
+    private static final String ROOT_ID = "rootId";
+    private static final String DOCUMENT_ID = "docId";
+    private static final String PARENT_DOCUMENT_ID = "parentDocId";
+    private static final String ANCESTOR_DOCUMENT_ID = "ancestorDocId";
+
+    private TestDocumentsProvider mProvider;
+
+    private ContentResolver mResolver;
+
+    public DocumentsProviderTest() {
+        super(TestDocumentsProvider.class, TestDocumentsProvider.AUTHORITY);
+    }
+
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mProvider = getProvider();
+        mResolver = getMockContentResolver();
+    }
+
+    public void testFindPath_docUri() throws Exception {
+        final Path expected = new Path(ROOT_ID, Arrays.asList(PARENT_DOCUMENT_ID, DOCUMENT_ID));
+        mProvider.nextPath = expected;
+
+        final Uri docUri =
+                DocumentsContract.buildDocumentUri(TestDocumentsProvider.AUTHORITY, DOCUMENT_ID);
+        try (ContentProviderClient client =
+                     mResolver.acquireUnstableContentProviderClient(docUri)) {
+            final Path actual = DocumentsContract.findPath(client, docUri);
+            assertEquals(expected, actual);
+        }
+    }
+
+    public void testFindPath_treeUri() throws Exception {
+        mProvider.nextIsChildDocument = true;
+
+        final Path expected = new Path(null, Arrays.asList(PARENT_DOCUMENT_ID, DOCUMENT_ID));
+        mProvider.nextPath = expected;
+
+        final Uri docUri = buildTreeDocumentUri(
+                TestDocumentsProvider.AUTHORITY, PARENT_DOCUMENT_ID, DOCUMENT_ID);
+        final List<String> actual = DocumentsContract.findPath(mResolver, docUri);
+
+        assertEquals(expected.getPath(), actual);
+    }
+
+    public void testFindPath_treeUri_throwsOnNonChildDocument() throws Exception {
+        mProvider.nextPath = new Path(null, Arrays.asList(PARENT_DOCUMENT_ID, DOCUMENT_ID));
+
+        final Uri docUri = buildTreeDocumentUri(
+                TestDocumentsProvider.AUTHORITY, PARENT_DOCUMENT_ID, DOCUMENT_ID);
+        assertNull(DocumentsContract.findPath(mResolver, docUri));
+    }
+
+    public void testFindPath_treeUri_throwsOnNonNullRootId() throws Exception {
+        mProvider.nextIsChildDocument = true;
+
+        mProvider.nextPath = new Path(ROOT_ID, Arrays.asList(PARENT_DOCUMENT_ID, DOCUMENT_ID));
+
+        final Uri docUri = buildTreeDocumentUri(
+                TestDocumentsProvider.AUTHORITY, PARENT_DOCUMENT_ID, DOCUMENT_ID);
+        assertNull(DocumentsContract.findPath(mResolver, docUri));
+    }
+
+    public void testFindPath_treeUri_throwsOnDifferentParentDocId() throws Exception {
+        mProvider.nextIsChildDocument = true;
+
+        mProvider.nextPath = new Path(
+                null, Arrays.asList(ANCESTOR_DOCUMENT_ID, PARENT_DOCUMENT_ID, DOCUMENT_ID));
+
+        final Uri docUri = buildTreeDocumentUri(
+                TestDocumentsProvider.AUTHORITY, PARENT_DOCUMENT_ID, DOCUMENT_ID);
+        assertNull(DocumentsContract.findPath(mResolver, docUri));
+    }
+
+    private static Uri buildTreeDocumentUri(String authority, String parentDocId, String docId) {
+        final Uri treeUri = DocumentsContract.buildTreeDocumentUri(authority, parentDocId);
+        return DocumentsContract.buildDocumentUriUsingTree(treeUri, docId);
+    }
+}
diff --git a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
new file mode 100644
index 0000000..8dcf566
--- /dev/null
+++ b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
@@ -0,0 +1,125 @@
+/*
+ * 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.provider;
+
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.CancellationSignal;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Path;
+
+import org.mockito.Mockito;
+
+import java.io.FileNotFoundException;
+
+/**
+ * Provides a test double of {@link DocumentsProvider}.
+ */
+public class TestDocumentsProvider extends DocumentsProvider {
+    public static final String AUTHORITY = "android.provider.TestDocumentsProvider";
+
+    public Path nextPath;
+
+    public boolean nextIsChildDocument;
+
+    public String lastDocumentId;
+    public String lastParentDocumentId;
+
+    @Override
+    public void attachInfoForTesting(Context context, ProviderInfo info) {
+        context = new TestContext(context);
+        super.attachInfoForTesting(context, info);
+    }
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
+        return null;
+    }
+
+    @Override
+    public Cursor queryDocument(String documentId, String[] projection)
+            throws FileNotFoundException {
+        return null;
+    }
+
+    @Override
+    public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
+            String sortOrder) throws FileNotFoundException {
+        return null;
+    }
+
+    @Override
+    public ParcelFileDescriptor openDocument(String documentId, String mode,
+            CancellationSignal signal) throws FileNotFoundException {
+        return null;
+    }
+
+    @Override
+    public boolean isChildDocument(String parentDocumentId, String documentId) {
+        return nextIsChildDocument;
+    }
+
+    @Override
+    public Path findPath(String documentId, @Nullable String parentDocumentId) {
+        lastDocumentId = documentId;
+        lastParentDocumentId = parentDocumentId;
+
+        return nextPath;
+    }
+
+    @Override
+    protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken) {
+        return AppOpsManager.MODE_ALLOWED;
+    }
+
+    @Override
+    protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken) {
+        return AppOpsManager.MODE_ALLOWED;
+    }
+
+    private static class TestContext extends ContextWrapper {
+
+        private TestContext(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void enforceCallingPermission(String permission, String message) {
+            // Always granted
+        }
+
+        @Override
+        public Object getSystemService(String name) {
+            if (Context.APP_OPS_SERVICE.equals(name)) {
+                return Mockito.mock(AppOpsManager.class);
+            }
+
+            return super.getSystemService(name);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/util/LocalLogTest.java b/core/tests/coretests/src/android/util/LocalLogTest.java
new file mode 100644
index 0000000..a63c8a0
--- /dev/null
+++ b/core/tests/coretests/src/android/util/LocalLogTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.util;
+
+import junit.framework.TestCase;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+
+public class LocalLogTest extends TestCase {
+
+    public void testA() {
+        String[] lines = {
+            "foo",
+            "bar",
+            "baz"
+        };
+        String[] want = lines;
+        testcase(new LocalLog(10), lines, want);
+    }
+
+    public void testB() {
+        String[] lines = {
+            "foo",
+            "bar",
+            "baz"
+        };
+        String[] want = {};
+        testcase(new LocalLog(0), lines, want);
+    }
+
+    public void testC() {
+        String[] lines = {
+            "dropped",
+            "dropped",
+            "dropped",
+            "dropped",
+            "dropped",
+            "dropped",
+            "foo",
+            "bar",
+            "baz",
+        };
+        String[] want = {
+            "foo",
+            "bar",
+            "baz",
+        };
+        testcase(new LocalLog(3), lines, want);
+    }
+
+    void testcase(LocalLog logger, String[] input, String[] want) {
+        for (String l : input) {
+            logger.log(l);
+        }
+        verifyAllLines(want, dump(logger).split("\n"));
+        verifyAllLines(reverse(want), reverseDump(logger).split("\n"));
+    }
+
+    void verifyAllLines(String[] wantLines, String[] gotLines) {
+        for (int i = 0; i < wantLines.length; i++) {
+            String want = wantLines[i];
+            String got = gotLines[i];
+            String msg = String.format("%s did not contain %s", quote(got), quote(want));
+            assertTrue(msg, got.contains(want));
+        }
+    }
+
+    static String dump(LocalLog logger) {
+        StringWriter buffer = new StringWriter();
+        PrintWriter writer = new PrintWriter(buffer);
+        logger.dump(null, writer, new String[0]);
+        return buffer.toString();
+    }
+
+    static String reverseDump(LocalLog logger) {
+        StringWriter buffer = new StringWriter();
+        PrintWriter writer = new PrintWriter(buffer);
+        logger.reverseDump(null, writer, new String[0]);
+        return buffer.toString();
+    }
+
+    static String quote(String s) {
+        return '"' + s + '"';
+    }
+
+    static String[] reverse(String[] ary) {
+        List<String> ls = Arrays.asList(ary);
+        Collections.reverse(ls);
+        return  ls.toArray(new String[ary.length]);
+    }
+}
diff --git a/core/tests/coretests/src/android/util/TimeUtilsTest.java b/core/tests/coretests/src/android/util/TimeUtilsTest.java
deleted file mode 100644
index 2370627..0000000
--- a/core/tests/coretests/src/android/util/TimeUtilsTest.java
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.util;
-
-import junit.framework.TestCase;
-
-import java.util.Calendar;
-import java.util.TimeZone;
-
-/**
- * TimeUtilsTest tests the time zone guesser.
- */
-public class TimeUtilsTest extends TestCase {
-    public void testMainstream() throws Exception {
-        String[] mainstream = new String[] {
-            "America/New_York", // Eastern
-            "America/Chicago", // Central
-            "America/Denver", // Mountain
-            "America/Los_Angeles", // Pacific
-            "America/Anchorage", // Alaska
-            "Pacific/Honolulu", // Hawaii, no DST
-        };
-
-        for (String name : mainstream) {
-            TimeZone tz = TimeZone.getTimeZone(name);
-            Calendar c = Calendar.getInstance(tz);
-            TimeZone guess;
-
-            c.set(2008, Calendar.OCTOBER, 20, 12, 00, 00);
-            guess = guess(c, "us");
-            assertEquals(name, guess.getID());
-
-            c.set(2009, Calendar.JANUARY, 20, 12, 00, 00);
-            guess = guess(c, "us");
-            assertEquals(name, guess.getID());
-        }
-    }
-
-    public void testWeird() throws Exception {
-        String[] weird = new String[] {
-            "America/Phoenix", // Mountain, no DST
-            "America/Adak", // Same as Hawaii, but with DST
-        };
-
-        for (String name : weird) {
-            TimeZone tz = TimeZone.getTimeZone(name);
-            Calendar c = Calendar.getInstance(tz);
-            TimeZone guess;
-
-            c.set(2008, Calendar.OCTOBER, 20, 12, 00, 00);
-            guess = guess(c, "us");
-            assertEquals(name, guess.getID());
-        }
-    }
-
-    public void testOld() throws Exception {
-        String[] old = new String[] {
-            "America/Indiana/Indianapolis", // Eastern, formerly no DST
-        };
-
-        for (String name : old) {
-            TimeZone tz = TimeZone.getTimeZone(name);
-            Calendar c = Calendar.getInstance(tz);
-            TimeZone guess;
-
-            c.set(2005, Calendar.OCTOBER, 20, 12, 00, 00);
-            guess = guess(c, "us");
-            assertEquals(name, guess.getID());
-        }
-    }
-
-    public void testWorld() throws Exception {
-        String[] world = new String[] {
-            "ad", "Europe/Andorra",
-            "ae", "Asia/Dubai",
-            "af", "Asia/Kabul",
-            "ag", "America/Antigua",
-            "ai", "America/Anguilla",
-            "al", "Europe/Tirane",
-            "am", "Asia/Yerevan",
-            "an", "America/Curacao",
-            "ao", "Africa/Luanda",
-            "aq", "Antarctica/McMurdo",
-            "aq", "Antarctica/DumontDUrville",
-            "aq", "Antarctica/Casey",
-            "aq", "Antarctica/Davis",
-            "aq", "Antarctica/Mawson",
-            "aq", "Antarctica/Syowa",
-            "aq", "Antarctica/Rothera",
-            "aq", "Antarctica/Palmer",
-            "ar", "America/Argentina/Buenos_Aires",
-            "as", "Pacific/Pago_Pago",
-            "at", "Europe/Vienna",
-            "au", "Australia/Sydney",
-            "au", "Australia/Adelaide",
-            "au", "Australia/Perth",
-            "au", "Australia/Eucla",
-            "aw", "America/Aruba",
-            "ax", "Europe/Mariehamn",
-            "az", "Asia/Baku",
-            "ba", "Europe/Sarajevo",
-            "bb", "America/Barbados",
-            "bd", "Asia/Dhaka",
-            "be", "Europe/Brussels",
-            "bf", "Africa/Ouagadougou",
-            "bg", "Europe/Sofia",
-            "bh", "Asia/Bahrain",
-            "bi", "Africa/Bujumbura",
-            "bj", "Africa/Porto-Novo",
-            "bm", "Atlantic/Bermuda",
-            "bn", "Asia/Brunei",
-            "bo", "America/La_Paz",
-            "br", "America/Noronha",
-            "br", "America/Sao_Paulo",
-            "br", "America/Manaus",
-            "bs", "America/Nassau",
-            "bt", "Asia/Thimphu",
-            "bw", "Africa/Gaborone",
-            "by", "Europe/Minsk",
-            "bz", "America/Belize",
-            "ca", "America/St_Johns",
-            "ca", "America/Halifax",
-            "ca", "America/Toronto",
-            "ca", "America/Winnipeg",
-            "ca", "America/Edmonton",
-            "ca", "America/Vancouver",
-            "cc", "Indian/Cocos",
-            "cd", "Africa/Lubumbashi",
-            "cd", "Africa/Kinshasa",
-            "cf", "Africa/Bangui",
-            "cg", "Africa/Brazzaville",
-            "ch", "Europe/Zurich",
-            "ci", "Africa/Abidjan",
-            "ck", "Pacific/Rarotonga",
-            "cl", "America/Santiago",
-            "cl", "Pacific/Easter",
-            "cm", "Africa/Douala",
-            "cn", "Asia/Shanghai",
-            "co", "America/Bogota",
-            "cr", "America/Costa_Rica",
-            "cu", "America/Havana",
-            "cv", "Atlantic/Cape_Verde",
-            "cx", "Indian/Christmas",
-            "cy", "Asia/Nicosia",
-            "cz", "Europe/Prague",
-            "de", "Europe/Berlin",
-            "dj", "Africa/Djibouti",
-            "dk", "Europe/Copenhagen",
-            "dm", "America/Dominica",
-            "do", "America/Santo_Domingo",
-            "dz", "Africa/Algiers",
-            "ec", "America/Guayaquil",
-            "ec", "Pacific/Galapagos",
-            "ee", "Europe/Tallinn",
-            "eg", "Africa/Cairo",
-            "eh", "Africa/El_Aaiun",
-            "er", "Africa/Asmara",
-            "es", "Europe/Madrid",
-            "es", "Atlantic/Canary",
-            "et", "Africa/Addis_Ababa",
-            "fi", "Europe/Helsinki",
-            "fj", "Pacific/Fiji",
-            "fk", "Atlantic/Stanley",
-            "fm", "Pacific/Ponape",
-            "fm", "Pacific/Truk",
-            "fo", "Atlantic/Faroe",
-            "fr", "Europe/Paris",
-            "ga", "Africa/Libreville",
-            "gb", "Europe/London",
-            "gd", "America/Grenada",
-            "ge", "Asia/Tbilisi",
-            "gf", "America/Cayenne",
-            "gg", "Europe/Guernsey",
-            "gh", "Africa/Accra",
-            "gi", "Europe/Gibraltar",
-            "gl", "America/Danmarkshavn",
-            "gl", "America/Scoresbysund",
-            "gl", "America/Godthab",
-            "gl", "America/Thule",
-            "gm", "Africa/Banjul",
-            "gn", "Africa/Conakry",
-            "gp", "America/Guadeloupe",
-            "gq", "Africa/Malabo",
-            "gr", "Europe/Athens",
-            "gs", "Atlantic/South_Georgia",
-            "gt", "America/Guatemala",
-            "gu", "Pacific/Guam",
-            "gw", "Africa/Bissau",
-            "gy", "America/Guyana",
-            "hk", "Asia/Hong_Kong",
-            "hn", "America/Tegucigalpa",
-            "hr", "Europe/Zagreb",
-            "ht", "America/Port-au-Prince",
-            "hu", "Europe/Budapest",
-            "id", "Asia/Jayapura",
-            "id", "Asia/Makassar",
-            "id", "Asia/Jakarta",
-            "ie", "Europe/Dublin",
-            "il", "Asia/Jerusalem",
-            "im", "Europe/Isle_of_Man",
-            "in", "Asia/Calcutta",
-            "io", "Indian/Chagos",
-            "iq", "Asia/Baghdad",
-            "ir", "Asia/Tehran",
-            "is", "Atlantic/Reykjavik",
-            "it", "Europe/Rome",
-            "je", "Europe/Jersey",
-            "jm", "America/Jamaica",
-            "jo", "Asia/Amman",
-            "jp", "Asia/Tokyo",
-            "ke", "Africa/Nairobi",
-            "kg", "Asia/Bishkek",
-            "kh", "Asia/Phnom_Penh",
-            "ki", "Pacific/Kiritimati",
-            "ki", "Pacific/Enderbury",
-            "ki", "Pacific/Tarawa",
-            "km", "Indian/Comoro",
-            "kn", "America/St_Kitts",
-            "kp", "Asia/Pyongyang",
-            "kr", "Asia/Seoul",
-            "kw", "Asia/Kuwait",
-            "ky", "America/Cayman",
-            "kz", "Asia/Almaty",
-            "kz", "Asia/Aqtau",
-            "la", "Asia/Vientiane",
-            "lb", "Asia/Beirut",
-            "lc", "America/St_Lucia",
-            "li", "Europe/Vaduz",
-            "lk", "Asia/Colombo",
-            "lr", "Africa/Monrovia",
-            "ls", "Africa/Maseru",
-            "lt", "Europe/Vilnius",
-            "lu", "Europe/Luxembourg",
-            "lv", "Europe/Riga",
-            "ly", "Africa/Tripoli",
-            "ma", "Africa/Casablanca",
-            "mc", "Europe/Monaco",
-            "md", "Europe/Chisinau",
-            "me", "Europe/Podgorica",
-            "mg", "Indian/Antananarivo",
-            "mh", "Pacific/Majuro",
-            "mk", "Europe/Skopje",
-            "ml", "Africa/Bamako",
-            "mm", "Asia/Rangoon",
-            "mn", "Asia/Choibalsan",
-            "mn", "Asia/Hovd",
-            "mo", "Asia/Macau",
-            "mp", "Pacific/Saipan",
-            "mq", "America/Martinique",
-            "mr", "Africa/Nouakchott",
-            "ms", "America/Montserrat",
-            "mt", "Europe/Malta",
-            "mu", "Indian/Mauritius",
-            "mv", "Indian/Maldives",
-            "mw", "Africa/Blantyre",
-            "mx", "America/Mexico_City",
-            "mx", "America/Chihuahua",
-            "mx", "America/Tijuana",
-            "my", "Asia/Kuala_Lumpur",
-            "mz", "Africa/Maputo",
-            "na", "Africa/Windhoek",
-            "nc", "Pacific/Noumea",
-            "ne", "Africa/Niamey",
-            "nf", "Pacific/Norfolk",
-            "ng", "Africa/Lagos",
-            "ni", "America/Managua",
-            "nl", "Europe/Amsterdam",
-            "no", "Europe/Oslo",
-            "np", "Asia/Katmandu",
-            "nr", "Pacific/Nauru",
-            "nu", "Pacific/Niue",
-            "nz", "Pacific/Auckland",
-            "nz", "Pacific/Chatham",
-            "om", "Asia/Muscat",
-            "pa", "America/Panama",
-            "pe", "America/Lima",
-            "pf", "Pacific/Gambier",
-            "pf", "Pacific/Marquesas",
-            "pf", "Pacific/Tahiti",
-            "pg", "Pacific/Port_Moresby",
-            "ph", "Asia/Manila",
-            "pk", "Asia/Karachi",
-            "pl", "Europe/Warsaw",
-            "pm", "America/Miquelon",
-            "pn", "Pacific/Pitcairn",
-            "pr", "America/Puerto_Rico",
-            "ps", "Asia/Gaza",
-            "pt", "Europe/Lisbon",
-            "pt", "Atlantic/Azores",
-            "pw", "Pacific/Palau",
-            "py", "America/Asuncion",
-            "qa", "Asia/Qatar",
-            "re", "Indian/Reunion",
-            "ro", "Europe/Bucharest",
-            "rs", "Europe/Belgrade",
-            "ru", "Asia/Kamchatka",
-            "ru", "Asia/Magadan",
-            "ru", "Asia/Vladivostok",
-            "ru", "Asia/Yakutsk",
-            "ru", "Asia/Irkutsk",
-            "ru", "Asia/Krasnoyarsk",
-            "ru", "Asia/Novosibirsk",
-            "ru", "Asia/Yekaterinburg",
-            "ru", "Europe/Samara",
-            "ru", "Europe/Moscow",
-            "ru", "Europe/Kaliningrad",
-            "rw", "Africa/Kigali",
-            "sa", "Asia/Riyadh",
-            "sb", "Pacific/Guadalcanal",
-            "sc", "Indian/Mahe",
-            "sd", "Africa/Khartoum",
-            "se", "Europe/Stockholm",
-            "sg", "Asia/Singapore",
-            "sh", "Atlantic/St_Helena",
-            "si", "Europe/Ljubljana",
-            "sj", "Arctic/Longyearbyen",
-            "sk", "Europe/Bratislava",
-            "sl", "Africa/Freetown",
-            "sm", "Europe/San_Marino",
-            "sn", "Africa/Dakar",
-            "so", "Africa/Mogadishu",
-            "sr", "America/Paramaribo",
-            "st", "Africa/Sao_Tome",
-            "sv", "America/El_Salvador",
-            "sy", "Asia/Damascus",
-            "sz", "Africa/Mbabane",
-            "tc", "America/Grand_Turk",
-            "td", "Africa/Ndjamena",
-            "tf", "Indian/Kerguelen",
-            "tg", "Africa/Lome",
-            "th", "Asia/Bangkok",
-            "tj", "Asia/Dushanbe",
-            "tk", "Pacific/Fakaofo",
-            "tl", "Asia/Dili",
-            "tm", "Asia/Ashgabat",
-            "tn", "Africa/Tunis",
-            "to", "Pacific/Tongatapu",
-            "tr", "Europe/Istanbul",
-            "tt", "America/Port_of_Spain",
-            "tv", "Pacific/Funafuti",
-            "tw", "Asia/Taipei",
-            "tz", "Africa/Dar_es_Salaam",
-            "ua", "Europe/Kiev",
-            "ug", "Africa/Kampala",
-            "um", "Pacific/Wake",
-            "um", "Pacific/Johnston",
-            "um", "Pacific/Midway",
-            "us", "America/New_York",
-            "us", "America/Chicago",
-            "us", "America/Denver",
-            "us", "America/Los_Angeles",
-            "us", "America/Anchorage",
-            "us", "Pacific/Honolulu",
-            "uy", "America/Montevideo",
-            "uz", "Asia/Tashkent",
-            "va", "Europe/Vatican",
-            "vc", "America/St_Vincent",
-            "ve", "America/Caracas",
-            "vg", "America/Tortola",
-            "vi", "America/St_Thomas",
-            "vn", "Asia/Saigon",
-            "vu", "Pacific/Efate",
-            "wf", "Pacific/Wallis",
-            "ws", "Pacific/Apia",
-            "ye", "Asia/Aden",
-            "yt", "Indian/Mayotte",
-            "za", "Africa/Johannesburg",
-            "zm", "Africa/Lusaka",
-            "zw", "Africa/Harare",
-        };
-
-        for (int i = 0; i < world.length; i += 2) {
-            String country = world[i];
-            String name = world[i + 1];
-
-            TimeZone tz = TimeZone.getTimeZone(name);
-            Calendar c = Calendar.getInstance(tz);
-            TimeZone guess;
-
-            c.set(2009, Calendar.JULY, 20, 12, 00, 00);
-            guess = guess(c, country);
-            assertEquals(name, guess.getID());
-
-            c.set(2009, Calendar.JANUARY, 20, 12, 00, 00);
-            guess = guess(c, country);
-            assertEquals(name, guess.getID());
-        }
-    }
-
-    public void testWorldWeird() throws Exception {
-        String[] world = new String[] {
-            // Distinguisable from Sydney only when DST not in effect
-            "au", "Australia/Lord_Howe",
-        };
-
-        for (int i = 0; i < world.length; i += 2) {
-            String country = world[i];
-            String name = world[i + 1];
-
-            TimeZone tz = TimeZone.getTimeZone(name);
-            Calendar c = Calendar.getInstance(tz);
-            TimeZone guess;
-
-            c.set(2009, Calendar.JULY, 20, 12, 00, 00);
-            guess = guess(c, country);
-            assertEquals(name, guess.getID());
-        }
-    }
-
-    private static TimeZone guess(Calendar c, String country) {
-        return TimeUtils.getTimeZone(c.get(c.ZONE_OFFSET) + c.get(c.DST_OFFSET),
-                                     c.get(c.DST_OFFSET) != 0,
-                                     c.getTimeInMillis(),
-                                     country);
-    }
-
-    public void testFormatDuration() {
-        assertFormatDuration("0", 0);
-        assertFormatDuration("-1ms", -1);
-        assertFormatDuration("+1ms", 1);
-        assertFormatDuration("+10ms", 10);
-        assertFormatDuration("+100ms", 100);
-        assertFormatDuration("+101ms", 101);
-        assertFormatDuration("+330ms", 330);
-        assertFormatDuration("+1s0ms", 1000);
-        assertFormatDuration("+1s330ms", 1330);
-        assertFormatDuration("+10s24ms", 10024);
-        assertFormatDuration("+1m0s30ms", 60030);
-        assertFormatDuration("+1h0m0s30ms", 3600030);
-        assertFormatDuration("+1d0h0m0s30ms", 86400030);
-    }
-
-    public void testFormatHugeDuration() {
-        assertFormatDuration("+15542d1h11m11s555ms", 1342833071555L);
-        assertFormatDuration("-15542d1h11m11s555ms", -1342833071555L);
-    }
-
-    private void assertFormatDuration(String expected, long duration) {
-        StringBuilder sb = new StringBuilder();
-        TimeUtils.formatDuration(duration, sb);
-        assertEquals("formatDuration(" + duration + ")", expected, sb.toString());
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/os/DebugTest.java b/core/tests/coretests/src/com/android/internal/os/DebugTest.java
index 88c7d1b..efb78d7 100644
--- a/core/tests/coretests/src/com/android/internal/os/DebugTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/DebugTest.java
@@ -64,4 +64,12 @@
     public void testGetCallers() {
         assertTrue(callDepth1().matches(EXPECTED_GET_CALLERS));
     }
+
+    /**
+     * Regression test for b/31943543. Note: must be run under CheckJNI to detect the issue.
+     */
+    public void testGetMemoryInfo() {
+        Debug.MemoryInfo info = new Debug.MemoryInfo();
+        Debug.getMemoryInfo(-1, info);
+    }
 }
diff --git a/core/tests/systemproperties/Android.mk b/core/tests/systemproperties/Android.mk
index ffc1282..e16c367 100644
--- a/core/tests/systemproperties/Android.mk
+++ b/core/tests/systemproperties/Android.mk
@@ -11,7 +11,6 @@
 LOCAL_STATIC_JAVA_LIBRARIES := android-common frameworks-core-util-lib
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_PACKAGE_NAME := FrameworksCoreSystemPropertiesTests
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 3a993d7..6185dab 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -289,6 +289,8 @@
   to: /design/patterns/app-structure.html
 - from: /guide/practices/ui_guidelines/menu_design.html
   to: /design/patterns/actionbar.html
+- from: /design/patterns/accessibility.html
+  to: https://material.google.com/usability/accessibility.html
 - from: /design/get-started/ui-overview.html
   to: /design/handhelds/index.html
 - from: /design/building-blocks/buttons.html
@@ -806,7 +808,7 @@
 - from: /preview/features/power-mgmt.html
   to: /training/monitoring-device-state/doze-standby.html
 - from: /preview/dev-community
-  to: https://plus.google.com/communities/103655397235276743411
+  to: https://plus.google.com/communities/105153134372062985968
 - from: /preview/bug
   to: https://source.android.com/source/report-bugs.html
 - from: /preview/bug/...
diff --git a/docs/html/about/versions/_project.yaml b/docs/html/about/versions/_project.yaml
new file mode 100644
index 0000000..3f0e85e
--- /dev/null
+++ b/docs/html/about/versions/_project.yaml
@@ -0,0 +1,6 @@
+name: "Versions"
+home_url: /about/versions/
+description: "Android, the world's most popular mobile platform"
+content_license: cc3-apache2
+buganizer_id: 30209417
+parent_project_metadata_path: /about/_project.yaml
diff --git a/docs/html/about/versions/nougat/android-7.0-samples.jd b/docs/html/about/versions/nougat/android-7.0-samples.jd
index e283a7a..ff63bef 100644
--- a/docs/html/about/versions/nougat/android-7.0-samples.jd
+++ b/docs/html/about/versions/nougat/android-7.0-samples.jd
@@ -6,7 +6,7 @@
 
 <p>
   Use the code samples below to learn about Android 7.0 capabilities and APIs. To
-  download the samples in Android Studio, select the <b>File &gt; Import
+  download the samples in Android Studio, select the <b>File &gt; New &gt; Import
   Samples</b> menu option.
 </p>
 
diff --git a/docs/html/auto/_project.yaml b/docs/html/auto/_project.yaml
new file mode 100644
index 0000000..fc4ab2b
--- /dev/null
+++ b/docs/html/auto/_project.yaml
@@ -0,0 +1,6 @@
+name: "Auto"
+home_url: /auto/
+description: "Let drivers listen to and control content in your music and other audio apps."
+content_license: cc3-apache2
+buganizer_id: 30209417
+parent_project_metadata_path: /about/_project.yaml
diff --git a/docs/html/design/_book.yaml b/docs/html/design/_book.yaml
index 18b4719..8ffa9a4 100644
--- a/docs/html/design/_book.yaml
+++ b/docs/html/design/_book.yaml
@@ -117,8 +117,6 @@
     path: /design/patterns/pure-android.html
   - title: Compatibility
     path: /design/patterns/compatibility.html
-  - title: Accessibility
-    path: /design/patterns/accessibility.html
   - title: Help
     path: /design/patterns/help.html
 
diff --git a/docs/html/design/patterns/accessibility.jd b/docs/html/design/patterns/accessibility.jd
deleted file mode 100644
index b910294..0000000
--- a/docs/html/design/patterns/accessibility.jd
+++ /dev/null
@@ -1,98 +0,0 @@
-page.title=Accessibility
-page.tags="accessibility","navigation","input"
-page.metaDescription=Design an app that's universally accessible to people with visual impairment, color deficiency, hearing loss, and limited dexterity.
-@jd:body
-
-<a class="notice-designers-material"
-  href="http://www.google.com/design/spec/usability/accessibility.html">
-  <div>
-    <h3>Material Design</h3>
-    <p>Accessibility<p>
-  </div>
-</a>
-
-<a class="notice-developers" href="{@docRoot}training/accessibility/index.html">
-  <div>
-    <h3>Developer Docs</h3>
-    <p>Implementing Accessibility</p>
-  </div>
-</a>
-
-<p>One of Android's missions is to organize the world's information and make it universally accessible and useful. Accessibility is the measure of how successfully a product can be used by people with varying abilities. Our mission applies to all users-including people with disabilities such as visual impairment, color deficiency, hearing loss, and limited dexterity.</p>
-<p><a href="https://www.google.com/#hl=en&q=universal+design&fp=1">Universal design</a> is the practice of making products that are inherently accessible to all users, regardless of ability. The Android design patterns were created in accordance with universal design principles, and following them will help your app meet basic usability standards. Adhering to universal design and enabling Android's accessibility tools will make your app as accessible as possible.</p>
-<p>Robust support for accessibility will increase your app's user base. It may also be required for adoption by some organizations.</p>
-<p><a href="http://www.google.com/accessibility/">Learn more about Google and accessibility.</a></p>
-
-<h2 id="tools">Android's Accessibility Tools</h2>
-<p>Android includes several features that support access for users with visual impairments; they don't require drastic visual changes to your app.</p>
-
-<ul>
-  <li><strong><a href="https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback">TalkBack</a></strong> is a pre-installed screen reader service provided by Google. It uses spoken feedback to describe the results of actions such as launching an app, and events such as notifications.</li>
-  <li><strong>Explore by Touch</strong> is a system feature that works with TalkBack, allowing you to touch your device's screen and hear what's under your finger via spoken feedback. This feature is helpful to users with low vision.</li>
-  <li><strong>Accessibility settings</strong> let you modify your device's display and sound options, such as increasing the text size, changing the speed at which text is spoken, and more.</li>
-</ul>
-
-<p>Some users use hardware or software directional controllers (such as a D-pad, trackball, keyboard) to jump from selection to selection on a screen. They interact with the structure of your app in a linear fashion, similar to 4-way remote control navigation on a television.</p>
-
-<h2 id="tools">Guidelines</h2>
-<p>The Android design principle "I should always know where I am" is key for accessibility concerns. As a user navigates through an application, they need feedback and a mental model of where they are. All users benefit from a strong sense of information hierarchy and an architecture that makes sense. Most users benefit from visual and haptic feedback during their navigation (such as labels, colors, icons, touch feedback) Low vision users benefit from explicit verbal descriptions and large visuals with high contrast.</p>
-<p>As you design your app, think about the labels and notations needed to navigate your app by sound. When using Explore by Touch, the user enables an invisible but audible layer of structure in your application. Like any other aspect of app design, this structure can be simple, elegant, and robust. The following are Android's recommended guidelines to enable effective navigation for all users.</p>
-
-<h4>Make navigation intuitive</h4>
-<p>Design well-defined, clear task flows with minimal navigation steps, especially for major user tasks. Make sure those tasks are navigable via focus controls. </p>
-
-<h4>Use recommended touch target sizes</h4>
-<p>48 dp is the recommended touch target size for on screen elements. Read about <a href="{@docRoot}design/style/metrics-grids.html">Android Metrics and Grids</a> to learn about implementation strategies to help most of your users. For certain users, it may be appropriate to use larger touch targets. An example of this is educational apps, where buttons larger than the minimum recommendations are appropriate for children with developing motor skills and people with manual dexterity challenges.</p>
-
-
-<h4>Label visual UI elements meaningfully</h4>
-<p>In your wireframes, <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#label-ui">label functional UI components</a> that have no visible text. Those components might be buttons, icons, tabs with icons, and icons with state (like stars). Developers can use the <code><a href="{@docRoot}guide/topics/ui/accessibility/apps.html#label-ui">contentDescription</a></code> attribute to set the label.</p>
-
-<div class ="cols">
-    <div class="col-8">
-      <img src="{@docRoot}design/media/accessibility_contentdesc.png">
-    </div>
-    <div class="col-5 with-callouts">
-      <ol>
-        <li class="value-1">group</li>
-        <li class="value-2">all contacts</li>
-        <li class="value-3">favorites</li>
-        <li class="value-4">search</li>
-        <li class="value-5">action overflow button</li>
-        <li class="value-6">
-          <em>when starred:</em> remove from favorites </br>
-          <em>when not starred:</em> add to favorties</li>
-        <li class="value-7">action overflow button</li>
-        <li class="value-8">text message</li>
-      </ol>
-  </div>
-</div>
-
-<h4>Provide alternatives to affordances that time out</h4>
-<p>Your app may have icons or controls that disappear after a certain amount of time. For example, five seconds after starting a video, playback controls may fade from the screen.</p>
-
-<p>Due to the way that TalkBack works, those controls are not read out loud unless they are focused on. If they fade out from the screen quickly, your user may not even be aware that they are available. Therefore, make sure that you are not relying on timed out controls for high priority task flows. (This is a good universal design guideline too.) If the controls enable an important function, make sure that the user can turn on the controls again and/or their function is duplicated elsewhere. You can also change the behavior of your app when accessibility services are turned on. Your developer may be able to make sure that timed-out controls won't disappear.</p>
-
-<h4>Use standard framework controls or enable TalkBack for custom controls</h4>
-<p>Standard Android framework controls work automatically with accessibility services and have ContentDescriptions built in by default.</p>
-
-<p>An oft-overlooked system control is font size. Users can turn on a system-wide large font size in Settings; using the default system font size in your application will enable the user's preferences in your app as well. To enable system font size in your app, mark text and their associated containers to be measured in <a href="{@docRoot}guide/practices/screens_support.html#screen-independence">scale pixels</a>.</p>
-
-<p>Also, keep in mind that when users have large fonts enabled or speak a different language than you, their type might be larger than the space you've allotted for it. Read <a href="{@docRoot}design/style/devices-displays.html">Devices and Displays</a> and <a href="http://developer.android.com/guide/practices/screens_support.html">Supporting Multiple Screens</a> for design strategies.</p>
-
-<p>If you use custom controls, Android has the developer tools in place to allow adherence to the above guidelines and provide meaningful descriptions about the UI. Provide adequate notation on your wireframes and direct your developer to the <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#custom-views">Custom Views</a> documentation.</p>
-
-<h4>Try it out yourself</h4>
-<p>Turn on the TalkBack service in <strong>Settings > Accessibility</strong> and navigate your application using directional controls or eyes-free navigation.</p>
-
-
-
-<h2>Checklist</h2>
-<ul>
-  <li>Make navigation intuitive</li>
-  <li>Use recommended touch target sizes</li>
-  <li>Label visual UI elements meaningfully</li>
-  <li>Provide alternatives to affordances that time out</li>
-  <li>Use standard framework controls or enable TalkBack for custom controls</li>
-  <li>Try it out yourself</li>
-</ul>
diff --git a/docs/html/distribute/stories/apps.jd b/docs/html/distribute/stories/apps.jd
index 76e9f5a..47f4f7f 100644
--- a/docs/html/distribute/stories/apps.jd
+++ b/docs/html/distribute/stories/apps.jd
@@ -25,8 +25,7 @@
   <h2 class="norule">Articles</h2>
 
   <div class="resource-widget resource-flow-layout col-16"
-      data-query="type:distribute+tag:developerstory+tag:apps"
-      data-sortOrder="-timestamp"
+      data-query="collection:distribute/stories/apps/docs"
       data-cardSizes="6x6"
       data-items-per-page="15"
       data-initial-results="6"></div>
diff --git a/docs/html/distribute/stories/apps/condenast-shopping.jd b/docs/html/distribute/stories/apps/condenast-shopping.jd
new file mode 100644
index 0000000..37c2b1f
--- /dev/null
+++ b/docs/html/distribute/stories/apps/condenast-shopping.jd
@@ -0,0 +1,76 @@
+page.title=Glamour.de Connects Offline and Online Shopping Experiences with Google Play Billing
+page.metaDescription=Cond&eacute; Nast improves features on its Glamour app.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/glamour.png
+page.timestamp=null
+
+@jd:body
+
+
+<h3>Background</h3>
+
+<div class="figure">
+  <img src="{@docRoot}images/distribute/stories/glamour-icon.png" />
+</div>
+
+<p>
+  Glamour is one of the main
+  <a class="external-link"
+  href="https://play.google.com/store/apps/developer?id=Cond%C3%A9%20Nast%20Verlag%20GmbH&hl=en">
+  Cond&eacute; Nast</a> traditional brands. Every year, Glamour hosts a
+  successful shopping event called
+  <a class="external-link"
+  href="https://play.google.com/store/apps/details?id=de.glamour.android&e=-EnableAppDetailsPageRedesign">
+  <em>GLAMOUR Shopping-Week</em></a> in Germany, Austria, and Switzerland.
+  This event has always been print-focused, as readers received a shopping
+  card with the magazine to redeem discounts in selected shops, both offline
+  and online, for one week.
+</p>
+
+<p>
+  In March 2016, Glamour digitized this experience.
+</p>
+
+<h3>What they did</h3>
+
+<p>
+  To make the most of <em>GLAMOUR Shopping-Week</em>, Cond&eacute; Nast relaunched the
+  <a class="external-link"
+  href="https://play.google.com/store/apps/details?id=de.condenast.glamourde&e=-EnableAppDetailsPageRedesign">
+  GLAMOUR app</a> with a more appealing design and an improved user experience:
+<ul>
+  <li>The main features updated for the shopping week included a shop finder, online offers, and
+      a digital shopping card.</li>
+  <li>The current e-paper magazine was made available through the app and sold via Google Play
+      Billing.</li>
+  <li>They offered readers the in-app purchase of digital shopping cards and activation codes
+      through Google Play Billing. Readers can activate digital shopping cards via in-app
+      purchases or with the print shopping card activation code.</li>
+  <li>The online and offline shopping experience was also supported by online shopping discount
+      codes in the app or offline through the shop finder.</li>
+</ul>
+</p>
+
+<h3>Results</h3>
+
+<p>
+  The offline and online combination resulted in positive engagement both in terms of app
+  installs and sales:
+<ul>
+  <li>There were 130,000 new app downloads, and 100,000 users enabled location access to use
+      the shop finder.</li>
+  <li><strong>Sessions increased by 140%</strong> compared to previous weeks. Session length
+      doubled and <strong>the number of active users grew by five times</strong>.</li>
+  <li>12,000 in-app purchases were generated, increasing general e-paper sales by six times,
+      which resulted in <strong>an increase in total magazine circulation</strong>.</li>
+  <li>The digital shopping card was shown more than 200,000 times to redeem offers in shops.</li>
+</ul>
+</p>
+
+<h3>Get started</h3>
+
+<p>
+  Find out more about
+  <a href="https://developer.android.com/google/play/billing/billing_overview.html">
+  in-app purchases</a>.
+</p>
\ No newline at end of file
diff --git a/docs/html/distribute/stories/apps/drupe-communications.jd b/docs/html/distribute/stories/apps/drupe-communications.jd
new file mode 100644
index 0000000..4284077
--- /dev/null
+++ b/docs/html/distribute/stories/apps/drupe-communications.jd
@@ -0,0 +1,98 @@
+page.title=drupe Launches Android First and Finds Global Success with Beta Testing
+page.metaDescription=Drupe uses beta testing to increase its global reach.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/drupe.jpg
+page.timestamp=1468901832
+
+@jd:body
+
+<div class="figure">
+  <img src="{@docRoot}images/distribute/stories/drupe-icon.png" />
+</div>
+
+<h3>
+  Background
+</h3>
+
+<p>
+  In 2015, <a class="external-link" href=
+  "https://play.google.com/store/apps/dev?id=8486231504544197967">
+  drupe mobile</a>, founded by Assaf Ziv and Barak Witkowski, launched the
+  <a class="external-link" href=
+  "https://play.google.com/store/apps/details?id=mobi.drupe.app">drupe app</a>
+  on Android first. With a unique, people-first approach, their communications
+  app is focused on reinventing the way people use their phone to do basic
+  actions. By constantly improving and expanding their cross-app
+  functionality, the app is used globally and was recently awarded Google
+  Play’s Editor’s Choice recognition.
+</p>
+
+<h3>
+  What they did
+</h3>
+
+<dl>
+  <dt><strong>Android openness</strong></dt>
+  <dd>From the start, drupe knew Android was their ideal mobile platform.
+  <em>"Thanks to the openness of the system, we can build a truly native
+  experience on Android. The real way to supply a people-centric experience
+  requires such an openness, not always existing on other platforms,"</em>
+  said Barak Witkowski, co-founder and CEO of drupe. Key to their innovative
+  approach, drupe uses the current context of the user to show them the
+  right contacts and actions to optimize the drupe experience.</dd>
+
+<div class="figure">
+  <img src="{@docRoot}images/distribute/stories/drupe-screenshot.png">
+</div>
+
+  <dt><strong>Beta testing</strong></dt>
+  <dd>They have a large community of 20,000 <em>druper</em> beta users on
+  Android, which has been critical to their success. To minimize risk and seek
+  feedback from valued users, the team built beta testing into their regular
+  development process. By having a dialogue with users worldwide, they are able
+  to gauge interest in new app versions, collect feature requests, and more.
+  This has helped the team achieve a 99.7% crash-free user ratio, as well
+  as verify new versions in real-life scenarios, on various devices, before
+  full launch.</dd>
+
+  <dt><strong>Going global</strong></dt>
+  <dd>With initial focus on building a high quality app, drupe then set out
+  to take advantage of Android’s global scale. Key to their international
+  growth, the app is now translated in 17 languages, and the store listing
+  page is available in 28 languages. This led to an increase in conversion
+  and retention rates. Additionally, when entering India, the team noticed
+  several user reviews requesting integration with a specific messaging app
+  widely used in the Indian market. Through a combination of this integration,
+  adding Hindi language translation, and other new features, drupe saw improved
+  performance. In six months, <strong>daily active users increased 300%, and
+  actions per average daily user increased 25% in the Indian
+  market</strong>.</dd>
+</dl>
+
+<h3>
+  Results
+</h3>
+
+<p>
+  Drupe’s focus on innovation and building a truly contextual and intuitive
+  app proved to be a model of success for attaining growth in both engagement
+  and new global reach. The team has continued to increase its relevance
+  through feedback loops and feature adoptions. <strong>This has led to 700%
+  growth in daily active users, and 550% growth in number of interactions
+  triggered via drupe</strong> in the past six months. The team is focused on
+  enhancing their recommendation engine to add even more contextual abilities
+  for their users while continuing to grow a successful business on Google
+  Play.
+</p>
+
+<h3>
+  Get started
+</h3>
+
+<p>
+  Learn more about
+  <a href="{@docRoot}distribute/engage/beta.html">beta testing</a>
+  and find out how to
+  <a href="{@docRoot}distribute/tools/localization-checklist.html">
+  localize your app</a> to create a high-quality experience for global users.
+</p>
\ No newline at end of file
diff --git a/docs/html/distribute/stories/apps/economist-espresso.jd b/docs/html/distribute/stories/apps/economist-espresso.jd
new file mode 100644
index 0000000..441393b
--- /dev/null
+++ b/docs/html/distribute/stories/apps/economist-espresso.jd
@@ -0,0 +1,70 @@
+page.title=The Economist Espresso Increases Ratings by Launching Rating Requests
+page.metaDescription=The Economist improves ratings through user participation.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/economist-espresso.png
+page.timestamp=null
+
+@jd:body
+
+
+<h3>Background</h3>
+
+<div class="figure">
+  <img src="{@docRoot}images/distribute/stories/economist-espresso-icon.png" />
+</div>
+
+<p>
+  <a class="external-link" href="https://play.google.com/store/apps/details?id=uk.co.economist">
+  The Economist</a> launched the
+  <a class="external-link" href="https://play.google.com/store/apps/details?id=com.economist.darwin">
+  Espresso</a> app in November 2014. Espresso offers a morning briefing from the editors of The
+  Economist, six days a week. Delivered to readers’ mobile phones first thing in the morning, it
+  provides an overview of the global agenda for the coming day. It informs readers about what to
+  look out for in business, finance, and politics, and most importantly, what to make of it.
+</p>
+
+<p>
+  While the app received a lot of positive feedback from users on traditional customer support
+  channels, it received less feedback through direct app reviews. The Economist decided to run
+  tests to increase app reviews, resulting in improved ratings.
+
+<h3>What they did</h3>
+
+<p>
+  In April 2016, The Economist began testing to determine if asking for reviews would improve
+  user participation. They introduced rating requests into the app whereby users received a
+  notification asking them to rate the app while using it.
+</p>
+
+<p>
+  They prompted only users who had fully experienced the app, notifying those who had read more
+  than 25 articles after using it for more than a week. The prompt text was branded:
+  <em>Are you enjoying the Economist Espresso?</em> Upon clicking <em>yes</em>, the user was
+  taken to the Google Play store to review and rate the app.
+
+<h3>Results</h3>
+
+<p>
+  By capturing readers’ feedback in the Play store, The Economist was able to share the goodwill
+  and positive sentiment, <strong>further increasing its star rating and the number of app
+  installs</strong>.
+</p>
+
+<p>
+  After just one week following the launch of rating requests, The Espresso app's star rating
+  increased by 5%, with <strong>the average number of ratings received growing 40 times</strong>.
+</p>
+
+<h3>Get started</h3>
+
+<p>
+  Find out more about
+  <a class="external-link" href="https://support.google.com/googleplay/android-developer/answer/138230">
+  ratings and reviews</a>.
+</p>
+
+<p>
+  Get best practices for news publishers in
+  <a class="external-link" href="https://play.google.com/store/books/details/Google_Inc_The_News_Publisher_Playbook_for_Android?id=O7T3CwAAQBAJ&hl=en_GB&e=-EnableAppDetailsPageRedesign">
+  The News Publisher Playbook (for Android development)</a>.
+</p>
\ No newline at end of file
diff --git a/docs/html/distribute/stories/apps/expressen-sports.jd b/docs/html/distribute/stories/apps/expressen-sports.jd
new file mode 100644
index 0000000..b53cb62
--- /dev/null
+++ b/docs/html/distribute/stories/apps/expressen-sports.jd
@@ -0,0 +1,57 @@
+page.title=Expressen Sport App Improves Content Engagement with New Onboarding and Navigation
+page.metaDescription=Expressen enhances their Sport app.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/expressen-sport.png
+page.timestamp=null
+
+@jd:body
+
+
+<h3>Background</h3>
+
+<div class="figure">
+  <img src="{@docRoot}images/distribute/stories/expressen-icon.png" />
+</div>
+
+<p>
+  In January 2016,
+  <a class="external-link" href="https://play.google.com/store/apps/details?id=se.expressen.launcher&hl=en">
+  Expressen</a> launched a new sports app to reach sports enthusiasts directly
+  and to better optimize the app for sports content. They decided to analyze
+  users' behavior by looking at user paths in existing sports content,
+  combined with user research and testing various prototypes with real users.
+  They found that readers have different needs and preferences. For example,
+  some people like a specific sport, league, or player that others have no
+  interest in. Following these results, they integrated two main changes to
+  increase appeal to different types of readers.
+</p>
+
+<h3>What they did</h3>
+
+<p>
+  Expressen introduced a new onboarding flow that allows users to select the
+  type of push notifications they want to subscribe to. They also implemented
+  contextual navigation where the top header navigational links change,
+  showing the most relevant links to the reader at that moment in time. For
+  example, if you're reading about football, relevant links about that sport
+  are displayed.
+</p>
+
+<h3>Results</h3>
+
+<p>
+  After the new release of the app, <strong>results showed a higher opt-in
+  rate for push notifications in the Sport app (+16.9%)</strong> compared to
+  their main app, and content consumption increased +7% for page views and
+  +8.3% for video views.
+</p>
+
+<h3>Get started</h3>
+
+<p>
+  Learn more about the
+  <a href="https://developer.android.com/training/tv/playback/onboarding.html?hl=mk">
+  user onboarding flow</a> and find out how to
+  <a href="https://developer.android.com/design/patterns/navigation.html">
+  implement contextual navigation</a>.
+</p>
\ No newline at end of file
diff --git a/docs/html/distribute/stories/apps/lifesum-health.jd b/docs/html/distribute/stories/apps/lifesum-health.jd
new file mode 100644
index 0000000..2d3f203
--- /dev/null
+++ b/docs/html/distribute/stories/apps/lifesum-health.jd
@@ -0,0 +1,60 @@
+page.title=Lifesum Doubles Retention of Google Fit Users Following Integration on Android
+page.metaDescription=Lifesum integrates Google Fit into their app.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/lifesum.png
+page.timestamp=null
+
+@jd:body
+
+
+<h3>Background</h3>
+
+<div class="figure">
+  <img src="{@docRoot}images/distribute/stories/lifesum-icon.png" />
+</div>
+
+<p>
+  <a class="external-link" href="https://play.google.com/store/apps/details?id=com.sillens.shapeupclub">
+  Lifesum</a> is a health and fitness app from Sweden that was launched on Android in 2012.
+  Since then, the app has had more than five million installs on Android, and Lifesum collaborated
+  with Google for the launch of <a class="external-link" href="http://www.google.com/fit/">
+  Google Fit</a> in 2014. Google Fit soon became a key component of user activity outside the
+  app and has enabled Lifesum to scale partner integrations, accelerate development cycle, and
+  increase user satisfaction and engagement.
+</p>
+
+<h3>What they did</h3>
+
+<p>
+  Lifesum integrated Google Fit APIs to gather more insightful data, leading to a shift in
+  focus from simply gathering large amounts of user data to actual analysis of it. Google Fit has
+  also made direct integrations with partners much easier to scale and sometimes even
+  unnecessary, and has largely reduced app development time. Lifesum used findings from the
+  integration to launch their second app, <em>Movesum</em>, a step-counter app that imports steps
+  and calories and displays the information in a fun way. Thanks to the integration, the app was
+  developed in just two weeks.
+</p>
+
+<h3>Results</h3>
+
+<p>
+  Lifesum’s users now actively request integration with Google Fit, resulting in an improvement
+  in the app's ratings and reviews on the Google Play store. Engagement is also much higher for
+  Google Fit-connected users, whose <strong>retention rate is twice that of other Android
+  users</strong>. User retention on Android is 5-10% better than on other platforms.
+</p>
+
+<p>
+  Joakim Hammer, Android developer at Lifesum, says "Google Fit is our infrastructure for
+  integrating with other apps. It's great for the user as it increases the trustworthiness of the
+  data. Personally, it’s been a great experience leading the integration. The implementation was
+  fast and easy, and it has helped us with everything from product development and user
+  engagement, to partnerships."
+</p>
+
+<h3>Get started</h3>
+
+<p>
+  Find out more about <a class="external-link" href="https://developers.google.com/fit/">
+  The Google Fit SDK</a>.
+</p>
\ No newline at end of file
diff --git a/docs/html/distribute/stories/apps/noom-health.jd b/docs/html/distribute/stories/apps/noom-health.jd
new file mode 100644
index 0000000..c99efac
--- /dev/null
+++ b/docs/html/distribute/stories/apps/noom-health.jd
@@ -0,0 +1,115 @@
+page.title=Noom Grows International Revenue by 80% Through Localization on Google Play
+page.metaDescription=Noom increases revenue by localizing their app.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/noom.jpg
+page.timestamp=1468901832
+
+@jd:body
+
+<div class="figure">
+  <img src="{@docRoot}images/distribute/stories/noom-icon.png" />
+</div>
+
+<h3>
+  Background
+</h3>
+
+<p>
+  With a mission to help people live healthier lives,
+  <a class="external-link" href=
+  "https://play.google.com/store/apps/developer?id=Noom+Inc.">Noom</a> guides
+  their users through behavior change programs to create lifestyle habits and
+  target global health challenges. Available initially on Google Play,
+  Android first and Noom have achieved success expanding to international
+  markets, taking advantage of the broad reach of Android.
+</p>
+
+<h3>
+  What they did
+</h3>
+
+<p>
+  Launching first in the US, Noom created a series of programs tailored to
+  their users’ specific <a class="external-link" href=
+  "https://play.google.com/store/apps/details?id=com.wsl.noom">
+  health goals</a>. Key to their approach is offering a holistic solution,
+  including simple personalized tasks, progress tracking, meal feedback, and
+  support from both personal coaches and peers. The team has a strategic
+  approach to expanding their user base globally. Noom localized their app to
+  better connect with users in the following areas:
+</p>
+
+<ul>
+  <li><strong>Localized product</strong>
+    <ul style="list-style: none;">
+    <li>In addition to translating their app to five languages and their store
+      listing page to 11 languages, Noom conducted extensive analysis to
+      determine the right financial model tailored to each international
+      market. This included evaluation of their competitive landscape and
+      local health and wellness spending behavior, in addition to running
+      pricing experiments to determine the optimal offering between
+      subscriptions, IAPs, or a premium app.</li>
+    </ul>
+  </li>
+
+  <li><strong>Localized cuisines</strong>
+    <ul style="list-style: none;">
+    <li>When Noom started researching the Korean, Japanese, German, and Latin
+      American markets, they immediately focused on localizing their food
+      database. Using a combination of local food editors, existing food
+      databases, and user suggestions, their app now includes local cuisine
+      and popular packaged food brands, offering a simpler and more
+      comprehensive experience for users.</li>
+    </ul>
+  </li>
+
+  <li><strong>Localized coaches</strong>
+    <ul style="list-style: none;">
+    <li>Hiring local coaches not only removed language barriers, but also
+      reduced response times as they are located within the same time zone
+      as their users. Using various notification types, Noom has increased
+      user engagement by three to four times.</li>
+    </ul>
+  </li>
+</ul>
+
+<img src="{@docRoot}images/distribute/stories/noom-screenshot.png">
+  <p class="img-caption">
+  <strong>Figure 1.</strong> German Play Store listing page, Korean recipes,
+  and Japanese meal plan
+  </p>
+
+<h3>
+  Results
+</h3>
+
+<p>
+  <em>"Android's global focus and great localization tooling made the decision
+  to go global much easier. Localization to new markets has been a consistent
+  growth driver at Noom,"</em> said Artem Petakov, co-founder and President
+  at Noom.
+</p>
+
+<p>
+  Over the last three years, Noom’s localization efforts led to an <strong>80%
+  increase in international revenue growth on Android</strong>. In Japan
+  alone, <strong>revenue increased more than 480%</strong> during the same
+  time period. To identify future expansion opportunities, the team looks
+  towards countries with strong Android penetration and install growth
+  using the English product and plans to apply their localization methods to
+  achieve even greater success.
+</p>
+
+<h3>
+  Get started
+</h3>
+
+<p>
+  Learn more about <a class="external-link" href=
+  "https://material.google.com/patterns/notifications.html">Notifications</a>,
+  and find out about
+  <a href="{@docRoot}distribute/tools/localization-checklist.html">
+  app localization</a> and how to
+  <a href="{@docRoot}distribute/users/expand-to-new-markets.html">
+  Expand Into New Markets</a>.
+</p>
\ No newline at end of file
diff --git a/docs/html/distribute/stories/games.jd b/docs/html/distribute/stories/games.jd
index daaac0d..cd31aae 100644
--- a/docs/html/distribute/stories/games.jd
+++ b/docs/html/distribute/stories/games.jd
@@ -25,8 +25,7 @@
   <h2 class="norule">Articles</h2>
 
   <div class="resource-widget resource-flow-layout col-16"
-      data-query="type:distribute+tag:developerstory+tag:games"
-      data-sortOrder="-timestamp"
+      data-query="collection:distribute/stories/games/docs"
       data-cardSizes="6x6"
       data-items-per-page="15"
       data-initial-results="6"></div>
diff --git a/docs/html/distribute/stories/games/animoca-star-girl.jd b/docs/html/distribute/stories/games/animoca-star-girl.jd
new file mode 100644
index 0000000..a38eed2
--- /dev/null
+++ b/docs/html/distribute/stories/games/animoca-star-girl.jd
@@ -0,0 +1,89 @@
+page.title=Star Girl Increases In-App Purchases by 3.5X Through More Flexible Minimum Pricing on Google Play
+page.metaDescription=Star Girl Increases In-App Purchases by 3.5X.
+page.tags="developerstory", "games", "googleplay", "google play"
+page.image=images/cards/distribute/stories/animoca.jpg
+
+@jd:body
+
+<style type="text/css">
+  span.positive{
+    color:green;
+    font-size: 125%;
+    font-weight:bold;">
+  }
+  span.negative{
+    color:red;
+    font-size: 125%;
+    font-weight:bold;">
+  }
+</style>
+
+<h3>Background</h3>
+
+<div class="figure">
+  <img src="{@docRoot}images/distribute/stories/animoca-logo.png" />
+</div>
+
+<p>
+  <a class="external-link"
+  href="https://play.google.com/store/apps/details?id=com.animoca.google.starGirl&hl=en&e=-EnableAppDetailsPageRedesign">
+  Star Girl</a> is a series of SIM/role playing games published by <a class="external-link"
+  href="https://play.google.com/store/apps/dev?id=8271704752057011334&hl=en&e=-EnableAppDetailsPageRedesign">
+  Animoca</a>, a Hong Kong based game developer. The Star Girl series has more than 70 million
+  downloads and is localized in 18 languages. With a fast-growing user base in markets
+  including SEA, India, and Latin America, Animoca is exploring ways to effectively increase
+  monetization with a localized pricing strategy.
+</p>
+
+<h3>What they did</h3>
+
+<p>
+ Following the introduction of
+ <a class="external-link" href="http://android-developers.blogspot.com/2015/11/minimum-purchase-price-for-apps-and-in.html">
+ more flexible minimum pricing</a> in November 2015, Animoca took the opportunity to test
+ sachet pricing models across Thailand, Malaysia, Philippines, Indonesia, Brazil, and Russia:
+</p>
+
+<p>
+ <img src="{@docRoot}images/distribute/stories/animoca-flow.jpg" />
+</p>
+
+<p>
+ Animoca created a new sachet SKU, which offered 100 diamonds and 5,000 coins, at the new lower
+ minimum price available in these markets. The new SKU is approximately 60% cheaper than the
+ previous minimum-priced product and is accessible only through geo-targeted, in-game
+ banners in localized languages.
+</p>
+
+<h3>Results</h3>
+
+<div class="figure">
+ <img src="{@docRoot}images/distribute/stories/animoca-graph.jpg" />
+</div>
+
+<p>
+ The changes to minimum prices across these markets resulted in positive results, with the
+ number of transactions increasing 3.5X in the three months following launch.
+</p>
+
+<p>
+ Also, 90% of these transactions were first-time new buyers, half of which
+ followed up with purchases of regular packages. This helps to create a more sustainable revenue
+ impact, as described by Yusuf Goolamabbas, CTO of Animoca:
+</p>
+
+<p>
+ <em>“Sachet marketing has made IAPs more affordable to users in emerging markets. We are seeing
+ significant growth in new buyers as well as returning buyers and a positive impact on revenue in
+ emerging markets.”</em>
+</p>
+
+<h3>Get started</h3>
+
+<p>
+ <a class="external-link" href="https://support.google.com/googleplay/android-developer/answer/6334373?hl=en-GB">
+ Learn more about flexible minimum pricing</a> and
+ <a class="external-link" href="http://g.co/play/playbook-dac-writtenstudies-evergreen">
+ get the Playbook for Developers app</a> to grow your business and improve
+ monetization with Google Play.
+</p>
\ No newline at end of file
diff --git a/docs/html/distribute/stories/games/happy-labs-experiment.jd b/docs/html/distribute/stories/games/happy-labs-experiment.jd
new file mode 100644
index 0000000..e317e21
--- /dev/null
+++ b/docs/html/distribute/stories/games/happy-labs-experiment.jd
@@ -0,0 +1,105 @@
+page.title=Happy Labs Increases Installs by 32% on Google Play with Store Listing Experiments
+page.metaDescription=Happy Labs Increases Installs by 32%.
+page.tags="developerstory", "games", "googleplay", "google play"
+page.image=images/cards/distribute/stories/happylabs-logo.png
+
+@jd:body
+
+<style type="text/css">
+  span.positive{
+    color:green;
+    font-size: 125%;
+    font-weight:bold;">
+  }
+  span.negative{
+    color:red;
+    font-size: 125%;
+    font-weight:bold;">
+  }
+</style>
+
+<h3>Background</h3>
+
+<div class="figure">
+  <img src="{@docRoot}images/distribute/stories/happylabs-logo.png" />
+</div>
+
+<p>
+  <a class="external-link"
+  href="https://play.google.com/store/apps/dev?id=5211519071117278745&hl=en">
+  Happy Labs</a>, founded in 2012, is a successful game developer in Southeast Asia with 13
+  game titles and over 30 million downloads. Its flagship free-to-play virtual sim game,
+  <a class="external-link"
+  href="https://play.google.com/store/apps/dev?id=5211519071117278745&hl=en">Happy Pet Story</a>,
+  launched in February 2016 and is designed for female gamers of all ages.
+</p>
+
+<p>
+ Following the announcement of Store Listing Experiments in May, Happy Labs decided to test
+ variations of their game icon and screenshots to optimize their store listing.
+</p>
+
+<h3>What they did</h3>
+
+<p>
+ Happy Labs used the Store Listing Experiments feature in the Google Play Developer Console to
+ test three new variations of their new game icon. Encouraged by early results, they then
+ optimized the game screenshots displayed in their store listing.
+</p>
+
+<h3>Results</h3>
+
+<p>
+ The results showed that the new icon, <em>Sweet Bubbles</em> without a frame, outperformed
+ the initial <em>Mojo</em> icon and two other variants, with a 38.6% increase in installs:
+</p>
+
+<p>
+ <img src="{@docRoot}images/distribute/stories/happylabs-happy_pet_icon.png" />
+</p>
+
+<p>
+ Based on these findings, Happy Labs changed the Happy Pet Story icon to the new image globally
+ on Google Play.
+</p>
+
+<p>
+ Following the positive icon testing results, Happy Labs ran global store listing experiments
+ with a combination of screenshots from their store listing over a five week period. They then took
+ their best performing screenshots from the experiments and tested them across three specific
+ countries: Indonesia, Thailand, and Japan. The results showed an average increase of 19.87% in
+ installs.
+</p>
+
+<p>
+ Migrating from the original images to the variants shown in the following figure increased organic
+ installs in Thailand by 13.9%:
+</p>
+
+<p>
+ <img src="{@docRoot}images/distribute/stories/happylabs-variant.png" />
+</p>
+
+<p>
+ With the combination of both store listing experiments, Happy Pet Story saw an average increase of
+ 32% in month-on-month organic daily downloads globally, as described by Jeffrey Chee, CEO of Happy
+ Labs:
+</p>
+
+<p>
+ <em>“Store listing experiments have been an invaluable tool for us in optimizing our Play store
+ presence. I am really happy that we were able to get an uplift of 32% in organic installs with
+ minimal investment in terms of resources.”</em>
+</p>
+
+<h3>Get started</h3>
+
+<p>
+ Learn how to run
+ <a class="external-link" href="https://support.google.com/googleplay/android-developer/answer/6227309">
+ Store Listing Experiments</a> and read our best practices for
+ <a href="https://developer.android.com/distribute/users/experiments.html">
+ running successful experiments</a>. For more best practices on growing your business with Google
+ Play, <a class="external-link" href="http://g.co/play/playbook-dac-writtenstudies-evergreen">
+ get the Playbook for Developers app</a>.
+</p>
\ No newline at end of file
diff --git a/docs/html/distribute/stories/games/playlab-puzzles.jd b/docs/html/distribute/stories/games/playlab-puzzles.jd
new file mode 100644
index 0000000..ef1ccff
--- /dev/null
+++ b/docs/html/distribute/stories/games/playlab-puzzles.jd
@@ -0,0 +1,87 @@
+page.title=Playlab Increases Juice Cubes Conversions by 25% with Store Listing Experiments
+page.metaDescription=Playlab uses store listing experiments to refresh their Juice Cubes icon.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/playlab.jpg
+page.timestamp=1468901832
+
+@jd:body
+
+<div class="figure">
+  <img src="{@docRoot}images/distribute/stories/playlab-icon.png" />
+</div>
+
+<h3>
+  Background
+</h3>
+
+<p>
+  <a class="external-link" href=
+  "https://play.google.com/store/apps/dev?id=9190927840679184784&e=-EnableAppDetailsPageRedesign">
+  Playlab</a> is a game developer and publisher based in Hong Kong, with
+  production studios in Bangkok and Manila. Playlab apps include
+  <a class="external-link" href=
+  "https://play.google.com/store/apps/details?id=ppl.unity.JuiceCubesBeta">
+  Juice Cubes</a>, <a class="external-link" href=
+  "https://play.google.com/store/apps/details?id=ppl.unity.junglecubes">
+  Jungle Cubes</a>, and <a class="external-link" href=
+  "https://play.google.com/store/apps/details?id=ppl.cocos2dx.ranchrun&hl=en">
+  Ranch Run</a>.
+
+  Released in 2013, <a class="external-link" href=
+  "https://play.google.com/store/apps/details?id=ppl.unity.JuiceCubesBeta">
+  Juice Cubes</a> is a strategy puzzle game with over 25 million downloads
+  worldwide and over 100,000 five-star reviews on Google Play. The game has
+  gained success in Southeast Asian markets such as Indonesia and Thailand,
+  and in Western markets such as the US, Australia, the UK, and Canada.
+</p>
+
+<h3>
+  What they did
+</h3>
+
+<p>
+  As part of Juice Cubes’ content update in April 2016, Playlab decided to
+  refresh its Play Store icon and test whether different icons could increase
+  their conversion rate.
+</p>
+
+<p>
+  Playlab used the <em>Store Listing Experiments</em> feature on the Google
+  Play Developer Console to test three variations of their new game icon.
+</p>
+
+<h3>
+  Results
+</h3>
+
+<p>
+  Within three days of running the store listing experiment, Playlab saw
+  positive results which led them to make an informed decision to change the
+  current icon to the best-performing version. Variant C outperformed the
+  initial control icon and the two other variants, with a <strong>25% increase
+  in installs</strong>. One month after applying the best-performing icon,
+  Juice Cubes continued to see a 25% increase in the number of conversions
+  from store visitors who made organic installs.
+</p>
+
+<img src="{@docRoot}images/distribute/stories/playlab-screenshot.png">
+
+<p>
+  <em>"Google Play Store Listing Experiments offer a fast, easy, and free way
+  to do A/B testing on an icon. The data provided after each test helped us
+  to make a decision really quickly. The best part is the team no longer needs
+  so many resources to decide which icon to use because we can let the
+  users decide."</em> said Jakob Lykkegaard, CEO and co-founder of Playlab.
+</p>
+
+<h3>
+  Get started
+</h3>
+
+<p>
+  Learn how to use <a class="external-link" href=
+  "https://support.google.com/googleplay/android-developer/answer/6227309">
+  A/B testing</a> and find out more about how to run
+  <a href="{@docRoot}distribute/users/experiments.html">
+  store listing experiments</a> on Google Play.
+</p>
\ No newline at end of file
diff --git a/docs/html/distribute/stories/index.jd b/docs/html/distribute/stories/index.jd
index 1745535..7d84ce4 100644
--- a/docs/html/distribute/stories/index.jd
+++ b/docs/html/distribute/stories/index.jd
@@ -21,11 +21,11 @@
   <h3 class="norule">Articles</h3>
 
   <div class="resource-widget resource-flow-layout col-16"
-      data-query="type:distribute+tag:developerstory+tag:apps"
-      data-sortOrder="-timestamp"
+      data-query="collection:distribute/stories/apps/docs"
       data-cardSizes="6x6"
       data-items-per-page="15"
       data-initial-results="6"></div>
+
 </div></section>
 
 <section class="dac-section dac-small" id="latest-games"><div class="wrap">
@@ -43,9 +43,9 @@
   <h3 class="norule">Articles</h3>
 
   <div class="resource-widget resource-flow-layout col-16"
-      data-query="type:distribute+tag:developerstory+tag:games"
-      data-sortOrder="-timestamp"
+      data-query="collection:distribute/stories/games/docs"
       data-cardSizes="6x6"
       data-items-per-page="15"
       data-initial-results="6"></div>
+
 </div></section>
diff --git a/docs/html/google/play/billing/billing_admin.jd b/docs/html/google/play/billing/billing_admin.jd
index ad09f1f..9936489 100644
--- a/docs/html/google/play/billing/billing_admin.jd
+++ b/docs/html/google/play/billing/billing_admin.jd
@@ -51,9 +51,9 @@
 listed on an app's product list. Each app has its own product list; you cannot sell
 items that appear on another app's product list.</p>
 
-<p>You can access an app's product list by opening the <strong>In-app Products</strong>
+<p>You can access an app's product list by opening the <em>In-app Products</em>
 page for an app that is listed in your developer account. The link to the
-<strong>In-app Products</strong> page appears only if you have a Google payments merchant
+<em>In-app Products</em> page appears only if you have a Google payments merchant
 account and the app's manifest includes the
 <code>com.android.vending.BILLING</code> permission. For more information about this
 permission, see <a href="{@docRoot}google/play/billing/billing_integrate.html#billing-permission">
@@ -73,7 +73,7 @@
 supported; instead, you must publish it to the alpha or beta distribution
 channel. For more information, see <a
 href="{@docRoot}google/play/billing/billing_testing.html#draft_apps">Draft Apps
-are No Longer Supported</a>.
+are No Longer Supported</a>.</p>
 
 <p>In addition, an app package can have only one product list. If you create a product
 list for an app, and you use the <a
@@ -82,8 +82,8 @@
 associated with the app listing. You cannot create individual product lists for each APK if
 you are using the multiple APK feature.</p>
 
-<p>You can add items to a product list two ways: you can add items one at a time on the <strong>In-app
-Products</strong> page, or you can add a batch of items by importing the items from a
+<p>You can add items to a product list two ways: you can add items one at a time on the <em>In-app
+Products</em> page, or you can add a batch of items by importing the items from a
 comma-separated values (CSV) file. Adding items one at a time is useful if your
 app has only a few in-app items or you are adding only a few items to a
 product list for testing purposes. The CSV file method is useful if your app has a large
@@ -100,14 +100,14 @@
 
 <ol>
   <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</li>
-  <li>In the <strong>All applications</strong> panel, click on the
-  app name, then open the <strong>In-app Products</strong> page.</li>
+  <li>In the <em>All applications</em> panel, click on the
+  app name, then open the <em>In-app Products</em> page.</li>
   <li><p>Click <strong>Add new product</strong>. After you provide the product type and ID for the item you are
   selling, click <strong>Continue</strong>.</p>
   <dl>
       <dt>Product Type</dt>
       <dd>
-        <p>The product type can be <strong>Managed product</strong> or <strong>Subscription</strong>. You cannot
+        <p>The product type can be "Managed product" or "Subscription." You cannot
         change an item's product type after you create the item. For more information, see
         <a href="#billing-purchase-type">Choosing a Product Type</a>.</p>
         <p class="note"><strong>Note: </strong>For subscription items, you cannot change the
@@ -169,7 +169,7 @@
         <p>You can also change prices for other currencies manually, but you can do
           this only if a currency is used in one of the target countries for your
           app. You can specify target countries for your app on the
-          <strong>Pricing &amp; Distribution</strong> page in the Google Play
+          <em>Pricing &amp; Distribution</em> page in the Google Play
           Developer Console.</p>
       </dd>
     </dl>
@@ -187,266 +187,412 @@
 
 <h3 id="billing-bulk-add">Adding a batch of items to a product list</h3>
 
-<p>To add a batch of items to a product list using a CSV file, you first need to create your CSV
-file. The data values that you specify in the CSV file represent the same data values you specify
-manually through the In-app Products UI (see <a href="#billing-form-add">Adding items one at a time
-to a product list</a>).
+<p>To add a batch of items to a product list using a CSV file, you first need to
+create your CSV file. The data values that you specify in the CSV file represent
+the options that you set when adding in-app products to a product list using the
+Google Play Developer Console UI. For more information about using this UI, see
+<a href="#billing-form-add">Adding items one at a time to a product list</a>.
 
-<p>If you are importing and exporting CSV files with in-app products, keep
-country-specific pricing in mind. If you use auto-fill, you can provide a
-tax-exclusive default price, and tax-inclusive prices will be auto-filled. If you
-do not use auto-fill, prices you provide must include tax.</p>
+<p class="note"><strong>Note:</strong> Batch upload of in-app product lists
+containing subscriptions is not supported. Also, when updating existing items in
+a batch upload, you cannot include changes to in-app products that are linked to
+a <a href="#pricing-template">pricing template</a>.</p>
 
-<p class="note"><strong>Note:</strong> Batch upload of product lists containing
-subscriptions is not supported. Also, when updating existing items in a batch
-upload, you cannot include changes to in-app products that are linked to a
-<a href="#pricing-template">pricing template</a>.</p>
-
-<p>To import the items that are specified in your CSV file, do the following:</p>
+<p>To import the in-app products that are specified in your CSV file, do the
+following:</p>
 
 <ol>
-  <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</li>
-  <li>In the <strong>All applications</strong> panel, select the app
-  name, then open the <strong>In-app Products</strong> page.</li>
-  <li>On the In-app Products List page, click <strong>Import/Export</strong>
-  &gt; <strong>Import in-app products from CSV file</strong>, then select your
-  CSV file.
-    <p>The CSV file must be on your local computer or on a local disk that is connected to your
-    computer.</p>
+  <li>
+    <a href="http://play.google.com/apps/publish">Log in</a> to your
+    publisher account.
   </li>
-  <li>Select the <strong>Overwrite</strong> checkbox if you want to overwrite existing items in
-  your product list.
-    <p>This option overwrites values of existing items only if the value of the <em>product_id</em>
-    in the CSV file matches the In-app Product ID for an existing item in the product list.
-    Overwriting doesn't delete items that are on a product list but not present in the CSV
-    file.</p>
+  <li>In the <em>All applications</em> panel, select the app
+  name, then open the <em>In-app Products</em> page.</li>
+  <li>
+    <p>On the <em>In-app Products</em> page, click
+    <strong>Import/Export</strong> &gt; <strong>Import in-app products from CSV
+    file</strong> to open the <em>Import In-app Products</em> dialog.</p>
+  </li>
+  <li>
+    <p>
+      If you want to overwrite existing in-app products in your product list
+      during the import process, select the <strong>Overwrite existing
+      products</strong> checkbox.
+    </p>
+    <p>
+      This option overwrites values of existing items only if the value of the
+      <code>Product ID</code> in the CSV file matches the in-app product ID for
+      an existing in-app product in the product list. The overwriting process
+      doesn't delete in-app products that exist in a product list but aren't
+      included in the CSV file
+    </p>
+    <p class="note"><strong>Note: </strong>If you choose not to overwrite
+    existing items, the <code>Product ID</code> given to each item in the CSV
+    file must be different from any of the <code>Product ID</code> values
+    assigned to existing in-app products.
+    </p>
+  </li>
+  <li>
+    Select <strong>Browse files</strong>, then choose the CSV file that contains
+    the items you want to import. The CSV file must be stored locally.
   </li>
 </ol>
 
-<p>You can also export an existing product list to a CSV file by clicking <strong>Export to CSV
-</strong> on the In-app Product List page. This is useful if you have manually added items to
-a product list and you want to start managing the product list through a CSV file.</p>
+<p>
+  You can also export an existing product list to a CSV file by clicking
+  <strong>Import/Export</strong> &gt; <strong>Export in-app products to CSV file
+  </strong> on the <em>In-app Products page</em>. This is useful if you have
+  used the UI to add in-app products to your app but you want to start managing
+  the product list through a CSV file instead.
+</p>
 
 <h4 id="billing-bulk-format">Formatting batches of items</h4>
 
-<p>The CSV file uses commas (,) and semicolons (;) to separate data values.
-Commas are used to separate primary data values, and semicolons are used to
-separate subvalues. For example, the syntax for the CSV file is as follows:</p>
-
-<p>"<em>product_id</em>","<em>publish_state</em>","<em>purchase_type</em>","<em>autotranslate</em>
-","<em>locale</em>; <em>title</em>; <em>description</em>","<em>autofill</em>","<em>country</em>;
-<em>price</em>", "<em>pricing_template_id</em>"
+<p>
+  The CSV file uses commas (<code>,</code>) and semicolons (<code>;</code>) to
+  separate data values. Commas are used to separate primary data values, and
+  semicolons are used to separate subvalues. Each item must appear entirely on a
+  single line within the CSV file.
+</p>
+<p>
+  When creating a CSV file that represents a list of items, you must specify the
+  CSV syntax on the first row, followed by the items themselves on subsequent
+  rows, as shown in the following example:
 </p>
 
-<p>Descriptions and usage details are provided below.</p>
+<pre class="no-pretty-print">
+Product ID,Published State,Purchase Type,Auto Translate,Locale; Title; Description,Auto Fill Prices,Price,Pricing Template ID
+basic_sleeping_potion,published,managed_by_android,false,en_US; Basic Sleeping Potion; Puts small creatures to sleep.; es_ES; Poción básica de dormir; Causa las criaturas pequeñas ir a dormir.,false,,4637138456024710495
+standard_sleeping_potion,published,managed_by_android,false,en_US; Standard Sleeping Potion; Puts all creatures to sleep for 2 minutes.,true, 1990000,
+invisibility_potion,published,managed_by_android,false,en_US; Invisibility Potion; Invisible to all enemies for 5 minutes.,false, US; 1990000; BR; 6990000; RU; 129000000; IN; 130000000; ID; 27000000000; MX; 37000000;
+</pre>
+
+<p>
+  This example contains details for three items, each of which represents an
+  in-app product:
+</p>
+<ul>
+  <li>
+    The first item defines a title and description for the <code>en_US</code>
+    and <code>es_ES</code> locales. A pricing template defines the item's
+    price.
+  </li>
+  <li>
+    The second item doesn't use a pricing template. Instead, it specifies a
+    price for the default country (US). The Google Play Developer Console
+    uses current exchange rates and locally relevant pricing patterns to
+    automatically set the prices in all other countries where the app is
+    distributed.
+  </li>
+  <li>
+    The third item also doesn't use a pricing template. The item's price is
+    specified manually for each country where the app is distributed.
+  </li>
+</ul>
+
+<p>
+  Each row in a CSV file can contain the following values, though at least one
+  of these values is undefined in each row:
+</p>
 
 <dl>
-  <dt>product_id</dt>
-  <dd>
-    This is equivalent to the In-app Product ID setting in the In-app Products UI. If you specify
-    a <em>product_id</em> that already exists in a product list, and you choose to overwrite
-    the product list while importing the CSV file, the data for the existing item is overwritten with
-    the values specified in the CSV file. The overwrite feature does not delete items that are on a
-    product list but not present in the CSV file.
-  </dd>
-  <dt>publish_state</dt>
-  <dd>
-    This is equivalent to the Publishing State setting in the In-app Products UI. Can be <code>
-    published</code> or <code>unpublished</code>.
-  </dd>
-  <dt>purchase_type</dt>
-  <dd>
-    This is equivalent to the Product Type setting in the In-app Products UI. Can be <code>
-    managed_by_android</code>, which is equivalent to <strong>Managed per user account
-    </strong> in the In-app Products UI, or <code>managed_by_publisher</code>, which is equivalent
-    to <strong>Unmanaged</strong> in the In-app Products UI.
-  </dd>
-  <dt>autotranslate</dt>
-  <dd>
-    This is equivalent to selecting the <strong>Fill fields with auto translation</strong>
-    checkbox in the In-app Products UI. Can be <code>true</code> or <code>false</code>.
-  </dd>
-  <dt>locale</dt>
-  <dd>
-    <p>This is equivalent to the Language setting in the In-app Products UI. You must have an entry
-    for the default locale. The default locale must be the first entry in the list of
-    locales, and it must include a <em>title</em> and <em>description</em>. If you want to provide
-    translated versions of the <em>title</em> and <em>description</em> in addition to the default,
-    you must use the following syntax rules:</p>
-    <ul>
-      <li>
-      <p>If <em>autotranslate</em> is <code>true</code>, you must specify the default locale,
-      default title, default description, and other locales using the following format:</p>
-      <p>"true,"<em>default_locale</em>; <em>default_locale_title</em>;
-      <em>default_locale_description</em>; <em>locale_2</em>;    <em>locale_3</em>, ..."</p>
-      </li>
-      <li>
-      <p>If <em>autotranslate</em> is <code>false</code>, you must specify the default locale,
-      default title, and default description as well as the translated titles and descriptions using
-      the following format:</p>
-      <p>"false,"<em>default_locale</em>; <em>default_locale_title</em>;
-      <em>default_locale_description</em>; <em>locale_2</em>; <em>locale_2_title</em>;
-      <em>local_2_description</em>; <em>locale_3</em>; <em>locale_3_title</em>;
-       <em>locale_3_description</em>; ..."</p>
-      </li>
-    </ul>
-    <p>See table 1 for a list of the language codes you can use with the <em>locale</em> field.</p>
-  </dd>
-  <dt>title</dt>
-  <dd>
-    This is equivalent to the Title setting in the In-app Products UI. If the <em>title</em>
-    contains a semicolon, it must be escaped with a backslash (for example, <code>\;</code>). Also, a backslash
-    must be escaped with a backslash (for example, <code>\\</code>).
-  </dd>
-  <dt>description</dt>
-  <dd>
-    This is equivalent to the Description in the In-app Products UI. If the <em>description</em>
-    contains a semicolon, it must be escaped with a backslash (for example, <code>\;</code>). Also, a backslash
-    must be escaped with a backslash (for example, <code>\\</code>).
-  </dd>
-  <dt>autofill</dt>
-  <dd>
-    <p>This is equivalent to clicking <strong>Auto Fill</strong> in the In-app Products UI. Can be
-    <code>true</code> or <code>false</code>. The syntax for specifying the <em>country</em>
-    and <em>price</em> varies depending on which <em>autofill</em> setting you use:</p>
-    <ul>
-      <li>
-        <p>If <em>autofill</em> is set to <code>true</code>, you need to specify only the default
-        price in your home currency, and you must use this syntax:</p>
-        <p>"true","<em>default_price_in_home_currency</em>"
-      </li>
-      <li>
-        <p>If <em>autofill</em> is set to <code>false</code>, you need to either specify the <em>pricing_template_id</em>
-        that is linked to the in-app product or specify a <em>country</em> and a <em>price</em> for each currency.
-        If you choose to specify countries and prices, you must use the following syntax:</p>
-        <p>"false", "<em>home_country</em>; <em>default_price_in_home_currency</em>; <em>country_2</em>;
-        <em>country_2_price</em>; <em>country_3</em>; <em>country_3_price</em>; ..."</p>
-      </li>
-    </ul>
-    <p class="note"><strong>Note: </strong>If you use an <em>autofill</em> value of <code>false</code>
-    and set country prices manually, you must incorporate country-specific
-    pricing patterns, including tax rates, into the prices you provide.</p>
-  </dd>
-  <dt>country</dt>
-  <dd>
-    The country for which you are specifying a price. You can only list countries that your
-    app is targeting. The country codes are two-letter uppercase
-    ISO country codes (such as "US"), as defined by
-    <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO 3166-2</a>.
-  </dd>
-  <dt>price</dt>
+  <dt><code>Product ID</code></dt>
   <dd>
     <p>
-    If you use this value, you shouldn't specify a value for the <em>pricing_template_id</em>.
+      Setting this value in the CSV file has the same effect as entering a
+      <em>Product ID</em> when creating a new in-app product.
     </p>
     <p>
-    This is equivalent to the Price in the In-app Products UI. The price must be specified in
-    micro-units. To convert a currency value to micro-units, you multiply the real value by
-    1,000,000.
-    For example, if you want to sell an in-app item for $1.99, you specify <code>1990000</code> in the
-    <em>price</em> field.
+      If you specify a <code>Product ID</code> assigned to an in-app product that already
+      exists in a product list, and you've checked the <strong>Overwrite
+      existing products</strong> checkbox in the <em>Import In-app Products</em>
+      dialog, the data for the existing in-app product is overwritten with the
+      values that you specify in the CSV file.
     </p>
   </dd>
-  <dt>pricing_template_id</dt>
+  <dt><code>Publish State</code></dt>
+  <dd>
+    <p>
+      This value must be set to <code>published</code>
+      or <code>unpublished</code>.
+    </p>
+    <p>
+      Setting this value to <code>published</code> has the same effect as
+      navigating to an item's <em>Managed Product Details</em> page and choosing
+      <strong>Active</strong> in the drop-down list next to the in-app product's
+      title and product ID. Setting the value to <code>unpublished</code>
+      has the same effect as choosing <strong>Inactive</strong> in the same
+      drop-down list.
+    </p>
+  </dd>
+  <dt><code>Purchase Type</code></dt>
+  <dd>
+    <p>
+      This value must be set to <code>managed_by_android</code> because batch
+      upload of product lists containing subscriptions is not supported.
+    </p>
+    <p>
+      Setting this value to <code>managed_by_android</code> has the same effect
+      as selecting <strong>Managed product</strong> in the <em>Add New
+      Product</em> dialog when creating an in-app product.
+    </p>
+  </dd>
+  <dt><code>Auto Translate</code></dt>
+  <dd>
+    <p>
+      This value must be set to <code>false</code> because auto-translation of
+      in-app product details isn't supported.
+    </p>
+    <p>
+      If you want to provide translations of an in-app product's title and
+      description, you need to specify these translations explicitly within the
+      <code>Locale</code> value.
+    </p>
+  </dd>
+  <dt><code>Locale</code>, <code>Title</code>, and <code>Description</code></dt>
+  <dd>
+    <p>
+      If you include only one locale for an item, you must specify your app's
+      default locale and the item's default title and description:
+    </p>
+
+<pre class="no-pretty-print">
+<var>app_default_locale</var>; <var>item_default_title</var>; <var>item_default_description</var>;
+</pre>
+
+    <p>
+      Setting these values has the same effect as performing the following
+      sequence of actions:
+    </p>
+    <ol>
+      <li>
+        Choosing a default language when you add a new app to your
+        publisher account.
+      </li>
+      <li>
+        Navigating to an in-app product's <em>Managed Product Details</em> page.
+      </li>
+      <li>
+        Specifying the in-app product's default title and description.
+      </li>
+    </ol>
+    <p>
+      When setting the <code>Locale</code> value, you can use any of the
+      language codes that appear within the <em>Add Your Own Translations</em>
+      dialog. You can access this dialog by navigating to an in-app product's
+      <em>Managed Product Details</em> page and clicking <strong>Add
+      translations</strong> or <strong>Manage translations</strong>.
+    </p>
+    <p class="note">
+      <strong>Note: </strong>When specifying the <code>Title</code> and
+      <code>Description</code> values, use backslashes to escape the semicolon
+      (<code>\;</code>) and backslash (<code>\\</code>) characters.
+    </p>
+    <p>
+      If you want to include translated versions of the item's title and
+      description, you must list the default locale, title, and description,
+      followed by the locales, titles, and descriptions for each translation.
+      In the following example, the in-app product uses <code>en_US</code>
+      (United States English) as the default locale and <code>es_ES</code>
+      (Spain Spanish) as a translation:
+    </p>
+<pre class="no-pretty-print">
+en_US; Invisibility Cloak; Makes you invisible.; es_ES; Capote Invisible; Se vuelven invisible.
+</pre>
+    <p class="note">
+      <strong>Note: </strong>An app contains a single default language, but each
+      in-app product maintains its own list of translations. Therefore, although
+      the first locale in each item's <code>Locale</code> value must be the same
+      throughout the CSV file, the other locales can differ from one item to
+      another.
+    </p>
+    <p>
+      Providing values for multiple translations has the same effect as
+      performing the following sequence of actions:
+    </p>
+    <ol>
+      <li>
+        Navigating to an in-app product's <em>Managed Product Details</em> page.
+      </li>
+      <li>
+        Clicking <strong>Add translations</strong>.
+      </li>
+      <li>
+        Selecting the languages for the translations and clicking
+        <strong>Add</strong>.
+      </li>
+      <li>
+        Choosing one of the languages you added in the previous step.
+      </li>
+      <li>
+        Specifying a new title and description, which serve as translations into
+        the selected language.
+      </li>
+      <li>
+        Repeating steps 4 and 5 to add translations into all other non-default
+        languages.
+      </li>
+    </ol>
+  </dd>
+  <dt><code>Auto Fill Prices</code>, <code>Country</code>, and
+  <code>Price</code></dt>
+  <dd>
+    <p>
+      You can set <code>Auto Fill Prices</code> to <code>true</code> or
+      <code>false</code>.
+      If an in-app product uses a <a href="#pricing-template">pricing
+      template</a>, you should set <code>Auto Fill Prices</code> to
+      <code>false</code>, and you shouldn't set a value for the
+      <code>Price</code>.
+    </p>
+    <p class="note">
+      <strong>Note: </strong>When you specify an item's price in a CSV file, you
+      provide a price in <em>micro-units</em>, where 1,000,000 micro-units is
+      equivalent to 1 unit of real currency.
+    </p>
+    <p>
+      The following sections describe how the value of
+      <code>Auto Fill Prices</code> affects the syntax and meaning of the
+      <code>Country</code> and <code>Price</code> values.
+    </p>
+    <h5>Using auto-filled prices</h5>
+    <p>
+      If you set <code>Auto Fill Prices</code> to <code>true</code>, you specify
+      only the item's default price; you don't include a <code>Country</code>
+      value. Setting <code>Auto Fill Prices</code> to <code>true</code> has the
+      same effect as performing the following sequence of actions:
+    </p>
+    <ol>
+      <li>
+        Navigating to an in-app product's <em>Managed Product Details</em> page.
+      </li>
+      <li>
+        Selecting <strong>Edit</strong> in the <em>Price</em> section.
+      </li>
+      <li>
+        Entering a default, tax-exclusive price. Auto-filled prices include tax.
+      </li>
+      <li>
+        Clicking the checkbox next to <em>COUNTRY</em> in the <em>Edit Local
+        Prices</em> dialog that appears.
+      </li>
+      <li>
+        Selecting <strong>Refresh exchange rates</strong>.
+      </li>
+      <li>
+        Selecting <strong>Apply</strong>.
+      </li>
+    </ol>
+    <p>
+      For example, under the following conditions:
+    </p>
+    <ul>
+      <li>Your app's default locale is <code>en_US</code>.</li>
+      <li>An in-app product's default, tax-exclusive price is $1.99.</li>
+      <li>You want the prices for other countries auto-filled.</li>
+    </ul>
+    <p>
+      ...you'd set the values of <code>Auto Fill Prices</code> and
+      <code>Price</code> at the end of a row in the CSV file as follows:
+    </p>
+
+<pre class="no-pretty-print">
+true,1990000,
+</pre>
+
+    <h5>Not using auto-filled prices</h5>
+    <p>
+      If you set <code>Auto Fill Prices</code> to <code>false</code> instead,
+      you specify a series of <code>Country</code> and <code>Price</code>
+      values for all countries where you distribute your app, including the country corresponding to your app's default locale.
+      Each <code>Country</code> value is the two-letter uppercase <a
+      class="external-link"
+      href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO country
+      code</a> that represents a country where your app is distributed.
+    </p>
+    <p class="note">
+      <strong>Note: </strong>You must provide a country code and price for each
+      country that your app is targeting. To view and edit the list of countries
+      that your app targets, open your app's <em>Pricing &amp; Distribution</em>
+      page.
+    </p>
+    <p>
+      Each <code>Price</code> value represents the cost of the item in
+      micro-units of the currency used in that country. Setting <code>Auto Fill
+      Prices</code> to <code>false</code> has the same effect as performing
+      the following sequence of actions:
+    </p>
+    <ol>
+      <li>
+        Navigating to an in-app product's <em>Managed Product Details</em> page.
+      </li>
+      <li>
+        Selecting <strong>Edit</strong> in the <em>Price</em> section.
+      </li>
+      <li>
+        Explicitly setting tax-inclusive prices for different countries in the
+        <em>Edit Local Prices</em> dialog that appears.
+      </li>
+      <li>
+        Selecting <strong>Apply</strong>.
+      </li>
+    </ol>
+    <p>
+      For example, if you're offering your app for the following prices (all
+      taxes included) in other countries:
+    </p>
+    <ul>
+      <li>R$6.99 in Brazil.</li>
+      <li>129&nbsp;&#8381; in Russia.</li>
+      <li>&#8377;130 in India.</li>
+      <li>Rp&nbsp;27,000 in Indonesia.</li>
+      <li>$37 in Mexico.</li>
+    </ul>
+    <p>
+      ...you'd set the values of <code>Auto Fill Prices</code>,
+      <code>Country</code>, and <code>Price</code> at the end of a row in the
+      CSV file as follows:
+    </p>
+
+<pre class="no-pretty-print">
+false, BR; 6990000; RU; 129000000; IN; 130000000; ID; 27000000000; MX; 37000000;
+</pre>
+
+  </dd>
+  <dt><code>Pricing Template ID</code></dt>
   <dd>
   <p>
-    If you use this value, you should set <em>autofill</em> to
-    <code>false</code> and leave the <em>price</em> column empty.
+    If an item is linked to a pricing template, you should set <code>Auto Fill
+    Prices</code> to <code>false</code>, and you shouldn't set a value for the
+    <code>Price</code> column. If the item isn't linked to a pricing template,
+    you shouldn't set a value for the <code>Pricing Template ID</code>; instead,
+    you should set <code>Auto Fill Prices</code>, <code>Country</code>, and
+    <code>Price</code> based on how you want to set the in-app product's prices.
   </p>
   <p>
-    This value represents the ID of the pricing template that you've linked to
-    the in-app product. This ID appears under a pricing template's name
-    on the <strong>Pricing template</strong> page. If an in-app product isn't
-    linked to a pricing template, its <em>pricing_template_id</em> value is
-    empty.
+    Setting this value has the same effect as navigating to an in-app product's
+    <em>Managed Product Details</em> page and linking the product's price to the
+    pricing template that has the same pricing template ID as the one specified
+    in the CSV file. This pricing template ID appears underneath a pricing
+    template's name on the <em>Pricing template</em> page.
   </p>
   <p>
-    If you import a CSV file and choose to overwrite the product list, you can
-    update the links between in-app products and pricing templates by changing
-    the value of an in-app product's <em>pricing_template_id</em>. Leave the
-    value empty to unlink an in-app product from all pricing templates.
+    If you import a CSV file, and you've checked the <strong>Overwrite existing
+    products</strong> checkbox in the <em>Import In-app Products</em> dialog,
+    you can update the links between in-app products and pricing templates. To
+    link the product to a specific pricing template, set the <code>Pricing
+    Template ID</code> value to that pricing template's ID. To unlink an in-app
+    product from all pricing templates, don't set a value for its <code>Pricing
+    Template ID</code>.
   </p>
   <p>
-    <strong>Note: </strong>You can link up to 100 app prices or in-app product
-    prices with a particular pricing template. Therefore, don't specify the same
-    <em>pricing_template_id</em> value in more than 100 rows of your CSV file.
+    You can link up to 100 app prices or in-app product prices to a particular
+    pricing template. Therefore, don't specify the same <code>Pricing Template
+    ID</code> value in more than 100 rows of a CSV file.
   </p>
   </dd>
 </dl>
 
-<p class="table-caption" id="language-table"><strong>Table 1.</strong> Language codes you can use
-with the <em>locale</em> field.</p>
-
-<table>
-
-<tr>
-<th>Language</th>
-<th>Code</th>
-<th>Language</th>
-<th>Code</th>
-</tr>
-<tr>
-<td>Chinese</td>
-<td>zh_TW</td>
-<td>Italian</td>
-<td>it_IT</td>
-</tr>
-<tr>
-<td>Czech</td>
-<td>cs_CZ</td>
-<td>Japanese</td>
-<td>ja_JP</td>
-</tr>
-<tr>
-<td>Danish</td>
-<td>da_DK</td>
-<td>Korean</td>
-<td>ko_KR</td>
-</tr>
-<tr>
-<td>Dutch</td>
-<td>nl_NL</td>
-<td>Norwegian</td>
-<td>no_NO</td>
-</tr>
-<tr>
-<td>English</td>
-<td>en_US</td>
-<td>Polish</td>
-<td>pl_PL</td>
-</tr>
-<tr>
-<td>French</td>
-<td>fr_FR</td>
-<td>Portuguese</td>
-<td>pt_PT</td>
-</tr>
-<tr>
-<td>Finnish</td>
-<td>fi_FI</td>
-<td>Russian</td>
-<td>ru_RU</td>
-</tr>
-<tr>
-<td>German</td>
-<td>de_DE</td>
-<td>Spanish</td>
-<td>es_ES</td>
-</tr>
-<tr>
-<td>Hebrew</td>
-<td>iw_IL</td>
-<td>Swedish</td>
-<td>sv_SE</td>
-</tr>
-<tr>
-<td>Hindi</td>
-<td>hi_IN</td>
-<td>--</td>
-<td>--</td>
-</tr>
-</table>
-
 <h2 id="pricing-template">
   Pricing Templates
 </h2>
@@ -466,7 +612,8 @@
   can apply to paid apps and in-app products. You can link the prices of up to
   100 apps and in-app products to a single pricing template.
 </p>
-</p>
+
+<p>
   To add a pricing template, do the following:
 </p>
 
@@ -476,14 +623,14 @@
     account.
   </li>
 
-  <li>In the <strong>Settings</strong> panel, open the <strong>Pricing
-  template</strong> page.
+  <li>In the <em>Settings</em> panel, open the <em>Pricing
+  template</em> page.
   </li>
 
   <li>
     <p>
-      If you are adding your first pricing template, the <strong>Add a Pricing
-      Template</strong> banner appears. Select <strong>Add template</strong> to
+      If you are adding your first pricing template, the <em>Add a Pricing
+      Template</em> banner appears. Select <strong>Add template</strong> to
       create a new template. The new template's <em>Pricing</em> tab appears.
     </p>
 
@@ -544,8 +691,8 @@
     account.
   </li>
 
-  <li>In the <strong>Settings</strong> panel, open the <strong>Pricing
-  template</strong> page. This page shows the list of pricing templates you have
+  <li>In the <em>Settings</em> panel, open the <em>Pricing
+  template</em> page. This page shows the list of pricing templates you have
   created for your account.
   </li>
 
@@ -605,8 +752,8 @@
     account.
   </li>
 
-  <li>In the <strong>All applications</strong> panel, select the app name, then
-  open the <strong>In-app Products</strong> page.
+  <li>In the <em>All applications</em> panel, select the app name, then
+  open the <em>In-app Products</em> page.
   </li>
 
   <li>Choose the in-app product that you want to link to a pricing template.
@@ -625,7 +772,7 @@
 
 <p>
   To link the price of a paid app to a pricing template, you follow a similar
-  process on the app's <strong>Pricing &amp; Distribution</strong> page.
+  process on the app's <em>Pricing &amp; Distribution</em> page.
 </p>
 
 <h3 id="delete-linked-item">
@@ -657,7 +804,7 @@
   <li>Select the app that contains the in-app product you want to delete.
   </li>
 
-  <li>Open the app's <strong>In-app Products</strong> page.
+  <li>Open the app's <em>In-app Products</em> page.
   </li>
 
   <li>Choose the in-app product that you want to delete.
@@ -731,8 +878,8 @@
     account.
   </li>
 
-  <li>In the <strong>Settings</strong> panel, open the <strong>Pricing
-  template</strong> page, which shows the list of pricing templates you have
+  <li>In the <em>Settings</em> panel, open the <em>Pricing
+  template</em> page, which shows the list of pricing templates you have
   created for your account.
   </li>
 
@@ -746,15 +893,15 @@
   </li>
 </ol>
 
-<h2 id="billing-purchase-type">Choosing a Product Type</h3>
+<h2 id="billing-purchase-type">Choosing a Product Type</h2>
 
 <p>An item's product type controls how Google Play manages the purchase of the item. The supported
 product types include "managed product" and "subscription." Since support for different product
 types can vary among versions of the In-app Billing API, make sure that you choose a product
-type that's valid for the version of the In-app Billing API that your app uses. </p>
+type that's valid for the version of the In-app Billing API that your app uses.</p>
 
 <p>For details, refer to the documentation for the <a
-href="{@docRoot}google/play/billing/api.html#producttype">In-app Billing API</a>.
+href="{@docRoot}google/play/billing/api.html#producttype">In-app Billing API</a>.</p>
 
 <h2 id="billing-refunds">Handling Refunds</h2>
 
@@ -782,9 +929,10 @@
 intent.</p>
 
 <p class="note">
-  <strong>Note:</strong> Test purchases don't have an <code>orderId</code>
-  field. To track test transactions, you use the <code>purchaseToken</code>
-  field instead. For more information about working with test purchases, see <a
+  <strong>Note:</strong> When a user completes a test purchase, the
+  <code>orderId</code> field remains blank. To track test transactions, use
+  the <code>purchaseToken</code> field instead. For more information about
+  working with test purchases, see <a
   href="{@docRoot}google/play/billing/billing_testing.html">Testing In-app
   Billing</a>.
 </p>
@@ -799,14 +947,14 @@
 
 <p>For transactions dated 5 December 2012 or later, Google payments assigns a
 Merchant Order Number (rather than a Google Order Number) and reports the Merchant
-Order Number as the value of <code>orderId</code>. Here's an
+Order Number as the value of <code>orderID</code>. Here's an
 example:</p>
 
 <pre>"orderId" : "GPA.1234-5678-9012-34567"</pre>
 
 <p>For transactions dated previous to 5 December 2012, Google checkout assigned
 a Google Order Number and reported that number as the value of
-<code>orderId</code>. Here's an example of an <code>orderId</code> holding a
+<code>orderID</code>. Here's an example of an <code>orderID</code> holding a
 Google Order Number:</p>
 
 <pre>"orderId" : "556515565155651"</pre>
@@ -853,8 +1001,8 @@
 
 <p>To locate the key for an app, follow these steps:</p>
 <ol>
-  <li>Open the <strong>All applications</strong> panel.</li>
-  <li>Click on the app name, then open the <strong>Services &amp; APIs</strong>
+  <li>Open the <em>All applications</em> panel.</li>
+  <li>Click on the app name, then open the <em>Services &amp; APIs</em>
   page.</li>
   <li>Scroll down to the section of the page labeled Your License Key for This
   Application, as shown in figure 5.</li>
@@ -869,7 +1017,7 @@
   width="700" alt="">
   <figcaption>
     <b>Figure 5. </b>You can find the license key for each app on the
-    <strong>Services &amp; APIs</strong> page.
+    <em>Services &amp; APIs</em> page.
   </figcaption>
 </figure>
 
diff --git a/docs/html/guide/topics/ui/drag-drop.jd b/docs/html/guide/topics/ui/drag-drop.jd
index d6e07a5..9280818 100644
--- a/docs/html/guide/topics/ui/drag-drop.jd
+++ b/docs/html/guide/topics/ui/drag-drop.jd
@@ -157,19 +157,22 @@
 </p>
 <p>
     Your application tells the system to start a drag by calling the
-    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+    {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+    startDragAndDrop()}
     method. This tells the system to start sending drag events. The method also sends the data that
     you are dragging.
 </p>
 <p>
     You can call
-    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+    {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+    startDragAndDrop()}
     for any attached View in the current layout. The system only uses the View object to get access
     to global settings in your layout.
 </p>
 <p>
     Once your application calls
-    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()},
+    {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+    startDragAndDrop()},
     the rest of the process uses events that the system sends to the View objects in your current
     layout.
 </p>
@@ -183,11 +186,13 @@
     </dt>
     <dd>
         In response to the user's gesture to begin a drag, your application calls
-        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
-        to tell the system to start a drag. The arguments
-        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
-        provide the data to be dragged, metadata for this data, and a callback for drawing the
-        drag shadow.
+        {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+        startDragAndDrop()}
+        to tell the system to start a drag. The
+        {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+        startDragAndDrop()}
+        arguments provide the data to be dragged, metadata for this data, and a callback for drawing
+        the drag shadow.
         <p>
             The system first responds by calling back to your application to get a drag shadow. It
             then displays the drag shadow on the device.
@@ -199,12 +204,13 @@
             including a possible drop event, a drag event listener must return <code>true</code>.
             This registers the listener with the system. Only registered listeners continue to
             receive drag events. At this point, listeners can also change the appearance of their
-            View object to show that the listener can accept a drop event.
+            View object to show that the listener can accept the dragged data.
         </p>
         <p>
             If the drag event listener returns <code>false</code>, then it will not receive drag
-            events for the current operation until the system sends a drag event with action type
-            {@link android.view.DragEvent#ACTION_DRAG_ENDED}. By sending <code>false</code>, the
+            events for the current operation, including the drag event with action type
+            {@link android.view.DragEvent#ACTION_DRAG_ENDED} that will conclude the
+            operation. By sending <code>false</code>, the
             listener tells the system that it is not interested in the drag operation and
             does not want to accept the dragged data.
         </p>
@@ -230,7 +236,8 @@
         object's listener a drag event with action type
         {@link android.view.DragEvent#ACTION_DROP}. The drag event contains the data that was
         passed to the system in the call to
-        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+        {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+        startDragAndDrop()}
         that started the operation. The listener is expected to return boolean <code>true</code> to
         the system if code for accepting the drop succeeds.
         <p>
@@ -297,7 +304,8 @@
 <p>
     The {@link android.view.DragEvent} object also contains the data that your application provided
     to the system in the call to
-    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+    {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+    startDragAndDrop()}.
     Some of the data is valid only for certain action types. The data that is valid for each action
     type is summarized in <a href="#table2">table 2</a>. It is also described in detail with
     the event for which it is valid in the section
@@ -316,8 +324,9 @@
         <td>
             A View object's drag event listener receives this event action type just after the
             application calls
-{@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()} and
-            gets a drag shadow.
+            {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+            startDragAndDrop()}
+            and gets a drag shadow.
             <p>
                 If the listener wants to continue receiving drag events for this operation, it must
                 return boolean <code>true</code> to the system.
@@ -345,8 +354,7 @@
         <td>{@link android.view.DragEvent#ACTION_DRAG_EXITED}</td>
         <td>
             A View object's drag event listener receives this event action type after it receives a
-            {@link android.view.DragEvent#ACTION_DRAG_ENTERED} and at least one
-            {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event, and after the user has moved
+            {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event, and after the user has moved
             the drag shadow outside the bounding box of the View or into a descendant view that can
             accept the data.
         </td>
@@ -355,7 +363,8 @@
         <td>{@link android.view.DragEvent#ACTION_DROP}</td>
         <td>
             A View object's drag event listener receives this event action type when the user
-            releases the drag shadow over the View object. This action type is only sent to a View
+            releases the drag shadow over the View object and not over its descendant view that can
+            accept the drag data. This action type is only sent to a View
             object's listener if the listener returned boolean <code>true</code> in response to the
             {@link android.view.DragEvent#ACTION_DRAG_STARTED} drag event. This action type is not
             sent if the user releases the drag shadow on a View whose listener is not registered,
@@ -472,9 +481,11 @@
     The image is called a drag shadow. You create it with methods you declare for a
     {@link android.view.View.DragShadowBuilder} object, and then pass it to the system when you
     start a drag using
-    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+    {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+    startDragAndDrop()}.
     As part of its response to
-    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()},
+    {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+    startDragAndDrop()},
     the system invokes the callback methods you've defined in
     {@link android.view.View.DragShadowBuilder} to obtain a drag shadow.
 </p>
@@ -516,7 +527,8 @@
     </dt>
     <dd>
         The system calls this method immediately after you call
-{@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}. Use it
+        {@link android.view.View#startDragAndDrop(ClipData,View.DragShadowBuilder,Object,int)
+        startDragAndDrop()}. Use it
         to send to the system the dimensions and touch point of the drag shadow. The method has two
         arguments:
         <dl>
@@ -616,10 +628,10 @@
 
     // Starts the drag
 
-            v.startDrag(dragData,  // the data to be dragged
-                        myShadow,  // the drag shadow builder
-                        null,      // no need to use local data
-                        0          // flags (not currently used, set to 0)
+            v.startDragAndDrop(dragData,  // the data to be dragged
+                               myShadow,  // the drag shadow builder
+                               null,      // no need to use local data
+                               0          // flags (not currently used, set to 0)
             );
 
     }
@@ -722,8 +734,7 @@
 <p>
     Note that for an {@link android.view.DragEvent#ACTION_DRAG_STARTED} event, these
     the following {@link android.view.DragEvent} methods are not valid:
-    {@link android.view.DragEvent#getClipData()}, {@link android.view.DragEvent#getX()},
-    {@link android.view.DragEvent#getY()}, and {@link android.view.DragEvent#getResult()}.
+    {@link android.view.DragEvent#getClipData()} and {@link android.view.DragEvent#getResult()}.
 </p>
 <h3 id="HandleDuring">Handling events during the drag</h3>
 <p>
@@ -751,7 +762,9 @@
         {@link android.view.DragEvent#ACTION_DRAG_LOCATION}: Once the listener receives an
         {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event, and before it receives an
         A{@link android.view.DragEvent#ACTION_DRAG_EXITED} event, it receives a new
-        {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event every time the touch point moves.
+        {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event immediately after the
+        {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event, and then every time the touch
+        point moves.
         The {@link android.view.DragEvent#getX()} and {@link android.view.DragEvent#getY()} methods
         return the X and Y coordinates of the touch point.
     </li>
@@ -769,9 +782,9 @@
 </p>
 <ul>
     <li>
-        In response to {@link android.view.DragEvent#ACTION_DRAG_ENTERED} or
-        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}, the listener can change the appearance
-        of the View to indicate that it is about to receive a drop.
+        In response to {@link android.view.DragEvent#ACTION_DRAG_ENTERED}, the listener can change
+        the appearance
+        of the View to indicate that it is ready to receive a drop.
     </li>
     <li>
         An event with the action type {@link android.view.DragEvent#ACTION_DRAG_LOCATION} contains
@@ -784,14 +797,14 @@
     <li>
         In response to {@link android.view.DragEvent#ACTION_DRAG_EXITED}, the listener should reset
         any appearance changes it applied in response to
-        {@link android.view.DragEvent#ACTION_DRAG_ENTERED} or
-        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}. This indicates to the user that
+        {@link android.view.DragEvent#ACTION_DRAG_ENTERED}. This indicates to the user that
         the View is no longer an imminent drop target.
     </li>
 </ul>
 <h3 id="HandleDrop">Responding to a drop</h3>
 <p>
-    When the user releases the drag shadow on a View in the application, and that View previously
+    When the user releases the drag shadow on a View in the application, but not on its descendant
+    view that can accept the data, and that View previously
     reported that it could accept the content being dragged, the system dispatches a drag event
     to that View with the action type {@link android.view.DragEvent#ACTION_DROP}. The listener
     should do the following:
@@ -800,8 +813,8 @@
     <li>
         Call {@link android.view.DragEvent#getClipData()} to get the
         {@link android.content.ClipData} object that was originally supplied in the call
-        to
-{@link android.view.View#startDrag(ClipData, View.DragShadowBuilder, Object, int) startDrag()}
+        to {@link android.view.View#startDragAndDrop(ClipData, View.DragShadowBuilder, Object, int)
+        startDragAndDrop()}
         and store it. If the drag and drop operation does not represent data movement,
         this may not be necessary.
     </li>
@@ -856,9 +869,6 @@
         including any case in which the system did not send out a
         {@link android.view.DragEvent#ACTION_DROP} event.
     </li>
-    <li>
-        The listener should return boolean <code>true</code> to the system.
-    </li>
 </ol>
 <p>
 </p>
diff --git a/docs/html/images/cards/distribute/stories/animoca.jpg b/docs/html/images/cards/distribute/stories/animoca.jpg
new file mode 100644
index 0000000..1886bce
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/animoca.jpg
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/drupe.jpg b/docs/html/images/cards/distribute/stories/drupe.jpg
new file mode 100644
index 0000000..5295695
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/drupe.jpg
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/economist-espresso.png b/docs/html/images/cards/distribute/stories/economist-espresso.png
new file mode 100644
index 0000000..923bf57
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/economist-espresso.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/expressen-sport.png b/docs/html/images/cards/distribute/stories/expressen-sport.png
new file mode 100644
index 0000000..842ed3d
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/expressen-sport.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/glamour.png b/docs/html/images/cards/distribute/stories/glamour.png
new file mode 100644
index 0000000..770b03f
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/glamour.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/happylabs-logo.png b/docs/html/images/cards/distribute/stories/happylabs-logo.png
new file mode 100644
index 0000000..ea20e71
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/happylabs-logo.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/lifesum.png b/docs/html/images/cards/distribute/stories/lifesum.png
new file mode 100644
index 0000000..3975ff2
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/lifesum.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/noom.jpg b/docs/html/images/cards/distribute/stories/noom.jpg
new file mode 100644
index 0000000..dde18a2
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/noom.jpg
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/playlab.jpg b/docs/html/images/cards/distribute/stories/playlab.jpg
new file mode 100644
index 0000000..3b641e6
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/playlab.jpg
Binary files differ
diff --git a/docs/html/images/distribute/stories/animoca-flow.jpg b/docs/html/images/distribute/stories/animoca-flow.jpg
new file mode 100644
index 0000000..d2aa2f6
--- /dev/null
+++ b/docs/html/images/distribute/stories/animoca-flow.jpg
Binary files differ
diff --git a/docs/html/images/distribute/stories/animoca-graph.jpg b/docs/html/images/distribute/stories/animoca-graph.jpg
new file mode 100644
index 0000000..c2a42f4
--- /dev/null
+++ b/docs/html/images/distribute/stories/animoca-graph.jpg
Binary files differ
diff --git a/docs/html/images/distribute/stories/animoca-logo.png b/docs/html/images/distribute/stories/animoca-logo.png
new file mode 100644
index 0000000..4b5b6b5
--- /dev/null
+++ b/docs/html/images/distribute/stories/animoca-logo.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/drupe-icon.png b/docs/html/images/distribute/stories/drupe-icon.png
new file mode 100644
index 0000000..1b75cca
--- /dev/null
+++ b/docs/html/images/distribute/stories/drupe-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/drupe-screenshot.png b/docs/html/images/distribute/stories/drupe-screenshot.png
new file mode 100644
index 0000000..6fd4445
--- /dev/null
+++ b/docs/html/images/distribute/stories/drupe-screenshot.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/economist-espresso-icon.png b/docs/html/images/distribute/stories/economist-espresso-icon.png
new file mode 100644
index 0000000..923bf57
--- /dev/null
+++ b/docs/html/images/distribute/stories/economist-espresso-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/expressen-icon.png b/docs/html/images/distribute/stories/expressen-icon.png
new file mode 100644
index 0000000..4547ce7
--- /dev/null
+++ b/docs/html/images/distribute/stories/expressen-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/glamour-icon.png b/docs/html/images/distribute/stories/glamour-icon.png
new file mode 100644
index 0000000..770b03f
--- /dev/null
+++ b/docs/html/images/distribute/stories/glamour-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/happylabs-happy_pet_icon.png b/docs/html/images/distribute/stories/happylabs-happy_pet_icon.png
new file mode 100644
index 0000000..9b24c4a
--- /dev/null
+++ b/docs/html/images/distribute/stories/happylabs-happy_pet_icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/happylabs-logo.png b/docs/html/images/distribute/stories/happylabs-logo.png
new file mode 100644
index 0000000..ea20e71
--- /dev/null
+++ b/docs/html/images/distribute/stories/happylabs-logo.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/happylabs-variant.png b/docs/html/images/distribute/stories/happylabs-variant.png
new file mode 100644
index 0000000..3ce5342
--- /dev/null
+++ b/docs/html/images/distribute/stories/happylabs-variant.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/lifesum-icon.png b/docs/html/images/distribute/stories/lifesum-icon.png
new file mode 100644
index 0000000..3975ff2
--- /dev/null
+++ b/docs/html/images/distribute/stories/lifesum-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/noom-icon.png b/docs/html/images/distribute/stories/noom-icon.png
new file mode 100644
index 0000000..a853218
--- /dev/null
+++ b/docs/html/images/distribute/stories/noom-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/noom-screenshot.png b/docs/html/images/distribute/stories/noom-screenshot.png
new file mode 100644
index 0000000..0293eea
--- /dev/null
+++ b/docs/html/images/distribute/stories/noom-screenshot.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/playlab-icon.png b/docs/html/images/distribute/stories/playlab-icon.png
new file mode 100644
index 0000000..af80183
--- /dev/null
+++ b/docs/html/images/distribute/stories/playlab-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/playlab-screenshot.png b/docs/html/images/distribute/stories/playlab-screenshot.png
new file mode 100644
index 0000000..42ffb6a
--- /dev/null
+++ b/docs/html/images/distribute/stories/playlab-screenshot.png
Binary files differ
diff --git a/docs/html/jd_extras_en.js b/docs/html/jd_extras_en.js
index f76cf36..1a97db4 100644
--- a/docs/html/jd_extras_en.js
+++ b/docs/html/jd_extras_en.js
@@ -2981,7 +2981,6 @@
     "type": "distribute",
     "category": "google"
   },
-
   {
     "lang": "en",
     "group": "",
@@ -5376,6 +5375,47 @@
       "https://storage.googleapis.com/androiddevelopers/shareables/stories/Senri_LeosFortune_gpgs.pdf"
     ]
   },
+  "distribute/stories/games/docs": {
+    "title": "",
+    "resources": [
+      "distribute/stories/games/animoca-star-girl.html",
+      "distribute/stories/games/happy-labs-experiment.html",
+      "distribute/stories/games/playlab-puzzles.html",
+      "distribute/stories/games/upbeat-games.html",
+      "distribute/stories/games/tapps.html",
+      "distribute/stories/games/noodlecake-super-stickman.html",
+      "distribute/stories/games/glu-tap-baseball.html",
+      "distribute/stories/games/doctor-who-legacy.html",
+      "distribute/stories/games/glu-dh.html",
+      "distribute/stories/games/dots.html",
+      "distribute/stories/games/kongregate-adv-cap.html",
+      "distribute/stories/games/kongregate-global-assault.html",
+      "distribute/stories/games/leos-fortune.html",
+      "distribute/stories/games/tiny-co.html",
+      "distribute/stories/games/g4a-indian-rummy.html",
+      "distribute/stories/games/rvappstudios-zombie.html",
+      "distribute/stories/games/glu-eternity-warriors.html",
+      "distribute/stories/games/hotheadgames-firefight.html",
+      "distribute/stories/games/concrete-bowling.html",
+      "distribute/stories/games/gameloft-asphalt8.html"
+    ]
+  },
+  "distribute/stories/apps/docs": {
+    "title": "",
+    "resources": [
+      "distribute/stories/apps/condenast-shopping.html",
+      "distribute/stories/apps/economist-espresso.html",
+      "distribute/stories/apps/expressen-sports.html",
+      "distribute/stories/apps/drupe-communications.html",
+      "distribute/stories/apps/noom-health.html",
+      "distribute/stories/apps/aftenposten.html",
+      "distribute/stories/apps/el-mundo.html",
+      "distribute/stories/apps/segundamano.html",
+      "distribute/stories/apps/remember-the-milk.html",
+      "distribute/stories/apps/intuit-mint.html",
+      "distribute/stories/apps/sayhi.html",
+    ]
+  },
   "training/testing/overview": {
     "title": "",
     "resources": [
diff --git a/docs/html/jd_extras_zh-cn.js b/docs/html/jd_extras_zh-cn.js
index cb1ccb7..866a87e 100644
--- a/docs/html/jd_extras_zh-cn.js
+++ b/docs/html/jd_extras_zh-cn.js
@@ -244,40 +244,40 @@
   "overview/zhcn/1": {
     "title": "",
     "resources": [
-      "intl/zh-cn/distribute/essentials/quality/core.html",
-      "intl/zh-cn/distribute/essentials/quality/tablets.html",
-      "intl/zh-cn/distribute/tools/launch-checklist.html",
-      "intl/zh-cn/tools/publishing/publishing_overview.html",
-      "intl/zh-cn/distribute/tools/localization-checklist.html"
+      "distribute/essentials/quality/core.html",
+      "distribute/essentials/quality/tablets.html",
+      "distribute/tools/launch-checklist.html",
+      "tools/publishing/publishing_overview.html",
+      "distribute/tools/localization-checklist.html"
     ]
   },
   "overview/zhcn/2": {
     "title": "",
     "resources": [
-      "intl/zh-cn/google/play/billing/index.html",
-      "intl/zh-cn/google/play/billing/api.html",
-      "intl/zh-cn/google/play/billing/billing_admin.html",
-      "intl/zh-cn/google/play/billing/billing_testing.html",
-      "intl/zh-cn/google/play/billing/billing_best_practices.html"
+      "google/play/billing/index.html",
+      "google/play/billing/api.html",
+      "google/play/billing/billing_admin.html",
+      "google/play/billing/billing_testing.html",
+      "google/play/billing/billing_best_practices.html"
     ]
   },
   "overview/zhcn/3": {
     "title": "",
     "resources": [
       "https://play.google.com/intl/en_us/badges/",
-      "intl/zh-cn/distribute/tools/promote/device-art.html",
-      "intl/zh-cn/distribute/tools/promote/linking.html",
-      "intl/zh-cn/distribute/tools/promote/brand.html",
-      "intl/zh-cn/tools/help/proguard.html"
+      "distribute/tools/promote/device-art.html",
+      "distribute/tools/promote/linking.html",
+      "distribute/tools/promote/brand.html",
+      "tools/help/proguard.html"
     ]
   },
   "overview/zhcn/4": {
     "title": "",
     "resources": [
-      "intl/zh-cn/design/style/writing.html",
-      "intl/zh-cn/training/basics/fragments/fragment-ui.html",
-      "intl/zh-cn/training/multiscreen/index.html",
-      "intl/zh-cn/training/monitoring-device-state/index.html"
+      "design/style/writing.html",
+      "training/basics/fragments/fragment-ui.html",
+      "training/multiscreen/index.html",
+      "training/monitoring-device-state/index.html"
     ]
   },
   "overview/carousel/zhcn": {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_additions.html b/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_additions.html
index 9786c92..fcff8ea 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_additions.html
@@ -332,7 +332,7 @@
 <!-- Method zBy -->
 <nobr><A HREF="android.support.v4.view.ViewPropertyAnimatorCompat.html#android.support.v4.view.ViewPropertyAnimatorCompat.zBy_added(float)" class="hiddenlink" target="rightframe"><b>zBy</b>
 (<code>float</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_all.html b/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_all.html
index 7055d15..4e923e6 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_all.html
@@ -425,7 +425,7 @@
 <!-- Method zBy -->
 <nobr><A HREF="android.support.v4.view.ViewPropertyAnimatorCompat.html#android.support.v4.view.ViewPropertyAnimatorCompat.zBy_added(float)" class="hiddenlink" target="rightframe"><b>zBy</b>
 (<code>float</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_changes.html b/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_changes.html
index c40c9f5..4002f63 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_changes.html
@@ -114,7 +114,7 @@
 <A HREF="android.support.v4.view.ViewParentCompat.html" class="hiddenlink" target="rightframe">ViewParentCompat</A><br>
 <!-- Class ViewPropertyAnimatorCompat -->
 <A HREF="android.support.v4.view.ViewPropertyAnimatorCompat.html" class="hiddenlink" target="rightframe">ViewPropertyAnimatorCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_removals.html b/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_removals.html
index 68d2c20..c6ec566 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/alldiffs_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.Builder.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.Builder.html
index ae6415e..42084ee 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.Builder.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.Builder.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.CustomAction.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.CustomAction.html
index 4e476b3..deab0af 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.CustomAction.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.CustomAction.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html
index bd3e5dd..16b5462 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html
@@ -144,7 +144,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewCompat.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewCompat.html
index 1574050..d48ce71 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewCompat.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewCompat.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewPager.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewPager.html
index f03c403..bed9612 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewPager.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewPager.html
@@ -140,7 +140,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewParentCompat.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewParentCompat.html
index 6cdd299..08d2ab2 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewParentCompat.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewParentCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewPropertyAnimatorCompat.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewPropertyAnimatorCompat.html
index 5706997..1bfa2b3 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewPropertyAnimatorCompat.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.ViewPropertyAnimatorCompat.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html
index e746f08..09b19c2 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html
@@ -151,7 +151,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatActivity.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatActivity.html
index ccce9c5..7b2f8bb 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatActivity.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatActivity.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatCallback.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatCallback.html
index f53a519..fd75b74 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatCallback.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatCallback.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatDelegate.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatDelegate.html
index 88490d4..5df87b9 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatDelegate.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatDelegate.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatDialog.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatDialog.html
index 42d29a8..6d992ad 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatDialog.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.app.AppCompatDialog.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.util.SortedList.html b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.util.SortedList.html
index 0364519..edfb8bd 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.util.SortedList.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/android.support.v7.util.SortedList.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/changes-summary.html b/docs/html/sdk/support_api_diff/22.2.0/changes/changes-summary.html
index c6736cd..72ddc5a 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/changes-summary.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/changes-summary.html
@@ -233,7 +233,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_additions.html b/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_additions.html
index ccd5b66..4537739 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_additions.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_all.html b/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_all.html
index 728e37d..50a77aa 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_all.html
@@ -88,7 +88,7 @@
 <A HREF="android.support.v4.view.ViewPager.html" class="hiddenlink" target="rightframe">ViewPager</A><br>
 <A HREF="android.support.v4.view.ViewParentCompat.html" class="hiddenlink" target="rightframe">ViewParentCompat</A><br>
 <A HREF="android.support.v4.view.ViewPropertyAnimatorCompat.html" class="hiddenlink" target="rightframe">ViewPropertyAnimatorCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_changes.html b/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_changes.html
index 64e7f44..04fc9bc 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_changes.html
@@ -88,7 +88,7 @@
 <A HREF="android.support.v4.view.ViewPager.html" class="hiddenlink" target="rightframe">ViewPager</A><br>
 <A HREF="android.support.v4.view.ViewParentCompat.html" class="hiddenlink" target="rightframe">ViewParentCompat</A><br>
 <A HREF="android.support.v4.view.ViewPropertyAnimatorCompat.html" class="hiddenlink" target="rightframe">ViewPropertyAnimatorCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_removals.html b/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_removals.html
index 792fc4e..8881d7d 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/classes_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_additions.html b/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_additions.html
index 3237ba3..603d376 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_additions.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_all.html b/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_all.html
index 637582e..a29ef64 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_all.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_changes.html b/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_changes.html
index 728fa2d..182ad3c 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_changes.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_removals.html b/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_removals.html
index 1b95544..9f9bb43 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/constructors_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_additions.html b/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_additions.html
index 48de992..6b0d997 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_additions.html
@@ -69,7 +69,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v4.media.session.PlaybackStateCompat.html#android.support.v4.media.session.PlaybackStateCompat.STATE_SKIPPING_TO_QUEUE_ITEM" class="hiddenlink" target="rightframe">STATE_SKIPPING_TO_QUEUE_ITEM</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_all.html b/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_all.html
index 02f6dc0..726deb6 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_all.html
@@ -69,7 +69,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v4.media.session.PlaybackStateCompat.html#android.support.v4.media.session.PlaybackStateCompat.STATE_SKIPPING_TO_QUEUE_ITEM" class="hiddenlink" target="rightframe">STATE_SKIPPING_TO_QUEUE_ITEM</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_changes.html b/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_changes.html
index 4ebfa31..e4376a5 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_changes.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_removals.html b/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_removals.html
index 09b0726..db6d007 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/fields_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_help.html b/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_help.html
index 8bfbd1d..e978be0 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_help.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_help.html
@@ -120,7 +120,7 @@
 There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass. 
 In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes. 
 </BLOCKQUOTE>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_statistics.html b/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_statistics.html
index 229819b..6a96e39 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_statistics.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_statistics.html
@@ -265,7 +265,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_topleftframe.html b/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_topleftframe.html
index 36f9836..6a2e76e 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_topleftframe.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/jdiff_topleftframe.html
@@ -49,7 +49,7 @@
   <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="fields_index_all.html" TARGET="bottomleftframe">By Field</A></FONT><br></TD>
 </TR>
 </TABLE>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_additions.html b/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_additions.html
index f7c8488..b7b94ac 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_additions.html
@@ -264,7 +264,7 @@
 (<code>float</code>)</A></nobr><br>
 <nobr><A HREF="android.support.v4.view.ViewPropertyAnimatorCompat.html#android.support.v4.view.ViewPropertyAnimatorCompat.zBy_added(float)" class="hiddenlink" target="rightframe"><b>zBy</b>
 (<code>float</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_all.html b/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_all.html
index 63a2848..04d38841 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_all.html
@@ -266,7 +266,7 @@
 (<code>float</code>)</A></nobr><br>
 <nobr><A HREF="android.support.v4.view.ViewPropertyAnimatorCompat.html#android.support.v4.view.ViewPropertyAnimatorCompat.zBy_added(float)" class="hiddenlink" target="rightframe"><b>zBy</b>
 (<code>float</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_changes.html b/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_changes.html
index 3e43f87..3bfd471 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_changes.html
@@ -53,7 +53,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.view.ViewPager.html#android.support.v4.view.ViewPager.setOnPageChangeListener_changed(android.support.v4.view.ViewPager.OnPageChangeListener)" class="hiddenlink" target="rightframe">setOnPageChangeListener
 (<code>OnPageChangeListener</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_removals.html b/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_removals.html
index b5aea4f..e85e6fc 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/methods_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_additions.html b/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_additions.html
index 7d92a82..183d500 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_additions.html
@@ -61,7 +61,7 @@
 <A HREF="changes-summary.html#android.support.v7.appcompat" class="hiddenlink" target="rightframe"><b>android.support.v7.appcompat</b></A><br>
 <A HREF="changes-summary.html#android.support.v7.recyclerview" class="hiddenlink" target="rightframe"><b>android.support.v7.recyclerview</b></A><br>
 <A HREF="changes-summary.html#android.support.v7.widget.helper" class="hiddenlink" target="rightframe"><b>android.support.v7.widget.helper</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_all.html b/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_all.html
index 2735fe9..0fb83cf 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_all.html
@@ -66,7 +66,7 @@
 <A HREF="changes-summary.html#android.support.v7.recyclerview" class="hiddenlink" target="rightframe"><b>android.support.v7.recyclerview</b></A><br>
 <A HREF="pkg_android.support.v7.util.html" class="hiddenlink" target="rightframe">android.support.v7.util</A><br>
 <A HREF="changes-summary.html#android.support.v7.widget.helper" class="hiddenlink" target="rightframe"><b>android.support.v7.widget.helper</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_changes.html b/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_changes.html
index 3e40878..917e060 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_changes.html
@@ -55,7 +55,7 @@
 <A HREF="pkg_android.support.v4.view.accessibility.html" class="hiddenlink" target="rightframe">android.support.v4.view.accessibility</A><br>
 <A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
 <A HREF="pkg_android.support.v7.util.html" class="hiddenlink" target="rightframe">android.support.v7.util</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_removals.html b/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_removals.html
index d0ffabc..d5a825d 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/packages_index_removals.html
@@ -49,7 +49,7 @@
 </div>
 <br>
 <div id="indexTableEntries">
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.media.session.html b/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.media.session.html
index 4dfd7de..992f05d 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.media.session.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.media.session.html
@@ -119,7 +119,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.view.accessibility.html b/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.view.accessibility.html
index f52efcb..86dc841 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.view.accessibility.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.view.accessibility.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.view.html b/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.view.html
index f05d812..ad51e62 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.view.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v4.view.html
@@ -126,7 +126,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v7.app.html b/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v7.app.html
index 44bf61d..508323f 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v7.app.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v7.app.html
@@ -126,7 +126,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v7.util.html b/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v7.util.html
index d08d9af..8f74fb7 100644
--- a/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v7.util.html
+++ b/docs/html/sdk/support_api_diff/22.2.0/changes/pkg_android.support.v7.util.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_additions.html b/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_additions.html
index 3374ffd..a1055f1 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_additions.html
@@ -660,7 +660,7 @@
 <!-- Method useStaticShadow -->
 <nobr><A HREF="android.support.v17.leanback.widget.ShadowOverlayContainer.html#android.support.v17.leanback.widget.ShadowOverlayContainer.useStaticShadow_added()" class="hiddenlink" target="rightframe"><b>useStaticShadow</b>
 ()</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_all.html b/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_all.html
index bb24c29..48f43d2 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_all.html
@@ -913,7 +913,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v17.leanback.widget.VerticalGridPresenter.html" class="hiddenlink" target="rightframe">VerticalGridPresenter</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_changes.html b/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_changes.html
index 8340749..d5b60c9 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_changes.html
@@ -389,7 +389,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v17.leanback.widget.VerticalGridPresenter.html" class="hiddenlink" target="rightframe">VerticalGridPresenter</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_removals.html b/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_removals.html
index 0d670c0..f2a8797 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/alldiffs_index_removals.html
@@ -83,7 +83,7 @@
 <!-- Field Platform_V12_AppCompat_Light -->
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.Platform_V12_AppCompat_Light" class="hiddenlink" target="rightframe"><strike>Platform_V12_AppCompat_Light</strike></A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.CoordinatorLayout.Behavior.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.CoordinatorLayout.Behavior.html
index 78392f4..c45efa2 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.CoordinatorLayout.Behavior.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.CoordinatorLayout.Behavior.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.FloatingActionButton.Behavior.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.FloatingActionButton.Behavior.html
index 6d68976..a23105a 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.FloatingActionButton.Behavior.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.FloatingActionButton.Behavior.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.FloatingActionButton.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.FloatingActionButton.html
index 21b55c0..91a6d77 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.FloatingActionButton.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.FloatingActionButton.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.Snackbar.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.Snackbar.html
index 028df73..24fdf70 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.Snackbar.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.Snackbar.html
@@ -130,7 +130,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.TabLayout.Tab.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.TabLayout.Tab.html
index 2acf995..74a296d 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.TabLayout.Tab.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.TabLayout.Tab.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.TabLayout.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.TabLayout.html
index 22a5ff5..3a8d151 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.TabLayout.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.design.widget.TabLayout.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.app.DetailsFragment.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.app.DetailsFragment.html
index 16e5798..7ae6ce1 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.app.DetailsFragment.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.app.DetailsFragment.html
@@ -136,7 +136,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.app.DetailsSupportFragment.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.app.DetailsSupportFragment.html
index 7825292..d1733ac 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.app.DetailsSupportFragment.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.app.DetailsSupportFragment.html
@@ -136,7 +136,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.DetailsOverviewRowPresenter.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.DetailsOverviewRowPresenter.html
index ba8e6af..799db3d 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.DetailsOverviewRowPresenter.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.DetailsOverviewRowPresenter.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder.html
index 25f1b48..f8c0cbf 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ItemBridgeAdapter.ViewHolder.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ItemBridgeAdapter.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ItemBridgeAdapter.html
index a88f694..b98c33e 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ItemBridgeAdapter.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ItemBridgeAdapter.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ListRowPresenter.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ListRowPresenter.html
index 5d71011..f9ad877 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ListRowPresenter.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ListRowPresenter.html
@@ -111,7 +111,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.OnChildSelectedListener.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.OnChildSelectedListener.html
index eb8a563..f13b147 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.OnChildSelectedListener.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.OnChildSelectedListener.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.Presenter.ViewHolder.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.Presenter.ViewHolder.html
index a94d9f5..55f3575 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.Presenter.ViewHolder.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.Presenter.ViewHolder.html
@@ -116,7 +116,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.Presenter.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.Presenter.html
index fde5e4b..417bf86 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.Presenter.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.Presenter.html
@@ -116,7 +116,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.PresenterSelector.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.PresenterSelector.html
index 06a0a79..827b2cf 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.PresenterSelector.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.PresenterSelector.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.RowPresenter.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.RowPresenter.html
index 6da5f9b..24b7683 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.RowPresenter.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.RowPresenter.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ShadowOverlayContainer.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ShadowOverlayContainer.html
index ac3ac3a..9814065 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ShadowOverlayContainer.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.ShadowOverlayContainer.html
@@ -172,7 +172,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.VerticalGridPresenter.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.VerticalGridPresenter.html
index ab9ce07..c18075e 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.VerticalGridPresenter.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v17.leanback.widget.VerticalGridPresenter.html
@@ -111,7 +111,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompat.Action.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompat.Action.html
index 8519610..d96b874 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompat.Action.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompat.Action.html
@@ -131,7 +131,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompatBase.Action.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompatBase.Action.html
index 498374e..09ae7fc 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompatBase.Action.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompatBase.Action.html
@@ -151,7 +151,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompatBase.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompatBase.html
index 309d7b6..9824574 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompatBase.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v4.app.NotificationCompatBase.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.attr.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.attr.html
index 229289c..541f134 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.attr.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.attr.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.dimen.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.dimen.html
index a253e59..584073e 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.dimen.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.dimen.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.drawable.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.drawable.html
index 4f87127..45a1dc7 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.drawable.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.drawable.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.id.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.id.html
index e856c8b..cecd912 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.id.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.id.html
@@ -192,7 +192,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.integer.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.integer.html
index 70585a7..4b90739 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.integer.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.integer.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.layout.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.layout.html
index 8130707..c0a1304 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.layout.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.layout.html
@@ -157,7 +157,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.string.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.string.html
index 6a01b20..39be2b2 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.string.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.string.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.style.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.style.html
index 886f2ce..ffc3690 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.style.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.style.html
@@ -186,7 +186,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.styleable.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.styleable.html
index cd9cd60..713526b 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.styleable.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.appcompat.R.styleable.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.util.SortedList.html b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.util.SortedList.html
index b38c632..181a0fc 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.util.SortedList.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/android.support.v7.util.SortedList.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/changes-summary.html b/docs/html/sdk/support_api_diff/22.2.1/changes/changes-summary.html
index e05b67d..b500246 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/changes-summary.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/changes-summary.html
@@ -177,7 +177,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_additions.html b/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_additions.html
index 52b4ab7..f2fe6ec 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_additions.html
@@ -103,7 +103,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="pkg_android.support.v17.leanback.widget.html#OnChildViewHolderSelectedListener" class="hiddenlink" target="rightframe"><b>OnChildViewHolderSelectedListener</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_all.html b/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_all.html
index 1edab7a..16ebdfa 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_all.html
@@ -339,7 +339,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v17.leanback.widget.VerticalGridPresenter.html" class="hiddenlink" target="rightframe">VerticalGridPresenter</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_changes.html b/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_changes.html
index f46bc67..8072f0f 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_changes.html
@@ -259,7 +259,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v17.leanback.widget.VerticalGridPresenter.html" class="hiddenlink" target="rightframe">VerticalGridPresenter</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_removals.html b/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_removals.html
index 09c0d19..757f5bb 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/classes_index_removals.html
@@ -63,7 +63,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="pkg_android.support.v17.leanback.widget.html#GridLayoutManager" class="hiddenlink" target="rightframe"><strike>GridLayoutManager</strike></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_additions.html b/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_additions.html
index e694216..3bced29 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_additions.html
@@ -53,7 +53,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.app.NotificationCompatBase.html#android.support.v4.app.NotificationCompatBase.ctor_added()" class="hiddenlink" target="rightframe"><b>NotificationCompatBase</b>
 ()</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_all.html b/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_all.html
index 27d7557..7769d75 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_all.html
@@ -53,7 +53,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.app.NotificationCompatBase.html#android.support.v4.app.NotificationCompatBase.ctor_added()" class="hiddenlink" target="rightframe"><b>NotificationCompatBase</b>
 ()</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_changes.html b/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_changes.html
index a5ca2ef..122cdce 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_changes.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_removals.html b/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_removals.html
index 74a09ba..dadd1cd 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/constructors_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_additions.html b/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_additions.html
index 2ae5237..5d6411a 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_additions.html
@@ -263,7 +263,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v7.appcompat.R.id.html#android.support.v7.appcompat.R.id.time" class="hiddenlink" target="rightframe">time</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_all.html b/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_all.html
index 4a9194d..85420c3 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_all.html
@@ -291,7 +291,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v7.appcompat.R.id.html#android.support.v7.appcompat.R.id.time" class="hiddenlink" target="rightframe">time</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_changes.html b/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_changes.html
index 0e2ccff..301881a 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_changes.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_removals.html b/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_removals.html
index 6245b05..b1bf691 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/fields_index_removals.html
@@ -55,7 +55,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.Platform_V12_AppCompat_Light" class="hiddenlink" target="rightframe"><strike>Platform_V12_AppCompat_Light</strike></A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_help.html b/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_help.html
index 25acfbe..f9c1f08 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_help.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_help.html
@@ -120,7 +120,7 @@
 There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass. 
 In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes. 
 </BLOCKQUOTE>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_statistics.html b/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_statistics.html
index 0f4805f..322ad44 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_statistics.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_statistics.html
@@ -368,7 +368,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_topleftframe.html b/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_topleftframe.html
index 36f9836..6a2e76e 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_topleftframe.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/jdiff_topleftframe.html
@@ -49,7 +49,7 @@
   <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="fields_index_all.html" TARGET="bottomleftframe">By Field</A></FONT><br></TD>
 </TR>
 </TABLE>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_additions.html b/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_additions.html
index 33a155f..5a237de 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_additions.html
@@ -224,7 +224,7 @@
 </A></nobr><br>
 <nobr><A HREF="android.support.v17.leanback.widget.ShadowOverlayContainer.html#android.support.v17.leanback.widget.ShadowOverlayContainer.useStaticShadow_added()" class="hiddenlink" target="rightframe"><b>useStaticShadow</b>
 ()</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_all.html b/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_all.html
index b9cf858..014ef9a 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_all.html
@@ -256,7 +256,7 @@
 </A></nobr><br>
 <nobr><A HREF="android.support.v17.leanback.widget.ShadowOverlayContainer.html#android.support.v17.leanback.widget.ShadowOverlayContainer.useStaticShadow_added()" class="hiddenlink" target="rightframe"><b>useStaticShadow</b>
 ()</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_changes.html b/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_changes.html
index 4e2d329..6b02e2a 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_changes.html
@@ -89,7 +89,7 @@
 &nbsp;&nbsp;<nobr><A HREF="android.support.v17.leanback.widget.VerticalGridPresenter.html#android.support.v17.leanback.widget.VerticalGridPresenter.isUsingZOrder_changed(android.content.Context)" class="hiddenlink" target="rightframe">type&nbsp;
 (<code>Context</code>)&nbsp;in&nbsp;android.support.v17.leanback.widget.VerticalGridPresenter
 </A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_removals.html b/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_removals.html
index b5aea4f..e85e6fc 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/methods_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_additions.html b/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_additions.html
index 6311752..d08c85c 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_additions.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_additions.html
@@ -51,7 +51,7 @@
 <div id="indexTableEntries">
 <A NAME="A"></A>
 <A HREF="changes-summary.html#android.support.v17.leanback.system" class="hiddenlink" target="rightframe"><b>android.support.v17.leanback.system</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_all.html b/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_all.html
index 3f5ee13..712eac9 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_all.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_all.html
@@ -58,7 +58,7 @@
 <A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
 <A HREF="pkg_android.support.v7.appcompat.html" class="hiddenlink" target="rightframe">android.support.v7.appcompat</A><br>
 <A HREF="pkg_android.support.v7.util.html" class="hiddenlink" target="rightframe">android.support.v7.util</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_changes.html b/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_changes.html
index a4637a7..e53ee87 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_changes.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_changes.html
@@ -57,7 +57,7 @@
 <A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
 <A HREF="pkg_android.support.v7.appcompat.html" class="hiddenlink" target="rightframe">android.support.v7.appcompat</A><br>
 <A HREF="pkg_android.support.v7.util.html" class="hiddenlink" target="rightframe">android.support.v7.util</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_removals.html b/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_removals.html
index d0ffabc..d5a825d 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_removals.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/packages_index_removals.html
@@ -49,7 +49,7 @@
 </div>
 <br>
 <div id="indexTableEntries">
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.design.widget.html b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.design.widget.html
index 345f33b..25070ce 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.design.widget.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.design.widget.html
@@ -140,7 +140,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v17.leanback.app.html b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v17.leanback.app.html
index 873bc6b..48f868b 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v17.leanback.app.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v17.leanback.app.html
@@ -112,7 +112,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v17.leanback.widget.html b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v17.leanback.widget.html
index 7197d3a..ac3d8435 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v17.leanback.widget.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v17.leanback.widget.html
@@ -324,7 +324,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v4.app.html b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v4.app.html
index 1d15399..3122461 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v4.app.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v4.app.html
@@ -119,7 +119,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.app.html b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.app.html
index 47c0894..5f69310 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.app.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.app.html
@@ -119,7 +119,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.appcompat.html b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.appcompat.html
index 4c562ae..00bcf19 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.appcompat.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.appcompat.html
@@ -161,7 +161,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.util.html b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.util.html
index bac0313..e0f4bcd 100644
--- a/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.util.html
+++ b/docs/html/sdk/support_api_diff/22.2.1/changes/pkg_android.support.v7.util.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_additions.html b/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_additions.html
index 5495f89..1717f7d 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_additions.html
@@ -1104,7 +1104,7 @@
 <!-- Field Widget_AppCompat_SeekBar -->
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.Widget_AppCompat_SeekBar" class="hiddenlink" target="rightframe">Widget_AppCompat_SeekBar</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_all.html b/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_all.html
index 575ee95..d4c30e3 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_all.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_all.html
@@ -1511,7 +1511,7 @@
 <!-- Field Widget_AppCompat_SeekBar -->
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.Widget_AppCompat_SeekBar" class="hiddenlink" target="rightframe">Widget_AppCompat_SeekBar</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_changes.html b/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_changes.html
index d7ebd36..6562fa8 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_changes.html
@@ -548,7 +548,7 @@
 <A HREF="android.support.v17.leanback.app.VerticalGridSupportFragment.html" class="hiddenlink" target="rightframe">VerticalGridSupportFragment</A><br>
 <!-- Class ViewCompat -->
 <A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_removals.html b/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_removals.html
index 0d7da0f..9b21b1d 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/alldiffs_index_removals.html
@@ -270,7 +270,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.setEntryTransitionEnabled_removed(boolean)" class="hiddenlink" target="rightframe"><strike>setEntryTransitionEnabled</strike>
 (<code>boolean</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsCallback.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsCallback.html
index 0466d5d..6ba5f831 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsCallback.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsCallback.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html
index e3aefb5..c53722b 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsIntent.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsIntent.html
index 9312755..db59258 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsIntent.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsIntent.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsService.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsService.html
index 2a0fd18..fd5a12b 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsService.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsService.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsSession.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsSession.html
index 6b70224..6910bab 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsSession.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsSession.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsSessionToken.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsSessionToken.html
index 2bdb42e..0282d49 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsSessionToken.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.customtabs.CustomTabsSessionToken.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.Behavior.SavedState.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.Behavior.SavedState.html
index bb89bbd..cea16c0 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.Behavior.SavedState.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.Behavior.SavedState.html
@@ -123,7 +123,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.Behavior.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.Behavior.html
index b538999a..672951d 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.Behavior.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.Behavior.html
@@ -131,7 +131,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.LayoutParams.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.LayoutParams.html
index 6d19d36..0218c30 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.LayoutParams.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.LayoutParams.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html
index c089db3..424a618 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html
@@ -124,7 +124,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.CollapsingToolbarLayout.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.CollapsingToolbarLayout.html
index 49d92737..8e708c0 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.CollapsingToolbarLayout.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.CollapsingToolbarLayout.html
@@ -143,7 +143,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.CoordinatorLayout.SavedState.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.CoordinatorLayout.SavedState.html
index f92babd..496a460 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.CoordinatorLayout.SavedState.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.CoordinatorLayout.SavedState.html
@@ -123,7 +123,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html
index 07fdda1..eba4247 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.FloatingActionButton.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.FloatingActionButton.html
index 90553fa..520fdcf 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.FloatingActionButton.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.FloatingActionButton.html
@@ -116,7 +116,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.NavigationView.SavedState.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.NavigationView.SavedState.html
index 8a9ae80..61428ca 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.NavigationView.SavedState.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.NavigationView.SavedState.html
@@ -123,7 +123,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.Snackbar.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.Snackbar.html
index d741863..f33e47a 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.Snackbar.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.Snackbar.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.TextInputLayout.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.TextInputLayout.html
index 30d0dd6..609e864 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.TextInputLayout.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.design.widget.TextInputLayout.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.percent.PercentLayoutHelper.PercentLayoutInfo.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.percent.PercentLayoutHelper.PercentLayoutInfo.html
index b6f2e48..967542f 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.percent.PercentLayoutHelper.PercentLayoutInfo.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.percent.PercentLayoutHelper.PercentLayoutInfo.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v14.preference.EditTextPreferenceDialogFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v14.preference.EditTextPreferenceDialogFragment.html
index 30f22a8..6b6151b 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v14.preference.EditTextPreferenceDialogFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v14.preference.EditTextPreferenceDialogFragment.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.BrowseFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.BrowseFragment.html
index f4d77bf..14f6fdfa 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.BrowseFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.BrowseFragment.html
@@ -150,7 +150,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html
index a48ea3b..7adcbe8 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html
@@ -150,7 +150,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.DetailsFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.DetailsFragment.html
index d38127c..2240f4e 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.DetailsFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.DetailsFragment.html
@@ -143,7 +143,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.DetailsSupportFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.DetailsSupportFragment.html
index a02b8f3..23ca151 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.DetailsSupportFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.DetailsSupportFragment.html
@@ -143,7 +143,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html
index 725281a..4c78b30 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html
@@ -215,7 +215,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.PlaybackOverlayFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.PlaybackOverlayFragment.html
index 71e230b..ecb35bef 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.PlaybackOverlayFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.PlaybackOverlayFragment.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html
index a794f14..1809374 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.SearchFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.SearchFragment.html
index 827f46b..2c444ae 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.SearchFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.SearchFragment.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.SearchSupportFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.SearchSupportFragment.html
index f1e2826..7ff0204 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.SearchSupportFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.SearchSupportFragment.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.VerticalGridFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.VerticalGridFragment.html
index 01bb4de..5516bda 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.VerticalGridFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.VerticalGridFragment.html
@@ -137,7 +137,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.VerticalGridSupportFragment.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.VerticalGridSupportFragment.html
index a818a79..0f09ec0 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.VerticalGridSupportFragment.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.app.VerticalGridSupportFragment.html
@@ -154,7 +154,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.FragmentAnimationProvider.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.FragmentAnimationProvider.html
index 1cf004d..e457402 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.FragmentAnimationProvider.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.FragmentAnimationProvider.html
@@ -165,7 +165,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidanceStylist.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidanceStylist.html
index e0b94bc..9794929 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidanceStylist.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidanceStylist.html
@@ -165,7 +165,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedAction.Builder.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedAction.Builder.html
index 96d30a4..3408bd9 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedAction.Builder.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedAction.Builder.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedAction.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedAction.html
index 84b93bf..857b7d8 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedAction.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedAction.html
@@ -143,7 +143,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder.html
index 38e83b4..497e985 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html
index 104f325..cd45d6d 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html
@@ -165,7 +165,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ImageCardView.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ImageCardView.html
index 1535ca0..a5aa07e 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ImageCardView.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ImageCardView.html
@@ -151,7 +151,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ListRowPresenter.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ListRowPresenter.html
index f536d92..11b95c40 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ListRowPresenter.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ListRowPresenter.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.RowPresenter.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.RowPresenter.html
index 3f10b29..0f254d7 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.RowPresenter.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.RowPresenter.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.SearchBar.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.SearchBar.html
index 2965c15..6e4b41c 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.SearchBar.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.SearchBar.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ShadowOverlayContainer.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ShadowOverlayContainer.html
index 761fd92..553bbb1 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ShadowOverlayContainer.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.ShadowOverlayContainer.html
@@ -127,7 +127,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.VerticalGridPresenter.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.VerticalGridPresenter.html
index e999838..f1d6fb6 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.VerticalGridPresenter.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v17.leanback.widget.VerticalGridPresenter.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.app.FragmentActivity.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.app.FragmentActivity.html
index c68356c..dd88aca 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.app.FragmentActivity.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.app.FragmentActivity.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.content.res.ResourcesCompat.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.content.res.ResourcesCompat.html
index 9bdd4f7..bb339da 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.content.res.ResourcesCompat.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.content.res.ResourcesCompat.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.media.session.MediaSessionCompat.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.media.session.MediaSessionCompat.html
index 5b5f1e3..278f42d 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.media.session.MediaSessionCompat.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.media.session.MediaSessionCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.view.ViewCompat.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.view.ViewCompat.html
index 2e39745..03dda58 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.view.ViewCompat.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.view.ViewCompat.html
@@ -179,7 +179,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.NestedScrollView.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.NestedScrollView.html
index 8d4cbaa..cdb3d13 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.NestedScrollView.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.NestedScrollView.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.ScrollerCompat.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.ScrollerCompat.html
index 7f47eae..9ef847e 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.ScrollerCompat.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.ScrollerCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.TextViewCompat.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.TextViewCompat.html
index 3641625..87b1da2 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.TextViewCompat.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v4.widget.TextViewCompat.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.attr.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.attr.html
index dc6fce2..ef31519 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.attr.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.attr.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.bool.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.bool.html
index 973cf83..c26367a 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.bool.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.bool.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.dimen.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.dimen.html
index ca5fec2..bd324cb 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.dimen.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.dimen.html
@@ -186,7 +186,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.drawable.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.drawable.html
index 3cfba65..c9264d6 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.drawable.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.drawable.html
@@ -157,7 +157,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.id.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.id.html
index a25139d..e7f9f95 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.id.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.id.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.layout.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.layout.html
index 0b485ea..c04d4f7 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.layout.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.layout.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.string.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.string.html
index b5b32c7..9dc84ab 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.string.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.string.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.style.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.style.html
index a7b4e2d..58f9025 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.style.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.style.html
@@ -158,7 +158,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.styleable.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.styleable.html
index 3f6d157..49adae8 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.styleable.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.appcompat.R.styleable.html
@@ -150,7 +150,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.graphics.Palette.Builder.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.graphics.Palette.Builder.html
index 03171fb..22ee483 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.graphics.Palette.Builder.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.graphics.Palette.Builder.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.graphics.drawable.DrawerArrowDrawable.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.graphics.drawable.DrawerArrowDrawable.html
index ec3cb15..77232ba 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.graphics.drawable.DrawerArrowDrawable.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.graphics.drawable.DrawerArrowDrawable.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouteDescriptor.Builder.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouteDescriptor.Builder.html
index aec06c0..5cac372 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouteDescriptor.Builder.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouteDescriptor.Builder.html
@@ -154,7 +154,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouteDescriptor.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouteDescriptor.html
index 381eb20..437c56d 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouteDescriptor.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouteDescriptor.html
@@ -147,7 +147,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouter.RouteInfo.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouter.RouteInfo.html
index 239341d..51afa4f 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouter.RouteInfo.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.media.MediaRouter.RouteInfo.html
@@ -166,7 +166,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.preference.EditTextPreferenceDialogFragmentCompat.html b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.preference.EditTextPreferenceDialogFragmentCompat.html
index 05b65ff..ac63d53 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.preference.EditTextPreferenceDialogFragmentCompat.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/android.support.v7.preference.EditTextPreferenceDialogFragmentCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/changes-summary.html b/docs/html/sdk/support_api_diff/23.1.0/changes/changes-summary.html
index 728ade1..d9658ba 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/changes-summary.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/changes-summary.html
@@ -232,7 +232,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_additions.html b/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_additions.html
index c0022c9..1a97c98 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_additions.html
@@ -197,7 +197,7 @@
 <A HREF="pkg_android.support.v17.leanback.widget.html#ShadowOverlayHelper" class="hiddenlink" target="rightframe"><b>ShadowOverlayHelper</b></A><br>
 <A HREF="pkg_android.support.v17.leanback.widget.html#ShadowOverlayHelper.Builder" class="hiddenlink" target="rightframe"><b>ShadowOverlayHelper.Builder</b></A><br>
 <A HREF="pkg_android.support.v17.leanback.widget.html#ShadowOverlayHelper.Options" class="hiddenlink" target="rightframe"><b>ShadowOverlayHelper.Options</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_all.html b/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_all.html
index 05f83b8..c8f86f4 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_all.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_all.html
@@ -471,7 +471,7 @@
 <A HREF="android.support.v17.leanback.widget.VerticalGridPresenter.html" class="hiddenlink" target="rightframe">VerticalGridPresenter</A><br>
 <A HREF="android.support.v17.leanback.app.VerticalGridSupportFragment.html" class="hiddenlink" target="rightframe">VerticalGridSupportFragment</A><br>
 <A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_changes.html b/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_changes.html
index b1ee972..f280906 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_changes.html
@@ -415,7 +415,7 @@
 <A HREF="android.support.v17.leanback.widget.VerticalGridPresenter.html" class="hiddenlink" target="rightframe">VerticalGridPresenter</A><br>
 <A HREF="android.support.v17.leanback.app.VerticalGridSupportFragment.html" class="hiddenlink" target="rightframe">VerticalGridSupportFragment</A><br>
 <A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_removals.html b/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_removals.html
index e6da73f..c466298 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/classes_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_additions.html b/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_additions.html
index 3bf8178..45f72f1 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_additions.html
@@ -97,7 +97,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.design.widget.NavigationView.SavedState.html#android.support.design.widget.NavigationView.SavedState.ctor_added(android.os.Parcel, java.lang.ClassLoader)" class="hiddenlink" target="rightframe"><b>NavigationView.SavedState</b>
 (<code>Parcel, ClassLoader</code>)</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_all.html b/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_all.html
index 546eae8..8dda68f 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_all.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_all.html
@@ -106,7 +106,7 @@
 (<code>Parcel</code>)</A></nobr>&nbsp;constructor<br>
 &nbsp;&nbsp;<nobr><A HREF="android.support.design.widget.NavigationView.SavedState.html#android.support.design.widget.NavigationView.SavedState.ctor_added(android.os.Parcel, java.lang.ClassLoader)" class="hiddenlink" target="rightframe"><b>NavigationView.SavedState</b>
 (<code>Parcel, ClassLoader</code>)</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_changes.html b/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_changes.html
index 52c8b49..d6584d1 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_changes.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_removals.html b/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_removals.html
index 337274d..49ee23c 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/constructors_index_removals.html
@@ -71,7 +71,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.design.widget.NavigationView.SavedState.html#android.support.design.widget.NavigationView.SavedState.ctor_removed(android.os.Parcel)" class="hiddenlink" target="rightframe"><strike>NavigationView.SavedState</strike>
 (<code>Parcel</code>)</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_additions.html b/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_additions.html
index d1ef3ac..0c43320 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_additions.html
@@ -329,7 +329,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.Widget_AppCompat_SeekBar" class="hiddenlink" target="rightframe">Widget_AppCompat_SeekBar</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_all.html b/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_all.html
index 697f16a..71d9b71 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_all.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_all.html
@@ -339,7 +339,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.Widget_AppCompat_SeekBar" class="hiddenlink" target="rightframe">Widget_AppCompat_SeekBar</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_changes.html b/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_changes.html
index 0e2ccff..301881a 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_changes.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_removals.html b/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_removals.html
index 93bcdc3..f520de6 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/fields_index_removals.html
@@ -67,7 +67,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.RtlOverlay_Widget_AppCompat_ActionButton_Overflow" class="hiddenlink" target="rightframe"><strike>RtlOverlay_Widget_AppCompat_ActionButton_Overflow</strike></A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_help.html b/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_help.html
index b03b763..0ba76e7 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_help.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_help.html
@@ -120,7 +120,7 @@
 There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass. 
 In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes. 
 </BLOCKQUOTE>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_statistics.html b/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_statistics.html
index bdda25f..ac4d43e 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_statistics.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_statistics.html
@@ -568,7 +568,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_topleftframe.html b/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_topleftframe.html
index 36f9836..6a2e76e 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_topleftframe.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/jdiff_topleftframe.html
@@ -49,7 +49,7 @@
   <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="fields_index_all.html" TARGET="bottomleftframe">By Field</A></FONT><br></TD>
 </TR>
 </TABLE>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_additions.html b/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_additions.html
index 9b4eab3..fee36df 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_additions.html
@@ -516,7 +516,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.customtabs.CustomTabsService.html#android.support.customtabs.CustomTabsService.updateVisuals_added(android.support.customtabs.CustomTabsSessionToken, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>updateVisuals</b>
 (<code>CustomTabsSessionToken, Bundle</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_all.html b/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_all.html
index d63656c..7a2fe5c 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_all.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_all.html
@@ -616,7 +616,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.customtabs.CustomTabsService.html#android.support.customtabs.CustomTabsService.updateVisuals_added(android.support.customtabs.CustomTabsSessionToken, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>updateVisuals</b>
 (<code>CustomTabsSessionToken, Bundle</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_changes.html b/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_changes.html
index 8271b35..254a721 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_changes.html
@@ -77,7 +77,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v7.media.MediaRouteDescriptor.Builder.html#android.support.v7.media.MediaRouteDescriptor.Builder.setConnecting_changed(boolean)" class="hiddenlink" target="rightframe">setConnecting
 (<code>boolean</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_removals.html b/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_removals.html
index 7250505..0b6f2b4 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/methods_index_removals.html
@@ -158,7 +158,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.setEntryTransitionEnabled_removed(boolean)" class="hiddenlink" target="rightframe"><strike>setEntryTransitionEnabled</strike>
 (<code>boolean</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_additions.html b/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_additions.html
index 1776064..e7ed63e 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_additions.html
@@ -49,7 +49,7 @@
 </div>
 <br>
 <div id="indexTableEntries">
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_all.html b/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_all.html
index 2bf0974..4236847 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_all.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_all.html
@@ -67,7 +67,7 @@
 <A HREF="pkg_android.support.v7.graphics.drawable.html" class="hiddenlink" target="rightframe">android.support.v7.graphics.drawable</A><br>
 <A HREF="pkg_android.support.v7.media.html" class="hiddenlink" target="rightframe">android.support.v7.media</A><br>
 <A HREF="pkg_android.support.v7.preference.html" class="hiddenlink" target="rightframe">android.support.v7.preference</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_changes.html b/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_changes.html
index 519e9aa..8d51ea2 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_changes.html
@@ -67,7 +67,7 @@
 <A HREF="pkg_android.support.v7.graphics.drawable.html" class="hiddenlink" target="rightframe">android.support.v7.graphics.drawable</A><br>
 <A HREF="pkg_android.support.v7.media.html" class="hiddenlink" target="rightframe">android.support.v7.media</A><br>
 <A HREF="pkg_android.support.v7.preference.html" class="hiddenlink" target="rightframe">android.support.v7.preference</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_removals.html b/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_removals.html
index 9fd0f7e..ae935f4 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/packages_index_removals.html
@@ -49,7 +49,7 @@
 </div>
 <br>
 <div id="indexTableEntries">
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.customtabs.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.customtabs.html
index d85f3f8..ea62004 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.customtabs.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.customtabs.html
@@ -140,7 +140,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.design.widget.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.design.widget.html
index 449afa6..45625b9 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.design.widget.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.design.widget.html
@@ -211,7 +211,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.percent.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.percent.html
index 53b92a9..13b9732 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.percent.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.percent.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v14.preference.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v14.preference.html
index 3ef0a0f..7364b7c 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v14.preference.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v14.preference.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v17.leanback.app.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v17.leanback.app.html
index 49ee52f..21763fb 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v17.leanback.app.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v17.leanback.app.html
@@ -211,7 +211,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v17.leanback.widget.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v17.leanback.widget.html
index 73d5050..ff00794 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v17.leanback.widget.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v17.leanback.widget.html
@@ -239,7 +239,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.app.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.app.html
index b1645a6..ccdb5fe 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.app.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.app.html
@@ -120,7 +120,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.content.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.content.html
index efc62c9..b1b6ffc 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.content.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.content.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.content.res.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.content.res.html
index fd9c9f8..f6a1367 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.content.res.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.content.res.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.media.session.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.media.session.html
index afd23b1..1182648 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.media.session.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.media.session.html
@@ -120,7 +120,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.view.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.view.html
index 7d74c82..b4fe9b2 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.view.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.view.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.widget.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.widget.html
index 4ca7874..e32ebc8 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.widget.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v4.widget.html
@@ -134,7 +134,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.appcompat.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.appcompat.html
index 553bdf2..b516a35 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.appcompat.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.appcompat.html
@@ -161,7 +161,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.graphics.drawable.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.graphics.drawable.html
index e9d5cd9..69c91d5 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.graphics.drawable.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.graphics.drawable.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.graphics.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.graphics.html
index ba9a092..13d6ef9 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.graphics.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.graphics.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.media.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.media.html
index 7892bf9..4c2094c 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.media.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.media.html
@@ -134,7 +134,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.preference.html b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.preference.html
index ced3a90..ed590bb 100644
--- a/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.preference.html
+++ b/docs/html/sdk/support_api_diff/23.1.0/changes/pkg_android.support.v7.preference.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_additions.html b/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_additions.html
index 09ec1eb..3b43f27 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_additions.html
@@ -1955,7 +1955,7 @@
 <!-- Method XYZToLAB -->
 <nobr><A HREF="android.support.v4.graphics.ColorUtils.html#android.support.v4.graphics.ColorUtils.XYZToLAB_added(double, double, double, double[])" class="hiddenlink" target="rightframe"><b>XYZToLAB</b>
 (<code>double, double, double, double[]</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_all.html b/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_all.html
index 770d615..6264757 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_all.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_all.html
@@ -2914,7 +2914,7 @@
 <!-- Method XYZToLAB -->
 <nobr><A HREF="android.support.v4.graphics.ColorUtils.html#android.support.v4.graphics.ColorUtils.XYZToLAB_added(double, double, double, double[])" class="hiddenlink" target="rightframe"><b>XYZToLAB</b>
 (<code>double, double, double, double[]</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_changes.html b/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_changes.html
index 134580d..6113a9e 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_changes.html
@@ -939,7 +939,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v4.view.WindowCompat.html" class="hiddenlink" target="rightframe">WindowCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_removals.html b/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_removals.html
index a60b244..2df39dc 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/alldiffs_index_removals.html
@@ -956,7 +956,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.view.WindowCompat.html#android.support.v4.view.WindowCompat.ctor_removed()" class="hiddenlink" target="rightframe"><strike>WindowCompat</strike>
 ()</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html
index 46a0548..3e97afd 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsIntent.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsIntent.html
index 7987724..d7745e6 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsIntent.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsIntent.html
@@ -151,7 +151,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsSession.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsSession.html
index 1296d4c..9b48018 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsSession.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.customtabs.CustomTabsSession.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html
index d539481..80c8e11 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html
@@ -136,7 +136,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html
index e47f317..e1ae295 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html
@@ -164,7 +164,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html
index 04efe89..ee87ca6 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html
@@ -121,7 +121,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.FloatingActionButton.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.FloatingActionButton.html
index 985adba..33d67e2 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.FloatingActionButton.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.FloatingActionButton.html
@@ -144,7 +144,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.HeaderScrollingViewBehavior.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.HeaderScrollingViewBehavior.html
index 7021ba2..0e24356 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.HeaderScrollingViewBehavior.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.HeaderScrollingViewBehavior.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.TabLayout.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.TabLayout.html
index 9224ddb..3d0eb9f 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.TabLayout.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.TabLayout.html
@@ -111,7 +111,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.TextInputLayout.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.TextInputLayout.html
index b0f5d63..d72b373 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.TextInputLayout.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.TextInputLayout.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.ViewOffsetBehavior.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.ViewOffsetBehavior.html
index 1b4625f..9faa826 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.ViewOffsetBehavior.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.design.widget.ViewOffsetBehavior.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.percent.PercentLayoutHelper.PercentLayoutInfo.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.percent.PercentLayoutHelper.PercentLayoutInfo.html
index c13de02..13c0b4e 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.percent.PercentLayoutHelper.PercentLayoutInfo.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.percent.PercentLayoutHelper.PercentLayoutInfo.html
@@ -130,7 +130,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v14.preference.PreferenceFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v14.preference.PreferenceFragment.html
index 3a910d0..7ead465 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v14.preference.PreferenceFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v14.preference.PreferenceFragment.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BaseRowFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BaseRowFragment.html
index 003f04b..9bd2bd7 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BaseRowFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BaseRowFragment.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BaseRowSupportFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BaseRowSupportFragment.html
index 6a30cc3..cf9900c 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BaseRowSupportFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BaseRowSupportFragment.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BrowseFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BrowseFragment.html
index 74cb151..d7d0e76 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BrowseFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BrowseFragment.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html
index a46a8ed..d7bb8c9 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.DetailsFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.DetailsFragment.html
index 34875c3..852b28a 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.DetailsFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.DetailsFragment.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.DetailsSupportFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.DetailsSupportFragment.html
index 4cd41ed..444a537 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.DetailsSupportFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.DetailsSupportFragment.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html
index 0962be7..1cfc19e 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html
@@ -330,7 +330,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.GuidedStepSupportFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.GuidedStepSupportFragment.html
index b464afa..c5f0d5a 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.GuidedStepSupportFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.GuidedStepSupportFragment.html
@@ -330,7 +330,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersFragment.OnHeaderClickedListener.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersFragment.OnHeaderClickedListener.html
index 0df02c4..800f32b 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersFragment.OnHeaderClickedListener.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersFragment.OnHeaderClickedListener.html
@@ -112,7 +112,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersFragment.OnHeaderViewSelectedListener.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersFragment.OnHeaderViewSelectedListener.html
index cc2eeda..70ec556 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersFragment.OnHeaderViewSelectedListener.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersFragment.OnHeaderViewSelectedListener.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderClickedListener.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderClickedListener.html
index 0c59abd..ee37373 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderClickedListener.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderClickedListener.html
@@ -112,7 +112,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderViewSelectedListener.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderViewSelectedListener.html
index ee27726..99e380d 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderViewSelectedListener.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.HeadersSupportFragment.OnHeaderViewSelectedListener.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.RowsFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.RowsFragment.html
index 612c05a..7c78322 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.RowsFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.RowsFragment.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.RowsSupportFragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.RowsSupportFragment.html
index 7cbdf0c..a112b19 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.RowsSupportFragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.app.RowsSupportFragment.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.ViewHolder.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.ViewHolder.html
index 674231e..ef74a40 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.ViewHolder.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.ViewHolder.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.html
index 74e170c..05a2205 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.DetailsOverviewLogoPresenter.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidanceStylist.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidanceStylist.html
index 0a20eb4..f67942e 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidanceStylist.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidanceStylist.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedAction.Builder.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedAction.Builder.html
index b77684b..4d1d86b 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedAction.Builder.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedAction.Builder.html
@@ -281,7 +281,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedAction.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedAction.html
index 20165c7..2ce2773 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedAction.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedAction.html
@@ -307,7 +307,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder.html
index 0849383..b9b78cb 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder.html
@@ -195,7 +195,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html
index a8dff6f..fbe6bb4 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html
@@ -306,7 +306,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.ImageCardView.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.ImageCardView.html
index f110a16..dde52dd 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.ImageCardView.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.ImageCardView.html
@@ -111,7 +111,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.ListRowPresenter.ViewHolder.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.ListRowPresenter.ViewHolder.html
index 2207a6d..9aadb33 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.ListRowPresenter.ViewHolder.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v17.leanback.widget.ListRowPresenter.ViewHolder.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html
index 2479a86..4545dc6 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.AppOpsManagerCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.AppOpsManagerCompat.html
index 15ddb44..8d4b281 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.AppOpsManagerCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.AppOpsManagerCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.BundleCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.BundleCompat.html
index 63ecf79..65cb6ce 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.BundleCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.BundleCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.Fragment.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.Fragment.html
index d6c9e88..adb8e8a 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.Fragment.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.Fragment.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.FragmentActivity.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.FragmentActivity.html
index 72bd4de..843cf68 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.FragmentActivity.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.FragmentActivity.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.FragmentHostCallback.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.FragmentHostCallback.html
index fcb311f..ca9cab8 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.FragmentHostCallback.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.FragmentHostCallback.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.NavUtils.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.NavUtils.html
index e4fb7fa..7267e50 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.NavUtils.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.NavUtils.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.NotificationManagerCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.NotificationManagerCompat.html
index be48aac..06346b2 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.NotificationManagerCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.NotificationManagerCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.RemoteInput.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.RemoteInput.html
index a6a2a2d..006eeee 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.RemoteInput.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.RemoteInput.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.ServiceCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.ServiceCompat.html
index c038e52..613affe 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.ServiceCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.ServiceCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.ShareCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.ShareCompat.html
index 8e9c945..90c0630 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.ShareCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.ShareCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.TaskStackBuilder.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.TaskStackBuilder.html
index 8a8a3c7..12d44de 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.TaskStackBuilder.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.app.TaskStackBuilder.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ContentResolverCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ContentResolverCompat.html
index 6abd31a..37ab80d 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ContentResolverCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ContentResolverCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ContextCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ContextCompat.html
index c0abad2..92f9469 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ContextCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ContextCompat.html
@@ -111,7 +111,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.IntentCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.IntentCompat.html
index 707b2de..37a8b42 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.IntentCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.IntentCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.LocalBroadcastManager.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.LocalBroadcastManager.html
index fb0f8eb..a3d8f89 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.LocalBroadcastManager.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.LocalBroadcastManager.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ParallelExecutorCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ParallelExecutorCompat.html
index 135c65a..3dd3598 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ParallelExecutorCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.ParallelExecutorCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.SharedPreferencesCompat.EditorCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.SharedPreferencesCompat.EditorCompat.html
index 2a46cc87..5159fec 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.SharedPreferencesCompat.EditorCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.SharedPreferencesCompat.EditorCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.SharedPreferencesCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.SharedPreferencesCompat.html
index 99e7e84..3c4513a 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.SharedPreferencesCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.SharedPreferencesCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.pm.ActivityInfoCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.pm.ActivityInfoCompat.html
index 201f6e2..1fa3936 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.pm.ActivityInfoCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.pm.ActivityInfoCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.res.ResourcesCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.res.ResourcesCompat.html
index 497d73b..77e6d43 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.res.ResourcesCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.content.res.ResourcesCompat.html
@@ -137,7 +137,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.database.DatabaseUtilsCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.database.DatabaseUtilsCompat.html
index 0feb04b..90a5d72 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.database.DatabaseUtilsCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.database.DatabaseUtilsCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.BitmapCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.BitmapCompat.html
index 3b50f8e..912d5ee 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.BitmapCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.BitmapCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.ColorUtils.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.ColorUtils.html
index 68c2dce..1dfcdc5 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.ColorUtils.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.ColorUtils.html
@@ -186,7 +186,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html
index 735909e..041cbfd 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html
@@ -152,7 +152,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory.html
index f0e4cbf..2323bf0 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.hardware.fingerprint.FingerprintManagerCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.hardware.fingerprint.FingerprintManagerCompat.html
index 3c5e74d..8a49a32 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.hardware.fingerprint.FingerprintManagerCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.hardware.fingerprint.FingerprintManagerCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.net.ConnectivityManagerCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.net.ConnectivityManagerCompat.html
index 585fbe1..45e77fa 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.net.ConnectivityManagerCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.net.ConnectivityManagerCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.net.TrafficStatsCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.net.TrafficStatsCompat.html
index d8d8d74..89403e7 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.net.TrafficStatsCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.net.TrafficStatsCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.AsyncTaskCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.AsyncTaskCompat.html
index 0ea4b47..fcde361 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.AsyncTaskCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.AsyncTaskCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.EnvironmentCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.EnvironmentCompat.html
index 4d625b1..914f3f0 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.EnvironmentCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.EnvironmentCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.ParcelableCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.ParcelableCompat.html
index 0192ed6..8933edd 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.ParcelableCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.ParcelableCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.TraceCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.TraceCompat.html
index 3f490ba..8778c2e4 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.TraceCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.os.TraceCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.ICUCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.ICUCompat.html
index 2b97440..c4ea966 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.ICUCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.ICUCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.TextDirectionHeuristicsCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.TextDirectionHeuristicsCompat.html
index 45557e1..351a162 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.TextDirectionHeuristicsCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.TextDirectionHeuristicsCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.TextUtilsCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.TextUtilsCompat.html
index 16d0835..d3ab7ce 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.TextUtilsCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.text.TextUtilsCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.GestureDetectorCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.GestureDetectorCompat.html
index 5c0463d..e66c261 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.GestureDetectorCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.GestureDetectorCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.GravityCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.GravityCompat.html
index 9ee14c5..95c665e 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.GravityCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.GravityCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.InputDeviceCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.InputDeviceCompat.html
index 4a7f385..38a1cd8 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.InputDeviceCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.InputDeviceCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.KeyEventCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.KeyEventCompat.html
index 49526ab..58692a9 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.KeyEventCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.KeyEventCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.LayoutInflaterCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.LayoutInflaterCompat.html
index 7329ff7..b62e876 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.LayoutInflaterCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.LayoutInflaterCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MarginLayoutParamsCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MarginLayoutParamsCompat.html
index 86a7b57..444980d 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MarginLayoutParamsCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MarginLayoutParamsCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MenuCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MenuCompat.html
index 22ead5ec..17b8b7d 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MenuCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MenuCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MenuItemCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MenuItemCompat.html
index a321ac3..415dae2 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MenuItemCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MenuItemCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MotionEventCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MotionEventCompat.html
index cb8895d..c1f81ba 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MotionEventCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.MotionEventCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ScaleGestureDetectorCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ScaleGestureDetectorCompat.html
index 23f8718..8733e6b 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ScaleGestureDetectorCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ScaleGestureDetectorCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.VelocityTrackerCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.VelocityTrackerCompat.html
index 31a2b66..078bb96 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.VelocityTrackerCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.VelocityTrackerCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewCompat.html
index bbfebc1..0647acb 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html
index 3deb282..0721e0c 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewGroupCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewGroupCompat.html
index 973f25d..7c3f280 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewGroupCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewGroupCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewParentCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewParentCompat.html
index 0ff6977..186cdce 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewParentCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewParentCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewPropertyAnimatorCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewPropertyAnimatorCompat.html
index dcb75fc..7611f00 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewPropertyAnimatorCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.ViewPropertyAnimatorCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.WindowCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.WindowCompat.html
index a9711fa..bf16942a 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.WindowCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.WindowCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html
index e2045d7..b9b15c8 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html
index d74f936..5180523 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.animation.PathInterpolatorCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.animation.PathInterpolatorCompat.html
index 6701f77..715f73f 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.animation.PathInterpolatorCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.view.animation.PathInterpolatorCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.DrawerLayout.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.DrawerLayout.html
index c2e7c83..f859501 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.DrawerLayout.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.DrawerLayout.html
@@ -148,7 +148,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.EdgeEffectCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.EdgeEffectCompat.html
index 6993bec..a476dfb 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.EdgeEffectCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.EdgeEffectCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.ListPopupWindowCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.ListPopupWindowCompat.html
index fc5ed8d..243f6d2 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.ListPopupWindowCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.ListPopupWindowCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.PopupMenuCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.PopupMenuCompat.html
index 1d55628..c3cca70 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.PopupMenuCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.PopupMenuCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.PopupWindowCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.PopupWindowCompat.html
index 215118c..0523e9f 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.PopupWindowCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.PopupWindowCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.ScrollerCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.ScrollerCompat.html
index ea76c92..f13086d 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.ScrollerCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.ScrollerCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.SearchViewCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.SearchViewCompat.html
index ce5abd3..e3de11d 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.SearchViewCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.SearchViewCompat.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.TextViewCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.TextViewCompat.html
index e2078f4..e3a0f9a 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.TextViewCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v4.widget.TextViewCompat.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.app.AppCompatDelegate.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.app.AppCompatDelegate.html
index 6fd286c..2dbee43 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.app.AppCompatDelegate.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.app.AppCompatDelegate.html
@@ -172,7 +172,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.attr.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.attr.html
index c399a8a..2a2364a 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.attr.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.attr.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.drawable.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.drawable.html
index ec1ee38..a2e1dc3 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.drawable.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.drawable.html
@@ -347,7 +347,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.style.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.style.html
index 478d333..32befe4 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.style.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.style.html
@@ -178,7 +178,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.styleable.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.styleable.html
index 498ec51..6433bc2 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.styleable.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.appcompat.R.styleable.html
@@ -1705,7 +1705,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.graphics.Palette.Builder.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.graphics.Palette.Builder.html
index 83f441b..2758189 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.graphics.Palette.Builder.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.graphics.Palette.Builder.html
@@ -140,7 +140,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.graphics.Palette.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.graphics.Palette.html
index be157a7..d7752f5 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.graphics.Palette.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.graphics.Palette.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouteDescriptor.Builder.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouteDescriptor.Builder.html
index 7db6666..9181648 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouteDescriptor.Builder.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouteDescriptor.Builder.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouteDescriptor.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouteDescriptor.html
index 315ba3d..0cb71cf 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouteDescriptor.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouteDescriptor.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouter.Callback.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouter.Callback.html
index 66be68d..5d68006 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouter.Callback.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.media.MediaRouter.Callback.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceFragmentCompat.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceFragmentCompat.html
index 68aa733..980ff0d 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceFragmentCompat.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceFragmentCompat.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceScreen.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceScreen.html
index 12de78c..de14ee0 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceScreen.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceScreen.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceViewHolder.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceViewHolder.html
index b27e66c..0597c2a 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceViewHolder.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.preference.PreferenceViewHolder.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.recyclerview.R.dimen.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.recyclerview.R.dimen.html
index b38c6dc..a56e112 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.recyclerview.R.dimen.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.recyclerview.R.dimen.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.OrientationHelper.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.OrientationHelper.html
index 6a2a9b3..9111877 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.OrientationHelper.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.OrientationHelper.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.ItemAnimator.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.ItemAnimator.html
index 95e642e..a641975 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.ItemAnimator.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.ItemAnimator.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.LayoutManager.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.LayoutManager.html
index 30b0a78..173d636 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.LayoutManager.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.LayoutManager.html
@@ -193,7 +193,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.State.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.State.html
index 2b3ac61..86d91dc 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.State.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.State.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.html
index 5cdc7a0..a53430b 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.RecyclerView.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.helper.ItemTouchHelper.Callback.html b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.helper.ItemTouchHelper.Callback.html
index 1237408..b241e6e 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.helper.ItemTouchHelper.Callback.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/android.support.v7.widget.helper.ItemTouchHelper.Callback.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/changes-summary.html b/docs/html/sdk/support_api_diff/23.2.0/changes/changes-summary.html
index d41ec1f..431b2ae 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/changes-summary.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/changes-summary.html
@@ -352,7 +352,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23.2.0/changes/classes_index_additions.html b/docs/html/sdk/support_api_diff/23.2.0/changes/classes_index_additions.html
index a2e1d44..eb0457c 100644
--- a/docs/html/sdk/support_api_diff/23.2.0/changes/classes_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23.2.0/changes/classes_index_additions.html
@@ -143,7 +143,7 @@
 <p><div style="line-height:1.5em;color:black">
 <A HREF="pkg_android.support.v17.leanback.widget.html#ViewHolderTask" class="hiddenlink" target="rightframe"><b><i>ViewHolderTask</i></b></A><br>
 <A HREF="pkg_android.support.design.widget.html#VisibilityAwareImageButton" class="hiddenlink" target="rightframe"><b>VisibilityAwareImageButton</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_additions.html b/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_additions.html
index 78c94e1..c526b45 100644
--- a/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_additions.html
@@ -1128,7 +1128,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.Widget_AppCompat_Button_Colored" class="hiddenlink" target="rightframe">Widget_AppCompat_Button_Colored</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_all.html b/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_all.html
index f39d82e..61459ad 100644
--- a/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_all.html
+++ b/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_all.html
@@ -1457,7 +1457,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.Widget_AppCompat_Button_Colored" class="hiddenlink" target="rightframe">Widget_AppCompat_Button_Colored</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_changes.html b/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_changes.html
index debbb14..0a63a58 100644
--- a/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_changes.html
@@ -485,7 +485,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_removals.html b/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_removals.html
index a6cdb59..9f13a01 100644
--- a/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23/changes/alldiffs_index_removals.html
@@ -332,7 +332,7 @@
 <!-- Field View_backgroundTintMode -->
 <nobr><A HREF="android.support.v7.appcompat.R.styleable.html#android.support.v7.appcompat.R.styleable.View_backgroundTintMode" class="hiddenlink" target="rightframe"><strike>View_backgroundTintMode</strike></A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.AppBarLayout.Behavior.html b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.AppBarLayout.Behavior.html
index a6bbf2d..352dcfd 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.AppBarLayout.Behavior.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.AppBarLayout.Behavior.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.AppBarLayout.html b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.AppBarLayout.html
index 71e3167..cd2a11f 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.AppBarLayout.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.AppBarLayout.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.CollapsingToolbarLayout.html b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.CollapsingToolbarLayout.html
index 7244be9..d80f7ee 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.CollapsingToolbarLayout.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.CollapsingToolbarLayout.html
@@ -150,7 +150,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.NavigationView.html b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.NavigationView.html
index a38990a..5dd3104 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.NavigationView.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.NavigationView.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.Snackbar.html b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.Snackbar.html
index 9a53448..2247297 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.Snackbar.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.Snackbar.html
@@ -116,7 +116,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TabLayout.Tab.html b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TabLayout.Tab.html
index b7a01f5..a0ea052 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TabLayout.Tab.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TabLayout.Tab.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TabLayout.html b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TabLayout.html
index df626ac..bd3c8e6 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TabLayout.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TabLayout.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TextInputLayout.html b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TextInputLayout.html
index 471e267..a9a7b49 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TextInputLayout.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.design.widget.TextInputLayout.html
@@ -165,7 +165,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v13.app.FragmentCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v13.app.FragmentCompat.html
index 9eb5b24..b61fb5a 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v13.app.FragmentCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v13.app.FragmentCompat.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder.html
index 3c6165f..f189083 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.ViewHolder.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.html
index b6d8863..cb2156a 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.html
@@ -179,7 +179,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.animation.AnimatorCompatHelper.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.animation.AnimatorCompatHelper.html
index 092a6c3..5d5a9fc 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.animation.AnimatorCompatHelper.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.animation.AnimatorCompatHelper.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.ActivityCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.ActivityCompat.html
index 76e8ce9..c318b70 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.ActivityCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.ActivityCompat.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.Fragment.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.Fragment.html
index 53a8bd5..2f56f59 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.Fragment.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.Fragment.html
@@ -190,7 +190,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.FragmentActivity.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.FragmentActivity.html
index 8d2321f..0338069 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.FragmentActivity.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.app.FragmentActivity.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.AsyncTaskLoader.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.AsyncTaskLoader.html
index 19be27c..5dfbe6c 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.AsyncTaskLoader.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.AsyncTaskLoader.html
@@ -133,7 +133,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.ContextCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.ContextCompat.html
index 6ed5b3e..64d09ac 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.ContextCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.ContextCompat.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.Loader.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.Loader.html
index d4c3bb0..f97def1 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.Loader.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.content.Loader.html
@@ -136,7 +136,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.graphics.drawable.DrawableCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.graphics.drawable.DrawableCompat.html
index 87fefee..ca42f3d 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.graphics.drawable.DrawableCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.graphics.drawable.DrawableCompat.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.graphics.drawable.RoundedBitmapDrawable.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.graphics.drawable.RoundedBitmapDrawable.html
index 7c72cf4..793bd8b 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.graphics.drawable.RoundedBitmapDrawable.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.graphics.drawable.RoundedBitmapDrawable.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.MediaDescriptionCompat.Builder.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.MediaDescriptionCompat.Builder.html
index c429c39..6ae7186 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.MediaDescriptionCompat.Builder.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.MediaDescriptionCompat.Builder.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.MediaDescriptionCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.MediaDescriptionCompat.html
index 4053435..dde12a5 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.MediaDescriptionCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.MediaDescriptionCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.MediaControllerCompat.TransportControls.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.MediaControllerCompat.TransportControls.html
index 4d10769..12743cd 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.MediaControllerCompat.TransportControls.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.MediaControllerCompat.TransportControls.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.MediaSessionCompat.Callback.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.MediaSessionCompat.Callback.html
index a0bbbf6..4acf244 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.MediaSessionCompat.Callback.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.MediaSessionCompat.Callback.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.PlaybackStateCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.PlaybackStateCompat.html
index 29e5f0b..0f568c4 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.PlaybackStateCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.media.session.PlaybackStateCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.text.ICUCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.text.ICUCompat.html
index 5f9f31e..e357c50 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.text.ICUCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.text.ICUCompat.html
@@ -130,7 +130,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.ViewCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.ViewCompat.html
index 548502c..caaf19a 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.ViewCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.ViewCompat.html
@@ -122,7 +122,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html
index ce98f64..c60e7e1 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html
@@ -255,7 +255,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html
index f3ef666..6f2e809 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html
@@ -361,7 +361,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.DrawerLayout.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.DrawerLayout.html
index 3297157..c18ae6c 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.DrawerLayout.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.DrawerLayout.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.ExploreByTouchHelper.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.ExploreByTouchHelper.html
index 4026cd2..be8512f 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.ExploreByTouchHelper.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.ExploreByTouchHelper.html
@@ -123,7 +123,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.PopupWindowCompat.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.PopupWindowCompat.html
index 8a9b9c6..284dab4 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.PopupWindowCompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.PopupWindowCompat.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.SwipeRefreshLayout.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.SwipeRefreshLayout.html
index 91a99cb..1fb912f 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.SwipeRefreshLayout.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v4.widget.SwipeRefreshLayout.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.app.AppCompatDelegate.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.app.AppCompatDelegate.html
index 42ef289..9f768b9 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.app.AppCompatDelegate.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.app.AppCompatDelegate.html
@@ -137,7 +137,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.attr.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.attr.html
index cc28516..98d2c2c 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.attr.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.attr.html
@@ -221,7 +221,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.color.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.color.html
index 5f1a3f6..852d595 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.color.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.color.html
@@ -193,7 +193,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.dimen.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.dimen.html
index c4fba92..893ea25 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.dimen.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.dimen.html
@@ -158,7 +158,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.drawable.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.drawable.html
index 0bf5ce1..482e9ff 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.drawable.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.drawable.html
@@ -144,7 +144,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.id.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.id.html
index 2b34b3a..818a5b0 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.id.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.id.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.layout.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.layout.html
index 9d24903..a0a33fb 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.layout.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.layout.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.style.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.style.html
index 8b16f1c..d084de0 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.style.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.style.html
@@ -207,7 +207,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.styleable.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.styleable.html
index 5365376..c021cbe 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.styleable.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.appcompat.R.styleable.html
@@ -333,7 +333,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.graphics.Palette.Builder.html b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.graphics.Palette.Builder.html
index 3893441..e707730 100644
--- a/docs/html/sdk/support_api_diff/23/changes/android.support.v7.graphics.Palette.Builder.html
+++ b/docs/html/sdk/support_api_diff/23/changes/android.support.v7.graphics.Palette.Builder.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/changes-summary.html b/docs/html/sdk/support_api_diff/23/changes/changes-summary.html
index 3deee46e..75c1eb3 100644
--- a/docs/html/sdk/support_api_diff/23/changes/changes-summary.html
+++ b/docs/html/sdk/support_api_diff/23/changes/changes-summary.html
@@ -310,7 +310,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/classes_index_additions.html b/docs/html/sdk/support_api_diff/23/changes/classes_index_additions.html
index 094fff5..bc69616 100644
--- a/docs/html/sdk/support_api_diff/23/changes/classes_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23/changes/classes_index_additions.html
@@ -160,7 +160,7 @@
 <A HREF="pkg_android.support.v4.content.html#SharedPreferencesCompat" class="hiddenlink" target="rightframe"><b>SharedPreferencesCompat</b></A><br>
 <A HREF="pkg_android.support.v4.content.html#SharedPreferencesCompat.EditorCompat" class="hiddenlink" target="rightframe"><b>SharedPreferencesCompat.EditorCompat</b></A><br>
 <A HREF="pkg_android.support.design.widget.html#Snackbar.Callback" class="hiddenlink" target="rightframe"><b>Snackbar.Callback</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/classes_index_all.html b/docs/html/sdk/support_api_diff/23/changes/classes_index_all.html
index cb1ed5f..33a23bf 100644
--- a/docs/html/sdk/support_api_diff/23/changes/classes_index_all.html
+++ b/docs/html/sdk/support_api_diff/23/changes/classes_index_all.html
@@ -419,7 +419,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/classes_index_changes.html b/docs/html/sdk/support_api_diff/23/changes/classes_index_changes.html
index b674f27..9588a73 100644
--- a/docs/html/sdk/support_api_diff/23/changes/classes_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23/changes/classes_index_changes.html
@@ -328,7 +328,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/classes_index_removals.html b/docs/html/sdk/support_api_diff/23/changes/classes_index_removals.html
index e6da73f..c466298 100644
--- a/docs/html/sdk/support_api_diff/23/changes/classes_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23/changes/classes_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/constructors_index_additions.html b/docs/html/sdk/support_api_diff/23/changes/constructors_index_additions.html
index d1e5215..ae8c0d3 100644
--- a/docs/html/sdk/support_api_diff/23/changes/constructors_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23/changes/constructors_index_additions.html
@@ -53,7 +53,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.design.widget.TextInputLayout.html#android.support.design.widget.TextInputLayout.ctor_added(android.content.Context, android.util.AttributeSet, int)" class="hiddenlink" target="rightframe"><b>TextInputLayout</b>
 (<code>Context, AttributeSet, int</code>)</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/constructors_index_all.html b/docs/html/sdk/support_api_diff/23/changes/constructors_index_all.html
index 4618d88..401df57 100644
--- a/docs/html/sdk/support_api_diff/23/changes/constructors_index_all.html
+++ b/docs/html/sdk/support_api_diff/23/changes/constructors_index_all.html
@@ -53,7 +53,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.design.widget.TextInputLayout.html#android.support.design.widget.TextInputLayout.ctor_added(android.content.Context, android.util.AttributeSet, int)" class="hiddenlink" target="rightframe"><b>TextInputLayout</b>
 (<code>Context, AttributeSet, int</code>)</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/constructors_index_changes.html b/docs/html/sdk/support_api_diff/23/changes/constructors_index_changes.html
index a5ca2ef..122cdce 100644
--- a/docs/html/sdk/support_api_diff/23/changes/constructors_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23/changes/constructors_index_changes.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/constructors_index_removals.html b/docs/html/sdk/support_api_diff/23/changes/constructors_index_removals.html
index 74a09ba..dadd1cd 100644
--- a/docs/html/sdk/support_api_diff/23/changes/constructors_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23/changes/constructors_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/fields_index_additions.html b/docs/html/sdk/support_api_diff/23/changes/fields_index_additions.html
index 2f6ac9c..f9137b8 100644
--- a/docs/html/sdk/support_api_diff/23/changes/fields_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23/changes/fields_index_additions.html
@@ -444,7 +444,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.Widget_AppCompat_Button_Colored" class="hiddenlink" target="rightframe">Widget_AppCompat_Button_Colored</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/fields_index_all.html b/docs/html/sdk/support_api_diff/23/changes/fields_index_all.html
index a7f5e18..909dbcc 100644
--- a/docs/html/sdk/support_api_diff/23/changes/fields_index_all.html
+++ b/docs/html/sdk/support_api_diff/23/changes/fields_index_all.html
@@ -538,7 +538,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v7.appcompat.R.style.html#android.support.v7.appcompat.R.style.Widget_AppCompat_Button_Colored" class="hiddenlink" target="rightframe">Widget_AppCompat_Button_Colored</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/fields_index_changes.html b/docs/html/sdk/support_api_diff/23/changes/fields_index_changes.html
index 0e2ccff..301881a 100644
--- a/docs/html/sdk/support_api_diff/23/changes/fields_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23/changes/fields_index_changes.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/fields_index_removals.html b/docs/html/sdk/support_api_diff/23/changes/fields_index_removals.html
index 5027374..174a576 100644
--- a/docs/html/sdk/support_api_diff/23/changes/fields_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23/changes/fields_index_removals.html
@@ -241,7 +241,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v7.appcompat.R.styleable.html#android.support.v7.appcompat.R.styleable.View_backgroundTintMode" class="hiddenlink" target="rightframe"><strike>View_backgroundTintMode</strike></A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/jdiff_help.html b/docs/html/sdk/support_api_diff/23/changes/jdiff_help.html
index acb8508..125d4e8 100644
--- a/docs/html/sdk/support_api_diff/23/changes/jdiff_help.html
+++ b/docs/html/sdk/support_api_diff/23/changes/jdiff_help.html
@@ -120,7 +120,7 @@
 There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass. 
 In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes. 
 </BLOCKQUOTE>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/jdiff_statistics.html b/docs/html/sdk/support_api_diff/23/changes/jdiff_statistics.html
index 4480788..1e865b7 100644
--- a/docs/html/sdk/support_api_diff/23/changes/jdiff_statistics.html
+++ b/docs/html/sdk/support_api_diff/23/changes/jdiff_statistics.html
@@ -467,7 +467,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/jdiff_topleftframe.html b/docs/html/sdk/support_api_diff/23/changes/jdiff_topleftframe.html
index 36f9836..6a2e76e 100644
--- a/docs/html/sdk/support_api_diff/23/changes/jdiff_topleftframe.html
+++ b/docs/html/sdk/support_api_diff/23/changes/jdiff_topleftframe.html
@@ -49,7 +49,7 @@
   <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="fields_index_all.html" TARGET="bottomleftframe">By Field</A></FONT><br></TD>
 </TR>
 </TABLE>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/methods_index_additions.html b/docs/html/sdk/support_api_diff/23/changes/methods_index_additions.html
index 3cec9a3..c3e4176 100644
--- a/docs/html/sdk/support_api_diff/23/changes/methods_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23/changes/methods_index_additions.html
@@ -529,7 +529,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.app.FragmentActivity.html#android.support.v4.app.FragmentActivity.validateRequestPermissionsRequestCode_added(int)" class="hiddenlink" target="rightframe"><b>validateRequestPermissionsRequestCode</b>
 (<code>int</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/methods_index_all.html b/docs/html/sdk/support_api_diff/23/changes/methods_index_all.html
index 072b2ff..7b2f1d4 100644
--- a/docs/html/sdk/support_api_diff/23/changes/methods_index_all.html
+++ b/docs/html/sdk/support_api_diff/23/changes/methods_index_all.html
@@ -550,7 +550,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.app.FragmentActivity.html#android.support.v4.app.FragmentActivity.validateRequestPermissionsRequestCode_added(int)" class="hiddenlink" target="rightframe"><b>validateRequestPermissionsRequestCode</b>
 (<code>int</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/methods_index_changes.html b/docs/html/sdk/support_api_diff/23/changes/methods_index_changes.html
index d190580..90a0a23 100644
--- a/docs/html/sdk/support_api_diff/23/changes/methods_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23/changes/methods_index_changes.html
@@ -83,7 +83,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.html#android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter.setBackgroundColor_changed(int)" class="hiddenlink" target="rightframe">setBackgroundColor
 (<code>int</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/methods_index_removals.html b/docs/html/sdk/support_api_diff/23/changes/methods_index_removals.html
index 25175750..ce89d27 100644
--- a/docs/html/sdk/support_api_diff/23/changes/methods_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23/changes/methods_index_removals.html
@@ -71,7 +71,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.app.Fragment.html#android.support.v4.app.Fragment.onAttach_removed(android.app.Activity)" class="hiddenlink" target="rightframe"><strike>onAttach</strike>
 (<code>Activity</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/packages_index_additions.html b/docs/html/sdk/support_api_diff/23/changes/packages_index_additions.html
index 446ee58..fc6d24d 100644
--- a/docs/html/sdk/support_api_diff/23/changes/packages_index_additions.html
+++ b/docs/html/sdk/support_api_diff/23/changes/packages_index_additions.html
@@ -59,7 +59,7 @@
 <A HREF="changes-summary.html#android.support.v7.graphics.drawable" class="hiddenlink" target="rightframe"><b>android.support.v7.graphics.drawable</b></A><br>
 <A HREF="changes-summary.html#android.support.v7.preference" class="hiddenlink" target="rightframe"><b>android.support.v7.preference</b></A><br>
 <A HREF="changes-summary.html#android.support.v8.renderscript" class="hiddenlink" target="rightframe"><b>android.support.v8.renderscript</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/packages_index_all.html b/docs/html/sdk/support_api_diff/23/changes/packages_index_all.html
index d1dbbe1..c770167 100644
--- a/docs/html/sdk/support_api_diff/23/changes/packages_index_all.html
+++ b/docs/html/sdk/support_api_diff/23/changes/packages_index_all.html
@@ -77,7 +77,7 @@
 <A HREF="changes-summary.html#android.support.v7.preference" class="hiddenlink" target="rightframe"><b>android.support.v7.preference</b></A><br>
 <A HREF="pkg_android.support.v7.util.html" class="hiddenlink" target="rightframe">android.support.v7.util</A><br>
 <A HREF="changes-summary.html#android.support.v8.renderscript" class="hiddenlink" target="rightframe"><b>android.support.v8.renderscript</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/packages_index_changes.html b/docs/html/sdk/support_api_diff/23/changes/packages_index_changes.html
index 730633e..2140313 100644
--- a/docs/html/sdk/support_api_diff/23/changes/packages_index_changes.html
+++ b/docs/html/sdk/support_api_diff/23/changes/packages_index_changes.html
@@ -68,7 +68,7 @@
 <A HREF="pkg_android.support.v7.appcompat.html" class="hiddenlink" target="rightframe">android.support.v7.appcompat</A><br>
 <A HREF="pkg_android.support.v7.graphics.html" class="hiddenlink" target="rightframe">android.support.v7.graphics</A><br>
 <A HREF="pkg_android.support.v7.util.html" class="hiddenlink" target="rightframe">android.support.v7.util</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/packages_index_removals.html b/docs/html/sdk/support_api_diff/23/changes/packages_index_removals.html
index d0ffabc..d5a825d 100644
--- a/docs/html/sdk/support_api_diff/23/changes/packages_index_removals.html
+++ b/docs/html/sdk/support_api_diff/23/changes/packages_index_removals.html
@@ -49,7 +49,7 @@
 </div>
 <br>
 <div id="indexTableEntries">
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.design.widget.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.design.widget.html
index a8630f7..6ebc3a7 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.design.widget.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.design.widget.html
@@ -169,7 +169,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v13.app.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v13.app.html
index c56e8a4..877fd6c 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v13.app.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v13.app.html
@@ -120,7 +120,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v17.leanback.widget.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v17.leanback.widget.html
index 3d7f780..ea3848e 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v17.leanback.widget.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v17.leanback.widget.html
@@ -112,7 +112,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.animation.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.animation.html
index 36965dd..4a51cf8 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.animation.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.animation.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.app.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.app.html
index 692e7ef..9fbee40 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.app.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.app.html
@@ -176,7 +176,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.content.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.content.html
index 44e9f81..9e654a6 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.content.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.content.html
@@ -169,7 +169,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.graphics.drawable.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.graphics.drawable.html
index 6139c8e..de77561 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.graphics.drawable.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.graphics.drawable.html
@@ -112,7 +112,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.media.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.media.html
index e6fe510..761e746 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.media.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.media.html
@@ -112,7 +112,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.media.session.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.media.session.html
index 9b0e472..18893f4 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.media.session.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.media.session.html
@@ -119,7 +119,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.os.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.os.html
index 9a76a7b..2ed8d04 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.os.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.os.html
@@ -119,7 +119,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.text.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.text.html
index b2a178a..c995ed8 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.text.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.text.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.view.accessibility.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.view.accessibility.html
index dcdbc56..ec69556 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.view.accessibility.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.view.accessibility.html
@@ -127,7 +127,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.view.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.view.html
index 2a955d3..2361c0f 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.view.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.view.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.widget.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.widget.html
index 482bf1f..c6b5e0c 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.widget.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v4.widget.html
@@ -141,7 +141,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.app.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.app.html
index 1dd5425..a99b641 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.app.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.app.html
@@ -120,7 +120,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.appcompat.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.appcompat.html
index e014278..eb5ed08 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.appcompat.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.appcompat.html
@@ -154,7 +154,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.graphics.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.graphics.html
index cb6c97b..9f88138 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.graphics.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.graphics.html
@@ -120,7 +120,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.util.html b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.util.html
index cc0065d..e4da229 100644
--- a/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.util.html
+++ b/docs/html/sdk/support_api_diff/23/changes/pkg_android.support.v7.util.html
@@ -119,7 +119,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_additions.html
index cb62aa8..f73d864 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_additions.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_additions.html
@@ -933,7 +933,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.view.WindowInsetsCompat.html#android.support.v4.view.WindowInsetsCompat.ctor_added(android.support.v4.view.WindowInsetsCompat)" class="hiddenlink" target="rightframe"><b>WindowInsetsCompat</b>
 (<code>WindowInsetsCompat</code>)</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_all.html
index 719f9af..fb553f8 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_all.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_all.html
@@ -1313,7 +1313,7 @@
 <!-- Constructor WindowInsetsCompat -->
 &nbsp;&nbsp;<nobr><A HREF="android.support.v4.view.WindowInsetsCompat.html#android.support.v4.view.WindowInsetsCompat.ctor_added(android.support.v4.view.WindowInsetsCompat)" class="hiddenlink" target="rightframe"><b>WindowInsetsCompat</b>
 (<code>WindowInsetsCompat</code>)</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_changes.html
index 854a487..4718b46 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_changes.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_changes.html
@@ -652,7 +652,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v4.view.WindowInsetsCompat.html" class="hiddenlink" target="rightframe">WindowInsetsCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_removals.html
index e6d9e07..179472a 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_removals.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_removals.html
@@ -110,7 +110,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v7.widget.StaggeredGridLayoutManager.html#android.support.v7.widget.StaggeredGridLayoutManager.TAG" class="hiddenlink" target="rightframe"><strike>TAG</strike></A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html
index d6a9415..41ac368 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.html
index dd0b511..c4f0bfb 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.html
@@ -130,7 +130,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsSession.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsSession.html
index 16cac31..1ccaab3 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsSession.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsSession.html
@@ -126,7 +126,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html
index 7e1e59a..ad3dfd8 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.BottomSheetBehavior.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.BottomSheetBehavior.html
index e98c6f3..22984b8 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.BottomSheetBehavior.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.BottomSheetBehavior.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html
index ebfdce1..a20a1ed 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html
index 8cf6146..edc96ed 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html
@@ -147,7 +147,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.LayoutParams.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.LayoutParams.html
index a36eab0..445da88 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.LayoutParams.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.LayoutParams.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.html
index 4a7247a..3ba5c1e 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html
index 633db38..07099d6 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html
@@ -144,7 +144,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TabLayout.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TabLayout.html
index 01d4b6d..a09656a 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TabLayout.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TabLayout.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TextInputLayout.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TextInputLayout.html
index ecd6fd4..9ad13eb 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TextInputLayout.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TextInputLayout.html
@@ -171,7 +171,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v14.preference.PreferenceFragment.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v14.preference.PreferenceFragment.html
index 9b31c9e..6b23c17 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v14.preference.PreferenceFragment.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v14.preference.PreferenceFragment.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder.html
index 9df6536..9f1f00c 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder.html
@@ -136,7 +136,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.html
index 16b03ad..a0b0aa9 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.html
@@ -151,7 +151,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.ObjectAdapter.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.ObjectAdapter.html
index 3e3ded0..3dad1a2 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.ObjectAdapter.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.ObjectAdapter.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.preference.LeanbackSettingsFragment.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.preference.LeanbackSettingsFragment.html
index 6e54465..690328a 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.preference.LeanbackSettingsFragment.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.preference.LeanbackSettingsFragment.html
@@ -94,7 +94,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html
index 0600e44..a353745 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html
@@ -126,7 +126,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityCompat.html
index 74ae6f6..95b4fc6 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityCompat.html
@@ -129,7 +129,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityOptionsCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityOptionsCompat.html
index ce96b49..e675b7f 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityOptionsCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityOptionsCompat.html
@@ -165,7 +165,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.FragmentController.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.FragmentController.html
index 13b2ce1..dfc1a60 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.FragmentController.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.FragmentController.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ServiceCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ServiceCompat.html
index 6a404eb..211a88f 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ServiceCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ServiceCompat.html
@@ -130,7 +130,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.SharedElementCallback.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.SharedElementCallback.html
index 1495fb4..7394059 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.SharedElementCallback.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.SharedElementCallback.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.content.ContextCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.content.ContextCompat.html
index 1d6b9b1..b6157a2 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.content.ContextCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.content.ContextCompat.html
@@ -111,7 +111,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html
index 3408caa..92f1ba4 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserCompat.MediaItem.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserCompat.MediaItem.html
index acc16c1..52da3d4 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserCompat.MediaItem.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserCompat.MediaItem.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot.html
index 7a9c73311..7ea97f3 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaDescriptionCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaDescriptionCompat.html
index fbbaa19..fa1d610 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaDescriptionCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaDescriptionCompat.html
@@ -157,7 +157,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaMetadataCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaMetadataCompat.html
index e52493b..7e0f137 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaMetadataCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaMetadataCompat.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaButtonReceiver.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaButtonReceiver.html
index 3e2c68b..65467b8 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaButtonReceiver.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaButtonReceiver.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.QueueItem.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.QueueItem.html
index 5ce173f..e3b0184 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.QueueItem.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.QueueItem.html
@@ -133,7 +133,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.html
index ee71244..90bd5eb 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.html
@@ -126,7 +126,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html
index 2c54c1d..07e2449 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.os.BuildCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.os.BuildCompat.html
index eb59ddb..372415a 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.os.BuildCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.os.BuildCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.KeyEventCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.KeyEventCompat.html
index b5f4371..d62437e 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.KeyEventCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.KeyEventCompat.html
@@ -141,7 +141,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.MotionEventCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.MotionEventCompat.html
index 9f85dab..8f58037 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.MotionEventCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.MotionEventCompat.html
@@ -161,7 +161,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewCompat.html
index 1b4ea0f..0974230 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewCompat.html
@@ -181,7 +181,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html
index dcb2023..3eec7fa0a 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html
@@ -111,7 +111,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.WindowInsetsCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.WindowInsetsCompat.html
index e0f77c9..c5c1d22 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.WindowInsetsCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.WindowInsetsCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html
index 6ff46b8..1f9801f 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html
@@ -158,7 +158,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat.html
index 5d63b93a..923ec80 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat.html
@@ -110,7 +110,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html
index 004d89e..defa406 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html
@@ -143,7 +143,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html
index 695028b..d6f719e 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html
@@ -157,7 +157,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat.html
index 17109ec..d087e4a 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat.html
index 30df540..84fc73b 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat.html
index 1d5a250..41abf7e 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html
index 727576d..005616a 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html
@@ -144,7 +144,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeProviderCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeProviderCompat.html
index 101070c..bd6b7f8 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeProviderCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeProviderCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityWindowInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityWindowInfoCompat.html
index a3b8d96..40f3ca2 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityWindowInfoCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityWindowInfoCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat.html
index cba004e..3d9f2ea 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat.html
@@ -95,7 +95,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat.html
index c15d1b9..df0f3e1 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat.html
@@ -95,7 +95,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.html
index cbb3925..4af1e46 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.html
@@ -121,7 +121,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SwipeRefreshLayout.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SwipeRefreshLayout.html
index 77dbdf6..5848782 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SwipeRefreshLayout.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SwipeRefreshLayout.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.TextViewCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.TextViewCompat.html
index a803634..87b9e69 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.TextViewCompat.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.TextViewCompat.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.ActionBarDrawerToggle.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.ActionBarDrawerToggle.html
index 2a864f0..bc8abd6 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.ActionBarDrawerToggle.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.ActionBarDrawerToggle.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.AppCompatDelegate.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.AppCompatDelegate.html
index adfcabb..7b131e6 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.AppCompatDelegate.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.AppCompatDelegate.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.content.res.AppCompatResources.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.content.res.AppCompatResources.html
index e26c32b..02f43fd 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.content.res.AppCompatResources.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.content.res.AppCompatResources.html
@@ -108,7 +108,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.graphics.Palette.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.graphics.Palette.html
index f588384..1999a48 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.graphics.Palette.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.graphics.Palette.html
@@ -115,7 +115,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.util.SortedList.Callback.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.util.SortedList.Callback.html
index d2350979..95be79c 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.util.SortedList.Callback.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.util.SortedList.Callback.html
@@ -138,7 +138,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearLayoutManager.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearLayoutManager.html
index cf5c0f6..2fdfb0e 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearLayoutManager.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearLayoutManager.html
@@ -109,7 +109,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearSmoothScroller.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearSmoothScroller.html
index 3e13735..5cf79ee 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearSmoothScroller.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearSmoothScroller.html
@@ -112,7 +112,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.RecyclerView.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.RecyclerView.html
index d5e36f0..5411a1f 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.RecyclerView.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.RecyclerView.html
@@ -116,7 +116,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.StaggeredGridLayoutManager.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.StaggeredGridLayoutManager.html
index 640ef38..9d0ab87 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.StaggeredGridLayoutManager.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.StaggeredGridLayoutManager.html
@@ -124,7 +124,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/changes-summary.html b/docs/html/sdk/support_api_diff/24.2.0/changes/changes-summary.html
index 12dfb4e..4456c22 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/changes-summary.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/changes-summary.html
@@ -315,7 +315,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_additions.html
index f3eb2ed..acb8115 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_additions.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_additions.html
@@ -291,7 +291,7 @@
 <A HREF="pkg_android.support.v7.widget.html#Toolbar.LayoutParams" class="hiddenlink" target="rightframe"><b>Toolbar.LayoutParams</b></A><br>
 <A HREF="pkg_android.support.v7.widget.html#Toolbar.OnMenuItemClickListener" class="hiddenlink" target="rightframe"><b><i>Toolbar.OnMenuItemClickListener</i></b></A><br>
 <A HREF="pkg_android.support.v7.widget.html#Toolbar.SavedState" class="hiddenlink" target="rightframe"><b>Toolbar.SavedState</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_all.html
index 410ac8a..3e77bf2 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_all.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_all.html
@@ -514,7 +514,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v4.view.WindowInsetsCompat.html" class="hiddenlink" target="rightframe">WindowInsetsCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_changes.html
index 1baef5c..58fe615 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_changes.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_changes.html
@@ -380,7 +380,7 @@
  <a href="#topheader"><font size="-2">TOP</font></a>
 <p><div style="line-height:1.5em;color:black">
 <A HREF="android.support.v4.view.WindowInsetsCompat.html" class="hiddenlink" target="rightframe">WindowInsetsCompat</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_removals.html
index e6da73f..c466298 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_removals.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_additions.html
index b0c0587..312effc 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_additions.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_additions.html
@@ -53,7 +53,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.view.WindowInsetsCompat.html#android.support.v4.view.WindowInsetsCompat.ctor_added(android.support.v4.view.WindowInsetsCompat)" class="hiddenlink" target="rightframe"><b>WindowInsetsCompat</b>
 (<code>WindowInsetsCompat</code>)</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_all.html
index 91568db..24310b7 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_all.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_all.html
@@ -71,7 +71,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.view.WindowInsetsCompat.html#android.support.v4.view.WindowInsetsCompat.ctor_added(android.support.v4.view.WindowInsetsCompat)" class="hiddenlink" target="rightframe"><b>WindowInsetsCompat</b>
 (<code>WindowInsetsCompat</code>)</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_changes.html
index b4142ed..62a75f8c 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_changes.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_changes.html
@@ -61,7 +61,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.ctor_changed()" class="hiddenlink" target="rightframe">ContextCompat
 ()</A></nobr>&nbsp;constructor<br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_removals.html
index f1a9952..2fbd2e1 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_removals.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_removals.html
@@ -47,7 +47,7 @@
 <div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
 Listed as: <span style="color:#069"><strong>Added</strong></span>,  <span style="color:#069"><strike>Removed</strike></span>,  <span style="color:#069">Changed</span></font>
 </div>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_additions.html
index 8923dbe..cdb8ee8 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_additions.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_additions.html
@@ -253,7 +253,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v4.view.accessibility.AccessibilityEventCompat.html#android.support.v4.view.accessibility.AccessibilityEventCompat.TYPE_WINDOWS_CHANGED" class="hiddenlink" target="rightframe">TYPE_WINDOWS_CHANGED</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_all.html
index 19cebb7..14b3e97 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_all.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_all.html
@@ -285,7 +285,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v4.view.accessibility.AccessibilityEventCompat.html#android.support.v4.view.accessibility.AccessibilityEventCompat.TYPE_WINDOWS_CHANGED" class="hiddenlink" target="rightframe">TYPE_WINDOWS_CHANGED</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_changes.html
index b5ab769..c72b2de 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_changes.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_changes.html
@@ -57,7 +57,7 @@
 </nobr><br>
 <nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.OVER_SCROLL_NEVER" class="hiddenlink" target="rightframe">OVER_SCROLL_NEVER</A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_removals.html
index 09ffac4..61820d1 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_removals.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_removals.html
@@ -53,7 +53,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v7.widget.StaggeredGridLayoutManager.html#android.support.v7.widget.StaggeredGridLayoutManager.TAG" class="hiddenlink" target="rightframe"><strike>TAG</strike></A>
 </nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_help.html b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_help.html
index ca0931f..966dda8 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_help.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_help.html
@@ -120,7 +120,7 @@
 There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass. 
 In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes. 
 </BLOCKQUOTE>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_statistics.html b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_statistics.html
index 698dbec..7010da6 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_statistics.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_statistics.html
@@ -583,7 +583,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_topleftframe.html b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_topleftframe.html
index 36f9836..6a2e76e 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_topleftframe.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_topleftframe.html
@@ -49,7 +49,7 @@
   <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="fields_index_all.html" TARGET="bottomleftframe">By Field</A></FONT><br></TD>
 </TR>
 </TABLE>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_additions.html
index 508018e..419a607 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_additions.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_additions.html
@@ -434,7 +434,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.media.session.PlaybackStateCompat.html#android.support.v4.media.session.PlaybackStateCompat.toKeyCode_added(long)" class="hiddenlink" target="rightframe"><b>toKeyCode</b>
 (<code>long</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_all.html
index a52d5c9..d33bfc0 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_all.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_all.html
@@ -565,7 +565,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v4.media.session.PlaybackStateCompat.html#android.support.v4.media.session.PlaybackStateCompat.toKeyCode_added(long)" class="hiddenlink" target="rightframe"><b>toKeyCode</b>
 (<code>long</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_changes.html
index 5faae42..ef008cb 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_changes.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_changes.html
@@ -208,7 +208,7 @@
 (<code>int, Bitmap, String</code>)</A></nobr><br>
 <nobr><A HREF="android.support.v4.view.KeyEventCompat.html#android.support.v4.view.KeyEventCompat.startTracking_changed(android.view.KeyEvent)" class="hiddenlink" target="rightframe">startTracking
 (<code>KeyEvent</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_removals.html
index 062ac8f..1c0c6be 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_removals.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_removals.html
@@ -79,7 +79,7 @@
 <p><div style="line-height:1.5em;color:black">
 <nobr><A HREF="android.support.v7.widget.LinearLayoutManager.html#android.support.v7.widget.LinearLayoutManager.prepareForDrop_removed(android.view.View, android.view.View, int, int)" class="hiddenlink" target="rightframe"><strike>prepareForDrop</strike>
 (<code>View, View, int, int</code>)</A></nobr><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_additions.html
index 2eff0f7..bb88d9f 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_additions.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_additions.html
@@ -52,7 +52,7 @@
 <A NAME="A"></A>
 <A HREF="changes-summary.html#android.support.transition" class="hiddenlink" target="rightframe"><b>android.support.transition</b></A><br>
 <A HREF="changes-summary.html#android.support.v4.text.util" class="hiddenlink" target="rightframe"><b>android.support.v4.text.util</b></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_all.html
index 58e51ed..78805db 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_all.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_all.html
@@ -77,7 +77,7 @@
 <A HREF="pkg_android.support.v7.util.html" class="hiddenlink" target="rightframe">android.support.v7.util</A><br>
 <A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
 <A HREF="changes-summary.html#android.support.v8.renderscript" class="hiddenlink" target="rightframe"><strike>android.support.v8.renderscript</strike></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_changes.html
index 1d9e428..f5f6425 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_changes.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_changes.html
@@ -72,7 +72,7 @@
 <A HREF="pkg_android.support.v7.preference.html" class="hiddenlink" target="rightframe">android.support.v7.preference</A><br>
 <A HREF="pkg_android.support.v7.util.html" class="hiddenlink" target="rightframe">android.support.v7.util</A><br>
 <A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_removals.html
index d52d40d..ce5ca58 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_removals.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_removals.html
@@ -53,7 +53,7 @@
 <A HREF="changes-summary.html#android.support.v7.appcompat" class="hiddenlink" target="rightframe"><strike>android.support.v7.appcompat</strike></A><br>
 <A HREF="changes-summary.html#android.support.v7.recyclerview" class="hiddenlink" target="rightframe"><strike>android.support.v7.recyclerview</strike></A><br>
 <A HREF="changes-summary.html#android.support.v8.renderscript" class="hiddenlink" target="rightframe"><strike>android.support.v8.renderscript</strike></A><br>
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.customtabs.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.customtabs.html
index 5959d63..45a31ff 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.customtabs.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.customtabs.html
@@ -119,7 +119,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.design.widget.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.design.widget.html
index 510b9bd..a311b48 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.design.widget.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.design.widget.html
@@ -161,7 +161,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v14.preference.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v14.preference.html
index 84efadc6..f24be00 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v14.preference.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v14.preference.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.leanback.widget.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.leanback.widget.html
index 4ce1f32..c07a487 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.leanback.widget.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.leanback.widget.html
@@ -119,7 +119,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.preference.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.preference.html
index ad0aadd..c61d79d 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.preference.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.preference.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.accessibilityservice.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.accessibilityservice.html
index e904a76..2c0f684 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.accessibilityservice.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.accessibilityservice.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.app.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.app.html
index f8e4cb1..58ed06f9 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.app.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.app.html
@@ -148,7 +148,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.content.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.content.html
index 31aa1da..65dd616 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.content.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.content.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.graphics.drawable.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.graphics.drawable.html
index b1efab3..f8b31a5 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.graphics.drawable.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.graphics.drawable.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.html
index 612a1a0..5300c86 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.html
@@ -126,7 +126,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.session.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.session.html
index 3e46335..459d0c3 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.session.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.session.html
@@ -126,7 +126,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.os.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.os.html
index b250855..6d7f399 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.os.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.os.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.util.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.util.html
index d34506e..6f0e777 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.util.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.util.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.accessibility.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.accessibility.html
index a6362fb..d5d126c 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.accessibility.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.accessibility.html
@@ -190,7 +190,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.html
index 10b1334..d720d41 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.html
@@ -133,7 +133,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.widget.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.widget.html
index 5ed0f65..2efef45 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.widget.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.widget.html
@@ -162,7 +162,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.app.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.app.html
index 8eb58aa..f36cba5 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.app.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.app.html
@@ -162,7 +162,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.content.res.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.content.res.html
index 90787f7..2e4b703 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.content.res.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.content.res.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.graphics.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.graphics.html
index bd9cf24..439c8d3 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.graphics.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.graphics.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.preference.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.preference.html
index b80e005..b2b781b 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.preference.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.preference.html
@@ -105,7 +105,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.util.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.util.html
index 365022f..c35fb8c 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.util.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.util.html
@@ -148,7 +148,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.widget.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.widget.html
index e07d5b8..72e5497 100644
--- a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.widget.html
+++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.widget.html
@@ -449,7 +449,7 @@
     </div> <!-- end footer -->
     </div><!-- end doc-content -->
     </div> <!-- end body-content --> 
-<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
 </script>
 <script type="text/javascript">
   try {
diff --git a/docs/html/training/location/geofencing.jd b/docs/html/training/location/geofencing.jd
index ce6ad55..046e99e 100644
--- a/docs/html/training/location/geofencing.jd
+++ b/docs/html/training/location/geofencing.jd
@@ -332,22 +332,39 @@
 <p>This section outlines recommendations for using geofencing with the location
 APIs for Android.</p>
 
-<h3>Reduce power consumption</h3>
+<h3>
+  Reduce power consumption
+</h3>
 
-<p>You can use the following techniques to optimize power consumption in your apps that use geofencing:</p>
+<p>
+  You can use the following techniques to optimize power consumption in your
+  apps that use geofencing:
+</p>
 
 <ul>
-<li><p>Set the <a href="{@docRoot}android/reference/com/google/android/gms/location/Geofence.Builder.html#setNotificationResponsiveness(int)">
-notification responsiveness</a> to a higher value. Doing so improves power consumption by
-increasing the latency of geofence alerts. For example, if you set a responsiveness value of five
-minutes your app only checks for an entrance or exit alert once every five minutes.
-Setting lower values does not necessarily mean that users will be notified within that time period
-(for example, if you set a value of 5 seconds it may take a bit longer than that to receive the
-alert).</p></li>
-<li><p>Use a larger geofence radius for locations where a user spends a significant amount of time,
-such as home or work. While a larger radius doesn't directly reduce power consumption, it reduces
-the frequency at which the app checks for entrance or exit, effectively lowering overall power
-consumption.</p></li>
+  <li>
+    <p>
+      Set the <a href=
+      "https://developers.google.com/android/reference/com/google/android/gms/location/Geofence.Builder.html#setNotificationResponsiveness(int)">
+      notification responsiveness</a> to a higher value. Doing so improves
+      power consumption by increasing the latency of geofence alerts. For
+      example, if you set a responsiveness value of five minutes your app only
+      checks for an entrance or exit alert once every five minutes. Setting
+      lower values does not necessarily mean that users will be notified
+      within that time period (for example, if you set a value of 5 seconds it
+      may take a bit longer than that to receive the alert).
+    </p>
+  </li>
+
+  <li>
+    <p>
+      Use a larger geofence radius for locations where a user spends a
+      significant amount of time, such as home or work. While a larger radius
+      doesn't directly reduce power consumption, it reduces the frequency at
+      which the app checks for entrance or exit, effectively lowering overall
+      power consumption.
+    </p>
+  </li>
 </ul>
 
 <h3>Choose the optimal radius for your geofence</h3>
diff --git a/docs/html/training/wearables/data-layer/messages.jd b/docs/html/training/wearables/data-layer/messages.jd
index ef9bfb1..8c4b730 100644
--- a/docs/html/training/wearables/data-layer/messages.jd
+++ b/docs/html/training/wearables/data-layer/messages.jd
@@ -10,12 +10,6 @@
   <li><a href="#SendMessage">Send a Message</a></li>
   <li><a href="#ReceiveMessage">Receive a Message</a></li>
 </ol>
-<h2>Try it out</h2>
-<ul>
-  <li>
-    <a href="https://github.com/googlesamples/android-FindMyPhone/" class="external-link">FindMyPhone</a>
-  </li>
-</ul>
 </div>
 </div>
 
@@ -27,6 +21,7 @@
   <li>An arbitrary payload (optional)</li>
   <li>A path that uniquely identifies the message's action</li>
 </ul>
+
 <p>
 Unlike with data items, there is no syncing between the handheld and wearable apps.
 Messages are a one-way communication mechanism that's good for remote procedure calls (RPC),
@@ -149,11 +144,9 @@
 <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>
 to detect capability changes, you may want to override the
 <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onConnectedNodes(java.util.List<com.google.android.gms.wearable.Node>)"><code>onConnectedNodes()</code></a>
-method to listen to finer-grained connectivity details, such as when a wearable device switches
-from Wi-Fi to a Bluetooth connection to the handset. For an example implementation, see the
-<code>DisconnectListenerService</code> class in the
-<a href="https://github.com/googlesamples/android-FindMyPhone/" class="external-link">FindMyPhone</a>
-sample. For more information on how to listen for important events, see
+method to listen to finer-grained connectivity details, such as when a wearable
+device switches from Wi-Fi to a Bluetooth connection to the handset.
+For more information on how to listen for important events, see
 <a href="{@docRoot}training/wearables/data-layer/events.html#Listen">Listen for Data Layer Events</a>.
 </p>
 
diff --git a/docs/html/tv/_project.yaml b/docs/html/tv/_project.yaml
new file mode 100644
index 0000000..d2d41e1
--- /dev/null
+++ b/docs/html/tv/_project.yaml
@@ -0,0 +1,6 @@
+name: "TV"
+home_url: /tv/
+description: "Bring your apps, games, and content to the biggest screen in the house."
+content_license: cc3-apache2
+buganizer_id: 30209417
+parent_project_metadata_path: /about/_project.yaml
diff --git a/docs/html/wear/_project.yaml b/docs/html/wear/_project.yaml
index 2a94274..114cc5b 100644
--- a/docs/html/wear/_project.yaml
+++ b/docs/html/wear/_project.yaml
@@ -3,3 +3,4 @@
 description: "Small, powerful devices, worn on the body. Useful information when you need it most."
 content_license: cc3-apache2
 buganizer_id: 30209417
+parent_project_metadata_path: /about/_project.yaml
diff --git a/docs/html/wear/preview/_project.yaml b/docs/html/wear/preview/_project.yaml
new file mode 100644
index 0000000..4f7083e
--- /dev/null
+++ b/docs/html/wear/preview/_project.yaml
@@ -0,0 +1,6 @@
+name: "Wear Preview"
+home_url: /wear/preview/
+description: "Small, powerful devices, worn on the body. Useful information when you need it most."
+content_license: cc3-apache2
+buganizer_id: 30209417
+parent_project_metadata_path: /wear/_project.yaml
diff --git a/docs/html/wear/preview/downloads.jd b/docs/html/wear/preview/downloads.jd
index da6a06d..bfa384b 100644
--- a/docs/html/wear/preview/downloads.jd
+++ b/docs/html/wear/preview/downloads.jd
@@ -346,7 +346,8 @@
     </p>
 
     <p class="warning">
-      <strong>Warning:</strong> Installing a system image on a watch removes all data from the
+      <strong>Warning:</strong> Installing a system image on a watch
+      removes all data from the
       watch, so you should back up your data first.
     </p>
 
@@ -355,8 +356,7 @@
     </h4>
 
     <p>
-      From the phone, unpair ("Forget") the watch.
-      Then on the watch, enable the Developer Options menu and ADB debugging as
+      On the watch, enable the Developer Options menu and ADB debugging as
       follows:
     </p>
 
@@ -365,14 +365,14 @@
       </li>
 
       <li>Scroll to the bottom of the menu. If no <strong>Developer
-      Options</strong> item is provided, tap <strong>About</strong>.
+      Options</strong> item is provided, tap <strong>System</strong>
+      and then <strong>About</strong>.
       </li>
 
       <li>Tap the build number 7 times.
       </li>
 
-      <li>From the Settings menu, tap the <strong>Developer Options</strong>
-      item.
+      <li>From the Settings menu, tap <strong>Developer Options</strong>.
       </li>
 
       <li>Enable ADB debugging.
@@ -418,7 +418,9 @@
       </li>
 
       <li>Use the following <a href="{@docRoot}tools/help/adb.html">adb
-      command</a> to confirm that the watch is available for flashing:
+      command</a> to confirm that the watch is recognized.
+      You may need to turn ADB debugging off and then on for the watch to
+      be recognized:
       <code>adb devices</code>
       </li>
 
@@ -432,11 +434,11 @@
       devices, <code>fastboot oem unlock</code>
       </li>
 
-      <li>On the watch, select the <strong>Unlock</strong> option.
+      <li>On the watch, select the option to unlock the bootloader.
       </li>
 
-      <li>Navigate to the directory where you unzipped the system image in Step
-      1. At the top level of that directory,
+      <li>On your computer, navigate to the directory where you unzipped the
+      system image in Step 1. At the top level of that directory,
       execute the <code>flash-all</code> script by typing
       <code>flash-all.sh</code> or, in the case of Windows,
       <code>flash-all.bat</code>. The following may need to
@@ -449,16 +451,16 @@
       Set up the watch
     </h4>
 
-      <p>
-        After the <code>flash-all</code> script finishes, your watch reboots.
-        Only pair the watch with a phone (so you can begin testing the preview)
-        by using the instructions in <a href="#set_up_a_phone">Set Up a Phone</a>.
-        Additionally, before installing an app, perform the
-        following steps on the watch to re-secure the watch's bootloader:
+    <p>
+      After the <code>flash-all</code> script finishes, the watch reboots.
+      Only pair the watch with a phone (so you can begin testing the preview)
+      by using the instructions in <a href="#set_up_a_phone">Set Up a Phone</a>.
+      Additionally, before installing an app, perform the
+      following steps on the watch to re-secure the watch's bootloader:
     </p>
 
     <ol>
-      <li>Open the Settings menu (on the watch).
+      <li>Open the Settings menu by long-pressing the physical button.
       </li>
 
       <li>Scroll to the bottom of the menu and tap <strong>About</strong>.
@@ -467,15 +469,16 @@
       <li>Tap the build number 7 times.
       </li>
 
-      <li>From the Settings menu, tap the <strong>Developer Options</strong>
-      item.
+      <li>From the Settings menu, tap <strong>Developer Options</strong>.
       </li>
 
       <li>Enable ADB debugging.
       </li>
 
       <li>Connect the watch to your computer and tap <strong>Always allow from
-      this computer</strong>.
+      this computer</strong>. (You may need to turn ADB debugging off
+      and then on, to be prompted to always allow ADB debugging from
+      the connected computer.)
       </li>
 
       <li>Use the following adb command to start the device in fastboot mode:
@@ -487,8 +490,11 @@
       devices, <code>fastboot oem lock</code>
       </li>
 
-      <li>On the watch, continue the boot by choosing
-      <strong>Start</strong> and touching <strong>'0'</strong>.
+      <li>On the watch, continue the boot as follows:
+      On an LGE Watch Urbane 2nd Edition, choose
+      <strong>Start</strong> and touch <strong>'0'</strong>.
+      On a Huawei Watch, confirm that <strong>Reboot</strong> is chosen and
+      long-press the physical button.
       </li>
     </ol>
 
@@ -610,7 +616,8 @@
 
     <p>
       After you install the beta version of the companion app on a phone,
-      you can pair the phone to the watch:
+      unpair ("Forget") any obsolete watch pairings, if necessary.
+      Then you can pair the phone to a newly-imaged watch:
     </p>
 
     <ol>
diff --git a/graphics/java/android/graphics/Atlas.java b/graphics/java/android/graphics/Atlas.java
deleted file mode 100644
index e0a5345..0000000
--- a/graphics/java/android/graphics/Atlas.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (C) 2013 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.graphics;
-
-/**
- * @hide
- */
-public class Atlas {
-    /**
-     * WARNING: These flag values are part of the on-disk configuration information,
-     * do not change their values.
-     */
-
-    /** DELETED: FLAG_ROTATION = 0x01 */
-
-    /**
-     * This flag indicates whether the packing algorithm should leave
-     * an empty 1 pixel wide border around each bitmap. This border can
-     * be useful if the content of the atlas will be used in OpenGL using
-     * bilinear filtering.
-     */
-    public static final int FLAG_ADD_PADDING = 0x2;
-    /**
-     * Default flags: allow rotations and add padding.
-     */
-    public static final int FLAG_DEFAULTS = FLAG_ADD_PADDING;
-
-    /**
-     * Each type defines a different packing algorithm that can
-     * be used by an {@link Atlas}. The best algorithm to use
-     * will depend on the source dataset and the dimensions of
-     * the atlas.
-     */
-    public enum Type {
-        SliceMinArea,
-        SliceMaxArea,
-        SliceShortAxis,
-        SliceLongAxis
-    }
-
-    /**
-     * Represents a bitmap packed in the atlas. Each entry has a location in
-     * pixels in the atlas and a rotation flag.
-     */
-    public static class Entry {
-        /**
-         * Location, in pixels, of the bitmap on the X axis in the atlas.
-         */
-        public int x;
-        /**
-         * Location, in pixels, of the bitmap on the Y axis in the atlas.
-         */
-        public int y;
-    }
-
-    private final Policy mPolicy;
-
-    /**
-     * Creates a new atlas with the specified algorithm and dimensions
-     * in pixels. Calling this constructor is equivalent to calling
-     * {@link #Atlas(Atlas.Type, int, int, int)} with {@link #FLAG_DEFAULTS}.
-     *
-     * @param type The algorithm to use to pack rectangles in the atlas
-     * @param width The width of the atlas in pixels
-     * @param height The height of the atlas in pixels
-     *
-     * @see #Atlas(Atlas.Type, int, int, int)
-     */
-    public Atlas(Type type, int width, int height) {
-        this(type, width, height, FLAG_DEFAULTS);
-    }
-
-    /**
-     * Creates a new atlas with the specified algorithm and dimensions
-     * in pixels. A set of flags can also be specified to control the
-     * behavior of the atlas.
-     *
-     * @param type The algorithm to use to pack rectangles in the atlas
-     * @param width The width of the atlas in pixels
-     * @param height The height of the atlas in pixels
-     * @param flags Optional flags to control the behavior of the atlas:
-     *              {@link #FLAG_ADD_PADDING}, {@link #FLAG_ALLOW_ROTATIONS}
-     *
-     * @see #Atlas(Atlas.Type, int, int)
-     */
-    public Atlas(Type type, int width, int height, int flags) {
-        mPolicy = findPolicy(type, width, height, flags);
-    }
-
-    /**
-     * Packs a rectangle of the specified dimensions in this atlas.
-     *
-     * @param width The width of the rectangle to pack in the atlas
-     * @param height The height of the rectangle to pack in the atlas
-     *
-     * @return An {@link Entry} instance if the rectangle was packed in
-     *         the atlas, or null if the rectangle could not fit
-     *
-     * @see #pack(int, int, Atlas.Entry)
-     */
-    public Entry pack(int width, int height) {
-        return pack(width, height, null);
-    }
-
-    /**
-     * Packs a rectangle of the specified dimensions in this atlas.
-     *
-     * @param width The width of the rectangle to pack in the atlas
-     * @param height The height of the rectangle to pack in the atlas
-     * @param entry Out parameter that will be filled in with the location
-     *              and attributes of the packed rectangle, can be null
-     *
-     * @return An {@link Entry} instance if the rectangle was packed in
-     *         the atlas, or null if the rectangle could not fit
-     *
-     * @see #pack(int, int)
-     */
-    public Entry pack(int width, int height, Entry entry) {
-        if (entry == null) entry = new Entry();
-        return mPolicy.pack(width, height, entry);
-    }
-
-    private static Policy findPolicy(Type type, int width, int height, int flags) {
-        switch (type) {
-            case SliceMinArea:
-                return new SlicePolicy(width, height, flags,
-                        new SlicePolicy.MinAreaSplitDecision());
-            case SliceMaxArea:
-                return new SlicePolicy(width, height, flags,
-                        new SlicePolicy.MaxAreaSplitDecision());
-            case SliceShortAxis:
-                return new SlicePolicy(width, height, flags,
-                        new SlicePolicy.ShorterFreeAxisSplitDecision());
-            case SliceLongAxis:
-                return new SlicePolicy(width, height, flags,
-                        new SlicePolicy.LongerFreeAxisSplitDecision());
-        }
-        return null;
-    }
-
-    /**
-     * A policy defines how the atlas performs the packing operation.
-     */
-    private static abstract class Policy {
-        abstract Entry pack(int width, int height, Entry entry);
-    }
-
-    /**
-     * The Slice algorightm divides the remaining empty space either
-     * horizontally or vertically after a bitmap is placed in the atlas.
-     *
-     * NOTE: the algorithm is explained below using a tree but is
-     * implemented using a linked list instead for performance reasons.
-     *
-     * The algorithm starts with a single empty cell covering the entire
-     * atlas:
-     *
-     *  -----------------------
-     * |                       |
-     * |                       |
-     * |                       |
-     * |      Empty space      |
-     * |          (C0)         |
-     * |                       |
-     * |                       |
-     * |                       |
-     *  -----------------------
-     *
-     * The tree of cells looks like this:
-     *
-     * N0(free)
-     *
-     * The algorithm then places a bitmap B1, if possible:
-     *
-     *  -----------------------
-     * |        |              |
-     * |   B1   |              |
-     * |        |              |
-     * |--------               |
-     * |                       |
-     * |                       |
-     * |                       |
-     * |                       |
-     *  -----------------------
-     *
-     *  After placing a bitmap in an empty cell, the algorithm splits
-     *  the remaining space in two new empty cells. The split can occur
-     *  vertically or horizontally (this is controlled by the "split
-     *  decision" parameter of the algorithm.)
-     *
-     *  Here is for the instance the result of a vertical split:
-     *
-     *  -----------------------
-     * |        |              |
-     * |   B1   |              |
-     * |        |              |
-     * |--------|      C2      |
-     * |        |              |
-     * |        |              |
-     * |   C1   |              |
-     * |        |              |
-     *  -----------------------
-     *
-     * The cells tree now looks like this:
-     *
-     *       C0(occupied)
-     *           / \
-     *          /   \
-     *         /     \
-     *        /       \
-     *    C1(free)  C2(free)
-     *
-     * For each bitmap to place in the atlas, the Slice algorithm
-     * will visit the free cells until it finds one where a bitmap can
-     * fit. It will then split the now occupied cell and proceed onto
-     * the next bitmap.
-     */
-    private static class SlicePolicy extends Policy {
-        private final Cell mRoot = new Cell();
-
-        private final SplitDecision mSplitDecision;
-
-        private final int mPadding;
-
-        /**
-         * A cell represents a sub-rectangle of the atlas. A cell is
-         * a node in a linked list representing the available free
-         * space in the atlas.
-         */
-        private static class Cell {
-            int x;
-            int y;
-
-            int width;
-            int height;
-
-            Cell next;
-
-            @Override
-            public String toString() {
-                return String.format("cell[x=%d y=%d width=%d height=%d", x, y, width, height);
-            }
-        }
-
-        SlicePolicy(int width, int height, int flags, SplitDecision splitDecision) {
-            mPadding = (flags & FLAG_ADD_PADDING) != 0 ? 1 : 0;
-
-            // The entire atlas is empty at first, minus padding
-            Cell first = new Cell();
-            first.x = first.y = mPadding;
-            first.width = width - 2 * mPadding;
-            first.height = height - 2 * mPadding;
-
-            mRoot.next = first;
-            mSplitDecision = splitDecision;
-        }
-
-        @Override
-        Entry pack(int width, int height, Entry entry) {
-            Cell cell = mRoot.next;
-            Cell prev = mRoot;
-
-            while (cell != null) {
-                if (insert(cell, prev, width, height, entry)) {
-                    return entry;
-                }
-
-                prev = cell;
-                cell = cell.next;
-            }
-
-            return null;
-        }
-
-        /**
-         * Defines how the remaining empty space should be split up:
-         * vertically or horizontally.
-         */
-        private static interface SplitDecision {
-            /**
-             * Returns true if the remaining space defined by
-             * <code>freeWidth</code> and <code>freeHeight</code>
-             * should be split horizontally.
-             *
-             * @param freeWidth The rectWidth of the free space after packing a rectangle
-             * @param freeHeight The rectHeight of the free space after packing a rectangle
-             * @param rectWidth The rectWidth of the rectangle that was packed in a cell
-             * @param rectHeight The rectHeight of the rectangle that was packed in a cell
-             */
-            boolean splitHorizontal(int freeWidth, int freeHeight,
-                    int rectWidth, int rectHeight);
-        }
-
-        // Splits the free area horizontally to minimize the horizontal section area
-        private static class MinAreaSplitDecision implements SplitDecision {
-            @Override
-            public boolean splitHorizontal(int freeWidth, int freeHeight,
-                    int rectWidth, int rectHeight) {
-                return rectWidth * freeHeight > freeWidth * rectHeight;
-            }
-        }
-
-        // Splits the free area horizontally to maximize the horizontal section area
-        private static class MaxAreaSplitDecision implements SplitDecision {
-            @Override
-            public boolean splitHorizontal(int freeWidth, int freeHeight,
-                    int rectWidth, int rectHeight) {
-                return rectWidth * freeHeight <= freeWidth * rectHeight;
-            }
-        }
-
-        // Splits the free area horizontally if the horizontal axis is shorter
-        private static class ShorterFreeAxisSplitDecision implements SplitDecision {
-            @Override
-            public boolean splitHorizontal(int freeWidth, int freeHeight,
-                    int rectWidth, int rectHeight) {
-                return freeWidth <= freeHeight;
-            }
-        }
-
-        // Splits the free area horizontally if the vertical axis is shorter
-        private static class LongerFreeAxisSplitDecision implements SplitDecision {
-            @Override
-            public boolean splitHorizontal(int freeWidth, int freeHeight,
-                    int rectWidth, int rectHeight) {
-                return freeWidth > freeHeight;
-            }
-        }
-
-        /**
-         * Attempts to pack a rectangle of specified dimensions in the available
-         * empty space.
-         *
-         * @param cell The cell representing free space in which to pack the rectangle
-         * @param prev The previous cell in the free space linked list
-         * @param width The width of the rectangle to pack
-         * @param height The height of the rectangle to pack
-         * @param entry Stores the location of the packged rectangle, if it fits
-         *
-         * @return True if the rectangle was packed in the atlas, false otherwise
-         */
-        private boolean insert(Cell cell, Cell prev, int width, int height, Entry entry) {
-            if (cell.width < width || cell.height < height) {
-                return false;
-            }
-
-            // Remaining free space after packing the rectangle
-            int deltaWidth = cell.width - width;
-            int deltaHeight = cell.height - height;
-
-            // Split the remaining free space into two new cells
-            Cell first = new Cell();
-            Cell second = new Cell();
-
-            first.x = cell.x + width + mPadding;
-            first.y = cell.y;
-            first.width = deltaWidth - mPadding;
-
-            second.x = cell.x;
-            second.y = cell.y + height + mPadding;
-            second.height = deltaHeight - mPadding;
-
-            if (mSplitDecision.splitHorizontal(deltaWidth, deltaHeight,
-                    width, height)) {
-                first.height = height;
-                second.width = cell.width;
-            } else {
-                first.height = cell.height;
-                second.width = width;
-
-                // The order of the cells matters for efficient packing
-                // We want to give priority to the cell chosen by the
-                // split decision heuristic
-                Cell temp = first;
-                first = second;
-                second = temp;
-            }
-
-            // Remove degenerate cases to keep the free list as small as possible
-            if (first.width > 0 && first.height > 0) {
-                prev.next = first;
-                prev = first;
-            }
-
-            if (second.width > 0 && second.height > 0) {
-                prev.next = second;
-                second.next = cell.next;
-            } else {
-                prev.next = cell.next;
-            }
-
-            // The cell is now completely removed from the free list
-            cell.next = null;
-
-            // Return the location and rotation of the packed rectangle
-            entry.x = cell.x;
-            entry.y = cell.y;
-
-            return true;
-        }
-    }
-}
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
new file mode 100644
index 0000000..f135484
--- /dev/null
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -0,0 +1,557 @@
+/*
+ * 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.graphics;
+
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.Size;
+import android.graphics.Canvas.VertexMode;
+import android.text.GraphicsOperations;
+import android.text.SpannableString;
+import android.text.SpannedString;
+import android.text.TextUtils;
+import android.view.RecordingCanvas;
+
+/**
+ * This class is a base class for Canvas's drawing operations. Any modifications here
+ * should be accompanied by a similar modification to {@link RecordingCanvas}.
+ *
+ * The purpose of this class is to minimize the cost of deciding between regular JNI
+ * and @FastNative JNI to just the virtual call that Canvas already has.
+ *
+ * @hide
+ */
+public abstract class BaseCanvas {
+    /**
+     * Should only be assigned in constructors (or setBitmap if software canvas),
+     * freed by NativeAllocation.
+     */
+    protected long mNativeCanvasWrapper;
+
+    /**
+     * Used to determine when compatibility scaling is in effect.
+     */
+    protected int mScreenDensity = Bitmap.DENSITY_NONE;
+    protected int mDensity = Bitmap.DENSITY_NONE;
+
+    protected void throwIfCannotDraw(Bitmap bitmap) {
+        if (bitmap.isRecycled()) {
+            throw new RuntimeException("Canvas: trying to use a recycled bitmap " + bitmap);
+        }
+        if (!bitmap.isPremultiplied() && bitmap.getConfig() == Bitmap.Config.ARGB_8888 &&
+                bitmap.hasAlpha()) {
+            throw new RuntimeException("Canvas: trying to use a non-premultiplied bitmap "
+                    + bitmap);
+        }
+    }
+
+    protected final static void checkRange(int length, int offset, int count) {
+        if ((offset | count) < 0 || offset + count > length) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+    }
+
+    public boolean isHardwareAccelerated() {
+        return false;
+    }
+
+    // ---------------------------------------------------------------------------
+    // Drawing methods
+    // These are also implemented in DisplayListCanvas so that we can
+    // selectively apply on them
+    // Everything below here is copy/pasted from Canvas.java
+    // The JNI registration is handled by android_view_Canvas.cpp
+    // ---------------------------------------------------------------------------
+
+    public void drawArc(float left, float top, float right, float bottom, float startAngle,
+            float sweepAngle, boolean useCenter, @NonNull Paint paint) {
+        nDrawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
+                useCenter, paint.getNativeInstance());
+    }
+
+    public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
+            @NonNull Paint paint) {
+        drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
+                paint);
+    }
+
+    public void drawARGB(int a, int r, int g, int b) {
+        drawColor(Color.argb(a, r, g, b));
+    }
+
+    public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
+        throwIfCannotDraw(bitmap);
+        nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top,
+                paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity,
+                bitmap.mDensity);
+    }
+
+    public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
+        nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(),
+                paint != null ? paint.getNativeInstance() : 0);
+    }
+
+    public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
+            @Nullable Paint paint) {
+        if (dst == null) {
+            throw new NullPointerException();
+        }
+        throwIfCannotDraw(bitmap);
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+
+        int left, top, right, bottom;
+        if (src == null) {
+            left = top = 0;
+            right = bitmap.getWidth();
+            bottom = bitmap.getHeight();
+        } else {
+            left = src.left;
+            right = src.right;
+            top = src.top;
+            bottom = src.bottom;
+        }
+
+        nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
+                dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
+                bitmap.mDensity);
+    }
+
+    public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
+            @Nullable Paint paint) {
+        if (dst == null) {
+            throw new NullPointerException();
+        }
+        throwIfCannotDraw(bitmap);
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+
+        float left, top, right, bottom;
+        if (src == null) {
+            left = top = 0;
+            right = bitmap.getWidth();
+            bottom = bitmap.getHeight();
+        } else {
+            left = src.left;
+            right = src.right;
+            top = src.top;
+            bottom = src.bottom;
+        }
+
+        nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
+                dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
+                bitmap.mDensity);
+    }
+
+    @Deprecated
+    public void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y,
+            int width, int height, boolean hasAlpha, @Nullable Paint paint) {
+        // check for valid input
+        if (width < 0) {
+            throw new IllegalArgumentException("width must be >= 0");
+        }
+        if (height < 0) {
+            throw new IllegalArgumentException("height must be >= 0");
+        }
+        if (Math.abs(stride) < width) {
+            throw new IllegalArgumentException("abs(stride) must be >= width");
+        }
+        int lastScanline = offset + (height - 1) * stride;
+        int length = colors.length;
+        if (offset < 0 || (offset + width > length) || lastScanline < 0
+                || (lastScanline + width > length)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        // quick escape if there's nothing to draw
+        if (width == 0 || height == 0) {
+            return;
+        }
+        // punch down to native for the actual draw
+        nDrawBitmap(mNativeCanvasWrapper, colors, offset, stride, x, y, width, height, hasAlpha,
+                paint != null ? paint.getNativeInstance() : 0);
+    }
+
+    @Deprecated
+    public void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y,
+            int width, int height, boolean hasAlpha, @Nullable Paint paint) {
+        // call through to the common float version
+        drawBitmap(colors, offset, stride, (float) x, (float) y, width, height,
+                hasAlpha, paint);
+    }
+
+    public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
+            @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
+            @Nullable Paint paint) {
+        if ((meshWidth | meshHeight | vertOffset | colorOffset) < 0) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (meshWidth == 0 || meshHeight == 0) {
+            return;
+        }
+        int count = (meshWidth + 1) * (meshHeight + 1);
+        // we mul by 2 since we need two floats per vertex
+        checkRange(verts.length, vertOffset, count * 2);
+        if (colors != null) {
+            // no mul by 2, since we need only 1 color per vertex
+            checkRange(colors.length, colorOffset, count);
+        }
+        nDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight,
+                verts, vertOffset, colors, colorOffset,
+                paint != null ? paint.getNativeInstance() : 0);
+    }
+
+    public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
+        nDrawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
+    }
+
+    public void drawColor(@ColorInt int color) {
+        nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
+    }
+
+    public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
+        nDrawColor(mNativeCanvasWrapper, color, mode.nativeInt);
+    }
+
+    public void drawLine(float startX, float startY, float stopX, float stopY,
+            @NonNull Paint paint) {
+        nDrawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
+    }
+
+    public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
+            @NonNull Paint paint) {
+        nDrawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
+    }
+
+    public void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) {
+        drawLines(pts, 0, pts.length, paint);
+    }
+
+    public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
+        nDrawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
+    }
+
+    public void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
+        if (oval == null) {
+            throw new NullPointerException();
+        }
+        drawOval(oval.left, oval.top, oval.right, oval.bottom, paint);
+    }
+
+    public void drawPaint(@NonNull Paint paint) {
+        nDrawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
+    }
+
+    public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
+        Bitmap bitmap = patch.getBitmap();
+        throwIfCannotDraw(bitmap);
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+        nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
+                dst.left, dst.top, dst.right, dst.bottom, nativePaint,
+                mDensity, patch.getDensity());
+    }
+
+    public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
+        Bitmap bitmap = patch.getBitmap();
+        throwIfCannotDraw(bitmap);
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+        nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
+                dst.left, dst.top, dst.right, dst.bottom, nativePaint,
+                mDensity, patch.getDensity());
+    }
+
+    public void drawPath(@NonNull Path path, @NonNull Paint paint) {
+        if (path.isSimplePath && path.rects != null) {
+            nDrawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
+        } else {
+            nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
+        }
+    }
+
+    public void drawPoint(float x, float y, @NonNull Paint paint) {
+        nDrawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
+    }
+
+    public void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
+            @NonNull Paint paint) {
+        nDrawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
+    }
+
+    public void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) {
+        drawPoints(pts, 0, pts.length, paint);
+    }
+
+    @Deprecated
+    public void drawPosText(@NonNull char[] text, int index, int count,
+            @NonNull @Size(multiple = 2) float[] pos,
+            @NonNull Paint paint) {
+        if (index < 0 || index + count > text.length || count * 2 > pos.length) {
+            throw new IndexOutOfBoundsException();
+        }
+        for (int i = 0; i < count; i++) {
+            drawText(text, index + i, 1, pos[i * 2], pos[i * 2 + 1], paint);
+        }
+    }
+
+    @Deprecated
+    public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos,
+            @NonNull Paint paint) {
+        drawPosText(text.toCharArray(), 0, text.length(), pos, paint);
+    }
+
+    public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
+        nDrawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
+    }
+
+    public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
+        drawRect(r.left, r.top, r.right, r.bottom, paint);
+    }
+
+    public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
+        nDrawRect(mNativeCanvasWrapper,
+                rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
+    }
+
+    public void drawRGB(int r, int g, int b) {
+        drawColor(Color.rgb(r, g, b));
+    }
+
+    public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+            @NonNull Paint paint) {
+        nDrawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry,
+                paint.getNativeInstance());
+    }
+
+    public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
+        drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
+    }
+
+    public void drawText(@NonNull char[] text, int index, int count, float x, float y,
+            @NonNull Paint paint) {
+        if ((index | count | (index + count) |
+                (text.length - index - count)) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+        nDrawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
+                paint.getNativeInstance(), paint.mNativeTypeface);
+    }
+
+    public void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
+            @NonNull Paint paint) {
+        if ((start | end | (end - start) | (text.length() - end)) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (text instanceof String || text instanceof SpannedString ||
+                text instanceof SpannableString) {
+            nDrawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
+                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+        } else if (text instanceof GraphicsOperations) {
+            ((GraphicsOperations) text).drawText(this, start, end, x, y,
+                    paint);
+        } else {
+            char[] buf = TemporaryBuffer.obtain(end - start);
+            TextUtils.getChars(text, start, end, buf, 0);
+            nDrawText(mNativeCanvasWrapper, buf, 0, end - start, x, y,
+                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+            TemporaryBuffer.recycle(buf);
+        }
+    }
+
+    public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
+        nDrawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
+                paint.getNativeInstance(), paint.mNativeTypeface);
+    }
+
+    public void drawText(@NonNull String text, int start, int end, float x, float y,
+            @NonNull Paint paint) {
+        if ((start | end | (end - start) | (text.length() - end)) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+        nDrawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
+                paint.getNativeInstance(), paint.mNativeTypeface);
+    }
+
+    public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
+            float hOffset, float vOffset, @NonNull Paint paint) {
+        if (index < 0 || index + count > text.length) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        nDrawTextOnPath(mNativeCanvasWrapper, text, index, count,
+                path.readOnlyNI(), hOffset, vOffset,
+                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+    }
+
+    public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
+            float vOffset, @NonNull Paint paint) {
+        if (text.length() > 0) {
+            nDrawTextOnPath(mNativeCanvasWrapper, text, path.readOnlyNI(), hOffset, vOffset,
+                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+        }
+    }
+
+    public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
+            int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
+
+        if (text == null) {
+            throw new NullPointerException("text is null");
+        }
+        if (paint == null) {
+            throw new NullPointerException("paint is null");
+        }
+        if ((index | count | contextIndex | contextCount | index - contextIndex
+                | (contextIndex + contextCount) - (index + count)
+                | text.length - (contextIndex + contextCount)) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        nDrawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount,
+                x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+    }
+
+    public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
+            int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
+
+        if (text == null) {
+            throw new NullPointerException("text is null");
+        }
+        if (paint == null) {
+            throw new NullPointerException("paint is null");
+        }
+        if ((start | end | contextStart | contextEnd | start - contextStart | end - start
+                | contextEnd - end | text.length() - contextEnd) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        if (text instanceof String || text instanceof SpannedString ||
+                text instanceof SpannableString) {
+            nDrawTextRun(mNativeCanvasWrapper, text.toString(), start, end, contextStart,
+                    contextEnd, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+        } else if (text instanceof GraphicsOperations) {
+            ((GraphicsOperations) text).drawTextRun(this, start, end,
+                    contextStart, contextEnd, x, y, isRtl, paint);
+        } else {
+            int contextLen = contextEnd - contextStart;
+            int len = end - start;
+            char[] buf = TemporaryBuffer.obtain(contextLen);
+            TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
+            nDrawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
+                    0, contextLen, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+            TemporaryBuffer.recycle(buf);
+        }
+    }
+
+    public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
+            int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
+            int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
+            @NonNull Paint paint) {
+        checkRange(verts.length, vertOffset, vertexCount);
+        if (isHardwareAccelerated()) {
+            return;
+        }
+        if (texs != null) {
+            checkRange(texs.length, texOffset, vertexCount);
+        }
+        if (colors != null) {
+            checkRange(colors.length, colorOffset, vertexCount / 2);
+        }
+        if (indices != null) {
+            checkRange(indices.length, indexOffset, indexCount);
+        }
+        nDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
+                vertOffset, texs, texOffset, colors, colorOffset,
+                indices, indexOffset, indexCount, paint.getNativeInstance());
+    }
+
+    private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top,
+            long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity);
+
+    private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float srcLeft,
+            float srcTop,
+            float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight,
+            float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity);
+
+    private static native void nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride,
+            float x, float y, int width, int height, boolean hasAlpha, long nativePaintOrZero);
+
+    private static native void nDrawColor(long nativeCanvas, int color, int mode);
+
+    private static native void nDrawPaint(long nativeCanvas, long nativePaint);
+
+    private static native void nDrawPoint(long canvasHandle, float x, float y, long paintHandle);
+
+    private static native void nDrawPoints(long canvasHandle, float[] pts, int offset, int count,
+            long paintHandle);
+
+    private static native void nDrawLine(long nativeCanvas, float startX, float startY, float stopX,
+            float stopY, long nativePaint);
+
+    private static native void nDrawLines(long canvasHandle, float[] pts, int offset, int count,
+            long paintHandle);
+
+    private static native void nDrawRect(long nativeCanvas, float left, float top, float right,
+            float bottom, long nativePaint);
+
+    private static native void nDrawOval(long nativeCanvas, float left, float top, float right,
+            float bottom, long nativePaint);
+
+    private static native void nDrawCircle(long nativeCanvas, float cx, float cy, float radius,
+            long nativePaint);
+
+    private static native void nDrawArc(long nativeCanvas, float left, float top, float right,
+            float bottom, float startAngle, float sweep, boolean useCenter, long nativePaint);
+
+    private static native void nDrawRoundRect(long nativeCanvas, float left, float top, float right,
+            float bottom, float rx, float ry, long nativePaint);
+
+    private static native void nDrawPath(long nativeCanvas, long nativePath, long nativePaint);
+
+    private static native void nDrawRegion(long nativeCanvas, long nativeRegion, long nativePaint);
+
+    private static native void nDrawNinePatch(long nativeCanvas, long nativeBitmap, long ninePatch,
+            float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero,
+            int screenDensity, int bitmapDensity);
+
+    private static native void nDrawBitmapMatrix(long nativeCanvas, Bitmap bitmap,
+            long nativeMatrix, long nativePaint);
+
+    private static native void nDrawBitmapMesh(long nativeCanvas, Bitmap bitmap, int meshWidth,
+            int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset,
+            long nativePaint);
+
+    private static native void nDrawVertices(long nativeCanvas, int mode, int n, float[] verts,
+            int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset,
+            short[] indices, int indexOffset, int indexCount, long nativePaint);
+
+    private static native void nDrawText(long nativeCanvas, char[] text, int index, int count,
+            float x, float y, int flags, long nativePaint, long nativeTypeface);
+
+    private static native void nDrawText(long nativeCanvas, String text, int start, int end,
+            float x, float y, int flags, long nativePaint, long nativeTypeface);
+
+    private static native void nDrawTextRun(long nativeCanvas, String text, int start, int end,
+            int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint,
+            long nativeTypeface);
+
+    private static native void nDrawTextRun(long nativeCanvas, char[] text, int start, int count,
+            int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint,
+            long nativeTypeface);
+
+    private static native void nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count,
+            long nativePath, float hOffset, float vOffset, int bidiFlags, long nativePaint,
+            long nativeTypeface);
+
+    private static native void nDrawTextOnPath(long nativeCanvas, String text, long nativePath,
+            float hOffset, float vOffset, int flags, long nativePaint, long nativeTypeface);
+}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 7ce750d..fd2f705 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -73,8 +73,8 @@
     private int mHeight;
     private boolean mRecycled;
 
-    // Package-scoped for fast access.
-    int mDensity = getDefaultDensity();
+    /** @hide */
+    public int mDensity = getDefaultDensity();
 
     private static volatile Matrix sScaleMatrix;
 
@@ -130,8 +130,9 @@
 
     /**
      * Return the pointer to the native object.
+     * @hide
      */
-    long getNativeInstance() {
+    public long getNativeInstance() {
         return mNativePtr;
     }
 
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index d29005c..3f0bed8 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -26,13 +26,15 @@
 import android.text.SpannedString;
 import android.text.TextUtils;
 
+import dalvik.annotation.optimization.FastNative;
+
+import libcore.util.NativeAllocationRegistry;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 import javax.microedition.khronos.opengles.GL;
 
-import libcore.util.NativeAllocationRegistry;
-
 /**
  * The Canvas class holds the "draw" calls. To draw something, you need
  * 4 basic components: A Bitmap to hold the pixels, a Canvas to host
@@ -46,17 +48,10 @@
  * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html">
  * Canvas and Drawables</a> developer guide.</p></div>
  */
-public class Canvas {
+public class Canvas extends BaseCanvas {
     /** @hide */
     public static boolean sCompatibilityRestore = false;
 
-    /**
-     * Should only be assigned in constructors (or setBitmap if software canvas),
-     * freed by NativeAllocation.
-     * @hide
-     */
-    protected long mNativeCanvasWrapper;
-
     /** @hide */
     public long getNativeCanvasWrapper() {
         return mNativeCanvasWrapper;
@@ -71,18 +66,6 @@
     // optional field set by the caller
     private DrawFilter mDrawFilter;
 
-    /**
-     * @hide
-     */
-    protected int mDensity = Bitmap.DENSITY_NONE;
-
-    /**
-     * Used to determine when compatibility scaling is in effect.
-     *
-     * @hide
-     */
-    protected int mScreenDensity = Bitmap.DENSITY_NONE;
-
     // Maximum bitmap size as defined in Skia's native code
     // (see SkCanvas.cpp, SkDraw.cpp)
     private static final int MAXMIMUM_BITMAP_SIZE = 32766;
@@ -94,7 +77,7 @@
     // Use a Holder to allow static initialization of Canvas in the boot image.
     private static class NoImagePreloadHolder {
         public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-                Canvas.class.getClassLoader(), getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+                Canvas.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
     }
 
     // This field is used to finalize the native Canvas properly
@@ -109,7 +92,7 @@
     public Canvas() {
         if (!isHardwareAccelerated()) {
             // 0 means no native bitmap
-            mNativeCanvasWrapper = initRaster(null);
+            mNativeCanvasWrapper = nInitRaster(null);
             mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
                     this, mNativeCanvasWrapper);
         } else {
@@ -131,7 +114,7 @@
             throw new IllegalStateException("Immutable bitmap passed to Canvas constructor");
         }
         throwIfCannotDraw(bitmap);
-        mNativeCanvasWrapper = initRaster(bitmap);
+        mNativeCanvasWrapper = nInitRaster(bitmap);
         mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
                 this, mNativeCanvasWrapper);
         mBitmap = bitmap;
@@ -190,7 +173,7 @@
         }
 
         if (bitmap == null) {
-            native_setBitmap(mNativeCanvasWrapper, null);
+            nSetBitmap(mNativeCanvasWrapper, null);
             mDensity = Bitmap.DENSITY_NONE;
         } else {
             if (!bitmap.isMutable()) {
@@ -198,7 +181,7 @@
             }
             throwIfCannotDraw(bitmap);
 
-            native_setBitmap(mNativeCanvasWrapper, bitmap);
+            nSetBitmap(mNativeCanvasWrapper, bitmap);
             mDensity = bitmap.mDensity;
         }
 
@@ -207,7 +190,7 @@
 
     /** @hide */
     public void setHighContrastText(boolean highContrastText) {
-        native_setHighContrastText(mNativeCanvasWrapper, highContrastText);
+        nSetHighContrastText(mNativeCanvasWrapper, highContrastText);
     }
 
     /** @hide */
@@ -223,7 +206,7 @@
      * @return true if the device that the current layer draws into is opaque
      */
     public boolean isOpaque() {
-        return native_isOpaque(mNativeCanvasWrapper);
+        return nIsOpaque(mNativeCanvasWrapper);
     }
 
     /**
@@ -232,7 +215,7 @@
      * @return the width of the current drawing layer
      */
     public int getWidth() {
-        return native_getWidth(mNativeCanvasWrapper);
+        return nGetWidth(mNativeCanvasWrapper);
     }
 
     /**
@@ -241,7 +224,7 @@
      * @return the height of the current drawing layer
      */
     public int getHeight() {
-        return native_getHeight(mNativeCanvasWrapper);
+        return nGetHeight(mNativeCanvasWrapper);
     }
 
     /**
@@ -369,7 +352,7 @@
      * @return The value to pass to restoreToCount() to balance this save()
      */
     public int save() {
-        return native_save(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+        return nSave(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
     }
 
     /**
@@ -389,7 +372,7 @@
      * @return The value to pass to restoreToCount() to balance this save()
      */
     public int save(@Saveflags int saveFlags) {
-        return native_save(mNativeCanvasWrapper, saveFlags);
+        return nSave(mNativeCanvasWrapper, saveFlags);
     }
 
     /**
@@ -441,7 +424,7 @@
      */
     public int saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint,
             @Saveflags int saveFlags) {
-        return native_saveLayer(mNativeCanvasWrapper, left, top, right, bottom,
+        return nSaveLayer(mNativeCanvasWrapper, left, top, right, bottom,
                 paint != null ? paint.getNativeInstance() : 0,
                 saveFlags);
     }
@@ -501,7 +484,7 @@
     public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
             @Saveflags int saveFlags) {
         alpha = Math.min(255, Math.max(0, alpha));
-        return native_saveLayerAlpha(mNativeCanvasWrapper, left, top, right, bottom,
+        return nSaveLayerAlpha(mNativeCanvasWrapper, left, top, right, bottom,
                                      alpha, saveFlags);
     }
 
@@ -519,7 +502,7 @@
      */
     public void restore() {
         boolean throwOnUnderflow = !sCompatibilityRestore || !isHardwareAccelerated();
-        native_restore(mNativeCanvasWrapper, throwOnUnderflow);
+        nRestore(mNativeCanvasWrapper, throwOnUnderflow);
     }
 
     /**
@@ -527,7 +510,7 @@
      * This will equal # save() calls - # restore() calls.
      */
     public int getSaveCount() {
-        return native_getSaveCount(mNativeCanvasWrapper);
+        return nGetSaveCount(mNativeCanvasWrapper);
     }
 
     /**
@@ -545,7 +528,7 @@
      */
     public void restoreToCount(int saveCount) {
         boolean throwOnUnderflow = !sCompatibilityRestore || !isHardwareAccelerated();
-        native_restoreToCount(mNativeCanvasWrapper, saveCount, throwOnUnderflow);
+        nRestoreToCount(mNativeCanvasWrapper, saveCount, throwOnUnderflow);
     }
 
     /**
@@ -556,7 +539,7 @@
     */
     public void translate(float dx, float dy) {
         if (dx == 0.0f && dy == 0.0f) return;
-        native_translate(mNativeCanvasWrapper, dx, dy);
+        nTranslate(mNativeCanvasWrapper, dx, dy);
     }
 
     /**
@@ -567,7 +550,7 @@
      */
     public void scale(float sx, float sy) {
         if (sx == 1.0f && sy == 1.0f) return;
-        native_scale(mNativeCanvasWrapper, sx, sy);
+        nScale(mNativeCanvasWrapper, sx, sy);
     }
 
     /**
@@ -592,7 +575,7 @@
      */
     public void rotate(float degrees) {
         if (degrees == 0.0f) return;
-        native_rotate(mNativeCanvasWrapper, degrees);
+        nRotate(mNativeCanvasWrapper, degrees);
     }
 
     /**
@@ -617,7 +600,7 @@
      */
     public void skew(float sx, float sy) {
         if (sx == 0.0f && sy == 0.0f) return;
-        native_skew(mNativeCanvasWrapper, sx, sy);
+        nSkew(mNativeCanvasWrapper, sx, sy);
     }
 
     /**
@@ -627,7 +610,7 @@
      * @param matrix The matrix to preconcatenate with the current matrix
      */
     public void concat(@Nullable Matrix matrix) {
-        if (matrix != null) native_concat(mNativeCanvasWrapper, matrix.native_instance);
+        if (matrix != null) nConcat(mNativeCanvasWrapper, matrix.native_instance);
     }
 
     /**
@@ -644,7 +627,7 @@
      * @see #concat(Matrix)
      */
     public void setMatrix(@Nullable Matrix matrix) {
-        native_setMatrix(mNativeCanvasWrapper,
+        nSetMatrix(mNativeCanvasWrapper,
                          matrix == null ? 0 : matrix.native_instance);
     }
 
@@ -660,7 +643,7 @@
      */
     @Deprecated
     public void getMatrix(@NonNull Matrix ctm) {
-        native_getCTM(mNativeCanvasWrapper, ctm.native_instance);
+        nGetCTM(mNativeCanvasWrapper, ctm.native_instance);
     }
 
     /**
@@ -689,7 +672,7 @@
      * @return true if the resulting clip is non-empty
      */
     public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) {
-        return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
+        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
                 op.nativeInt);
     }
 
@@ -702,7 +685,7 @@
      * @return true if the resulting clip is non-empty
      */
     public boolean clipRect(@NonNull Rect rect, @NonNull Region.Op op) {
-        return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
+        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
                 op.nativeInt);
     }
 
@@ -714,7 +697,7 @@
      * @return true if the resulting clip is non-empty
      */
     public boolean clipRect(@NonNull RectF rect) {
-        return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
+        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
                 Region.Op.INTERSECT.nativeInt);
     }
 
@@ -726,7 +709,7 @@
      * @return true if the resulting clip is non-empty
      */
     public boolean clipRect(@NonNull Rect rect) {
-        return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
+        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
                 Region.Op.INTERSECT.nativeInt);
     }
 
@@ -747,7 +730,7 @@
      */
     public boolean clipRect(float left, float top, float right, float bottom,
             @NonNull Region.Op op) {
-        return native_clipRect(mNativeCanvasWrapper, left, top, right, bottom, op.nativeInt);
+        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, op.nativeInt);
     }
 
     /**
@@ -764,7 +747,7 @@
      * @return       true if the resulting clip is non-empty
      */
     public boolean clipRect(float left, float top, float right, float bottom) {
-        return native_clipRect(mNativeCanvasWrapper, left, top, right, bottom,
+        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
                 Region.Op.INTERSECT.nativeInt);
     }
 
@@ -782,7 +765,7 @@
      * @return       true if the resulting clip is non-empty
      */
     public boolean clipRect(int left, int top, int right, int bottom) {
-        return native_clipRect(mNativeCanvasWrapper, left, top, right, bottom,
+        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
                 Region.Op.INTERSECT.nativeInt);
     }
 
@@ -794,7 +777,7 @@
      * @return     true if the resulting is non-empty
      */
     public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) {
-        return native_clipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt);
+        return nClipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt);
     }
 
     /**
@@ -823,7 +806,7 @@
      */
     @Deprecated
     public boolean clipRegion(@NonNull Region region, @NonNull Region.Op op) {
-        return native_clipRegion(mNativeCanvasWrapper, region.ni(), op.nativeInt);
+        return nClipRegion(mNativeCanvasWrapper, region.ni(), op.nativeInt);
     }
 
     /**
@@ -854,7 +837,7 @@
             nativeFilter = filter.mNativeInt;
         }
         mDrawFilter = filter;
-        nativeSetDrawFilter(mNativeCanvasWrapper, nativeFilter);
+        nSetDrawFilter(mNativeCanvasWrapper, nativeFilter);
     }
 
     /**
@@ -902,7 +885,7 @@
      *              does not intersect with the canvas' clip
      */
     public boolean quickReject(@NonNull RectF rect, @NonNull EdgeType type) {
-        return native_quickReject(mNativeCanvasWrapper,
+        return nQuickReject(mNativeCanvasWrapper,
                 rect.left, rect.top, rect.right, rect.bottom);
     }
 
@@ -922,7 +905,7 @@
      *                    does not intersect with the canvas' clip
      */
     public boolean quickReject(@NonNull Path path, @NonNull EdgeType type) {
-        return native_quickReject(mNativeCanvasWrapper, path.readOnlyNI());
+        return nQuickReject(mNativeCanvasWrapper, path.readOnlyNI());
     }
 
     /**
@@ -947,7 +930,7 @@
      */
     public boolean quickReject(float left, float top, float right, float bottom,
             @NonNull EdgeType type) {
-        return native_quickReject(mNativeCanvasWrapper, left, top, right, bottom);
+        return nQuickReject(mNativeCanvasWrapper, left, top, right, bottom);
     }
 
     /**
@@ -961,7 +944,7 @@
      * @return true if the current clip is non-empty.
      */
     public boolean getClipBounds(@Nullable Rect bounds) {
-        return native_getClipBounds(mNativeCanvasWrapper, bounds);
+        return nGetClipBounds(mNativeCanvasWrapper, bounds);
     }
 
     /**
@@ -976,209 +959,206 @@
     }
 
     /**
-     * Fill the entire canvas' bitmap (restricted to the current clip) with the
-     * specified RGB color, using srcover porterduff mode.
+     * Save the canvas state, draw the picture, and restore the canvas state.
+     * This differs from picture.draw(canvas), which does not perform any
+     * save/restore.
      *
-     * @param r red component (0..255) of the color to draw onto the canvas
-     * @param g green component (0..255) of the color to draw onto the canvas
-     * @param b blue component (0..255) of the color to draw onto the canvas
+     * <p>
+     * <strong>Note:</strong> This forces the picture to internally call
+     * {@link Picture#endRecording} in order to prepare for playback.
+     *
+     * @param picture  The picture to be drawn
      */
-    public void drawRGB(int r, int g, int b) {
-        drawColor(Color.rgb(r, g, b));
+    public void drawPicture(@NonNull Picture picture) {
+        picture.endRecording();
+        int restoreCount = save();
+        picture.draw(this);
+        restoreToCount(restoreCount);
     }
 
     /**
-     * Fill the entire canvas' bitmap (restricted to the current clip) with the
-     * specified ARGB color, using srcover porterduff mode.
-     *
-     * @param a alpha component (0..255) of the color to draw onto the canvas
-     * @param r red component (0..255) of the color to draw onto the canvas
-     * @param g green component (0..255) of the color to draw onto the canvas
-     * @param b blue component (0..255) of the color to draw onto the canvas
+     * Draw the picture, stretched to fit into the dst rectangle.
      */
-    public void drawARGB(int a, int r, int g, int b) {
-        drawColor(Color.argb(a, r, g, b));
-    }
-
-    /**
-     * Fill the entire canvas' bitmap (restricted to the current clip) with the
-     * specified color, using srcover porterduff mode.
-     *
-     * @param color the color to draw onto the canvas
-     */
-    public void drawColor(@ColorInt int color) {
-        native_drawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
-    }
-
-    /**
-     * Fill the entire canvas' bitmap (restricted to the current clip) with the
-     * specified color and porter-duff xfermode.
-     *
-     * @param color the color to draw with
-     * @param mode  the porter-duff mode to apply to the color
-     */
-    public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
-        native_drawColor(mNativeCanvasWrapper, color, mode.nativeInt);
-    }
-
-    /**
-     * Fill the entire canvas' bitmap (restricted to the current clip) with
-     * the specified paint. This is equivalent (but faster) to drawing an
-     * infinitely large rectangle with the specified paint.
-     *
-     * @param paint The paint used to draw onto the canvas
-     */
-    public void drawPaint(@NonNull Paint paint) {
-        native_drawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
-    }
-
-    /**
-     * Draw a series of points. Each point is centered at the coordinate
-     * specified by pts[], and its diameter is specified by the paint's stroke
-     * width (as transformed by the canvas' CTM), with special treatment for
-     * a stroke width of 0, which always draws exactly 1 pixel (or at most 4
-     * if antialiasing is enabled). The shape of the point is controlled by
-     * the paint's Cap type. The shape is a square, unless the cap type is
-     * Round, in which case the shape is a circle.
-     *
-     * @param pts      Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
-     * @param offset   Number of values to skip before starting to draw.
-     * @param count    The number of values to process, after skipping offset
-     *                 of them. Since one point uses two values, the number of
-     *                 "points" that are drawn is really (count >> 1).
-     * @param paint    The paint used to draw the points
-     */
-    public void drawPoints(@Size(multiple=2) float[] pts, int offset, int count,
-            @NonNull Paint paint) {
-        native_drawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
-    }
-
-    /**
-     * Helper for drawPoints() that assumes you want to draw the entire array
-     */
-    public void drawPoints(@Size(multiple=2) @NonNull float[] pts, @NonNull Paint paint) {
-        drawPoints(pts, 0, pts.length, paint);
-    }
-
-    /**
-     * Helper for drawPoints() for drawing a single point.
-     */
-    public void drawPoint(float x, float y, @NonNull Paint paint) {
-        native_drawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
-    }
-
-    /**
-     * Draw a line segment with the specified start and stop x,y coordinates,
-     * using the specified paint.
-     *
-     * <p>Note that since a line is always "framed", the Style is ignored in the paint.</p>
-     *
-     * <p>Degenerate lines (length is 0) will not be drawn.</p>
-     *
-     * @param startX The x-coordinate of the start point of the line
-     * @param startY The y-coordinate of the start point of the line
-     * @param paint  The paint used to draw the line
-     */
-    public void drawLine(float startX, float startY, float stopX, float stopY,
-            @NonNull Paint paint) {
-        native_drawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
-    }
-
-    /**
-     * Draw a series of lines. Each line is taken from 4 consecutive values
-     * in the pts array. Thus to draw 1 line, the array must contain at least 4
-     * values. This is logically the same as drawing the array as follows:
-     * drawLine(pts[0], pts[1], pts[2], pts[3]) followed by
-     * drawLine(pts[4], pts[5], pts[6], pts[7]) and so on.
-     *
-     * @param pts      Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
-     * @param offset   Number of values in the array to skip before drawing.
-     * @param count    The number of values in the array to process, after
-     *                 skipping "offset" of them. Since each line uses 4 values,
-     *                 the number of "lines" that are drawn is really
-     *                 (count >> 2).
-     * @param paint    The paint used to draw the points
-     */
-    public void drawLines(@Size(multiple=4) @NonNull float[] pts, int offset, int count,
-            @NonNull Paint paint) {
-        native_drawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
-    }
-
-    public void drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint) {
-        drawLines(pts, 0, pts.length, paint);
-    }
-
-    /**
-     * Draw the specified Rect using the specified paint. The rectangle will
-     * be filled or framed based on the Style in the paint.
-     *
-     * @param rect  The rect to be drawn
-     * @param paint The paint used to draw the rect
-     */
-    public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
-        native_drawRect(mNativeCanvasWrapper,
-                rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
-    }
-
-    /**
-     * Draw the specified Rect using the specified Paint. The rectangle
-     * will be filled or framed based on the Style in the paint.
-     *
-     * @param r        The rectangle to be drawn.
-     * @param paint    The paint used to draw the rectangle
-     */
-    public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
-        drawRect(r.left, r.top, r.right, r.bottom, paint);
-    }
-
-
-    /**
-     * Draw the specified Rect using the specified paint. The rectangle will
-     * be filled or framed based on the Style in the paint.
-     *
-     * @param left   The left side of the rectangle to be drawn
-     * @param top    The top side of the rectangle to be drawn
-     * @param right  The right side of the rectangle to be drawn
-     * @param bottom The bottom side of the rectangle to be drawn
-     * @param paint  The paint used to draw the rect
-     */
-    public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
-        native_drawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
-    }
-
-    /**
-     * Draw the specified oval using the specified paint. The oval will be
-     * filled or framed based on the Style in the paint.
-     *
-     * @param oval The rectangle bounds of the oval to be drawn
-     */
-    public void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
-        if (oval == null) {
-            throw new NullPointerException();
+    public void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
+        save();
+        translate(dst.left, dst.top);
+        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
+            scale((float) dst.width() / picture.getWidth(),
+                    (float) dst.height() / picture.getHeight());
         }
-        drawOval(oval.left, oval.top, oval.right, oval.bottom, paint);
+        drawPicture(picture);
+        restore();
     }
 
     /**
-     * Draw the specified oval using the specified paint. The oval will be
-     * filled or framed based on the Style in the paint.
+     * Draw the picture, stretched to fit into the dst rectangle.
      */
-    public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
-        native_drawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
+    public void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
+        save();
+        translate(dst.left, dst.top);
+        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
+            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
+        }
+        drawPicture(picture);
+        restore();
+    }
+
+    public enum VertexMode {
+        TRIANGLES(0),
+        TRIANGLE_STRIP(1),
+        TRIANGLE_FAN(2);
+
+        VertexMode(int nativeInt) {
+            this.nativeInt = nativeInt;
+        }
+
+        /**
+         * @hide
+         */
+        public final int nativeInt;
     }
 
     /**
-     * Draw the specified circle using the specified paint. If radius is <= 0,
-     * then nothing will be drawn. The circle will be filled or framed based
-     * on the Style in the paint.
+     * Releases the resources associated with this canvas.
      *
-     * @param cx     The x-coordinate of the center of the cirle to be drawn
-     * @param cy     The y-coordinate of the center of the cirle to be drawn
-     * @param radius The radius of the cirle to be drawn
-     * @param paint  The paint used to draw the circle
+     * @hide
      */
-    public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
-        native_drawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
+    public void release() {
+        mNativeCanvasWrapper = 0;
+        if (mFinalizer != null) {
+            mFinalizer.run();
+            mFinalizer = null;
+        }
+    }
+
+    /**
+     * Free up as much memory as possible from private caches (e.g. fonts, images)
+     *
+     * @hide
+     */
+    public static void freeCaches() {
+        nFreeCaches();
+    }
+
+    /**
+     * Free up text layout caches
+     *
+     * @hide
+     */
+    public static void freeTextLayoutCaches() {
+        nFreeTextLayoutCaches();
+    }
+
+    private static native void nFreeCaches();
+    private static native void nFreeTextLayoutCaches();
+    private static native long nInitRaster(Bitmap bitmap);
+    private static native long nGetNativeFinalizer();
+
+    // ---------------- @FastNative -------------------
+
+    @FastNative
+    private static native void nSetBitmap(long canvasHandle,
+                                                Bitmap bitmap);
+    @FastNative
+    private static native boolean nIsOpaque(long canvasHandle);
+    @FastNative
+    private static native void nSetHighContrastText(long renderer, boolean highContrastText);
+    @FastNative
+    private static native int nGetWidth(long canvasHandle);
+    @FastNative
+    private static native int nGetHeight(long canvasHandle);
+
+    @FastNative
+    private static native int nSave(long canvasHandle, int saveFlags);
+    @FastNative
+    private static native int nSaveLayer(long nativeCanvas, float l,
+                                               float t, float r, float b,
+                                               long nativePaint,
+                                               int layerFlags);
+    @FastNative
+    private static native int nSaveLayerAlpha(long nativeCanvas, float l,
+                                                    float t, float r, float b,
+                                                    int alpha, int layerFlags);
+    @FastNative
+    private static native void nRestore(long canvasHandle, boolean tolerateUnderflow);
+    @FastNative
+    private static native void nRestoreToCount(long canvasHandle,
+                                                     int saveCount,
+                                                     boolean tolerateUnderflow);
+    @FastNative
+    private static native int nGetSaveCount(long canvasHandle);
+
+    @FastNative
+    private static native void nTranslate(long canvasHandle,
+                                                float dx, float dy);
+    @FastNative
+    private static native void nScale(long canvasHandle,
+                                            float sx, float sy);
+    @FastNative
+    private static native void nRotate(long canvasHandle, float degrees);
+    @FastNative
+    private static native void nSkew(long canvasHandle,
+                                           float sx, float sy);
+    @FastNative
+    private static native void nConcat(long nativeCanvas,
+                                             long nativeMatrix);
+    @FastNative
+    private static native void nSetMatrix(long nativeCanvas,
+                                                long nativeMatrix);
+    @FastNative
+    private static native boolean nClipRect(long nativeCanvas,
+                                                  float left, float top,
+                                                  float right, float bottom,
+                                                  int regionOp);
+    @FastNative
+    private static native boolean nClipPath(long nativeCanvas,
+                                                  long nativePath,
+                                                  int regionOp);
+    @FastNative
+    private static native boolean nClipRegion(long nativeCanvas,
+                                                    long nativeRegion,
+                                                    int regionOp);
+    @FastNative
+    private static native void nSetDrawFilter(long nativeCanvas,
+                                                   long nativeFilter);
+    @FastNative
+    private static native boolean nGetClipBounds(long nativeCanvas,
+                                                       Rect bounds);
+    @FastNative
+    private static native void nGetCTM(long nativeCanvas,
+                                             long nativeMatrix);
+    @FastNative
+    private static native boolean nQuickReject(long nativeCanvas,
+                                                     long nativePath);
+    @FastNative
+    private static native boolean nQuickReject(long nativeCanvas,
+                                                     float left, float top,
+                                                     float right, float bottom);
+
+    /**
+     * <p>Draw the specified arc, which will be scaled to fit inside the
+     * specified oval.</p>
+     *
+     * <p>If the start angle is negative or >= 360, the start angle is treated
+     * as start angle modulo 360.</p>
+     *
+     * <p>If the sweep angle is >= 360, then the oval is drawn
+     * completely. Note that this differs slightly from SkPath::arcTo, which
+     * treats the sweep angle modulo 360. If the sweep angle is negative,
+     * the sweep angle is treated as sweep angle modulo 360</p>
+     *
+     * <p>The arc is drawn clockwise. An angle of 0 degrees correspond to the
+     * geometric angle of 0 degrees (3 o'clock on a watch.)</p>
+     *
+     * @param startAngle Starting angle (in degrees) where the arc begins
+     * @param sweepAngle Sweep angle (in degrees) measured clockwise
+     * @param useCenter If true, include the center of the oval in the arc, and
+                        close it if it is being stroked. This will draw a wedge
+     * @param paint      The paint used to draw the arc
+     */
+    public void drawArc(float left, float top, float right, float bottom, float startAngle,
+            float sweepAngle, boolean useCenter, @NonNull Paint paint) {
+        super.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
     }
 
     /**
@@ -1206,126 +1186,20 @@
      */
     public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
             @NonNull Paint paint) {
-        drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
-                paint);
+        super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
     }
 
     /**
-     * <p>Draw the specified arc, which will be scaled to fit inside the
-     * specified oval.</p>
+     * Fill the entire canvas' bitmap (restricted to the current clip) with the
+     * specified ARGB color, using srcover porterduff mode.
      *
-     * <p>If the start angle is negative or >= 360, the start angle is treated
-     * as start angle modulo 360.</p>
-     *
-     * <p>If the sweep angle is >= 360, then the oval is drawn
-     * completely. Note that this differs slightly from SkPath::arcTo, which
-     * treats the sweep angle modulo 360. If the sweep angle is negative,
-     * the sweep angle is treated as sweep angle modulo 360</p>
-     *
-     * <p>The arc is drawn clockwise. An angle of 0 degrees correspond to the
-     * geometric angle of 0 degrees (3 o'clock on a watch.)</p>
-     *
-     * @param startAngle Starting angle (in degrees) where the arc begins
-     * @param sweepAngle Sweep angle (in degrees) measured clockwise
-     * @param useCenter If true, include the center of the oval in the arc, and
-                        close it if it is being stroked. This will draw a wedge
-     * @param paint      The paint used to draw the arc
+     * @param a alpha component (0..255) of the color to draw onto the canvas
+     * @param r red component (0..255) of the color to draw onto the canvas
+     * @param g green component (0..255) of the color to draw onto the canvas
+     * @param b blue component (0..255) of the color to draw onto the canvas
      */
-    public void drawArc(float left, float top, float right, float bottom, float startAngle,
-            float sweepAngle, boolean useCenter, @NonNull Paint paint) {
-        native_drawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
-                useCenter, paint.getNativeInstance());
-    }
-
-    /**
-     * Draw the specified round-rect using the specified paint. The roundrect
-     * will be filled or framed based on the Style in the paint.
-     *
-     * @param rect  The rectangular bounds of the roundRect to be drawn
-     * @param rx    The x-radius of the oval used to round the corners
-     * @param ry    The y-radius of the oval used to round the corners
-     * @param paint The paint used to draw the roundRect
-     */
-    public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
-        drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
-    }
-
-    /**
-     * Draw the specified round-rect using the specified paint. The roundrect
-     * will be filled or framed based on the Style in the paint.
-     *
-     * @param rx    The x-radius of the oval used to round the corners
-     * @param ry    The y-radius of the oval used to round the corners
-     * @param paint The paint used to draw the roundRect
-     */
-    public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
-            @NonNull Paint paint) {
-        native_drawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, paint.getNativeInstance());
-    }
-
-    /**
-     * Draw the specified path using the specified paint. The path will be
-     * filled or framed based on the Style in the paint.
-     *
-     * @param path  The path to be drawn
-     * @param paint The paint used to draw the path
-     */
-    public void drawPath(@NonNull Path path, @NonNull Paint paint) {
-        if (path.isSimplePath && path.rects != null) {
-            native_drawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
-        } else {
-            native_drawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
-        }
-    }
-
-    /**
-     * @hide
-     */
-    protected void throwIfCannotDraw(Bitmap bitmap) {
-        if (bitmap.isRecycled()) {
-            throw new RuntimeException("Canvas: trying to use a recycled bitmap " + bitmap);
-        }
-        if (!bitmap.isPremultiplied() && bitmap.getConfig() == Bitmap.Config.ARGB_8888 &&
-                bitmap.hasAlpha()) {
-            throw new RuntimeException("Canvas: trying to use a non-premultiplied bitmap "
-                    + bitmap);
-        }
-    }
-
-    /**
-     * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
-     *
-     * @param patch The ninepatch object to render
-     * @param dst The destination rectangle.
-     * @param paint The paint to draw the bitmap with. may be null
-     *
-     * @hide
-     */
-    public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
-        Bitmap bitmap = patch.getBitmap();
-        throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-        native_drawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
-                dst.left, dst.top, dst.right, dst.bottom, nativePaint,
-                mDensity, patch.getDensity());
-    }
-
-    /**
-     * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
-     *
-     * @param patch The ninepatch object to render
-     * @param dst The destination rectangle.
-     * @param paint The paint to draw the bitmap with. may be null
-     *
-     * @hide
-     */
-    public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
-        Bitmap bitmap = patch.getBitmap();
-        throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-        native_drawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
-                dst.left, dst.top, dst.right, dst.bottom, nativePaint,
-                mDensity, patch.getDensity());
+    public void drawARGB(int a, int r, int g, int b) {
+        super.drawARGB(a, r, g, b);
     }
 
     /**
@@ -1348,57 +1222,19 @@
      * @param paint  The paint used to draw the bitmap (may be null)
      */
     public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
-        throwIfCannotDraw(bitmap);
-        native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top,
-                paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity);
+        super.drawBitmap(bitmap, left, top, paint);
     }
 
     /**
-     * Draw the specified bitmap, scaling/translating automatically to fill
-     * the destination rectangle. If the source rectangle is not null, it
-     * specifies the subset of the bitmap to draw.
+     * Draw the bitmap using the specified matrix.
      *
-     * <p>Note: if the paint contains a maskfilter that generates a mask which
-     * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
-     * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
-     * Thus the color outside of the original width/height will be the edge
-     * color replicated.
-     *
-     * <p>This function <em>ignores the density associated with the bitmap</em>.
-     * This is because the source and destination rectangle coordinate
-     * spaces are in their respective densities, so must already have the
-     * appropriate scaling factor applied.
-     *
-     * @param bitmap The bitmap to be drawn
-     * @param src    May be null. The subset of the bitmap to be drawn
-     * @param dst    The rectangle that the bitmap will be scaled/translated
-     *               to fit into
+     * @param bitmap The bitmap to draw
+     * @param matrix The matrix used to transform the bitmap when it is drawn
      * @param paint  May be null. The paint used to draw the bitmap
      */
-    public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
-            @Nullable Paint paint) {
-      if (dst == null) {
-          throw new NullPointerException();
-      }
-      throwIfCannotDraw(bitmap);
-      final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-
-      float left, top, right, bottom;
-      if (src == null) {
-          left = top = 0;
-          right = bitmap.getWidth();
-          bottom = bitmap.getHeight();
-      } else {
-          left = src.left;
-          right = src.right;
-          top = src.top;
-          bottom = src.bottom;
-      }
-
-      native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
-              dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
-              bitmap.mDensity);
-  }
+    public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
+        super.drawBitmap(bitmap, matrix, paint);
+    }
 
     /**
      * Draw the specified bitmap, scaling/translating automatically to fill
@@ -1424,30 +1260,37 @@
      */
     public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
             @Nullable Paint paint) {
-        if (dst == null) {
-            throw new NullPointerException();
-        }
-        throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-
-        int left, top, right, bottom;
-        if (src == null) {
-            left = top = 0;
-            right = bitmap.getWidth();
-            bottom = bitmap.getHeight();
-        } else {
-            left = src.left;
-            right = src.right;
-            top = src.top;
-            bottom = src.bottom;
-        }
-
-        native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
-            dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
-            bitmap.mDensity);
+        super.drawBitmap(bitmap, src, dst, paint);
     }
 
     /**
+         * Draw the specified bitmap, scaling/translating automatically to fill
+         * the destination rectangle. If the source rectangle is not null, it
+         * specifies the subset of the bitmap to draw.
+         *
+         * <p>Note: if the paint contains a maskfilter that generates a mask which
+         * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
+         * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
+         * Thus the color outside of the original width/height will be the edge
+         * color replicated.
+         *
+         * <p>This function <em>ignores the density associated with the bitmap</em>.
+         * This is because the source and destination rectangle coordinate
+         * spaces are in their respective densities, so must already have the
+         * appropriate scaling factor applied.
+         *
+         * @param bitmap The bitmap to be drawn
+         * @param src    May be null. The subset of the bitmap to be drawn
+         * @param dst    The rectangle that the bitmap will be scaled/translated
+         *               to fit into
+         * @param paint  May be null. The paint used to draw the bitmap
+         */
+        public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
+                @Nullable Paint paint) {
+          super.drawBitmap(bitmap, src, dst, paint);
+      }
+
+    /**
      * Treat the specified array of colors as a bitmap, and draw it. This gives
      * the same result as first creating a bitmap from the array, and then
      * drawing it, but this method avoids explicitly creating a bitmap object
@@ -1474,29 +1317,7 @@
     @Deprecated
     public void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y,
             int width, int height, boolean hasAlpha, @Nullable Paint paint) {
-        // check for valid input
-        if (width < 0) {
-            throw new IllegalArgumentException("width must be >= 0");
-        }
-        if (height < 0) {
-            throw new IllegalArgumentException("height must be >= 0");
-        }
-        if (Math.abs(stride) < width) {
-            throw new IllegalArgumentException("abs(stride) must be >= width");
-        }
-        int lastScanline = offset + (height - 1) * stride;
-        int length = colors.length;
-        if (offset < 0 || (offset + width > length) || lastScanline < 0
-                || (lastScanline + width > length)) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-        // quick escape if there's nothing to draw
-        if (width == 0 || height == 0) {
-            return;
-        }
-        // punch down to native for the actual draw
-        native_drawBitmap(mNativeCanvasWrapper, colors, offset, stride, x, y, width, height, hasAlpha,
-                paint != null ? paint.getNativeInstance() : 0);
+        super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
     }
 
     /**
@@ -1510,30 +1331,7 @@
     @Deprecated
     public void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y,
             int width, int height, boolean hasAlpha, @Nullable Paint paint) {
-        // call through to the common float version
-        drawBitmap(colors, offset, stride, (float)x, (float)y, width, height,
-                   hasAlpha, paint);
-    }
-
-    /**
-     * Draw the bitmap using the specified matrix.
-     *
-     * @param bitmap The bitmap to draw
-     * @param matrix The matrix used to transform the bitmap when it is drawn
-     * @param paint  May be null. The paint used to draw the bitmap
-     */
-    public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
-        nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(),
-                paint != null ? paint.getNativeInstance() : 0);
-    }
-
-    /**
-     * @hide
-     */
-    protected static void checkRange(int length, int offset, int count) {
-        if ((offset | count) < 0 || offset + count > length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+        super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
     }
 
     /**
@@ -1565,89 +1363,299 @@
     public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
             @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
             @Nullable Paint paint) {
-        if ((meshWidth | meshHeight | vertOffset | colorOffset) < 0) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-        if (meshWidth == 0 || meshHeight == 0) {
-            return;
-        }
-        int count = (meshWidth + 1) * (meshHeight + 1);
-        // we mul by 2 since we need two floats per vertex
-        checkRange(verts.length, vertOffset, count * 2);
-        if (colors != null) {
-            // no mul by 2, since we need only 1 color per vertex
-            checkRange(colors.length, colorOffset, count);
-        }
-        nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight,
-                verts, vertOffset, colors, colorOffset,
-                paint != null ? paint.getNativeInstance() : 0);
-    }
-
-    public enum VertexMode {
-        TRIANGLES(0),
-        TRIANGLE_STRIP(1),
-        TRIANGLE_FAN(2);
-
-        VertexMode(int nativeInt) {
-            this.nativeInt = nativeInt;
-        }
-
-        /**
-         * @hide
-         */
-        public final int nativeInt;
+        super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset,
+                paint);
     }
 
     /**
-     * Draw the array of vertices, interpreted as triangles (based on mode). The
-     * verts array is required, and specifies the x,y pairs for each vertex. If
-     * texs is non-null, then it is used to specify the coordinate in shader
-     * coordinates to use at each vertex (the paint must have a shader in this
-     * case). If there is no texs array, but there is a color array, then each
-     * color is interpolated across its corresponding triangle in a gradient. If
-     * both texs and colors arrays are present, then they behave as before, but
-     * the resulting color at each pixels is the result of multiplying the
-     * colors from the shader and the color-gradient together. The indices array
-     * is optional, but if it is present, then it is used to specify the index
-     * of each triangle, rather than just walking through the arrays in order.
+     * Draw the specified circle using the specified paint. If radius is <= 0,
+     * then nothing will be drawn. The circle will be filled or framed based
+     * on the Style in the paint.
      *
-     * @param mode How to interpret the array of vertices
-     * @param vertexCount The number of values in the vertices array (and
-     *      corresponding texs and colors arrays if non-null). Each logical
-     *      vertex is two values (x, y), vertexCount must be a multiple of 2.
-     * @param verts Array of vertices for the mesh
-     * @param vertOffset Number of values in the verts to skip before drawing.
-     * @param texs May be null. If not null, specifies the coordinates to sample
-     *      into the current shader (e.g. bitmap tile or gradient)
-     * @param texOffset Number of values in texs to skip before drawing.
-     * @param colors May be null. If not null, specifies a color for each
-     *      vertex, to be interpolated across the triangle.
-     * @param colorOffset Number of values in colors to skip before drawing.
-     * @param indices If not null, array of indices to reference into the
-     *      vertex (texs, colors) array.
-     * @param indexCount number of entries in the indices array (if not null).
-     * @param paint Specifies the shader to use if the texs array is non-null.
+     * @param cx     The x-coordinate of the center of the cirle to be drawn
+     * @param cy     The y-coordinate of the center of the cirle to be drawn
+     * @param radius The radius of the cirle to be drawn
+     * @param paint  The paint used to draw the circle
      */
-    public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
-            int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
-            int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
+    public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
+        super.drawCircle(cx, cy, radius, paint);
+    }
+
+    /**
+     * Fill the entire canvas' bitmap (restricted to the current clip) with the
+     * specified color, using srcover porterduff mode.
+     *
+     * @param color the color to draw onto the canvas
+     */
+    public void drawColor(@ColorInt int color) {
+        super.drawColor(color);
+    }
+
+    /**
+     * Fill the entire canvas' bitmap (restricted to the current clip) with the
+     * specified color and porter-duff xfermode.
+     *
+     * @param color the color to draw with
+     * @param mode  the porter-duff mode to apply to the color
+     */
+    public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
+        super.drawColor(color, mode);
+    }
+
+    /**
+     * Draw a line segment with the specified start and stop x,y coordinates,
+     * using the specified paint.
+     *
+     * <p>Note that since a line is always "framed", the Style is ignored in the paint.</p>
+     *
+     * <p>Degenerate lines (length is 0) will not be drawn.</p>
+     *
+     * @param startX The x-coordinate of the start point of the line
+     * @param startY The y-coordinate of the start point of the line
+     * @param paint  The paint used to draw the line
+     */
+    public void drawLine(float startX, float startY, float stopX, float stopY,
             @NonNull Paint paint) {
-        checkRange(verts.length, vertOffset, vertexCount);
-        if (isHardwareAccelerated()) {
-            return;
-        }
-        if (texs != null) {
-            checkRange(texs.length, texOffset, vertexCount);
-        }
-        if (colors != null) {
-            checkRange(colors.length, colorOffset, vertexCount / 2);
-        }
-        if (indices != null) {
-            checkRange(indices.length, indexOffset, indexCount);
-        }
-        nativeDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
-                vertOffset, texs, texOffset, colors, colorOffset,
-                indices, indexOffset, indexCount, paint.getNativeInstance());
+        super.drawLine(startX, startY, stopX, stopY, paint);
+    }
+
+    /**
+     * Draw a series of lines. Each line is taken from 4 consecutive values
+     * in the pts array. Thus to draw 1 line, the array must contain at least 4
+     * values. This is logically the same as drawing the array as follows:
+     * drawLine(pts[0], pts[1], pts[2], pts[3]) followed by
+     * drawLine(pts[4], pts[5], pts[6], pts[7]) and so on.
+     *
+     * @param pts      Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
+     * @param offset   Number of values in the array to skip before drawing.
+     * @param count    The number of values in the array to process, after
+     *                 skipping "offset" of them. Since each line uses 4 values,
+     *                 the number of "lines" that are drawn is really
+     *                 (count >> 2).
+     * @param paint    The paint used to draw the points
+     */
+    public void drawLines(@Size(multiple=4) @NonNull float[] pts, int offset, int count,
+            @NonNull Paint paint) {
+        super.drawLines(pts, offset, count, paint);
+    }
+
+    public void drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint) {
+        super.drawLines(pts, paint);
+    }
+
+    /**
+     * Draw the specified oval using the specified paint. The oval will be
+     * filled or framed based on the Style in the paint.
+     */
+    public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
+        super.drawOval(left, top, right, bottom, paint);
+    }
+
+    /**
+     * Draw the specified oval using the specified paint. The oval will be
+     * filled or framed based on the Style in the paint.
+     *
+     * @param oval The rectangle bounds of the oval to be drawn
+     */
+    public void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
+        super.drawOval(oval, paint);
+    }
+
+    /**
+     * Fill the entire canvas' bitmap (restricted to the current clip) with
+     * the specified paint. This is equivalent (but faster) to drawing an
+     * infinitely large rectangle with the specified paint.
+     *
+     * @param paint The paint used to draw onto the canvas
+     */
+    public void drawPaint(@NonNull Paint paint) {
+        super.drawPaint(paint);
+    }
+
+    /**
+     * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
+     *
+     * @param patch The ninepatch object to render
+     * @param dst The destination rectangle.
+     * @param paint The paint to draw the bitmap with. may be null
+     *
+     * @hide
+     */
+    public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
+        super.drawPatch(patch, dst, paint);
+    }
+
+    /**
+     * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
+     *
+     * @param patch The ninepatch object to render
+     * @param dst The destination rectangle.
+     * @param paint The paint to draw the bitmap with. may be null
+     *
+     * @hide
+     */
+    public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
+        super.drawPatch(patch, dst, paint);
+    }
+
+    /**
+     * Draw the specified path using the specified paint. The path will be
+     * filled or framed based on the Style in the paint.
+     *
+     * @param path  The path to be drawn
+     * @param paint The paint used to draw the path
+     */
+    public void drawPath(@NonNull Path path, @NonNull Paint paint) {
+        super.drawPath(path, paint);
+    }
+
+    /**
+     * Helper for drawPoints() for drawing a single point.
+     */
+    public void drawPoint(float x, float y, @NonNull Paint paint) {
+        super.drawPoint(x, y, paint);
+    }
+
+    /**
+     * Draw a series of points. Each point is centered at the coordinate
+     * specified by pts[], and its diameter is specified by the paint's stroke
+     * width (as transformed by the canvas' CTM), with special treatment for
+     * a stroke width of 0, which always draws exactly 1 pixel (or at most 4
+     * if antialiasing is enabled). The shape of the point is controlled by
+     * the paint's Cap type. The shape is a square, unless the cap type is
+     * Round, in which case the shape is a circle.
+     *
+     * @param pts      Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
+     * @param offset   Number of values to skip before starting to draw.
+     * @param count    The number of values to process, after skipping offset
+     *                 of them. Since one point uses two values, the number of
+     *                 "points" that are drawn is really (count >> 1).
+     * @param paint    The paint used to draw the points
+     */
+    public void drawPoints(@Size(multiple=2) float[] pts, int offset, int count,
+            @NonNull Paint paint) {
+        super.drawPoints(pts, offset, count, paint);
+    }
+
+    /**
+     * Helper for drawPoints() that assumes you want to draw the entire array
+     */
+    public void drawPoints(@Size(multiple=2) @NonNull float[] pts, @NonNull Paint paint) {
+        super.drawPoints(pts, paint);
+    }
+
+    /**
+     * Draw the text in the array, with each character's origin specified by
+     * the pos array.
+     *
+     * @param text     The text to be drawn
+     * @param index    The index of the first character to draw
+     * @param count    The number of characters to draw, starting from index.
+     * @param pos      Array of [x,y] positions, used to position each
+     *                 character
+     * @param paint    The paint used for the text (e.g. color, size, style)
+     *
+     * @deprecated This method does not support glyph composition and decomposition and
+     * should therefore not be used to render complex scripts. It also doesn't
+     * handle supplementary characters (eg emoji).
+     */
+    @Deprecated
+    public void drawPosText(@NonNull char[] text, int index, int count,
+            @NonNull @Size(multiple=2) float[] pos,
+            @NonNull Paint paint) {
+        super.drawPosText(text, index, count, pos, paint);
+    }
+
+    /**
+     * Draw the text in the array, with each character's origin specified by
+     * the pos array.
+     *
+     * @param text  The text to be drawn
+     * @param pos   Array of [x,y] positions, used to position each character
+     * @param paint The paint used for the text (e.g. color, size, style)
+     *
+     * @deprecated This method does not support glyph composition and decomposition and
+     * should therefore not be used to render complex scripts. It also doesn't
+     * handle supplementary characters (eg emoji).
+     */
+    @Deprecated
+    public void drawPosText(@NonNull String text, @NonNull @Size(multiple=2) float[] pos,
+            @NonNull Paint paint) {
+        super.drawPosText(text, pos, paint);
+    }
+
+    /**
+     * Draw the specified Rect using the specified paint. The rectangle will
+     * be filled or framed based on the Style in the paint.
+     *
+     * @param left   The left side of the rectangle to be drawn
+     * @param top    The top side of the rectangle to be drawn
+     * @param right  The right side of the rectangle to be drawn
+     * @param bottom The bottom side of the rectangle to be drawn
+     * @param paint  The paint used to draw the rect
+     */
+    public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
+        super.drawRect(left, top, right, bottom, paint);
+    }
+
+    /**
+     * Draw the specified Rect using the specified Paint. The rectangle
+     * will be filled or framed based on the Style in the paint.
+     *
+     * @param r        The rectangle to be drawn.
+     * @param paint    The paint used to draw the rectangle
+     */
+    public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
+        super.drawRect(r, paint);
+    }
+
+    /**
+     * Draw the specified Rect using the specified paint. The rectangle will
+     * be filled or framed based on the Style in the paint.
+     *
+     * @param rect  The rect to be drawn
+     * @param paint The paint used to draw the rect
+     */
+    public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
+        super.drawRect(rect, paint);
+    }
+
+    /**
+     * Fill the entire canvas' bitmap (restricted to the current clip) with the
+     * specified RGB color, using srcover porterduff mode.
+     *
+     * @param r red component (0..255) of the color to draw onto the canvas
+     * @param g green component (0..255) of the color to draw onto the canvas
+     * @param b blue component (0..255) of the color to draw onto the canvas
+     */
+    public void drawRGB(int r, int g, int b) {
+        super.drawRGB(r, g, b);
+    }
+
+    /**
+     * Draw the specified round-rect using the specified paint. The roundrect
+     * will be filled or framed based on the Style in the paint.
+     *
+     * @param rx    The x-radius of the oval used to round the corners
+     * @param ry    The y-radius of the oval used to round the corners
+     * @param paint The paint used to draw the roundRect
+     */
+    public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+            @NonNull Paint paint) {
+        super.drawRoundRect(left, top, right, bottom, rx, ry, paint);
+    }
+
+    /**
+     * Draw the specified round-rect using the specified paint. The roundrect
+     * will be filled or framed based on the Style in the paint.
+     *
+     * @param rect  The rectangular bounds of the roundRect to be drawn
+     * @param rx    The x-radius of the oval used to round the corners
+     * @param ry    The y-radius of the oval used to round the corners
+     * @param paint The paint used to draw the roundRect
+     */
+    public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
+        super.drawRoundRect(rect, rx, ry, paint);
     }
 
     /**
@@ -1661,46 +1669,7 @@
      */
     public void drawText(@NonNull char[] text, int index, int count, float x, float y,
             @NonNull Paint paint) {
-        if ((index | count | (index + count) |
-            (text.length - index - count)) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-        native_drawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
-                paint.getNativeInstance(), paint.mNativeTypeface);
-    }
-
-    /**
-     * Draw the text, with origin at (x,y), using the specified paint. The
-     * origin is interpreted based on the Align setting in the paint.
-     *
-     * @param text  The text to be drawn
-     * @param x     The x-coordinate of the origin of the text being drawn
-     * @param y     The y-coordinate of the baseline of the text being drawn
-     * @param paint The paint used for the text (e.g. color, size, style)
-     */
-    public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
-        native_drawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
-                paint.getNativeInstance(), paint.mNativeTypeface);
-    }
-
-    /**
-     * Draw the text, with origin at (x,y), using the specified paint.
-     * The origin is interpreted based on the Align setting in the paint.
-     *
-     * @param text  The text to be drawn
-     * @param start The index of the first character in text to draw
-     * @param end   (end - 1) is the index of the last character in text to draw
-     * @param x     The x-coordinate of the origin of the text being drawn
-     * @param y     The y-coordinate of the baseline of the text being drawn
-     * @param paint The paint used for the text (e.g. color, size, style)
-     */
-    public void drawText(@NonNull String text, int start, int end, float x, float y,
-            @NonNull Paint paint) {
-        if ((start | end | (end - start) | (text.length() - end)) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-        native_drawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
-                paint.getNativeInstance(), paint.mNativeTypeface);
+        super.drawText(text, index, count, x, y, paint);
     }
 
     /**
@@ -1718,23 +1687,72 @@
      */
     public void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
             @NonNull Paint paint) {
-        if ((start | end | (end - start) | (text.length() - end)) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (text instanceof String || text instanceof SpannedString ||
-            text instanceof SpannableString) {
-            native_drawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
-                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
-        } else if (text instanceof GraphicsOperations) {
-            ((GraphicsOperations) text).drawText(this, start, end, x, y,
-                    paint);
-        } else {
-            char[] buf = TemporaryBuffer.obtain(end - start);
-            TextUtils.getChars(text, start, end, buf, 0);
-            native_drawText(mNativeCanvasWrapper, buf, 0, end - start, x, y,
-                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
-            TemporaryBuffer.recycle(buf);
-        }
+        super.drawText(text, start, end, x, y, paint);
+    }
+
+    /**
+     * Draw the text, with origin at (x,y), using the specified paint. The
+     * origin is interpreted based on the Align setting in the paint.
+     *
+     * @param text  The text to be drawn
+     * @param x     The x-coordinate of the origin of the text being drawn
+     * @param y     The y-coordinate of the baseline of the text being drawn
+     * @param paint The paint used for the text (e.g. color, size, style)
+     */
+    public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
+        super.drawText(text, x, y, paint);
+    }
+
+    /**
+     * Draw the text, with origin at (x,y), using the specified paint.
+     * The origin is interpreted based on the Align setting in the paint.
+     *
+     * @param text  The text to be drawn
+     * @param start The index of the first character in text to draw
+     * @param end   (end - 1) is the index of the last character in text to draw
+     * @param x     The x-coordinate of the origin of the text being drawn
+     * @param y     The y-coordinate of the baseline of the text being drawn
+     * @param paint The paint used for the text (e.g. color, size, style)
+     */
+    public void drawText(@NonNull String text, int start, int end, float x, float y,
+            @NonNull Paint paint) {
+        super.drawText(text, start, end, x, y, paint);
+    }
+
+    /**
+     * Draw the text, with origin at (x,y), using the specified paint, along
+     * the specified path. The paint's Align setting determins where along the
+     * path to start the text.
+     *
+     * @param text     The text to be drawn
+     * @param path     The path the text should follow for its baseline
+     * @param hOffset  The distance along the path to add to the text's
+     *                 starting position
+     * @param vOffset  The distance above(-) or below(+) the path to position
+     *                 the text
+     * @param paint    The paint used for the text (e.g. color, size, style)
+     */
+    public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
+            float hOffset, float vOffset, @NonNull Paint paint) {
+        super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint);
+    }
+
+    /**
+     * Draw the text, with origin at (x,y), using the specified paint, along
+     * the specified path. The paint's Align setting determins where along the
+     * path to start the text.
+     *
+     * @param text     The text to be drawn
+     * @param path     The path the text should follow for its baseline
+     * @param hOffset  The distance along the path to add to the text's
+     *                 starting position
+     * @param vOffset  The distance above(-) or below(+) the path to position
+     *                 the text
+     * @param paint    The paint used for the text (e.g. color, size, style)
+     */
+    public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
+            float vOffset, @NonNull Paint paint) {
+        super.drawTextOnPath(text, path, hOffset, vOffset, paint);
     }
 
     /**
@@ -1762,21 +1780,7 @@
      */
     public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
             int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
-
-        if (text == null) {
-            throw new NullPointerException("text is null");
-        }
-        if (paint == null) {
-            throw new NullPointerException("paint is null");
-        }
-        if ((index | count | contextIndex | contextCount | index - contextIndex
-                | (contextIndex + contextCount) - (index + count)
-                | text.length - (contextIndex + contextCount)) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        native_drawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount,
-                x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+        super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint);
     }
 
     /**
@@ -1816,347 +1820,44 @@
      */
     public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
             int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
-
-        if (text == null) {
-            throw new NullPointerException("text is null");
-        }
-        if (paint == null) {
-            throw new NullPointerException("paint is null");
-        }
-        if ((start | end | contextStart | contextEnd | start - contextStart | end - start
-                | contextEnd - end | text.length() - contextEnd) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        if (text instanceof String || text instanceof SpannedString ||
-                text instanceof SpannableString) {
-            native_drawTextRun(mNativeCanvasWrapper, text.toString(), start, end, contextStart,
-                    contextEnd, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
-        } else if (text instanceof GraphicsOperations) {
-            ((GraphicsOperations) text).drawTextRun(this, start, end,
-                    contextStart, contextEnd, x, y, isRtl, paint);
-        } else {
-            int contextLen = contextEnd - contextStart;
-            int len = end - start;
-            char[] buf = TemporaryBuffer.obtain(contextLen);
-            TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
-            native_drawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
-                    0, contextLen, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
-            TemporaryBuffer.recycle(buf);
-        }
+        super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint);
     }
 
     /**
-     * Draw the text in the array, with each character's origin specified by
-     * the pos array.
+     * Draw the array of vertices, interpreted as triangles (based on mode). The
+     * verts array is required, and specifies the x,y pairs for each vertex. If
+     * texs is non-null, then it is used to specify the coordinate in shader
+     * coordinates to use at each vertex (the paint must have a shader in this
+     * case). If there is no texs array, but there is a color array, then each
+     * color is interpolated across its corresponding triangle in a gradient. If
+     * both texs and colors arrays are present, then they behave as before, but
+     * the resulting color at each pixels is the result of multiplying the
+     * colors from the shader and the color-gradient together. The indices array
+     * is optional, but if it is present, then it is used to specify the index
+     * of each triangle, rather than just walking through the arrays in order.
      *
-     * @param text     The text to be drawn
-     * @param index    The index of the first character to draw
-     * @param count    The number of characters to draw, starting from index.
-     * @param pos      Array of [x,y] positions, used to position each
-     *                 character
-     * @param paint    The paint used for the text (e.g. color, size, style)
-     *
-     * @deprecated This method does not support glyph composition and decomposition and
-     * should therefore not be used to render complex scripts. It also doesn't
-     * handle supplementary characters (eg emoji).
+     * @param mode How to interpret the array of vertices
+     * @param vertexCount The number of values in the vertices array (and
+     *      corresponding texs and colors arrays if non-null). Each logical
+     *      vertex is two values (x, y), vertexCount must be a multiple of 2.
+     * @param verts Array of vertices for the mesh
+     * @param vertOffset Number of values in the verts to skip before drawing.
+     * @param texs May be null. If not null, specifies the coordinates to sample
+     *      into the current shader (e.g. bitmap tile or gradient)
+     * @param texOffset Number of values in texs to skip before drawing.
+     * @param colors May be null. If not null, specifies a color for each
+     *      vertex, to be interpolated across the triangle.
+     * @param colorOffset Number of values in colors to skip before drawing.
+     * @param indices If not null, array of indices to reference into the
+     *      vertex (texs, colors) array.
+     * @param indexCount number of entries in the indices array (if not null).
+     * @param paint Specifies the shader to use if the texs array is non-null.
      */
-    @Deprecated
-    public void drawPosText(@NonNull char[] text, int index, int count,
-            @NonNull @Size(multiple=2) float[] pos,
+    public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
+            int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
+            int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
             @NonNull Paint paint) {
-        if (index < 0 || index + count > text.length || count*2 > pos.length) {
-            throw new IndexOutOfBoundsException();
-        }
-        for (int i = 0; i < count; i++) {
-            drawText(text, index + i, 1, pos[i * 2], pos[i * 2 + 1], paint);
-        }
+        super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset,
+                colors, colorOffset, indices, indexOffset, indexCount, paint);
     }
-
-    /**
-     * Draw the text in the array, with each character's origin specified by
-     * the pos array.
-     *
-     * @param text  The text to be drawn
-     * @param pos   Array of [x,y] positions, used to position each character
-     * @param paint The paint used for the text (e.g. color, size, style)
-     *
-     * @deprecated This method does not support glyph composition and decomposition and
-     * should therefore not be used to render complex scripts. It also doesn't
-     * handle supplementary characters (eg emoji).
-     */
-    @Deprecated
-    public void drawPosText(@NonNull String text, @NonNull @Size(multiple=2) float[] pos,
-            @NonNull Paint paint) {
-        drawPosText(text.toCharArray(), 0, text.length(), pos, paint);
-    }
-
-    /**
-     * Draw the text, with origin at (x,y), using the specified paint, along
-     * the specified path. The paint's Align setting determins where along the
-     * path to start the text.
-     *
-     * @param text     The text to be drawn
-     * @param path     The path the text should follow for its baseline
-     * @param hOffset  The distance along the path to add to the text's
-     *                 starting position
-     * @param vOffset  The distance above(-) or below(+) the path to position
-     *                 the text
-     * @param paint    The paint used for the text (e.g. color, size, style)
-     */
-    public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
-            float hOffset, float vOffset, @NonNull Paint paint) {
-        if (index < 0 || index + count > text.length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-        native_drawTextOnPath(mNativeCanvasWrapper, text, index, count,
-                path.readOnlyNI(), hOffset, vOffset,
-                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
-    }
-
-    /**
-     * Draw the text, with origin at (x,y), using the specified paint, along
-     * the specified path. The paint's Align setting determins where along the
-     * path to start the text.
-     *
-     * @param text     The text to be drawn
-     * @param path     The path the text should follow for its baseline
-     * @param hOffset  The distance along the path to add to the text's
-     *                 starting position
-     * @param vOffset  The distance above(-) or below(+) the path to position
-     *                 the text
-     * @param paint    The paint used for the text (e.g. color, size, style)
-     */
-    public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
-            float vOffset, @NonNull Paint paint) {
-        if (text.length() > 0) {
-            native_drawTextOnPath(mNativeCanvasWrapper, text, path.readOnlyNI(), hOffset, vOffset,
-                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
-        }
-    }
-
-    /**
-     * Save the canvas state, draw the picture, and restore the canvas state.
-     * This differs from picture.draw(canvas), which does not perform any
-     * save/restore.
-     *
-     * <p>
-     * <strong>Note:</strong> This forces the picture to internally call
-     * {@link Picture#endRecording} in order to prepare for playback.
-     *
-     * @param picture  The picture to be drawn
-     */
-    public void drawPicture(@NonNull Picture picture) {
-        picture.endRecording();
-        int restoreCount = save();
-        picture.draw(this);
-        restoreToCount(restoreCount);
-    }
-
-    /**
-     * Draw the picture, stretched to fit into the dst rectangle.
-     */
-    public void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
-        save();
-        translate(dst.left, dst.top);
-        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
-            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
-        }
-        drawPicture(picture);
-        restore();
-    }
-
-    /**
-     * Draw the picture, stretched to fit into the dst rectangle.
-     */
-    public void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
-        save();
-        translate(dst.left, dst.top);
-        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
-            scale((float) dst.width() / picture.getWidth(),
-                    (float) dst.height() / picture.getHeight());
-        }
-        drawPicture(picture);
-        restore();
-    }
-
-    /**
-     * Releases the resources associated with this canvas.
-     *
-     * @hide
-     */
-    public void release() {
-        mNativeCanvasWrapper = 0;
-        if (mFinalizer != null) {
-            mFinalizer.run();
-            mFinalizer = null;
-        }
-    }
-
-    /**
-     * Free up as much memory as possible from private caches (e.g. fonts, images)
-     *
-     * @hide
-     */
-    public static native void freeCaches();
-
-    /**
-     * Free up text layout caches
-     *
-     * @hide
-     */
-    public static native void freeTextLayoutCaches();
-
-    private static native long initRaster(Bitmap bitmap);
-    private static native void native_setBitmap(long canvasHandle,
-                                                Bitmap bitmap);
-    private static native boolean native_isOpaque(long canvasHandle);
-    private static native void native_setHighContrastText(long renderer, boolean highContrastText);
-    private static native int native_getWidth(long canvasHandle);
-    private static native int native_getHeight(long canvasHandle);
-
-    private static native int native_save(long canvasHandle, int saveFlags);
-    private static native int native_saveLayer(long nativeCanvas, float l,
-                                               float t, float r, float b,
-                                               long nativePaint,
-                                               int layerFlags);
-    private static native int native_saveLayerAlpha(long nativeCanvas, float l,
-                                                    float t, float r, float b,
-                                                    int alpha, int layerFlags);
-    private static native void native_restore(long canvasHandle, boolean tolerateUnderflow);
-    private static native void native_restoreToCount(long canvasHandle,
-                                                     int saveCount,
-                                                     boolean tolerateUnderflow);
-    private static native int native_getSaveCount(long canvasHandle);
-
-    private static native void native_translate(long canvasHandle,
-                                                float dx, float dy);
-    private static native void native_scale(long canvasHandle,
-                                            float sx, float sy);
-    private static native void native_rotate(long canvasHandle, float degrees);
-    private static native void native_skew(long canvasHandle,
-                                           float sx, float sy);
-    private static native void native_concat(long nativeCanvas,
-                                             long nativeMatrix);
-    private static native void native_setMatrix(long nativeCanvas,
-                                                long nativeMatrix);
-    private static native boolean native_clipRect(long nativeCanvas,
-                                                  float left, float top,
-                                                  float right, float bottom,
-                                                  int regionOp);
-    private static native boolean native_clipPath(long nativeCanvas,
-                                                  long nativePath,
-                                                  int regionOp);
-    private static native boolean native_clipRegion(long nativeCanvas,
-                                                    long nativeRegion,
-                                                    int regionOp);
-    private static native void nativeSetDrawFilter(long nativeCanvas,
-                                                   long nativeFilter);
-    private static native boolean native_getClipBounds(long nativeCanvas,
-                                                       Rect bounds);
-    private static native void native_getCTM(long nativeCanvas,
-                                             long nativeMatrix);
-    private static native boolean native_quickReject(long nativeCanvas,
-                                                     long nativePath);
-    private static native boolean native_quickReject(long nativeCanvas,
-                                                     float left, float top,
-                                                     float right, float bottom);
-    private static native void native_drawColor(long nativeCanvas, int color,
-                                                int mode);
-    private static native void native_drawPaint(long nativeCanvas,
-                                                long nativePaint);
-    private static native void native_drawPoint(long canvasHandle, float x, float y,
-                                                long paintHandle);
-    private static native void native_drawPoints(long canvasHandle, float[] pts,
-                                                 int offset, int count,
-                                                 long paintHandle);
-    private static native void native_drawLine(long nativeCanvas, float startX,
-                                               float startY, float stopX,
-                                               float stopY, long nativePaint);
-    private static native void native_drawLines(long canvasHandle, float[] pts,
-                                                int offset, int count,
-                                                long paintHandle);
-    private static native void native_drawRect(long nativeCanvas, float left,
-                                               float top, float right,
-                                               float bottom,
-                                               long nativePaint);
-    private static native void native_drawOval(long nativeCanvas, float left, float top,
-                                               float right, float bottom, long nativePaint);
-    private static native void native_drawCircle(long nativeCanvas, float cx,
-                                                 float cy, float radius,
-                                                 long nativePaint);
-    private static native void native_drawArc(long nativeCanvas, float left, float top,
-                                              float right, float bottom,
-                                              float startAngle, float sweep, boolean useCenter,
-                                              long nativePaint);
-    private static native void native_drawRoundRect(long nativeCanvas,
-            float left, float top, float right, float bottom,
-            float rx, float ry, long nativePaint);
-    private static native void native_drawPath(long nativeCanvas,
-                                               long nativePath,
-                                               long nativePaint);
-    private static native void native_drawRegion(long nativeCanvas,
-            long nativeRegion, long nativePaint);
-    private native void native_drawNinePatch(long nativeCanvas, long nativeBitmap,
-            long ninePatch, float dstLeft, float dstTop, float dstRight, float dstBottom,
-            long nativePaintOrZero, int screenDensity, int bitmapDensity);
-    private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap,
-                                                 float left, float top,
-                                                 long nativePaintOrZero,
-                                                 int canvasDensity,
-                                                 int screenDensity,
-                                                 int bitmapDensity);
-    private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap,
-            float srcLeft, float srcTop, float srcRight, float srcBottom,
-            float dstLeft, float dstTop, float dstRight, float dstBottom,
-            long nativePaintOrZero, int screenDensity, int bitmapDensity);
-    private static native void native_drawBitmap(long nativeCanvas, int[] colors,
-                                                int offset, int stride, float x,
-                                                 float y, int width, int height,
-                                                 boolean hasAlpha,
-                                                 long nativePaintOrZero);
-    private static native void nativeDrawBitmapMatrix(long nativeCanvas,
-                                                      Bitmap bitmap,
-                                                      long nativeMatrix,
-                                                      long nativePaint);
-    private static native void nativeDrawBitmapMesh(long nativeCanvas,
-                                                    Bitmap bitmap,
-                                                    int meshWidth, int meshHeight,
-                                                    float[] verts, int vertOffset,
-                                                    int[] colors, int colorOffset,
-                                                    long nativePaint);
-    private static native void nativeDrawVertices(long nativeCanvas, int mode, int n,
-                   float[] verts, int vertOffset, float[] texs, int texOffset,
-                   int[] colors, int colorOffset, short[] indices,
-                   int indexOffset, int indexCount, long nativePaint);
-
-    private static native void native_drawText(long nativeCanvas, char[] text,
-                                               int index, int count, float x,
-                                               float y, int flags, long nativePaint,
-                                               long nativeTypeface);
-    private static native void native_drawText(long nativeCanvas, String text,
-                                               int start, int end, float x,
-                                               float y, int flags, long nativePaint,
-                                               long nativeTypeface);
-
-    private static native void native_drawTextRun(long nativeCanvas, String text,
-            int start, int end, int contextStart, int contextEnd,
-            float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
-
-    private static native void native_drawTextRun(long nativeCanvas, char[] text,
-            int start, int count, int contextStart, int contextCount,
-            float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
-
-    private static native void native_drawTextOnPath(long nativeCanvas,
-                                                     char[] text, int index,
-                                                     int count, long nativePath,
-                                                     float hOffset,
-                                                     float vOffset, int bidiFlags,
-                                                     long nativePaint, long nativeTypeface);
-    private static native void native_drawTextOnPath(long nativeCanvas,
-                                                     String text, long nativePath,
-                                                     float hOffset,
-                                                     float vOffset,
-                                                     int flags, long nativePaint, long nativeTypeface);
-    private static native long getNativeFinalizer();
 }
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index 35cedae..486070c 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -838,7 +838,8 @@
 
     }
 
-    /* package */ final long ni() {
+    /** @hide */
+    public final long ni() {
         return native_instance;
     }
 
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 2294b86..4ed2581 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -775,7 +775,8 @@
         }
     }
 
-    final long readOnlyNI() {
+    /** @hide */
+    public final long readOnlyNI() {
         return mNativePath;
     }
 
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index dcca431..40a2833 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -57,6 +57,9 @@
 import com.android.internal.R;
 
 import com.android.internal.util.VirtualRefBasePtr;
+
+import dalvik.annotation.optimization.FastNative;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -455,7 +458,11 @@
 
         int eventType = parser.getEventType();
         float pathErrorScale = 1;
-        while (eventType != XmlPullParser.END_DOCUMENT) {
+        final int innerDepth = parser.getDepth() + 1;
+
+        // Parse everything until the end of the animated-vector element.
+        while (eventType != XmlPullParser.END_DOCUMENT
+                && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) {
             if (eventType == XmlPullParser.START_TAG) {
                 final String tagName = parser.getName();
                 if (ANIMATED_VECTOR.equals(tagName)) {
@@ -1719,22 +1726,30 @@
     private static native void nAddAnimator(long setPtr, long propertyValuesHolder,
             long nativeInterpolator, long startDelay, long duration, int repeatCount,
             int repeatMode);
-
-    private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
-            float startValue, float endValue);
-
-    private static native long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
-            long endValuePtr);
-    private static native long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
-            int startValue, int endValue);
-    private static native long nCreatePathPropertyHolder(long nativePtr, int propertyId,
-            float startValue, float endValue);
-    private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
-            float endValue);
     private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length);
     private static native void nSetPropertyHolderData(long nativePtr, int[] data, int length);
     private static native void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id);
     private static native void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id);
+
+    // ------------- @FastNative -------------------
+
+    @FastNative
+    private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
+            float startValue, float endValue);
+    @FastNative
+    private static native long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
+            long endValuePtr);
+    @FastNative
+    private static native long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
+            int startValue, int endValue);
+    @FastNative
+    private static native long nCreatePathPropertyHolder(long nativePtr, int propertyId,
+            float startValue, float endValue);
+    @FastNative
+    private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
+            float endValue);
+    @FastNative
     private static native void nEnd(long animatorSetPtr);
+    @FastNative
     private static native void nReset(long animatorSetPtr);
 }
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 9d8ede0..6deeb0d 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -49,7 +49,6 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
-import java.util.Collection;
 
 /**
  * A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a
@@ -463,31 +462,14 @@
         return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
     }
 
-    private void updateMirrorMatrix(float dx) {
-        if (mMirrorMatrix == null) {
-            mMirrorMatrix = new Matrix();
-        }
-        mMirrorMatrix.setTranslate(dx, 0);
-        mMirrorMatrix.preScale(-1.0f, 1.0f);
-    }
-
     @Override
     protected void onBoundsChange(Rect bounds) {
         mDstRectAndInsetsDirty = true;
 
+        final Bitmap bitmap = mBitmapState.mBitmap;
         final Shader shader = mBitmapState.mPaint.getShader();
-        if (shader != null) {
-            if (needMirroring()) {
-                updateMirrorMatrix(bounds.right - bounds.left);
-                shader.setLocalMatrix(mMirrorMatrix);
-                mBitmapState.mPaint.setShader(shader);
-            } else {
-                if (mMirrorMatrix != null) {
-                    mMirrorMatrix = null;
-                    shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
-                    mBitmapState.mPaint.setShader(shader);
-                }
-            }
+        if (bitmap != null && shader != null) {
+            updateShaderMatrix(bitmap, mBitmapState.mPaint, shader, needMirroring());
         }
     }
 
@@ -548,19 +530,7 @@
                 canvas.restore();
             }
         } else {
-            if (needMirroring) {
-                // Mirror the bitmap
-                updateMirrorMatrix(mDstRect.right - mDstRect.left);
-                shader.setLocalMatrix(mMirrorMatrix);
-                paint.setShader(shader);
-            } else {
-                if (mMirrorMatrix != null) {
-                    mMirrorMatrix = null;
-                    shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
-                    paint.setShader(shader);
-                }
-            }
-
+            updateShaderMatrix(bitmap, paint, shader, needMirroring);
             canvas.drawRect(mDstRect, paint);
         }
 
@@ -573,6 +543,51 @@
         }
     }
 
+    /**
+     * Updates the {@code paint}'s shader matrix to be consistent with the
+     * destination size and layout direction.
+     *
+     * @param bitmap the bitmap to be drawn
+     * @param paint the paint used to draw the bitmap
+     * @param shader the shader to set on the paint
+     * @param needMirroring whether the bitmap should be mirrored
+     */
+    private void updateShaderMatrix(@NonNull Bitmap bitmap, @NonNull Paint paint,
+            @NonNull Shader shader, boolean needMirroring) {
+        final int sourceDensity = bitmap.getDensity();
+        final int targetDensity = mTargetDensity;
+        final boolean needScaling = sourceDensity != 0 && sourceDensity != targetDensity;
+        if (needScaling || needMirroring) {
+            final Matrix matrix = getOrCreateMirrorMatrix();
+            matrix.reset();
+
+            if (needMirroring) {
+                final int dx = mDstRect.right - mDstRect.left;
+                matrix.setTranslate(dx, 0);
+                matrix.setScale(-1, 1);
+            }
+
+            if (needScaling) {
+                final float densityScale = targetDensity / (float) sourceDensity;
+                matrix.postScale(densityScale, densityScale);
+            }
+
+            shader.setLocalMatrix(matrix);
+        } else {
+            mMirrorMatrix = null;
+            shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
+        }
+
+        paint.setShader(shader);
+    }
+
+    private Matrix getOrCreateMirrorMatrix() {
+        if (mMirrorMatrix == null) {
+            mMirrorMatrix = new Matrix();
+        }
+        return mMirrorMatrix;
+    }
+
     private void updateDstRectAndInsetsIfDirty() {
         if (mDstRectAndInsetsDirty) {
             if (mBitmapState.mTileModeX == null && mBitmapState.mTileModeY == null) {
@@ -941,14 +956,6 @@
         }
 
         @Override
-        public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
-            if (isAtlasable(mBitmap) && atlasList.add(mBitmap)) {
-                return mBitmap.getWidth() * mBitmap.getHeight();
-            }
-            return 0;
-        }
-
-        @Override
         public Drawable newDrawable() {
             return new BitmapDrawable(this, null);
         }
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 10f0dda..6ddc2d7 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -58,7 +58,6 @@
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
-import java.util.Collection;
 
 /**
  * A Drawable is a general abstraction for "something that can be drawn."  Most
@@ -1367,19 +1366,6 @@
         public abstract @Config int getChangingConfigurations();
 
         /**
-         * @return Total pixel count
-         * @hide
-         */
-        public int addAtlasableBitmaps(@NonNull Collection<Bitmap> atlasList) {
-            return 0;
-        }
-
-        /** @hide */
-        protected final boolean isAtlasable(@Nullable Bitmap bitmap) {
-            return bitmap != null && bitmap.getConfig() == Bitmap.Config.ARGB_8888;
-        }
-
-        /**
          * Return whether this constant state can have a theme applied.
          */
         public boolean canApplyTheme() {
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index c7a3c75..abdc2b9 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -21,7 +21,6 @@
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
-import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.Insets;
@@ -35,8 +34,6 @@
 import android.util.SparseArray;
 import android.view.View;
 
-import java.util.Collection;
-
 /**
  * A helper class that contains several {@link Drawable}s and selects which one to use.
  *
@@ -1194,19 +1191,6 @@
             return true;
         }
 
-        /** @hide */
-        @Override
-        public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
-            final int N = mNumChildren;
-            int pixelCount = 0;
-            for (int i = 0; i < N; i++) {
-                final ConstantState state = getChild(i).getConstantState();
-                if (state != null) {
-                    pixelCount += state.addAtlasableBitmaps(atlasList);
-                }
-            }
-            return pixelCount;
-        }
     }
 
     protected void setConstantState(DrawableContainerState state) {
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index 5abfc54..5887939 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -28,7 +28,6 @@
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
-import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.Insets;
@@ -41,7 +40,6 @@
 import android.view.View;
 
 import java.io.IOException;
-import java.util.Collection;
 
 /**
  * Drawable container with only one child element.
@@ -508,15 +506,6 @@
         }
 
         @Override
-        public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
-            final Drawable.ConstantState state = mDrawableState;
-            if (state != null) {
-                return state.addAtlasableBitmaps(atlasList);
-            }
-            return 0;
-        }
-
-        @Override
         public Drawable newDrawable() {
             return newDrawable(null);
         }
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index c30c4c2..e09fea5 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -23,7 +23,6 @@
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
-import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.Outline;
@@ -42,7 +41,6 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
-import java.util.Collection;
 
 /**
  * A Drawable that manages an array of other Drawables. These are drawn in array
@@ -2128,22 +2126,6 @@
             mHaveIsStateful = false;
         }
 
-        @Override
-        public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
-            final ChildDrawable[] array = mChildren;
-            final int N = mNum;
-            int pixelCount = 0;
-            for (int i = 0; i < N; i++) {
-                final Drawable dr = array[i].mDrawable;
-                if (dr != null) {
-                    final ConstantState state = dr.getConstantState();
-                    if (state != null) {
-                        pixelCount += state.addAtlasableBitmaps(atlasList);
-                    }
-                }
-            }
-            return pixelCount;
-        }
     }
 }
 
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index d962385..c7183d9 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -49,7 +49,6 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Collection;
 
 /**
  *
@@ -633,15 +632,6 @@
         }
 
         @Override
-        public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
-            final Bitmap bitmap = mNinePatch.getBitmap();
-            if (isAtlasable(bitmap) && atlasList.add(bitmap)) {
-                return bitmap.getWidth() * bitmap.getHeight();
-            }
-            return 0;
-        }
-
-        @Override
         public Drawable newDrawable() {
             return new NinePatchDrawable(this, null);
         }
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 9ff6965..e83104d 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -55,6 +55,7 @@
 import java.util.HashMap;
 import java.util.Stack;
 
+import dalvik.annotation.optimization.FastNative;
 import dalvik.system.VMRuntime;
 
 /**
@@ -76,27 +77,36 @@
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of this vector drawable.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:width</code></dt>
  * <dd>Used to define the intrinsic width of the drawable.
  * This support all the dimension units, normally specified with dp.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:height</code></dt>
  * <dd>Used to define the intrinsic height the drawable.
  * This support all the dimension units, normally specified with dp.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:viewportWidth</code></dt>
  * <dd>Used to define the width of the viewport space. Viewport is basically
  * the virtual canvas where the paths are drawn on.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:viewportHeight</code></dt>
  * <dd>Used to define the height of the viewport space. Viewport is basically
  * the virtual canvas where the paths are drawn on.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:tint</code></dt>
  * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:tintMode</code></dt>
  * <dd>The Porter-Duff blending mode for the tint color. The default value is src_in.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:autoMirrored</code></dt>
  * <dd>Indicates if the drawable needs to be mirrored when its layout direction is
  * RTL (right-to-left).</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:alpha</code></dt>
  * <dd>The opacity of this drawable.</dd>
+ * <dd>Animatable : Yes.</dd>
  * </dl></dd>
  * </dl>
  *
@@ -108,24 +118,32 @@
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of the group.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:rotation</code></dt>
  * <dd>The degrees of rotation of the group.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:pivotX</code></dt>
  * <dd>The X coordinate of the pivot for the scale and rotation of the group.
  * This is defined in the viewport space.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:pivotY</code></dt>
  * <dd>The Y coordinate of the pivot for the scale and rotation of the group.
  * This is defined in the viewport space.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:scaleX</code></dt>
  * <dd>The amount of scale on the X Coordinate.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:scaleY</code></dt>
  * <dd>The amount of scale on the Y coordinate.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:translateX</code></dt>
  * <dd>The amount of translation on the X coordinate.
  * This is defined in the viewport space.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:translateY</code></dt>
  * <dd>The amount of translation on the Y coordinate.
  * This is defined in the viewport space.</dd>
+ * <dd>Animatable : Yes.</dd>
  * </dl></dd>
  * </dl>
  *
@@ -135,45 +153,60 @@
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of the path.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:pathData</code></dt>
  * <dd>Defines path data using exactly same format as "d" attribute
  * in the SVG's path data. This is defined in the viewport space.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:fillColor</code></dt>
  * <dd>Specifies the color used to fill the path. May be a color or, for SDK 24+, a color state list
  * or a gradient color (See {@link android.R.styleable#GradientColor}
  * and {@link android.R.styleable#GradientColorItem}).
  * If this property is animated, any value set by the animation will override the original value.
  * No path fill is drawn if this property is not specified.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:strokeColor</code></dt>
  * <dd>Specifies the color used to draw the path outline. May be a color or, for SDK 24+, a color
  * state list or a gradient color (See {@link android.R.styleable#GradientColor}
  * and {@link android.R.styleable#GradientColorItem}).
  * If this property is animated, any value set by the animation will override the original value.
  * No path outline is drawn if this property is not specified.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:strokeWidth</code></dt>
  * <dd>The width a path stroke.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:strokeAlpha</code></dt>
  * <dd>The opacity of a path stroke.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:fillAlpha</code></dt>
  * <dd>The opacity to fill the path with.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:trimPathStart</code></dt>
  * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:trimPathEnd</code></dt>
  * <dd>The fraction of the path to trim from the end, in the range from 0 to 1.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:trimPathOffset</code></dt>
  * <dd>Shift trim region (allows showed region to include the start and end), in the range
  * from 0 to 1.</dd>
+ * <dd>Animatable : Yes.</dd>
  * <dt><code>android:strokeLineCap</code></dt>
  * <dd>Sets the linecap for a stroked path: butt, round, square.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:strokeLineJoin</code></dt>
  * <dd>Sets the lineJoin for a stroked path: miter,round,bevel.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:strokeMiterLimit</code></dt>
  * <dd>Sets the Miter limit for a stroked path.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:fillType</code></dt>
  * <dd>Sets the fillType for a path. The types can be either "evenOdd" or "nonZero". They behave the
  * same as SVG's "fill-rule" properties. For more details, see
  * <a href="https://www.w3.org/TR/SVG/painting.html#FillRuleProperty">FillRuleProperty</a></dd>
+ * <dd>Animatable : No.</dd>
  * </dl></dd>
+ *
  * </dl>
  *
  * <dl>
@@ -183,9 +216,11 @@
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of the clip path.</dd>
+ * <dd>Animatable : No.</dd>
  * <dt><code>android:pathData</code></dt>
  * <dd>Defines clip path using the same format as "d" attribute
  * in the SVG's path data.</dd>
+ * <dd>Animatable : Yes.</dd>
  * </dl></dd>
  * </dl>
  * <li>Here is a simple VectorDrawable in this vectordrawable.xml file.
@@ -710,7 +745,11 @@
         groupStack.push(state.mRootGroup);
 
         int eventType = parser.getEventType();
-        while (eventType != XmlPullParser.END_DOCUMENT) {
+        final int innerDepth = parser.getDepth() + 1;
+
+        // Parse everything until the end of the vector element.
+        while (eventType != XmlPullParser.END_DOCUMENT
+                && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) {
             if (eventType == XmlPullParser.START_TAG) {
                 final String tagName = parser.getName();
                 final VGroup currentGroup = groupStack.peek();
@@ -2112,41 +2151,61 @@
         abstract Property getProperty(String propertyName);
     }
 
-    private static native long nCreateTree(long rootGroupPtr);
-    private static native long nCreateTreeFromCopy(long treeToCopy, long rootGroupPtr);
-    private static native void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
-            float viewportHeight);
-    private static native boolean nSetRootAlpha(long rendererPtr, float alpha);
-    private static native float nGetRootAlpha(long rendererPtr);
-    private static native void nSetAllowCaching(long rendererPtr, boolean allowCaching);
-
     private static native int nDraw(long rendererPtr, long canvasWrapperPtr,
             long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache);
-    private static native long nCreateFullPath();
-    private static native long nCreateFullPath(long nativeFullPathPtr);
     private static native boolean nGetFullPathProperties(long pathPtr, byte[] properties,
             int length);
+    private static native void nSetName(long nodePtr, String name);
+    private static native boolean nGetGroupProperties(long groupPtr, float[] properties,
+            int length);
+    private static native void nSetPathString(long pathPtr, String pathString, int length);
 
+    // ------------- @FastNative ------------------
+
+    @FastNative
+    private static native long nCreateTree(long rootGroupPtr);
+    @FastNative
+    private static native long nCreateTreeFromCopy(long treeToCopy, long rootGroupPtr);
+    @FastNative
+    private static native void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
+            float viewportHeight);
+    @FastNative
+    private static native boolean nSetRootAlpha(long rendererPtr, float alpha);
+    @FastNative
+    private static native float nGetRootAlpha(long rendererPtr);
+    @FastNative
+    private static native void nSetAllowCaching(long rendererPtr, boolean allowCaching);
+
+    @FastNative
+    private static native long nCreateFullPath();
+    @FastNative
+    private static native long nCreateFullPath(long nativeFullPathPtr);
+
+    @FastNative
     private static native void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
             int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
             float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
             int strokeLineJoin, int fillType);
+    @FastNative
     private static native void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr);
+    @FastNative
     private static native void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr);
 
+    @FastNative
     private static native long nCreateClipPath();
+    @FastNative
     private static native long nCreateClipPath(long clipPathPtr);
 
+    @FastNative
     private static native long nCreateGroup();
+    @FastNative
     private static native long nCreateGroup(long groupPtr);
-    private static native void nSetName(long nodePtr, String name);
-    private static native boolean nGetGroupProperties(long groupPtr, float[] properties,
-            int length);
+    @FastNative
     private static native void nUpdateGroupProperties(long groupPtr, float rotate, float pivotX,
             float pivotY, float scaleX, float scaleY, float translateX, float translateY);
 
+    @FastNative
     private static native void nAddChild(long groupPtr, long nodePtr);
-    private static native void nSetPathString(long pathPtr, String pathString, int length);
 
     /**
      * The setters and getters below for paths and groups are here temporarily, and will be
@@ -2155,37 +2214,68 @@
      * for VD during animation, and these setters and getters will be obsolete.
      */
     // Setters and getters during animation.
+    @FastNative
     private static native float nGetRotation(long groupPtr);
+    @FastNative
     private static native void nSetRotation(long groupPtr, float rotation);
+    @FastNative
     private static native float nGetPivotX(long groupPtr);
+    @FastNative
     private static native void nSetPivotX(long groupPtr, float pivotX);
+    @FastNative
     private static native float nGetPivotY(long groupPtr);
+    @FastNative
     private static native void nSetPivotY(long groupPtr, float pivotY);
+    @FastNative
     private static native float nGetScaleX(long groupPtr);
+    @FastNative
     private static native void nSetScaleX(long groupPtr, float scaleX);
+    @FastNative
     private static native float nGetScaleY(long groupPtr);
+    @FastNative
     private static native void nSetScaleY(long groupPtr, float scaleY);
+    @FastNative
     private static native float nGetTranslateX(long groupPtr);
+    @FastNative
     private static native void nSetTranslateX(long groupPtr, float translateX);
+    @FastNative
     private static native float nGetTranslateY(long groupPtr);
+    @FastNative
     private static native void nSetTranslateY(long groupPtr, float translateY);
 
     // Setters and getters for VPath during animation.
+    @FastNative
     private static native void nSetPathData(long pathPtr, long pathDataPtr);
+    @FastNative
     private static native float nGetStrokeWidth(long pathPtr);
+    @FastNative
     private static native void nSetStrokeWidth(long pathPtr, float width);
+    @FastNative
     private static native int nGetStrokeColor(long pathPtr);
+    @FastNative
     private static native void nSetStrokeColor(long pathPtr, int strokeColor);
+    @FastNative
     private static native float nGetStrokeAlpha(long pathPtr);
+    @FastNative
     private static native void nSetStrokeAlpha(long pathPtr, float alpha);
+    @FastNative
     private static native int nGetFillColor(long pathPtr);
+    @FastNative
     private static native void nSetFillColor(long pathPtr, int fillColor);
+    @FastNative
     private static native float nGetFillAlpha(long pathPtr);
+    @FastNative
     private static native void nSetFillAlpha(long pathPtr, float fillAlpha);
+    @FastNative
     private static native float nGetTrimPathStart(long pathPtr);
+    @FastNative
     private static native void nSetTrimPathStart(long pathPtr, float trimPathStart);
+    @FastNative
     private static native float nGetTrimPathEnd(long pathPtr);
+    @FastNative
     private static native void nSetTrimPathEnd(long pathPtr, float trimPathEnd);
+    @FastNative
     private static native float nGetTrimPathOffset(long pathPtr);
+    @FastNative
     private static native void nSetTrimPathOffset(long pathPtr, float trimPathOffset);
 }
diff --git a/include/androidfw/Asset.h b/include/androidfw/Asset.h
index ee77e97..52c8637 100644
--- a/include/androidfw/Asset.h
+++ b/include/androidfw/Asset.h
@@ -44,7 +44,7 @@
  */
 class Asset {
 public:
-    virtual ~Asset(void);
+    virtual ~Asset(void) = default;
 
     static int32_t getGlobalCount();
     static String8 getAssetAllocations();
@@ -119,6 +119,19 @@
     const char* getAssetSource(void) const { return mAssetSource.string(); }
 
 protected:
+    /*
+     * Adds this Asset to the global Asset list for debugging and
+     * accounting.
+     * Concrete subclasses must call this in their constructor.
+     */
+    static void registerAsset(Asset* asset);
+
+    /*
+     * Removes this Asset from the global Asset list.
+     * Concrete subclasses must call this in their destructor.
+     */
+    static void unregisterAsset(Asset* asset);
+
     Asset(void);        // constructor; only invoked indirectly
 
     /* handle common seek() housekeeping */
diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
index ce8d0f8..7aec323 100644
--- a/include/androidfw/AssetManager.h
+++ b/include/androidfw/AssetManager.h
@@ -71,7 +71,7 @@
     static const char* OVERLAY_DIR;
     /*
      * If OVERLAY_SKU_DIR_PROPERTY is set, search for runtime resource overlay
-     * APKs in OVERLAY_DIR/<value of OVERLAY_SKU_DIR_PROPERTY> rather than in
+     * APKs in OVERLAY_DIR/<value of OVERLAY_SKU_DIR_PROPERTY> in addition to
      * OVERLAY_DIR.
      */
     static const char* OVERLAY_SKU_DIR_PROPERTY;
@@ -136,9 +136,6 @@
     /*
      * Open an asset.
      *
-     * This will search through locale-specific and vendor-specific
-     * directories and packages to find the file.
-     *
      * The object returned does not depend on the AssetManager.  It should
      * be freed by calling Asset::close().
      */
@@ -148,9 +145,8 @@
      * Open a non-asset file as an asset.
      *
      * This is for opening files that are included in an asset package
-     * but aren't assets.  These sit outside the usual "locale/vendor"
-     * path hierarchy, and will not be seen by "AssetDir" or included
-     * in our filename cache.
+     * but aren't assets.  These sit outside the usual "assets/"
+     * path hierarchy, and will not be seen by "AssetDir".
      */
     Asset* openNonAsset(const char* fileName, AccessMode mode, int32_t* outCookie = NULL);
 
@@ -163,11 +159,6 @@
     /*
      * Open a directory within the asset hierarchy.
      *
-     * The contents of the directory are an amalgam of vendor-specific,
-     * locale-specific, and generic assets stored loosely or in asset
-     * packages.  Depending on the cache setting and previous accesses,
-     * this call may incur significant disk overhead.
-     *
      * To open the top-level directory, pass in "".
      */
     AssetDir* openDir(const char* dirName);
@@ -175,11 +166,6 @@
     /*
      * Open a directory within a particular path of the asset manager.
      *
-     * The contents of the directory are an amalgam of vendor-specific,
-     * locale-specific, and generic assets stored loosely or in asset
-     * packages.  Depending on the cache setting and previous accesses,
-     * this call may incur significant disk overhead.
-     *
      * To open the top-level directory, pass in "".
      */
     AssetDir* openNonAssetDir(const int32_t cookie, const char* dirName);
@@ -231,8 +217,6 @@
 
     Asset* openNonAssetInPathLocked(const char* fileName, AccessMode mode,
         const asset_path& path);
-    String8 createPathNameLocked(const asset_path& path, const char* locale,
-        const char* vendor);
     String8 createPathNameLocked(const asset_path& path, const char* rootDir);
     String8 createZipSourceNameLocked(const String8& zipFileName,
         const String8& dirName, const String8& fileName);
@@ -306,8 +290,8 @@
      */
     class ZipSet {
     public:
-        ZipSet(void);
-        ~ZipSet(void);
+        ZipSet() = default;
+        ~ZipSet();
 
         /*
          * Return a ZipFileRO structure for a ZipFileRO with the specified
diff --git a/include/androidfw/AttributeResolution.h b/include/androidfw/AttributeResolution.h
new file mode 100644
index 0000000..2f60a1d
--- /dev/null
+++ b/include/androidfw/AttributeResolution.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROIDFW_ATTRIBUTERESOLUTION_H
+#define ANDROIDFW_ATTRIBUTERESOLUTION_H
+
+#include <androidfw/ResourceTypes.h>
+
+namespace android {
+
+// These are all variations of the same method. They each perform the exact same operation,
+// but on various data sources. I *think* they are re-written to avoid an extra branch
+// in the inner loop, but after one branch miss (some pointer != null), the branch predictor should
+// predict the rest of the iterations' branch correctly.
+// TODO(adamlesinski): Run performance tests against these methods and a new, single method
+// that uses all the sources and branches to the right ones within the inner loop.
+
+bool resolveAttrs(ResTable::Theme* theme,
+                  uint32_t defStyleAttr,
+                  uint32_t defStyleRes,
+                  uint32_t* srcValues, size_t srcValuesLength,
+                  uint32_t* attrs, size_t attrsLength,
+                  uint32_t* outValues,
+                  uint32_t* outIndices);
+
+bool applyStyle(ResTable::Theme* theme, ResXMLParser* xmlParser,
+                uint32_t defStyleAttr,
+                uint32_t defStyleRes,
+                uint32_t* attrs, size_t attrsLength,
+                uint32_t* outValues,
+                uint32_t* outIndices);
+
+bool retrieveAttributes(const ResTable* res, ResXMLParser* xmlParser,
+                        uint32_t* attrs, size_t attrsLength,
+                        uint32_t* outValues,
+                        uint32_t* outIndices);
+
+} // namespace android
+
+#endif /* ANDROIDFW_ATTRIBUTERESOLUTION_H */
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 70e4b6f..00d786a 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -626,6 +626,16 @@
         }
     }
 
+    /**
+     * Notify keystore that the device went off-body.
+     */
+    public void onDeviceOffBody() {
+        try {
+            mBinder.onDeviceOffBody();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Cannot connect to keystore", e);
+        }
+    }
 
     /**
      * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk
index 6bbfcd2..7d7d42c7 100644
--- a/libs/androidfw/Android.mk
+++ b/libs/androidfw/Android.mk
@@ -21,6 +21,7 @@
     Asset.cpp \
     AssetDir.cpp \
     AssetManager.cpp \
+    AttributeResolution.cpp \
     LocaleData.cpp \
     misc.cpp \
     ObbFile.cpp \
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index 2cfa666..8e8c6a2 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -52,6 +52,47 @@
 static Asset* gHead = NULL;
 static Asset* gTail = NULL;
 
+void Asset::registerAsset(Asset* asset)
+{
+    AutoMutex _l(gAssetLock);
+    gCount++;
+    asset->mNext = asset->mPrev = NULL;
+    if (gTail == NULL) {
+        gHead = gTail = asset;
+    } else {
+        asset->mPrev = gTail;
+        gTail->mNext = asset;
+        gTail = asset;
+    }
+
+    if (kIsDebug) {
+        ALOGI("Creating Asset %p #%d\n", asset, gCount);
+    }
+}
+
+void Asset::unregisterAsset(Asset* asset)
+{
+    AutoMutex _l(gAssetLock);
+    gCount--;
+    if (gHead == asset) {
+        gHead = asset->mNext;
+    }
+    if (gTail == asset) {
+        gTail = asset->mPrev;
+    }
+    if (asset->mNext != NULL) {
+        asset->mNext->mPrev = asset->mPrev;
+    }
+    if (asset->mPrev != NULL) {
+        asset->mPrev->mNext = asset->mNext;
+    }
+    asset->mNext = asset->mPrev = NULL;
+
+    if (kIsDebug) {
+        ALOGI("Destroying Asset in %p #%d\n", asset, gCount);
+    }
+}
+
 int32_t Asset::getGlobalCount()
 {
     AutoMutex _l(gAssetLock);
@@ -79,43 +120,8 @@
 }
 
 Asset::Asset(void)
-    : mAccessMode(ACCESS_UNKNOWN)
+    : mAccessMode(ACCESS_UNKNOWN), mNext(NULL), mPrev(NULL)
 {
-    AutoMutex _l(gAssetLock);
-    gCount++;
-    mNext = mPrev = NULL;
-    if (gTail == NULL) {
-        gHead = gTail = this;
-    } else {
-        mPrev = gTail;
-        gTail->mNext = this;
-        gTail = this;
-    }
-    if (kIsDebug) {
-        ALOGI("Creating Asset %p #%d\n", this, gCount);
-    }
-}
-
-Asset::~Asset(void)
-{
-    AutoMutex _l(gAssetLock);
-    gCount--;
-    if (gHead == this) {
-        gHead = mNext;
-    }
-    if (gTail == this) {
-        gTail = mPrev;
-    }
-    if (mNext != NULL) {
-        mNext->mPrev = mPrev;
-    }
-    if (mPrev != NULL) {
-        mPrev->mNext = mNext;
-    }
-    mNext = mPrev = NULL;
-    if (kIsDebug) {
-        ALOGI("Destroying Asset in %p #%d\n", this, gCount);
-    }
 }
 
 /*
@@ -361,6 +367,9 @@
 _FileAsset::_FileAsset(void)
     : mStart(0), mLength(0), mOffset(0), mFp(NULL), mFileName(NULL), mMap(NULL), mBuf(NULL)
 {
+    // Register the Asset with the global list here after it is fully constructed and its
+    // vtable pointer points to this concrete type. b/31113965
+    registerAsset(this);
 }
 
 /*
@@ -369,6 +378,10 @@
 _FileAsset::~_FileAsset(void)
 {
     close();
+
+    // Unregister the Asset from the global list here before it is destructed and while its vtable
+    // pointer still points to this concrete type. b/31113965
+    unregisterAsset(this);
 }
 
 /*
@@ -685,6 +698,9 @@
     : mStart(0), mCompressedLen(0), mUncompressedLen(0), mOffset(0),
       mMap(NULL), mFd(-1), mZipInflater(NULL), mBuf(NULL)
 {
+    // Register the Asset with the global list here after it is fully constructed and its
+    // vtable pointer points to this concrete type. b/31113965
+    registerAsset(this);
 }
 
 /*
@@ -693,6 +709,10 @@
 _CompressedAsset::~_CompressedAsset(void)
 {
     close();
+
+    // Unregister the Asset from the global list here before it is destructed and while its vtable
+    // pointer still points to this concrete type. b/31113965
+    unregisterAsset(this);
 }
 
 /*
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 394a9ab..371bc9a 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -35,6 +35,9 @@
 #include <utils/threads.h>
 #include <utils/Timers.h>
 #include <utils/Trace.h>
+#ifndef _WIN32
+#include <sys/file.h>
+#endif
 
 #include <assert.h>
 #include <dirent.h>
@@ -56,12 +59,6 @@
 
 static const bool kIsDebug = false;
 
-/*
- * Names for default app, locale, and vendor.  We might want to change
- * these to be an actual locale, e.g. always use en-US as the default.
- */
-static const char* kDefaultLocale = "default";
-static const char* kDefaultVendor = "default";
 static const char* kAssetsRoot = "assets";
 static const char* kAppZipName = NULL; //"classes.jar";
 static const char* kSystemAssets = "framework/framework-res.apk";
@@ -370,23 +367,11 @@
 /*
  * Open an asset.
  *
- * The data could be;
- *  - In a file on disk (assetBase + fileName).
- *  - In a compressed file on disk (assetBase + fileName.gz).
- *  - In a Zip archive, uncompressed or compressed.
+ * The data could be in any asset path. Each asset path could be:
+ *  - A directory on disk.
+ *  - A Zip archive, uncompressed or compressed.
  *
- * It can be in a number of different directories and Zip archives.
- * The search order is:
- *  - [appname]
- *    - locale + vendor
- *    - "default" + vendor
- *    - locale + "default"
- *    - "default + "default"
- *  - "common"
- *    - (same as above)
- *
- * To find a particular file, we have to try up to eight paths with
- * all three forms of data.
+ * If the file is in a directory, it could have a .gz suffix, meaning it is compressed.
  *
  * We should probably reject requests for "illegal" filenames, e.g. those
  * with illegal characters or "../" backward relative paths.
@@ -421,8 +406,7 @@
 /*
  * Open a non-asset file as if it were an asset.
  *
- * The "fileName" is the partial path starting from the application
- * name.
+ * The "fileName" is the partial path starting from the application name.
  */
 Asset* AssetManager::openNonAsset(const char* fileName, AccessMode mode, int32_t* outCookie)
 {
@@ -488,10 +472,11 @@
     pAsset = open(fileName, Asset::ACCESS_STREAMING);
     delete pAsset;
 
-    if (pAsset == NULL)
+    if (pAsset == NULL) {
         return kFileTypeNonexistent;
-    else
+    } else {
         return kFileTypeRegular;
+    }
 }
 
 bool AssetManager::appendPathToResTable(const asset_path& ap, bool appAsLib) const {
@@ -665,6 +650,12 @@
         return;
     }
 
+#ifndef _WIN32
+    if (TEMP_FAILURE_RETRY(flock(fileno(fin), LOCK_SH)) != 0) {
+        fclose(fin);
+        return;
+    }
+#endif
     char buf[1024];
     while (fgets(buf, sizeof(buf), fin)) {
         // format of each line:
@@ -695,6 +686,10 @@
             const_cast<AssetManager*>(this)->mZipSet.addOverlay(targetPackagePath, oap);
         }
     }
+
+#ifndef _WIN32
+    TEMP_FAILURE_RETRY(flock(fileno(fin), LOCK_UN));
+#endif
     fclose(fin);
 }
 
@@ -792,18 +787,6 @@
 }
 
 /*
- * Create a path to a loose asset (asset-base/app/locale/vendor).
- */
-String8 AssetManager::createPathNameLocked(const asset_path& ap, const char* locale,
-    const char* vendor)
-{
-    String8 path(ap.path);
-    path.appendPath((locale != NULL) ? locale : kDefaultLocale);
-    path.appendPath((vendor != NULL) ? vendor : kDefaultVendor);
-    return path;
-}
-
-/*
  * Create a path to a loose asset (asset-base/app/rootDir).
  */
 String8 AssetManager::createPathNameLocked(const asset_path& ap, const char* rootDir)
@@ -816,15 +799,6 @@
 /*
  * Return a pointer to one of our open Zip archives.  Returns NULL if no
  * matching Zip file exists.
- *
- * Right now we have 2 possible Zip files (1 each in app/"common").
- *
- * If caching is set to CACHE_OFF, to get the expected behavior we
- * need to reopen the Zip file on every request.  That would be silly
- * and expensive, so instead we just check the file modification date.
- *
- * Pass in NULL values for "appName", "locale", and "vendor" if the
- * generics should be used.
  */
 ZipFileRO* AssetManager::getZipFileLocked(const asset_path& ap)
 {
@@ -909,14 +883,10 @@
     return pAsset;
 }
 
-
-
 /*
  * Open a directory in the asset namespace.
  *
- * An "asset directory" is simply the combination of all files in all
- * locations, with ".gz" stripped for loose files.  With app, locale, and
- * vendor defined, we have 8 directories and 2 Zip archives to scan.
+ * An "asset directory" is simply the combination of all asset paths' "assets/" directories.
  *
  * Pass in "" for the root dir.
  */
@@ -974,9 +944,7 @@
 /*
  * Open a directory in the non-asset namespace.
  *
- * An "asset directory" is simply the combination of all files in all
- * locations, with ".gz" stripped for loose files.  With app, locale, and
- * vendor defined, we have 8 directories and 2 Zip archives to scan.
+ * An "asset directory" is simply the combination of all asset paths' "assets/" directories.
  *
  * Pass in "" for the root dir.
  */
@@ -1502,13 +1470,6 @@
  */
 
 /*
- * Constructor.
- */
-AssetManager::ZipSet::ZipSet(void)
-{
-}
-
-/*
  * Destructor.  Close any open archives.
  */
 AssetManager::ZipSet::~ZipSet(void)
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
new file mode 100644
index 0000000..ad428a4
--- /dev/null
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -0,0 +1,500 @@
+/*
+ * 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 "androidfw/AttributeFinder.h"
+#include "androidfw/AttributeResolution.h"
+#include "androidfw/ResourceTypes.h"
+
+#include <android/log.h>
+#include <cstdint>
+
+constexpr bool kDebugStyles = false;
+
+namespace android {
+
+enum {
+    STYLE_NUM_ENTRIES = 6,
+    STYLE_TYPE = 0,
+    STYLE_DATA = 1,
+    STYLE_ASSET_COOKIE = 2,
+    STYLE_RESOURCE_ID = 3,
+    STYLE_CHANGING_CONFIGURATIONS = 4,
+    STYLE_DENSITY = 5
+};
+
+class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, size_t> {
+public:
+    explicit XmlAttributeFinder(const ResXMLParser* parser) :
+        BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0),
+        mParser(parser) {
+    }
+
+    inline uint32_t getAttribute(size_t index) const {
+        return mParser->getAttributeNameResID(index);
+    }
+
+private:
+    const ResXMLParser* mParser;
+};
+
+class BagAttributeFinder :
+        public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
+public:
+    BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end) :
+        BackTrackingAttributeFinder(start, end) {}
+
+    inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
+        return entry->map.name.ident;
+    }
+};
+
+bool resolveAttrs(ResTable::Theme* theme,
+                  uint32_t defStyleAttr,
+                  uint32_t defStyleRes,
+                  uint32_t* srcValues, size_t srcValuesLength,
+                  uint32_t* attrs, size_t attrsLength,
+                  uint32_t* outValues,
+                  uint32_t* outIndices) {
+    if (kDebugStyles) {
+        ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x "
+              "defStyleRes=0x%x", theme, defStyleAttr, defStyleRes);
+    }
+
+    const ResTable& res = theme->getResTable();
+    ResTable_config config;
+    Res_value value;
+
+    int indicesIdx = 0;
+
+    // Load default style from attribute, if specified...
+    uint32_t defStyleBagTypeSetFlags = 0;
+    if (defStyleAttr != 0) {
+        Res_value value;
+        if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
+            if (value.dataType == Res_value::TYPE_REFERENCE) {
+                defStyleRes = value.data;
+            }
+        }
+    }
+
+    // Now lock down the resource object and start pulling stuff from it.
+    res.lock();
+
+    // Retrieve the default style bag, if requested.
+    const ResTable::bag_entry* defStyleStart = NULL;
+    uint32_t defStyleTypeSetFlags = 0;
+    ssize_t bagOff = defStyleRes != 0
+            ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
+    defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
+    const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
+    BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
+
+    // Now iterate through all of the attributes that the client has requested,
+    // filling in each with whatever data we can find.
+    ssize_t block = 0;
+    uint32_t typeSetFlags;
+    for (size_t ii=0; ii<attrsLength; ii++) {
+        const uint32_t curIdent = attrs[ii];
+
+        if (kDebugStyles) {
+            ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
+        }
+
+        // Try to find a value for this attribute...  we prioritize values
+        // coming from, first XML attributes, then XML style, then default
+        // style, and finally the theme.
+        value.dataType = Res_value::TYPE_NULL;
+        value.data = Res_value::DATA_NULL_UNDEFINED;
+        typeSetFlags = 0;
+        config.density = 0;
+
+        // Retrieve the current input value if available.
+        if (srcValuesLength > 0 && srcValues[ii] != 0) {
+            block = -1;
+            value.dataType = Res_value::TYPE_ATTRIBUTE;
+            value.data = srcValues[ii];
+            if (kDebugStyles) {
+                ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
+            }
+        }
+
+        if (value.dataType == Res_value::TYPE_NULL) {
+            const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
+            if (defStyleEntry != defStyleEnd) {
+                block = defStyleEntry->stringBlock;
+                typeSetFlags = defStyleTypeSetFlags;
+                value = defStyleEntry->map.value;
+                if (kDebugStyles) {
+                    ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
+                }
+            }
+        }
+
+        uint32_t resid = 0;
+        if (value.dataType != Res_value::TYPE_NULL) {
+            // Take care of resolving the found resource to its final value.
+            ssize_t newBlock = theme->resolveAttributeReference(&value, block,
+                    &resid, &typeSetFlags, &config);
+            if (newBlock >= 0) block = newBlock;
+            if (kDebugStyles) {
+                ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
+            }
+        } else {
+            // If we still don't have a value for this attribute, try to find
+            // it in the theme!
+            ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
+            if (newBlock >= 0) {
+                if (kDebugStyles) {
+                    ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+                }
+                newBlock = res.resolveReference(&value, block, &resid,
+                        &typeSetFlags, &config);
+                if (newBlock >= 0) block = newBlock;
+                if (kDebugStyles) {
+                    ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+                }
+            }
+        }
+
+        // Deal with the special @null value -- it turns back to TYPE_NULL.
+        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
+            if (kDebugStyles) {
+                ALOGI("-> Setting to @null!");
+            }
+            value.dataType = Res_value::TYPE_NULL;
+            value.data = Res_value::DATA_NULL_UNDEFINED;
+            block = -1;
+        }
+
+        if (kDebugStyles) {
+            ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
+                  value.data);
+        }
+
+        // Write the final value back to Java.
+        outValues[STYLE_TYPE] = value.dataType;
+        outValues[STYLE_DATA] = value.data;
+        outValues[STYLE_ASSET_COOKIE] = block != -1
+                ? static_cast<uint32_t>(res.getTableCookie(block)) : static_cast<uint32_t>(-1);
+        outValues[STYLE_RESOURCE_ID] = resid;
+        outValues[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+        outValues[STYLE_DENSITY] = config.density;
+
+        if (outIndices != NULL && value.dataType != Res_value::TYPE_NULL) {
+            indicesIdx++;
+            outIndices[indicesIdx] = ii;
+        }
+
+        outValues += STYLE_NUM_ENTRIES;
+    }
+
+    res.unlock();
+
+    if (outIndices != NULL) {
+        outIndices[0] = indicesIdx;
+    }
+    return true;
+}
+
+bool applyStyle(ResTable::Theme* theme, ResXMLParser* xmlParser,
+                uint32_t defStyleAttr,
+                uint32_t defStyleRes,
+                uint32_t* attrs, size_t attrsLength,
+                uint32_t* outValues,
+                uint32_t* outIndices) {
+    if (kDebugStyles) {
+        ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p",
+              theme, defStyleAttr, defStyleRes, xmlParser);
+    }
+
+    const ResTable& res = theme->getResTable();
+    ResTable_config config;
+    Res_value value;
+
+    int indicesIdx = 0;
+
+    // Load default style from attribute, if specified...
+    uint32_t defStyleBagTypeSetFlags = 0;
+    if (defStyleAttr != 0) {
+        Res_value value;
+        if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
+            if (value.dataType == Res_value::TYPE_REFERENCE) {
+                defStyleRes = value.data;
+            }
+        }
+    }
+
+    // Retrieve the style class associated with the current XML tag.
+    int style = 0;
+    uint32_t styleBagTypeSetFlags = 0;
+    if (xmlParser != NULL) {
+        ssize_t idx = xmlParser->indexOfStyle();
+        if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
+            if (value.dataType == value.TYPE_ATTRIBUTE) {
+                if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
+                    value.dataType = Res_value::TYPE_NULL;
+                }
+            }
+            if (value.dataType == value.TYPE_REFERENCE) {
+                style = value.data;
+            }
+        }
+    }
+
+    // Now lock down the resource object and start pulling stuff from it.
+    res.lock();
+
+    // Retrieve the default style bag, if requested.
+    const ResTable::bag_entry* defStyleAttrStart = NULL;
+    uint32_t defStyleTypeSetFlags = 0;
+    ssize_t bagOff = defStyleRes != 0
+            ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
+    defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
+    const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
+    BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
+
+    // Retrieve the style class bag, if requested.
+    const ResTable::bag_entry* styleAttrStart = NULL;
+    uint32_t styleTypeSetFlags = 0;
+    bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
+    styleTypeSetFlags |= styleBagTypeSetFlags;
+    const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
+    BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
+
+    // Retrieve the XML attributes, if requested.
+    static const ssize_t kXmlBlock = 0x10000000;
+    XmlAttributeFinder xmlAttrFinder(xmlParser);
+    const size_t xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
+
+    // Now iterate through all of the attributes that the client has requested,
+    // filling in each with whatever data we can find.
+    ssize_t block = 0;
+    uint32_t typeSetFlags;
+    for (size_t ii = 0; ii < attrsLength; ii++) {
+        const uint32_t curIdent = attrs[ii];
+
+        if (kDebugStyles) {
+            ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
+        }
+
+        // Try to find a value for this attribute...  we prioritize values
+        // coming from, first XML attributes, then XML style, then default
+        // style, and finally the theme.
+        value.dataType = Res_value::TYPE_NULL;
+        value.data = Res_value::DATA_NULL_UNDEFINED;
+        typeSetFlags = 0;
+        config.density = 0;
+
+        // Walk through the xml attributes looking for the requested attribute.
+        const size_t xmlAttrIdx = xmlAttrFinder.find(curIdent);
+        if (xmlAttrIdx != xmlAttrEnd) {
+            // We found the attribute we were looking for.
+            block = kXmlBlock;
+            xmlParser->getAttributeValue(xmlAttrIdx, &value);
+            if (kDebugStyles) {
+                ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
+            }
+        }
+
+        if (value.dataType == Res_value::TYPE_NULL) {
+            // Walk through the style class values looking for the requested attribute.
+            const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
+            if (styleAttrEntry != styleAttrEnd) {
+                // We found the attribute we were looking for.
+                block = styleAttrEntry->stringBlock;
+                typeSetFlags = styleTypeSetFlags;
+                value = styleAttrEntry->map.value;
+                if (kDebugStyles) {
+                    ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
+                }
+            }
+        }
+
+        if (value.dataType == Res_value::TYPE_NULL) {
+            // Walk through the default style values looking for the requested attribute.
+            const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
+            if (defStyleAttrEntry != defStyleAttrEnd) {
+                // We found the attribute we were looking for.
+                block = defStyleAttrEntry->stringBlock;
+                typeSetFlags = styleTypeSetFlags;
+                value = defStyleAttrEntry->map.value;
+                if (kDebugStyles) {
+                    ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
+                }
+            }
+        }
+
+        uint32_t resid = 0;
+        if (value.dataType != Res_value::TYPE_NULL) {
+            // Take care of resolving the found resource to its final value.
+            ssize_t newBlock = theme->resolveAttributeReference(&value, block,
+                    &resid, &typeSetFlags, &config);
+            if (newBlock >= 0) {
+                block = newBlock;
+            }
+
+            if (kDebugStyles) {
+                ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
+            }
+        } else {
+            // If we still don't have a value for this attribute, try to find
+            // it in the theme!
+            ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
+            if (newBlock >= 0) {
+                if (kDebugStyles) {
+                    ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+                }
+                newBlock = res.resolveReference(&value, block, &resid,
+                        &typeSetFlags, &config);
+
+                if (newBlock >= 0) {
+                    block = newBlock;
+                }
+
+                if (kDebugStyles) {
+                    ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+                }
+            }
+        }
+
+        // Deal with the special @null value -- it turns back to TYPE_NULL.
+        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
+            if (kDebugStyles) {
+                ALOGI("-> Setting to @null!");
+            }
+            value.dataType = Res_value::TYPE_NULL;
+            value.data = Res_value::DATA_NULL_UNDEFINED;
+            block = kXmlBlock;
+        }
+
+        if (kDebugStyles) {
+            ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
+        }
+
+        // Write the final value back to Java.
+        outValues[STYLE_TYPE] = value.dataType;
+        outValues[STYLE_DATA] = value.data;
+        outValues[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
+            static_cast<uint32_t>(res.getTableCookie(block)) : static_cast<uint32_t>(-1);
+        outValues[STYLE_RESOURCE_ID] = resid;
+        outValues[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+        outValues[STYLE_DENSITY] = config.density;
+
+        if (outIndices != NULL && value.dataType != Res_value::TYPE_NULL) {
+            indicesIdx++;
+            outIndices[indicesIdx] = ii;
+        }
+
+        outValues += STYLE_NUM_ENTRIES;
+    }
+
+    res.unlock();
+
+    if (outIndices != NULL) {
+        outIndices[0] = indicesIdx;
+    }
+    return true;
+}
+
+bool retrieveAttributes(const ResTable* res, ResXMLParser* xmlParser,
+                        uint32_t* attrs, size_t attrsLength,
+                        uint32_t* outValues,
+                        uint32_t* outIndices) {
+    ResTable_config config;
+    Res_value value;
+
+    int indicesIdx = 0;
+
+    // Now lock down the resource object and start pulling stuff from it.
+    res->lock();
+
+    // Retrieve the XML attributes, if requested.
+    const size_t NX = xmlParser->getAttributeCount();
+    size_t ix=0;
+    uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
+
+    static const ssize_t kXmlBlock = 0x10000000;
+
+    // Now iterate through all of the attributes that the client has requested,
+    // filling in each with whatever data we can find.
+    ssize_t block = 0;
+    uint32_t typeSetFlags;
+    for (size_t ii=0; ii<attrsLength; ii++) {
+        const uint32_t curIdent = attrs[ii];
+
+        // Try to find a value for this attribute...
+        value.dataType = Res_value::TYPE_NULL;
+        value.data = Res_value::DATA_NULL_UNDEFINED;
+        typeSetFlags = 0;
+        config.density = 0;
+
+        // Skip through XML attributes until the end or the next possible match.
+        while (ix < NX && curIdent > curXmlAttr) {
+            ix++;
+            curXmlAttr = xmlParser->getAttributeNameResID(ix);
+        }
+        // Retrieve the current XML attribute if it matches, and step to next.
+        if (ix < NX && curIdent == curXmlAttr) {
+            block = kXmlBlock;
+            xmlParser->getAttributeValue(ix, &value);
+            ix++;
+            curXmlAttr = xmlParser->getAttributeNameResID(ix);
+        }
+
+        //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
+        uint32_t resid = 0;
+        if (value.dataType != Res_value::TYPE_NULL) {
+            // Take care of resolving the found resource to its final value.
+            //printf("Resolving attribute reference\n");
+            ssize_t newBlock = res->resolveReference(&value, block, &resid,
+                    &typeSetFlags, &config);
+            if (newBlock >= 0) block = newBlock;
+        }
+
+        // Deal with the special @null value -- it turns back to TYPE_NULL.
+        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
+            value.dataType = Res_value::TYPE_NULL;
+            value.data = Res_value::DATA_NULL_UNDEFINED;
+        }
+
+        //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
+
+        // Write the final value back to Java.
+        outValues[STYLE_TYPE] = value.dataType;
+        outValues[STYLE_DATA] = value.data;
+        outValues[STYLE_ASSET_COOKIE] = block != kXmlBlock
+                ? static_cast<uint32_t>(res->getTableCookie(block)) : static_cast<uint32_t>(-1);
+        outValues[STYLE_RESOURCE_ID] = resid;
+        outValues[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+        outValues[STYLE_DENSITY] = config.density;
+
+        if (outIndices != NULL && value.dataType != Res_value::TYPE_NULL) {
+            indicesIdx++;
+            outIndices[indicesIdx] = ii;
+        }
+
+        outValues += STYLE_NUM_ENTRIES;
+    }
+
+    res->unlock();
+
+    if (outIndices != NULL) {
+        outIndices[0] = indicesIdx;
+    }
+    return true;
+}
+
+} // namespace android
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index b423f6c..b16279c 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -739,7 +739,7 @@
                         ALOGW("CREATING STRING CACHE OF %zu bytes",
                                 static_cast<size_t>(mHeader->stringCount*sizeof(char16_t**)));
 #endif
-                        mCache = (char16_t**)calloc(mHeader->stringCount, sizeof(char16_t**));
+                        mCache = (char16_t**)calloc(mHeader->stringCount, sizeof(char16_t*));
                         if (mCache == NULL) {
                             ALOGW("No memory trying to allocate decode cache table of %d bytes\n",
                                     (int)(mHeader->stringCount*sizeof(char16_t**)));
@@ -4390,10 +4390,12 @@
             if (set->numAttrs >= set->availAttrs) {
                 // Need to alloc more memory...
                 const size_t newAvail = set->availAttrs+N;
+                void *oldSet = set;
                 set = (bag_set*)realloc(set,
                                         sizeof(bag_set)
                                         + sizeof(bag_entry)*newAvail);
                 if (set == NULL) {
+                    free(oldSet);
                     return NO_MEMORY;
                 }
                 set->availAttrs = newAvail;
@@ -4440,7 +4442,7 @@
         pos++;
         const size_t size = dtohs(map->value.size);
         curOff += size + sizeof(*map)-sizeof(map->value);
-    };
+    }
 
     if (curEntry > set->numAttrs) {
         set->numAttrs = curEntry;
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 2bc026b7..1fe1773 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -22,6 +22,7 @@
 
 testFiles := \
     AppAsLib_test.cpp \
+    Asset_test.cpp \
     AttributeFinder_test.cpp \
     ByteBucketArray_test.cpp \
     Config_test.cpp \
diff --git a/libs/androidfw/tests/Asset_test.cpp b/libs/androidfw/tests/Asset_test.cpp
new file mode 100644
index 0000000..45c8cef
--- /dev/null
+++ b/libs/androidfw/tests/Asset_test.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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 <androidfw/Asset.h>
+
+#include <gtest/gtest.h>
+
+using namespace android;
+
+TEST(AssetTest, FileAssetRegistersItself) {
+    const int32_t count = Asset::getGlobalCount();
+    Asset* asset = new _FileAsset();
+    EXPECT_EQ(count + 1, Asset::getGlobalCount());
+    delete asset;
+    EXPECT_EQ(count, Asset::getGlobalCount());
+}
+
+TEST(AssetTest, CompressedAssetRegistersItself) {
+    const int32_t count = Asset::getGlobalCount();
+    Asset* asset = new _CompressedAsset();
+    EXPECT_EQ(count + 1, Asset::getGlobalCount());
+    delete asset;
+    EXPECT_EQ(count, Asset::getGlobalCount());
+}
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 81a1831..1282846 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
-BUGREPORT_FONT_CACHE_USAGE := true
+BUGREPORT_FONT_CACHE_USAGE := false
 
 # Enables fine-grained GLES error checking
 # If set to true, every GLES call is wrapped & error checked
@@ -16,6 +16,7 @@
     hwui/MinikinSkia.cpp \
     hwui/MinikinUtils.cpp \
     hwui/PaintImpl.cpp \
+    hwui/PixelRef.cpp \
     hwui/Typeface.cpp \
     renderstate/Blend.cpp \
     renderstate/MeshState.cpp \
@@ -45,7 +46,6 @@
     AnimationContext.cpp \
     Animator.cpp \
     AnimatorManager.cpp \
-    AssetAtlas.cpp \
     BakedOpDispatcher.cpp \
     BakedOpRenderer.cpp \
     BakedOpState.cpp \
@@ -56,7 +56,6 @@
     DeferredLayerUpdater.cpp \
     DeviceInfo.cpp \
     DisplayList.cpp \
-    Dither.cpp \
     Extensions.cpp \
     FboCache.cpp \
     FontRenderer.cpp \
@@ -95,6 +94,7 @@
     ShadowTessellator.cpp \
     SkiaCanvas.cpp \
     SkiaCanvasProxy.cpp \
+    SkiaDisplayList.cpp \
     SkiaShader.cpp \
     Snapshot.cpp \
     SpotShadow.cpp \
@@ -130,6 +130,14 @@
     hwui_cflags += -DUSE_HWC2
 endif
 
+# TODO: Linear blending should be enabled by default, but we are
+# TODO: making it an opt-in while it's a work in progress
+# TODO: The final test should be:
+# TODO: ifneq ($(TARGET_ENABLE_LINEAR_BLENDING),false)
+ifeq ($(TARGET_ENABLE_LINEAR_BLENDING),true)
+    hwui_cflags += -DANDROID_ENABLE_LINEAR_BLENDING
+endif
+
 # GCC false-positives on this warning, and since we -Werror that's
 # a problem
 hwui_cflags += -Wno-free-nonheap-object
@@ -143,7 +151,6 @@
     hwui_cflags += -DBUGREPORT_FONT_CACHE_USAGE
 endif
 
-
 ifndef HWUI_COMPILE_SYMBOLS
     hwui_cflags += -fvisibility=hidden
 endif
@@ -280,6 +287,7 @@
     tests/unit/RenderNodeTests.cpp \
     tests/unit/RenderPropertiesTests.cpp \
     tests/unit/SkiaBehaviorTests.cpp \
+    tests/unit/SkiaDisplayListTests.cpp \
     tests/unit/SkiaCanvasTests.cpp \
     tests/unit/SnapshotTests.cpp \
     tests/unit/StringUtilsTests.cpp \
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
deleted file mode 100644
index e2e70372..0000000
--- a/libs/hwui/AssetAtlas.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2013 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 "AssetAtlas.h"
-#include "Caches.h"
-#include "Image.h"
-
-#include <GLES2/gl2ext.h>
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Lifecycle
-///////////////////////////////////////////////////////////////////////////////
-
-void AssetAtlas::init(const sp<GraphicBuffer>& buffer, int64_t* map, int count) {
-    if (mImage) {
-        return;
-    }
-
-    ATRACE_NAME("AssetAtlas::init");
-
-    mImage = new Image(buffer);
-    if (mImage->getTexture()) {
-        if (!mTexture) {
-            Caches& caches = Caches::getInstance();
-            mTexture = new Texture(caches);
-            mTexture->wrap(mImage->getTexture(),
-                    buffer->getWidth(), buffer->getHeight(), GL_RGBA);
-            createEntries(caches, map, count);
-        }
-    } else {
-        ALOGW("Could not create atlas image");
-        terminate();
-    }
-}
-
-void AssetAtlas::terminate() {
-    delete mImage;
-    mImage = nullptr;
-    delete mTexture;
-    mTexture = nullptr;
-    mEntries.clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Entries
-///////////////////////////////////////////////////////////////////////////////
-
-AssetAtlas::Entry* AssetAtlas::getEntry(const SkPixelRef* pixelRef) const {
-    auto result = mEntries.find(pixelRef);
-    return result != mEntries.end() ? result->second.get() : nullptr;
-}
-
-Texture* AssetAtlas::getEntryTexture(const SkPixelRef* pixelRef) const {
-    auto result = mEntries.find(pixelRef);
-    return result != mEntries.end() ? result->second->texture : nullptr;
-}
-
-/**
- * Delegates changes to wrapping and filtering to the base atlas texture
- * instead of applying the changes to the virtual textures.
- */
-struct DelegateTexture: public Texture {
-    DelegateTexture(Caches& caches, Texture* delegate)
-            : Texture(caches), mDelegate(delegate) { }
-
-    virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
-            bool force = false, GLenum renderTarget = GL_TEXTURE_2D) override {
-        mDelegate->setWrapST(wrapS, wrapT, bindTexture, force, renderTarget);
-    }
-
-    virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
-            bool force = false, GLenum renderTarget = GL_TEXTURE_2D) override {
-        mDelegate->setFilterMinMag(min, mag, bindTexture, force, renderTarget);
-    }
-
-private:
-    Texture* const mDelegate;
-}; // struct DelegateTexture
-
-void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) {
-    const float width = float(mTexture->width());
-    const float height = float(mTexture->height());
-
-    for (int i = 0; i < count; ) {
-        SkPixelRef* pixelRef = reinterpret_cast<SkPixelRef*>(map[i++]);
-        // NOTE: We're converting from 64 bit signed values to 32 bit
-        // signed values. This is guaranteed to be safe because the "x"
-        // and "y" coordinate values are guaranteed to be representable
-        // with 32 bits. The array is 64 bits wide so that it can carry
-        // pointers on 64 bit architectures.
-        const int x = static_cast<int>(map[i++]);
-        const int y = static_cast<int>(map[i++]);
-
-        // Bitmaps should never be null, we're just extra paranoid
-        if (!pixelRef) continue;
-
-        const UvMapper mapper(
-                x / width, (x + pixelRef->info().width()) / width,
-                y / height, (y + pixelRef->info().height()) / height);
-
-        Texture* texture = new DelegateTexture(caches, mTexture);
-        texture->blend = !SkAlphaTypeIsOpaque(pixelRef->info().alphaType());
-        texture->wrap(mTexture->id(), pixelRef->info().width(),
-                pixelRef->info().height(), mTexture->format());
-
-        std::unique_ptr<Entry> entry(new Entry(pixelRef, texture, mapper, *this));
-        texture->uvMapper = &entry->uvMapper;
-
-        mEntries.emplace(entry->pixelRef, std::move(entry));
-    }
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
deleted file mode 100644
index b32e518..0000000
--- a/libs/hwui/AssetAtlas.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2013 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 ANDROID_HWUI_ASSET_ATLAS_H
-#define ANDROID_HWUI_ASSET_ATLAS_H
-
-#include "Texture.h"
-#include "UvMapper.h"
-
-#include <cutils/compiler.h>
-#include <GLES2/gl2.h>
-#include <ui/GraphicBuffer.h>
-#include <SkBitmap.h>
-
-#include <memory>
-#include <unordered_map>
-
-namespace android {
-namespace uirenderer {
-
-class Caches;
-class Image;
-
-/**
- * An asset atlas holds a collection of framework bitmaps in a single OpenGL
- * texture. Each bitmap is associated with a location, defined in pixels,
- * inside the atlas. The atlas is generated by the framework and bound as
- * an external texture using the EGLImageKHR extension.
- */
-class AssetAtlas {
-public:
-    /**
-     * Entry representing the texture and uvMapper of a PixelRef in the
-     * atlas
-     */
-    class Entry {
-    public:
-        /*
-         * A "virtual texture" object that represents the texture
-         * this entry belongs to. This texture should never be
-         * modified.
-         */
-        Texture* texture;
-
-        /**
-         * Maps texture coordinates in the [0..1] range into the
-         * correct range to sample this entry from the atlas.
-         */
-        const UvMapper uvMapper;
-
-        /**
-         * Unique identifier used to merge bitmaps and 9-patches stored
-         * in the atlas.
-         */
-        const void* getMergeId() const {
-            return texture->blend ? &atlas.mBlendKey : &atlas.mOpaqueKey;
-        }
-
-        ~Entry() {
-            delete texture;
-        }
-
-    private:
-        /**
-         * The pixel ref that generated this atlas entry.
-         */
-        SkPixelRef* pixelRef;
-
-        /**
-         * Atlas this entry belongs to.
-         */
-        const AssetAtlas& atlas;
-
-        Entry(SkPixelRef* pixelRef, Texture* texture, const UvMapper& mapper,
-                    const AssetAtlas& atlas)
-                : texture(texture)
-                , uvMapper(mapper)
-                , pixelRef(pixelRef)
-                , atlas(atlas) {
-        }
-
-        friend class AssetAtlas;
-    };
-
-    AssetAtlas(): mTexture(nullptr), mImage(nullptr),
-            mBlendKey(true), mOpaqueKey(false) { }
-    ~AssetAtlas() { terminate(); }
-
-    /**
-     * Initializes the atlas with the specified buffer and
-     * map. The buffer is a gralloc'd texture that will be
-     * used as an EGLImage. The map is a list of SkBitmap*
-     * and their (x, y) positions
-     *
-     * This method returns immediately if the atlas is already
-     * initialized. To re-initialize the atlas, you must
-     * first call terminate().
-     */
-    ANDROID_API void init(const sp<GraphicBuffer>& buffer, int64_t* map, int count);
-
-    /**
-     * Destroys the atlas texture. This object can be
-     * re-initialized after calling this method.
-     *
-     * After calling this method, the width, height
-     * and texture are set to 0.
-     */
-    void terminate();
-
-    /**
-     * Returns the width of this atlas in pixels.
-     * Can return 0 if the atlas is not initialized.
-     */
-    uint32_t getWidth() const {
-        return mTexture ? mTexture->width() : 0;
-    }
-
-    /**
-     * Returns the height of this atlas in pixels.
-     * Can return 0 if the atlas is not initialized.
-     */
-    uint32_t getHeight() const {
-        return mTexture ? mTexture->height() : 0;
-    }
-
-    /**
-     * Returns the OpenGL name of the texture backing this atlas.
-     * Can return 0 if the atlas is not initialized.
-     */
-    GLuint getTexture() const {
-        return mTexture ? mTexture->id() : 0;
-    }
-
-    /**
-     * Returns the entry in the atlas associated with the specified
-     * pixelRef. If the pixelRef is not in the atlas, return NULL.
-     */
-    Entry* getEntry(const SkPixelRef* pixelRef) const;
-
-    /**
-     * Returns the texture for the atlas entry associated with the
-     * specified pixelRef. If the pixelRef is not in the atlas, return NULL.
-     */
-    Texture* getEntryTexture(const SkPixelRef* pixelRef) const;
-
-private:
-    void createEntries(Caches& caches, int64_t* map, int count);
-
-    Texture* mTexture;
-    Image* mImage;
-
-    const bool mBlendKey;
-    const bool mOpaqueKey;
-
-    std::unordered_map<const SkPixelRef*, std::unique_ptr<Entry>> mEntries;
-}; // class AssetAtlas
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_ASSET_ATLAS_H
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 8b3f172..840c79d 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -35,11 +35,11 @@
 namespace android {
 namespace uirenderer {
 
-static void storeTexturedRect(TextureVertex* vertices, const Rect& bounds, const Rect& texCoord) {
-    vertices[0] = { bounds.left, bounds.top, texCoord.left, texCoord.top };
-    vertices[1] = { bounds.right, bounds.top, texCoord.right, texCoord.top };
-    vertices[2] = { bounds.left, bounds.bottom, texCoord.left, texCoord.bottom };
-    vertices[3] = { bounds.right, bounds.bottom, texCoord.right, texCoord.bottom };
+static void storeTexturedRect(TextureVertex* vertices, const Rect& bounds) {
+    vertices[0] = { bounds.left,  bounds.top,    0, 0 };
+    vertices[1] = { bounds.right, bounds.top,    1, 0 };
+    vertices[2] = { bounds.left,  bounds.bottom, 0, 1 };
+    vertices[3] = { bounds.right, bounds.bottom, 1, 1 };
 }
 
 void BakedOpDispatcher::onMergedBitmapOps(BakedOpRenderer& renderer,
@@ -48,16 +48,11 @@
     const BakedOpState& firstState = *(opList.states[0]);
     const SkBitmap* bitmap = (static_cast<const BitmapOp*>(opList.states[0]->op))->bitmap;
 
-    AssetAtlas::Entry* entry = renderer.renderState().assetAtlas().getEntry(bitmap->pixelRef());
-    Texture* texture = entry ? entry->texture : renderer.caches().textureCache.get(bitmap);
+    Texture* texture = renderer.caches().textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
 
     TextureVertex vertices[opList.count * 4];
-    Rect texCoords(0, 0, 1, 1);
-    if (entry) {
-        entry->uvMapper.map(texCoords);
-    }
     for (size_t i = 0; i < opList.count; i++) {
         const BakedOpState& state = *(opList.states[i]);
         TextureVertex* rectVerts = &vertices[i * 4];
@@ -69,7 +64,7 @@
             // pure translate, so snap (same behavior as onBitmapOp)
             opBounds.snapToPixelBoundaries();
         }
-        storeTexturedRect(rectVerts, opBounds, texCoords);
+        storeTexturedRect(rectVerts, opBounds);
         renderer.dirtyRenderTarget(opBounds);
     }
 
@@ -92,8 +87,6 @@
         const MergedBakedOpList& opList) {
     const PatchOp& firstOp = *(static_cast<const PatchOp*>(opList.states[0]->op));
     const BakedOpState& firstState = *(opList.states[0]);
-    AssetAtlas::Entry* entry = renderer.renderState().assetAtlas().getEntry(
-            firstOp.bitmap->pixelRef());
 
     // Batches will usually contain a small number of items so it's
     // worth performing a first iteration to count the exact number
@@ -105,7 +98,7 @@
 
         // TODO: cache mesh lookups
         const Patch* opMesh = renderer.caches().patchCache.get(
-                entry, op.bitmap->width(), op.bitmap->height(),
+                op.bitmap->width(), op.bitmap->height(),
                 op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.patch);
         totalVertices += opMesh->verticesCount;
     }
@@ -126,7 +119,7 @@
 
         // TODO: cache mesh lookups
         const Patch* opMesh = renderer.caches().patchCache.get(
-                entry, op.bitmap->width(), op.bitmap->height(),
+                op.bitmap->width(), op.bitmap->height(),
                 op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.patch);
 
 
@@ -172,7 +165,7 @@
     }
 
 
-    Texture* texture = entry ? entry->texture : renderer.caches().textureCache.get(firstOp.bitmap);
+    Texture* texture = renderer.caches().textureCache.get(firstOp.bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
 
@@ -299,7 +292,7 @@
     Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
     int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha;
-    SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(op.paint);
+    SkBlendMode mode = PaintUtils::getBlendModeDirect(op.paint);
     TextDrawFunctor functor(&renderer, &state, renderClip,
             x, y, pureTranslate, alpha, mode, op.paint);
 
@@ -442,7 +435,12 @@
 }
 
 void BakedOpDispatcher::onBitmapMeshOp(BakedOpRenderer& renderer, const BitmapMeshOp& op, const BakedOpState& state) {
-    const static UvMapper defaultUvMapper;
+    Texture* texture = renderer.caches().textureCache.get(op.bitmap);
+    if (!texture) {
+        return;
+    }
+    const AutoTexture autoCleanup(texture);
+
     const uint32_t elementCount = op.meshWidth * op.meshHeight * 6;
 
     std::unique_ptr<ColorTextureVertex[]> mesh(new ColorTextureVertex[elementCount]);
@@ -457,9 +455,6 @@
         colors = tempColors.get();
     }
 
-    Texture* texture = renderer.renderState().assetAtlas().getEntryTexture(op.bitmap->pixelRef());
-    const UvMapper& mapper(texture && texture->uvMapper ? *texture->uvMapper : defaultUvMapper);
-
     for (int32_t y = 0; y < op.meshHeight; y++) {
         for (int32_t x = 0; x < op.meshWidth; x++) {
             uint32_t i = (y * (op.meshWidth + 1) + x) * 2;
@@ -469,8 +464,6 @@
             float v1 = float(y) / op.meshHeight;
             float v2 = float(y + 1) / op.meshHeight;
 
-            mapper.map(u1, v1, u2, v2);
-
             int ax = i + (op.meshWidth + 1) * 2;
             int ay = ax + 1;
             int bx = i;
@@ -491,14 +484,6 @@
         }
     }
 
-    if (!texture) {
-        texture = renderer.caches().textureCache.get(op.bitmap);
-        if (!texture) {
-            return;
-        }
-    }
-    const AutoTexture autoCleanup(texture);
-
     /*
      * TODO: handle alpha_8 textures correctly by applying paint color, but *not*
      * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh.
@@ -543,7 +528,7 @@
 void BakedOpDispatcher::onColorOp(BakedOpRenderer& renderer, const ColorOp& op, const BakedOpState& state) {
     SkPaint paint;
     paint.setColor(op.color);
-    paint.setXfermodeMode(op.mode);
+    paint.setBlendMode(op.mode);
 
     Glop glop;
     GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
@@ -599,12 +584,11 @@
     }
 
     // TODO: avoid redoing the below work each frame:
-    AssetAtlas::Entry* entry = renderer.renderState().assetAtlas().getEntry(op.bitmap->pixelRef());
     const Patch* mesh = renderer.caches().patchCache.get(
-            entry, op.bitmap->width(), op.bitmap->height(),
+            op.bitmap->width(), op.bitmap->height(),
             op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.patch);
 
-    Texture* texture = entry ? entry->texture : renderer.caches().textureCache.get(op.bitmap);
+    Texture* texture = renderer.caches().textureCache.get(op.bitmap);
     if (CC_LIKELY(texture)) {
         const AutoTexture autoCleanup(texture);
         Glop glop;
@@ -760,7 +744,7 @@
     Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
     int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha;
-    SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(op.paint);
+    SkBlendMode mode = PaintUtils::getBlendModeDirect(op.paint);
     TextDrawFunctor functor(&renderer, &state, renderTargetClip,
             0.0f, 0.0f, false, alpha, mode, op.paint);
 
@@ -792,11 +776,11 @@
 }
 
 void renderRectForLayer(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state,
-        int color, SkXfermode::Mode mode, SkColorFilter* colorFilter) {
+        int color, SkBlendMode mode, SkColorFilter* colorFilter) {
     SkPaint paint;
     paint.setColor(color);
-    paint.setXfermodeMode(mode);
-    paint.setColorFilter(colorFilter);
+    paint.setBlendMode(mode);
+    paint.setColorFilter(sk_ref_sp(colorFilter));
     RectOp rectOp(op.unmappedBounds, op.localMatrix, op.localClip, &paint);
     BakedOpDispatcher::onRectOp(renderer, rectOp, state);
 }
@@ -824,11 +808,11 @@
         if (CC_UNLIKELY(Properties::debugLayersUpdates)) {
             // render debug layer highlight
             renderRectForLayer(renderer, op, state,
-                    0x7f00ff00, SkXfermode::Mode::kSrcOver_Mode, nullptr);
+                    0x7f00ff00, SkBlendMode::kSrcOver, nullptr);
         } else if (CC_UNLIKELY(Properties::debugOverdraw)) {
             // render transparent to increment overdraw for repaint area
             renderRectForLayer(renderer, op, state,
-                    SK_ColorTRANSPARENT, SkXfermode::Mode::kSrcOver_Mode, nullptr);
+                    SK_ColorTRANSPARENT, SkBlendMode::kSrcOver, nullptr);
         }
     }
 }
@@ -845,14 +829,14 @@
         if (op.paint && op.paint->getAlpha() < 255) {
             SkPaint layerPaint;
             layerPaint.setAlpha(op.paint->getAlpha());
-            layerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
-            layerPaint.setColorFilter(op.paint->getColorFilter());
+            layerPaint.setBlendMode(SkBlendMode::kDstIn);
+            layerPaint.setColorFilter(sk_ref_sp(op.paint->getColorFilter()));
             RectOp rectOp(state.computedState.clippedBounds, Matrix4::identity(), nullptr, &layerPaint);
             BakedOpDispatcher::onRectOp(renderer, rectOp, state);
         }
 
         OffscreenBuffer& layer = **(op.layerHandle);
-        auto mode = PaintUtils::getXfermodeDirect(op.paint);
+        auto mode = PaintUtils::getBlendModeDirect(op.paint);
         Glop glop;
         GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
                 .setRoundRectClipState(state.roundRectClipState)
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 6db345a..ac7a600 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -182,11 +182,7 @@
 }
 
 Texture* BakedOpRenderer::getTexture(const SkBitmap* bitmap) {
-    Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap->pixelRef());
-    if (!texture) {
-        return mCaches.textureCache.get(bitmap);
-    }
-    return texture;
+    return mCaches.textureCache.get(bitmap);
 }
 
 void BakedOpRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 741cdcc..b463e45 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -53,7 +53,6 @@
         : gradientCache(mExtensions)
         , patchCache(renderState)
         , programCache(mExtensions)
-        , dither(*this)
         , mRenderState(&renderState)
         , mInitialized(false) {
     INIT_LOGD("Creating OpenGL renderer caches");
@@ -238,7 +237,6 @@
             gradientCache.clear();
             fontRenderer.clear();
             fboCache.clear();
-            dither.clear();
             // fall through
         case FlushMode::Moderate:
             fontRenderer.flush();
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 344ee71..7c2e78c 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -16,8 +16,6 @@
 
 #pragma once
 
-#include "AssetAtlas.h"
-#include "Dither.h"
 #include "Extensions.h"
 #include "FboCache.h"
 #include "GammaFontRenderer.h"
@@ -130,6 +128,15 @@
     TextureVertex* getRegionMesh();
 
     /**
+     * Returns the GL RGBA internal format to use for the current device
+     * If the device supports linear blending and needSRGB is true,
+     * this function returns GL_SRGB8_ALPHA8, otherwise it returns GL_RGBA
+     */
+    constexpr GLint rgbaInternalFormat(bool needSRGB = true) const {
+        return extensions().hasSRGB() && needSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA;
+    }
+
+    /**
      * Displays the memory usage of each cache and the total sum.
      */
     void dumpMemoryUsage();
@@ -157,8 +164,6 @@
 
     TaskManager tasks;
 
-    Dither dither;
-
     bool gpuPixelBuffersEnabled;
 
     // Debug methods
@@ -169,7 +174,7 @@
     void setProgram(const ProgramDescription& description);
     void setProgram(Program* program);
 
-    Extensions& extensions() { return mExtensions; }
+    const Extensions& extensions() const { return mExtensions; }
     Program& program() { return *mProgram; }
     PixelBufferState& pixelBufferState() { return *mPixelBufferState; }
     TextureState& textureState() { return *mTextureState; }
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index c42ff1a..a7d5f60 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -45,7 +45,7 @@
 
 void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
     mAlpha = PaintUtils::getAlphaDirect(paint);
-    mMode = PaintUtils::getXfermodeDirect(paint);
+    mMode = PaintUtils::getBlendModeDirect(paint);
     SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : nullptr;
     SkRefCnt_SafeAssign(mColorFilter, colorFilter);
 }
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 7420112..7335008 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -101,7 +101,7 @@
     bool mBlend;
     SkColorFilter* mColorFilter;
     int mAlpha;
-    SkXfermode::Mode mMode;
+    SkBlendMode mMode;
     sp<GLConsumer> mSurfaceTexture;
     SkMatrix* mTransform;
     bool mNeedsGLContextAttach;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index ca9e2bd..6e7d11f 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -19,10 +19,12 @@
 
 #include <utils/Trace.h>
 
+#include "DamageAccumulator.h"
 #include "Debug.h"
 #include "DisplayList.h"
 #include "RecordedOp.h"
 #include "RenderNode.h"
+#include "VectorDrawable.h"
 
 namespace android {
 namespace uirenderer {
@@ -86,5 +88,46 @@
     return index;
 }
 
+void DisplayList::syncContents() {
+    for (auto& iter : functors) {
+        (*iter.functor)(DrawGlInfo::kModeSync, nullptr);
+    }
+    for (auto& vectorDrawable : vectorDrawables) {
+        vectorDrawable->syncProperties();
+    }
+}
+
+void DisplayList::updateChildren(std::function<void(RenderNode*)> updateFn) {
+    for (auto&& child : children) {
+        updateFn(child->renderNode);
+    }
+}
+
+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);
+    }
+    for (auto&& op : children) {
+        RenderNode* childNode = op->renderNode;
+        info.damageAccumulator->pushTransform(&op->localMatrix);
+        bool childFunctorsNeedLayer = functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip;
+        childFn(childNode, info, childFunctorsNeedLayer);
+        info.damageAccumulator->popTransform();
+    }
+
+    bool isDirty = false;
+    for (auto& vectorDrawable : vectorDrawables) {
+        // If any vector drawable in the display list needs update, damage the node.
+        if (vectorDrawable->isDirty()) {
+            isDirty = true;
+        }
+        vectorDrawable->setPropertyChangeWillBeConsumed(true);
+    }
+    return isDirty;
+}
+
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index c5d8767..06b0891 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <SkCamera.h>
+#include <SkDrawable.h>
 #include <SkMatrix.h>
 
 #include <private/hwui/DrawGlInfo.h>
@@ -36,6 +37,7 @@
 #include "GlFunctorLifecycleListener.h"
 #include "Matrix.h"
 #include "RenderProperties.h"
+#include "TreeInfo.h"
 
 #include <vector>
 
@@ -89,7 +91,7 @@
     };
 
     DisplayList();
-    ~DisplayList();
+    virtual ~DisplayList();
 
     // index of DisplayListOp restore, after which projected descendants should be drawn
     int projectionReceiveIndex;
@@ -100,8 +102,6 @@
     const LsaVector<NodeOpType*>& getChildren() const { return children; }
 
     const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; }
-    const LsaVector<FunctorContainer>& getFunctors() const { return functors; }
-    const LsaVector<VectorDrawableRoot*>& getVectorDrawables() const { return vectorDrawables; }
 
     size_t addChild(NodeOpType* childOp);
 
@@ -113,15 +113,26 @@
     size_t getUsedSize() {
         return allocator.usedSize();
     }
-    bool isEmpty() {
-        return ops.empty();
+
+    virtual bool isEmpty() const { return ops.empty(); }
+    virtual bool hasFunctor() const { return !functors.empty(); }
+    virtual bool hasVectorDrawables() const { return !vectorDrawables.empty(); }
+    virtual bool isSkiaDL() const { return false; }
+    virtual bool reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) {
+        return false;
     }
 
-private:
+    virtual void syncContents();
+    virtual void updateChildren(std::function<void(RenderNode*)> updateFn);
+    virtual bool prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
+            std::function<void(RenderNode*, TreeInfo&, bool)> childFn);
+
+protected:
     // allocator into which all ops and LsaVector arrays allocated
     LinearAllocator allocator;
     LinearStdAllocator<void*> stdAllocator;
 
+private:
     LsaVector<Chunk> chunks;
     LsaVector<BaseOpType*> ops;
 
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
deleted file mode 100644
index ec2013e..0000000
--- a/libs/hwui/Dither.cpp
+++ /dev/null
@@ -1,98 +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.
- */
-
-#include "Caches.h"
-#include "Dither.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Lifecycle
-///////////////////////////////////////////////////////////////////////////////
-
-Dither::Dither(Caches& caches)
-        : mCaches(caches)
-        , mInitialized(false)
-        , mDitherTexture(0) {
-}
-
-void Dither::bindDitherTexture() {
-    if (!mInitialized) {
-        glGenTextures(1, &mDitherTexture);
-        mCaches.textureState().bindTexture(mDitherTexture);
-
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-
-        if (mCaches.extensions().hasFloatTextures()) {
-            // We use a R16F texture, let's remap the alpha channel to the
-            // red channel to avoid changing the shader sampling code on GL ES 3.0+
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
-
-            float dither = 1.0f / (255.0f * DITHER_KERNEL_SIZE * DITHER_KERNEL_SIZE);
-            const GLfloat pattern[] = {
-                 0 * dither,  8 * dither,  2 * dither, 10 * dither,
-                12 * dither,  4 * dither, 14 * dither,  6 * dither,
-                 3 * dither, 11 * dither,  1 * dither,  9 * dither,
-                15 * dither,  7 * dither, 13 * dither,  5 * dither
-            };
-
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
-                    GL_RED, GL_FLOAT, &pattern);
-        } else {
-            const uint8_t pattern[] = {
-                 0,  8,  2, 10,
-                12,  4, 14,  6,
-                 3, 11,  1,  9,
-                15,  7, 13,  5
-            };
-
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
-                    GL_ALPHA, GL_UNSIGNED_BYTE, &pattern);
-        }
-
-        mInitialized = true;
-    } else {
-        mCaches.textureState().bindTexture(mDitherTexture);
-    }
-}
-
-void Dither::clear() {
-    if (mInitialized) {
-        mCaches.textureState().deleteTexture(mDitherTexture);
-        mInitialized = false;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Program management
-///////////////////////////////////////////////////////////////////////////////
-
-void Dither::setupProgram(Program& program, GLuint* textureUnit) {
-    GLuint textureSlot = (*textureUnit)++;
-    mCaches.textureState().activateTexture(textureSlot);
-
-    bindDitherTexture();
-
-    glUniform1i(program.getUniform("ditherSampler"), textureSlot);
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/Dither.h b/libs/hwui/Dither.h
deleted file mode 100644
index 6af3e83..0000000
--- a/libs/hwui/Dither.h
+++ /dev/null
@@ -1,56 +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.
- */
-
-#ifndef ANDROID_HWUI_DITHER_H
-#define ANDROID_HWUI_DITHER_H
-
-#include <GLES3/gl3.h>
-
-namespace android {
-namespace uirenderer {
-
-class Caches;
-class Extensions;
-class Program;
-
-// Must be a power of two
-#define DITHER_KERNEL_SIZE 4
-// These must not use the .0f notation as they are used from GLSL
-#define DITHER_KERNEL_SIZE_INV (1.0 / 4.0)
-#define DITHER_KERNEL_SIZE_INV_SQUARE (1.0 / 16.0)
-
-/**
- * Handles dithering for programs.
- */
-class Dither {
-public:
-    explicit Dither(Caches& caches);
-
-    void clear();
-    void setupProgram(Program& program, GLuint* textureUnit);
-
-private:
-    void bindDitherTexture();
-
-    Caches& mCaches;
-    bool mInitialized;
-    GLuint mDitherTexture;
-};
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_DITHER_H
diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp
index 02caaa4..1d67579 100644
--- a/libs/hwui/Extensions.cpp
+++ b/libs/hwui/Extensions.cpp
@@ -22,6 +22,7 @@
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
+
 #include <utils/Log.h>
 
 namespace android {
@@ -45,6 +46,19 @@
     mHas4BitStencil = extensions.has("GL_OES_stencil4");
     mHasUnpackSubImage = extensions.has("GL_EXT_unpack_subimage");
 
+#ifdef ANDROID_ENABLE_LINEAR_BLENDING
+    mHasSRGB = mVersionMajor >= 3 || extensions.has("GL_EXT_sRGB");
+    mHasSRGBWriteControl = extensions.has("GL_EXT_sRGB_write_control");
+
+    // If linear blending is enabled, the device must have (ES3.0 or EXT_sRGB)
+    // and EXT_sRGB_write_control
+    LOG_ALWAYS_FATAL_IF(!mHasSRGB, "Linear blending requires ES 3.0 or EXT_sRGB");
+    LOG_ALWAYS_FATAL_IF(!mHasSRGBWriteControl, "Linear blending requires EXT_sRGB_write_control");
+#else
+    mHasSRGB = false;
+    mHasSRGBWriteControl = false;
+#endif
+
     const char* version = (const char*) glGetString(GL_VERSION);
 
     // Section 6.1.5 of the OpenGL ES specification indicates the GL version
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index 67cc747..2c38507 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -43,6 +43,8 @@
     inline bool hasPixelBufferObjects() const { return mVersionMajor >= 3; }
     inline bool hasOcclusionQueries() const { return mVersionMajor >= 3; }
     inline bool hasFloatTextures() const { return mVersionMajor >= 3; }
+    inline bool hasSRGB() const { return mHasSRGB; }
+    inline bool hasSRGBWriteControl() const { return hasSRGB() && mHasSRGBWriteControl; }
 
     inline int getMajorGlVersion() const { return mVersionMajor; }
     inline int getMinorGlVersion() const { return mVersionMinor; }
@@ -55,6 +57,8 @@
     bool mHas1BitStencil;
     bool mHas4BitStencil;
     bool mHasUnpackSubImage;
+    bool mHasSRGB;
+    bool mHasSRGBWriteControl;
 
     int mVersionMajor;
     int mVersionMinor;
diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h
index 9a39ec2..9df7338 100644
--- a/libs/hwui/FloatColor.h
+++ b/libs/hwui/FloatColor.h
@@ -16,6 +16,7 @@
 #ifndef FLOATCOLOR_H
 #define FLOATCOLOR_H
 
+#include "utils/Color.h"
 #include "utils/Macros.h"
 #include "utils/MathUtils.h"
 
@@ -25,11 +26,25 @@
 namespace uirenderer {
 
 struct FloatColor {
+    // "color" is a gamma-encoded sRGB color
+    // After calling this method, the color is stored as a pre-multiplied linear color
+    // if linear blending is enabled. Otherwise, the color is stored as a pre-multiplied
+    // gamma-encoded sRGB color
     void set(uint32_t color) {
         a = ((color >> 24) & 0xff) / 255.0f;
-        r = a * ((color >> 16) & 0xff) / 255.0f;
-        g = a * ((color >>  8) & 0xff) / 255.0f;
-        b = a * ((color      ) & 0xff) / 255.0f;
+        r = a * EOCF(((color >> 16) & 0xff) / 255.0f);
+        g = a * EOCF(((color >>  8) & 0xff) / 255.0f);
+        b = a * EOCF(((color      ) & 0xff) / 255.0f);
+    }
+
+    // "color" is a gamma-encoded sRGB color
+    // After calling this method, the color is stored as a pre-multiplied linear color
+    // if linear blending is enabled.
+    void setSRGB(uint32_t color) {
+        a = ((color >> 24) & 0xff) / 255.0f;
+        r = a * EOCF_sRGB(((color >> 16) & 0xff) / 255.0f);
+        g = a * EOCF_sRGB(((color >>  8) & 0xff) / 255.0f);
+        b = a * EOCF_sRGB(((color      ) & 0xff) / 255.0f);
     }
 
     bool isNotBlack() {
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 9b60dfc..effc65e 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -60,11 +60,17 @@
     }
     int transformFlags = pureTranslate
             ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
+#ifdef ANDROID_ENABLE_LINEAR_BLENDING
+    bool gammaCorrection = true;
+#else
+    bool gammaCorrection = false;
+#endif
     Glop glop;
     GlopBuilder(renderer->renderState(), renderer->caches(), &glop)
             .setRoundRectClipState(bakedState->roundRectClipState)
             .setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount())
             .setFillTexturePaint(texture.getTexture(), textureFillFlags, paint, bakedState->alpha)
+            .setGammaCorrection(gammaCorrection)
             .setTransform(bakedState->computedState.transform, transformFlags)
             .setModelViewIdentityEmptyBounds()
             .build();
@@ -287,24 +293,23 @@
     // Copy the glyph image, taking the mask format into account
     switch (format) {
         case SkMask::kA8_Format: {
-            uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
             uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX
                     - TEXTURE_BORDER_SIZE;
             // write leading border line
             memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
             // write glyph data
             if (mGammaTable) {
-                for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) {
+                for (uint32_t cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) {
                     row = cacheY * cacheWidth;
                     cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0;
-                    for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
+                    for (uint32_t cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
                         uint8_t tempCol = bitmapBuffer[bY + bX];
                         cacheBuffer[row + cacheX] = mGammaTable[tempCol];
                     }
                     cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0;
                 }
             } else {
-                for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) {
+                for (uint32_t cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) {
                     row = cacheY * cacheWidth;
                     memcpy(&cacheBuffer[row + startX], &bitmapBuffer[bY], glyph.fWidth);
                     cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index e836c20..dd9c40f 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -58,7 +58,7 @@
             const BakedOpState* bakedState,
             const ClipBase* clip,
             float x, float y, bool pureTranslate,
-            int alpha, SkXfermode::Mode mode, const SkPaint* paint)
+            int alpha, SkBlendMode mode, const SkPaint* paint)
         : renderer(renderer)
         , bakedState(bakedState)
         , clip(clip)
@@ -79,7 +79,7 @@
     float y;
     bool pureTranslate;
     int alpha;
-    SkXfermode::Mode mode;
+    SkBlendMode mode;
     const SkPaint* paint;
 };
 
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index be4fdac..f35d605 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -591,7 +591,7 @@
 }
 
 static bool hasMergeableClip(const BakedOpState& state) {
-    return state.computedState.clipState
+    return !state.computedState.clipState
             || state.computedState.clipState->mode == ClipMode::Rectangle;
 }
 
@@ -608,11 +608,10 @@
     // MergingDrawBatch::canMergeWith()
     if (bakedState->computedState.transform.isSimple()
             && bakedState->computedState.transform.positiveScale()
-            && PaintUtils::getXfermodeDirect(op.paint) == SkXfermode::kSrcOver_Mode
+            && PaintUtils::getBlendModeDirect(op.paint) == SkBlendMode::kSrcOver
             && op.bitmap->colorType() != kAlpha_8_SkColorType
             && hasMergeableClip(*bakedState)) {
         mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.bitmap->getGenerationID());
-        // TODO: AssetAtlas in mergeId
         currentLayer().deferMergeableOp(mAllocator, bakedState, OpBatchType::Bitmap, mergeId);
     } else {
         currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
@@ -684,10 +683,9 @@
     if (!bakedState) return; // quick rejected
 
     if (bakedState->computedState.transform.isPureTranslate()
-            && PaintUtils::getXfermodeDirect(op.paint) == SkXfermode::kSrcOver_Mode
+            && PaintUtils::getBlendModeDirect(op.paint) == SkBlendMode::kSrcOver
             && hasMergeableClip(*bakedState)) {
         mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.bitmap->getGenerationID());
-        // TODO: AssetAtlas in mergeId
 
         // Only use the MergedPatch batchId when merged, so Bitmap+Patch don't try to merge together
         currentLayer().deferMergeableOp(mAllocator, bakedState, OpBatchType::MergedPatch, mergeId);
@@ -752,7 +750,7 @@
 
     batchid_t batchId = textBatchId(*(op.paint));
     if (bakedState->computedState.transform.isPureTranslate()
-            && PaintUtils::getXfermodeDirect(op.paint) == SkXfermode::kSrcOver_Mode
+            && PaintUtils::getBlendModeDirect(op.paint) == SkBlendMode::kSrcOver
             && hasMergeableClip(*bakedState)) {
         mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.paint->getColor());
         currentLayer().deferMergeableOp(mAllocator, bakedState, batchId, mergeId);
diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp
index 96cac86..8aff0a2 100644
--- a/libs/hwui/GammaFontRenderer.cpp
+++ b/libs/hwui/GammaFontRenderer.cpp
@@ -24,12 +24,13 @@
 GammaFontRenderer::GammaFontRenderer() {
     INIT_LOGD("Creating lookup gamma font renderer");
 
+#ifndef ANDROID_ENABLE_LINEAR_BLENDING
     // Compute the gamma tables
     const float gamma = 1.0f / Properties::textGamma;
-
     for (uint32_t i = 0; i <= 255; i++) {
         mGammaTable[i] = uint8_t((float)::floor(pow(i / 255.0f, gamma) * 255.0f + 0.5f));
     }
+#endif
 }
 
 void GammaFontRenderer::endPrecaching() {
diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h
index bd27a1a..c9cf69b 100644
--- a/libs/hwui/GammaFontRenderer.h
+++ b/libs/hwui/GammaFontRenderer.h
@@ -18,11 +18,6 @@
 #define ANDROID_HWUI_GAMMA_FONT_RENDERER_H
 
 #include "FontRenderer.h"
-#include "Program.h"
-
-#include <SkPaint.h>
-
-#include <utils/String8.h>
 
 namespace android {
 namespace uirenderer {
@@ -43,7 +38,11 @@
 
     FontRenderer& getFontRenderer() {
         if (!mRenderer) {
-            mRenderer.reset(new FontRenderer(&mGammaTable[0]));
+            const uint8_t* table = nullptr;
+#ifndef ANDROID_ENABLE_LINEAR_BLENDING
+            table = &mGammaTable[0];
+#endif
+            mRenderer.reset(new FontRenderer(table));
         }
         return *mRenderer;
     }
@@ -64,7 +63,9 @@
 
 private:
     std::unique_ptr<FontRenderer> mRenderer;
+#ifndef ANDROID_ENABLE_LINEAR_BLENDING
     uint8_t mGammaTable[256];
+#endif
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 1091736..f14b50a 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -220,19 +220,19 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 void GlopBuilder::setFill(int color, float alphaScale,
-        SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage,
+        SkBlendMode mode, Blend::ModeOrderSwap modeUsage,
         const SkShader* shader, const SkColorFilter* colorFilter) {
-    if (mode != SkXfermode::kClear_Mode) {
-        float alpha = (SkColorGetA(color) / 255.0f) * alphaScale;
+    if (mode != SkBlendMode::kClear) {
         if (!shader) {
-            float colorScale = alpha / 255.0f;
-            mOutGlop->fill.color = {
-                    colorScale * SkColorGetR(color),
-                    colorScale * SkColorGetG(color),
-                    colorScale * SkColorGetB(color),
-                    alpha
-            };
+            FloatColor c;
+            c.set(color);
+            c.r *= alphaScale;
+            c.g *= alphaScale;
+            c.b *= alphaScale;
+            c.a *= alphaScale;
+            mOutGlop->fill.color = c;
         } else {
+            float alpha = (SkColorGetA(color) / 255.0f) * alphaScale;
             mOutGlop->fill.color = { 1, 1, 1, alpha };
         }
     } else {
@@ -246,8 +246,8 @@
             || mOutGlop->roundRectClipState
             || PaintUtils::isBlendedShader(shader)
             || PaintUtils::isBlendedColorFilter(colorFilter)
-            || mode != SkXfermode::kSrcOver_Mode) {
-        if (CC_LIKELY(mode <= SkXfermode::kScreen_Mode)) {
+            || mode != SkBlendMode::kSrcOver) {
+        if (CC_LIKELY(mode <= SkBlendMode::kScreen)) {
             Blend::getFactors(mode, modeUsage,
                     &mOutGlop->blend.src, &mOutGlop->blend.dst);
         } else {
@@ -257,12 +257,12 @@
             // 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 = mode;
+                mDescription.framebufferMode = (SkXfermode::Mode)mode;
                 mDescription.swapSrcDst = (modeUsage == Blend::ModeOrderSwap::Swap);
                 // blending in shader, don't enable
             } else {
                 // unsupported
-                Blend::getFactors(SkXfermode::kSrcOver_Mode, modeUsage,
+                Blend::getFactors(SkBlendMode::kSrcOver, modeUsage,
                         &mOutGlop->blend.src, &mOutGlop->blend.dst);
             }
         }
@@ -271,20 +271,12 @@
 
     if (colorFilter) {
         SkColor color;
-        SkXfermode::Mode mode;
+        SkXfermode::Mode xmode;
         SkScalar srcColorMatrix[20];
-        if (colorFilter->asColorMode(&color, &mode)) {
+        if (colorFilter->asColorMode(&color, &xmode)) {
             mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Blend;
-            mDescription.colorMode = mode;
-
-            const float alpha = SkColorGetA(color) / 255.0f;
-            float colorScale = alpha / 255.0f;
-            mOutGlop->fill.filter.color = {
-                    colorScale * SkColorGetR(color),
-                    colorScale * SkColorGetG(color),
-                    colorScale * SkColorGetB(color),
-                    alpha,
-            };
+            mDescription.colorMode = xmode;
+            mOutGlop->fill.filter.color.set(color);
         } else if (colorFilter->asColorMatrix(srcColorMatrix)) {
             mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Matrix;
 
@@ -297,10 +289,10 @@
             // Skia uses the range [0..255] for the addition vector, but we need
             // the [0..1] range to apply the vector in GLSL
             float* colorVector = mOutGlop->fill.filter.matrix.vector;
-            colorVector[0] = srcColorMatrix[4] / 255.0f;
-            colorVector[1] = srcColorMatrix[9] / 255.0f;
-            colorVector[2] = srcColorMatrix[14] / 255.0f;
-            colorVector[3] = srcColorMatrix[19] / 255.0f;
+            colorVector[0] = EOCF(srcColorMatrix[4]  / 255.0f);
+            colorVector[1] = EOCF(srcColorMatrix[9]  / 255.0f);
+            colorVector[2] = EOCF(srcColorMatrix[14] / 255.0f);
+            colorVector[3] =      srcColorMatrix[19] / 255.0f;  // alpha is linear
         } else {
             LOG_ALWAYS_FATAL("unsupported ColorFilter");
         }
@@ -329,7 +321,7 @@
             shader = nullptr;
         }
         setFill(color, alphaScale,
-                PaintUtils::getXfermode(paint->getXfermode()), Blend::ModeOrderSwap::NoSwap,
+                paint->getBlendMode(), Blend::ModeOrderSwap::NoSwap,
                 shader, paint->getColorFilter());
     } else {
         mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale };
@@ -338,7 +330,7 @@
                 || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
                 || texture.blend
                 || mOutGlop->roundRectClipState) {
-            Blend::getFactors(SkXfermode::kSrcOver_Mode, Blend::ModeOrderSwap::NoSwap,
+            Blend::getFactors(SkBlendMode::kSrcOver, Blend::ModeOrderSwap::NoSwap,
                     &mOutGlop->blend.src, &mOutGlop->blend.dst);
         } else {
             mOutGlop->blend = { GL_ZERO, GL_ZERO };
@@ -368,7 +360,7 @@
     }
 
     setFill(paint.getColor(), alphaScale,
-            PaintUtils::getXfermode(paint.getXfermode()), Blend::ModeOrderSwap::NoSwap,
+            paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
             paint.getShader(), paint.getColorFilter());
     mDescription.useShadowAlphaInterp = shadowInterp;
     mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
@@ -384,7 +376,7 @@
     mOutGlop->fill.texture = { &texture, GL_TEXTURE_2D, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
 
     setFill(paint.getColor(), alphaScale,
-            PaintUtils::getXfermode(paint.getXfermode()), Blend::ModeOrderSwap::NoSwap,
+            paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
             paint.getShader(), paint.getColorFilter());
 
     mDescription.hasAlpha8Texture = true;
@@ -408,7 +400,7 @@
     }
 
     setFill(shadowColor, alphaScale,
-            PaintUtils::getXfermode(paint.getXfermode()), Blend::ModeOrderSwap::NoSwap,
+            paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
             paint.getShader(), paint.getColorFilter());
 
     mDescription.hasAlpha8Texture = true;
@@ -421,7 +413,7 @@
     REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
-    setFill(SK_ColorBLACK, 1.0f, SkXfermode::kSrcOver_Mode, Blend::ModeOrderSwap::NoSwap,
+    setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kSrcOver, Blend::ModeOrderSwap::NoSwap,
             nullptr, nullptr);
     return *this;
 }
@@ -431,13 +423,13 @@
     REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
-    setFill(SK_ColorBLACK, 1.0f, SkXfermode::kClear_Mode, Blend::ModeOrderSwap::NoSwap,
+    setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kClear, Blend::ModeOrderSwap::NoSwap,
             nullptr, nullptr);
     return *this;
 }
 
 GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
-        float alpha, SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage) {
+        float alpha, SkBlendMode mode, Blend::ModeOrderSwap modeUsage) {
     TRIGGER_STAGE(kFillStage);
     REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
@@ -473,7 +465,7 @@
             GL_TEXTURE_EXTERNAL_OES, GL_LINEAR, GL_CLAMP_TO_EDGE,
             &textureTransform };
 
-    setFill(SK_ColorWHITE, 1.0f, SkXfermode::kSrc_Mode, Blend::ModeOrderSwap::NoSwap,
+    setFill(SK_ColorWHITE, 1.0f, SkBlendMode::kSrc, Blend::ModeOrderSwap::NoSwap,
             nullptr, nullptr);
 
     mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
@@ -481,6 +473,13 @@
     return *this;
 }
 
+GlopBuilder& GlopBuilder::setGammaCorrection(bool enabled) {
+    REQUIRE_STAGES(kFillStage);
+
+    mDescription.hasGammaCorrection = enabled;
+    return *this;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Transform
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 1152461..d511ccb 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -70,7 +70,7 @@
     GlopBuilder& setFillBlack();
     GlopBuilder& setFillClear();
     GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
-            float alpha, SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage);
+            float alpha, SkBlendMode mode, Blend::ModeOrderSwap modeUsage);
     GlopBuilder& setFillTextureLayer(Layer& layer, float alpha);
     // TODO: Texture should probably know and own its target.
     // setFillLayer() forces it to GL_TEXTURE which isn't always correct.
@@ -105,12 +105,14 @@
 
     GlopBuilder& setRoundRectClipState(const RoundRectClipState* roundRectClipState);
 
+    GlopBuilder& setGammaCorrection(bool enabled);
+
     void build();
 
     static void dump(const Glop& glop);
 private:
     void setFill(int color, float alphaScale,
-            SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage,
+            SkBlendMode mode, Blend::ModeOrderSwap modeUsage,
             const SkShader* shader, const SkColorFilter* colorFilter);
 
     enum StageFlags {
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index c8f5e94..0972ac1 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -67,7 +67,8 @@
         , mSize(0)
         , mMaxSize(Properties::gradientCacheSize)
         , mUseFloatTexture(extensions.hasFloatTextures())
-        , mHasNpot(extensions.hasNPot()){
+        , mHasNpot(extensions.hasNPot())
+        , mHasSRGB(extensions.hasSRGB()) {
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
 
     mCache.setOnEntryRemovedListener(this);
@@ -176,71 +177,56 @@
 
 size_t GradientCache::bytesPerPixel() const {
     // We use 4 channels (RGBA)
+    return 4 * (mUseFloatTexture ? /* fp16 */ 2 : sizeof(uint8_t));
+}
+
+size_t GradientCache::sourceBytesPerPixel() const {
+    // We use 4 channels (RGBA) and upload from floats (not half floats)
     return 4 * (mUseFloatTexture ? sizeof(float) : sizeof(uint8_t));
 }
 
-void GradientCache::splitToBytes(uint32_t inColor, GradientColor& outColor) const {
-    outColor.r = (inColor >> 16) & 0xff;
-    outColor.g = (inColor >>  8) & 0xff;
-    outColor.b = (inColor >>  0) & 0xff;
-    outColor.a = (inColor >> 24) & 0xff;
-}
-
-void GradientCache::splitToFloats(uint32_t inColor, GradientColor& outColor) const {
-    outColor.r = ((inColor >> 16) & 0xff) / 255.0f;
-    outColor.g = ((inColor >>  8) & 0xff) / 255.0f;
-    outColor.b = ((inColor >>  0) & 0xff) / 255.0f;
-    outColor.a = ((inColor >> 24) & 0xff) / 255.0f;
-}
-
-void GradientCache::mixBytes(GradientColor& start, GradientColor& end, float amount,
-        uint8_t*& dst) const {
+void GradientCache::mixBytes(const FloatColor& start, const FloatColor& end,
+        float amount, uint8_t*& dst) const {
     float oppAmount = 1.0f - amount;
-    const float alpha = start.a * oppAmount + end.a * amount;
-    const float a = alpha / 255.0f;
-
-    *dst++ = uint8_t(a * (start.r * oppAmount + end.r * amount));
-    *dst++ = uint8_t(a * (start.g * oppAmount + end.g * amount));
-    *dst++ = uint8_t(a * (start.b * oppAmount + end.b * amount));
-    *dst++ = uint8_t(alpha);
+    *dst++ = uint8_t(OECF_sRGB(start.r * oppAmount + end.r * amount) * 255.0f);
+    *dst++ = uint8_t(OECF_sRGB(start.g * oppAmount + end.g * amount) * 255.0f);
+    *dst++ = uint8_t(OECF_sRGB(start.b * oppAmount + end.b * amount) * 255.0f);
+    *dst++ = uint8_t(         (start.a * oppAmount + end.a * amount) * 255.0f);
 }
 
-void GradientCache::mixFloats(GradientColor& start, GradientColor& end, float amount,
-        uint8_t*& dst) const {
+void GradientCache::mixFloats(const FloatColor& start, const FloatColor& end,
+        float amount, uint8_t*& dst) const {
     float oppAmount = 1.0f - amount;
-    const float a = start.a * oppAmount + end.a * amount;
-
     float* d = (float*) dst;
-    *d++ = a * (start.r * oppAmount + end.r * amount);
-    *d++ = a * (start.g * oppAmount + end.g * amount);
-    *d++ = a * (start.b * oppAmount + end.b * amount);
-    *d++ = a;
-
+#ifdef ANDROID_ENABLE_LINEAR_BLENDING
+    *d++ = start.r * oppAmount + end.r * amount;
+    *d++ = start.g * oppAmount + end.g * amount;
+    *d++ = start.b * oppAmount + end.b * amount;
+#else
+    *d++ = OECF_sRGB(start.r * oppAmount + end.r * amount);
+    *d++ = OECF_sRGB(start.g * oppAmount + end.g * amount);
+    *d++ = OECF_sRGB(start.b * oppAmount + end.b * amount);
+#endif
+    *d++ = start.a * oppAmount + end.a * amount;
     dst += 4 * sizeof(float);
 }
 
 void GradientCache::generateTexture(uint32_t* colors, float* positions,
         const uint32_t width, const uint32_t height, Texture* texture) {
-    const GLsizei rowBytes = width * bytesPerPixel();
+    const GLsizei rowBytes = width * sourceBytesPerPixel();
     uint8_t pixels[rowBytes * height];
 
-    static ChannelSplitter gSplitters[] = {
-            &android::uirenderer::GradientCache::splitToBytes,
-            &android::uirenderer::GradientCache::splitToFloats,
-    };
-    ChannelSplitter split = gSplitters[mUseFloatTexture];
-
     static ChannelMixer gMixers[] = {
-            &android::uirenderer::GradientCache::mixBytes,
-            &android::uirenderer::GradientCache::mixFloats,
+            &android::uirenderer::GradientCache::mixBytes,  // colors are stored gamma-encoded
+            &android::uirenderer::GradientCache::mixFloats, // colors are stored in linear
     };
     ChannelMixer mix = gMixers[mUseFloatTexture];
 
-    GradientColor start;
-    (this->*split)(colors[0], start);
+    FloatColor start;
+    start.setSRGB(colors[0]);
 
-    GradientColor end;
-    (this->*split)(colors[1], end);
+    FloatColor end;
+    end.setSRGB(colors[1]);
 
     int currentPos = 1;
     float startPos = positions[0];
@@ -255,7 +241,7 @@
 
             currentPos++;
 
-            (this->*split)(colors[currentPos], end);
+            end.setSRGB(colors[currentPos]);
             distance = positions[currentPos] - startPos;
         }
 
@@ -266,10 +252,10 @@
     memcpy(pixels + rowBytes, pixels, rowBytes);
 
     if (mUseFloatTexture) {
-        // We have to use GL_RGBA16F because GL_RGBA32F does not support filtering
         texture->upload(GL_RGBA16F, width, height, GL_RGBA, GL_FLOAT, pixels);
     } else {
-        texture->upload(GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+        GLint internalFormat = mHasSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA;
+        texture->upload(internalFormat, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
     }
 
     texture->setFilter(GL_LINEAR);
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 49be19a..5e35435 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -26,6 +26,8 @@
 #include <utils/LruCache.h>
 #include <utils/Mutex.h>
 
+#include "FloatColor.h"
+
 namespace android {
 namespace uirenderer {
 
@@ -150,25 +152,15 @@
     void getGradientInfo(const uint32_t* colors, const int count, GradientInfo& info);
 
     size_t bytesPerPixel() const;
+    size_t sourceBytesPerPixel() const;
 
-    struct GradientColor {
-        float r;
-        float g;
-        float b;
-        float a;
-    };
-
-    typedef void (GradientCache::*ChannelSplitter)(uint32_t inColor,
-            GradientColor& outColor) const;
-
-    void splitToBytes(uint32_t inColor, GradientColor& outColor) const;
-    void splitToFloats(uint32_t inColor, GradientColor& outColor) const;
-
-    typedef void (GradientCache::*ChannelMixer)(GradientColor& start, GradientColor& end,
+    typedef void (GradientCache::*ChannelMixer)(const FloatColor& start, const FloatColor& end,
             float amount, uint8_t*& dst) const;
 
-    void mixBytes(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
-    void mixFloats(GradientColor& start, GradientColor& end, float amount, uint8_t*& dst) const;
+    void mixBytes(const FloatColor& start, const FloatColor& end,
+            float amount, uint8_t*& dst) const;
+    void mixFloats(const FloatColor& start, const FloatColor& end,
+            float amount, uint8_t*& dst) const;
 
     LruCache<GradientCacheEntry, Texture*> mCache;
 
@@ -178,6 +170,7 @@
     GLint mMaxTextureSize;
     bool mUseFloatTexture;
     bool mHasNpot;
+    bool mHasSRGB;
 
     mutable Mutex mLock;
 }; // class GradientCache
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index c688a96..9874ce2 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -28,7 +28,7 @@
 #include <ui/Region.h>
 
 #include <SkPaint.h>
-#include <SkXfermode.h>
+#include <SkBlendMode.h>
 
 #include "Matrix.h"
 #include "Rect.h"
@@ -75,7 +75,7 @@
     }
 
     void setSize(uint32_t width, uint32_t height) {
-        texture.updateSize(width, height, texture.format());
+        texture.updateSize(width, height, texture.internalFormat(), texture.format());
     }
 
     inline void setBlend(bool blend) {
@@ -98,7 +98,7 @@
         this->alpha = alpha;
     }
 
-    inline void setAlpha(int alpha, SkXfermode::Mode mode) {
+    inline void setAlpha(int alpha, SkBlendMode mode) {
         this->alpha = alpha;
         this->mode = mode;
     }
@@ -107,7 +107,7 @@
         return alpha;
     }
 
-    inline SkXfermode::Mode getMode() const {
+    inline SkBlendMode getMode() const {
         return mode;
     }
 
@@ -208,7 +208,7 @@
     /**
      * Blending mode of the layer.
      */
-    SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
+    SkBlendMode mode = SkBlendMode::kSrcOver;
 
     /**
      * Optional texture coordinates transform.
diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp
index 66413dc..c5d5492 100644
--- a/libs/hwui/LayerBuilder.cpp
+++ b/libs/hwui/LayerBuilder.cpp
@@ -274,7 +274,7 @@
         // One or more unclipped saveLayers have been enqueued, with deferred clears.
         // Flush all of these clears with a single draw
         SkPaint* paint = allocator.create<SkPaint>();
-        paint->setXfermodeMode(SkXfermode::kClear_Mode);
+        paint->setBlendMode(SkBlendMode::kClear);
         SimpleRectsOp* op = allocator.create_trivial<SimpleRectsOp>(bounds,
                 Matrix4::identity(), nullptr, paint,
                 verts, vertCount);
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index a6c281d..52c62cc 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -225,17 +225,15 @@
 
 static const UvMapper sIdentity;
 
-const Patch* PatchCache::get(const AssetAtlas::Entry* entry,
-        const uint32_t bitmapWidth, const uint32_t bitmapHeight,
+const Patch* PatchCache::get( const uint32_t bitmapWidth, const uint32_t bitmapHeight,
         const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) {
 
     const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch);
     const Patch* mesh = mCache.get(description);
 
     if (!mesh) {
-        const UvMapper& mapper = entry ? entry->uvMapper : sIdentity;
         Patch* newMesh = new Patch(bitmapWidth, bitmapHeight,
-                pixelWidth, pixelHeight, mapper, patch);
+                pixelWidth, pixelHeight, sIdentity, patch);
 
         if (newMesh->vertices) {
             setupMesh(newMesh);
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 6e6a730..0624c35 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -22,7 +22,6 @@
 
 #include <androidfw/ResourceTypes.h>
 
-#include "AssetAtlas.h"
 #include "Debug.h"
 #include "utils/Pair.h"
 
@@ -54,8 +53,7 @@
     explicit PatchCache(RenderState& renderState);
     ~PatchCache();
 
-    const Patch* get(const AssetAtlas::Entry* entry,
-            const uint32_t bitmapWidth, const uint32_t bitmapHeight,
+    const Patch* get(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
             const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch);
     void clear();
 
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index eb606cb..d46c46f93 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -17,6 +17,8 @@
 #include <SkBitmap.h>
 #include <SkCanvas.h>
 #include <SkColor.h>
+#include <SkColorFilter.h>
+#include <SkMaskFilter.h>
 #include <SkPaint.h>
 #include <SkPath.h>
 #include <SkPathEffect.h>
@@ -149,8 +151,7 @@
     paint.setColorFilter(nullptr);
     paint.setMaskFilter(nullptr);
     paint.setShader(nullptr);
-    SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
-    SkSafeUnref(paint.setXfermode(mode));
+    paint.setBlendMode(SkBlendMode::kSrc);
 }
 
 static SkBitmap* drawPath(const SkPath* path, const SkPaint* paint, PathTexture* texture,
@@ -182,8 +183,7 @@
 PathCache::PathCache()
         : mCache(LruCache<PathDescription, PathTexture*>::kUnlimitedCapacity)
         , mSize(0)
-        , mMaxSize(Properties::pathCacheSize)
-        , mTexNum(0) {
+        , mMaxSize(Properties::pathCacheSize) {
     mCache.setOnEntryRemovedListener(this);
 
     GLint maxTextureSize;
@@ -239,7 +239,6 @@
                         "the cache in an inconsistent state", size);
             }
             mSize -= size;
-            mTexNum--;
         }
 
         PATH_LOGD("PathCache::delete name, size, mSize = %d, %d, %d",
@@ -264,7 +263,14 @@
 }
 
 void PathCache::trim() {
-    while (mSize > mMaxSize || mTexNum > DEFAULT_PATH_TEXTURE_CAP) {
+    // 25 is just an arbitrary lower bound to ensure we aren't in weird edge cases
+    // of things like a cap of 0 or 1 as that's going to break things.
+    // It does not represent a reasonable minimum value
+    static_assert(DEFAULT_PATH_TEXTURE_CAP > 25, "Path cache texture cap is too small");
+
+    while (mSize > mMaxSize || mCache.size() > DEFAULT_PATH_TEXTURE_CAP) {
+        LOG_ALWAYS_FATAL_IF(!mCache.size(), "Inconsistent mSize! Ran out of items to remove!"
+                " mSize = %u, mMaxSize = %u", mSize, mMaxSize);
         mCache.removeOldest();
     }
 }
@@ -312,7 +318,6 @@
     ATRACE_NAME("Upload Path Texture");
     texture->upload(bitmap);
     texture->setFilter(GL_LINEAR);
-    mTexNum++;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index b45a2c5..18bcc56 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -281,12 +281,6 @@
 
     bool mDebugEnabled;
 
-    /**
-     * Driver allocated 4k/8k/16k memory for small path cache,
-     * limit the number of PathTexture in case occupy too much memory in hardware.
-     */
-    uint32_t mTexNum;
-
     sp<PathProcessor> mProcessor;
 
     std::vector<uint32_t> mGarbage;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index e5200a5..f5beb62 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -85,6 +85,8 @@
 #define PROGRAM_HAS_DEBUG_HIGHLIGHT 42
 #define PROGRAM_HAS_ROUND_RECT_CLIP 43
 
+#define PROGRAM_HAS_GAMMA_CORRECTION 44
+
 ///////////////////////////////////////////////////////////////////////////////
 // Types
 ///////////////////////////////////////////////////////////////////////////////
@@ -158,6 +160,8 @@
     bool hasDebugHighlight;
     bool hasRoundRectClip;
 
+    bool hasGammaCorrection;
+
     /**
      * Resets this description. All fields are reset back to the default
      * values they hold after building a new instance.
@@ -196,6 +200,8 @@
 
         hasDebugHighlight = false;
         hasRoundRectClip = false;
+
+        hasGammaCorrection = false;
     }
 
     /**
@@ -262,6 +268,7 @@
         if (hasColors) key |= programid(0x1) << PROGRAM_HAS_COLORS;
         if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT;
         if (hasRoundRectClip) key |= programid(0x1) << PROGRAM_HAS_ROUND_RECT_CLIP;
+        if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
         return key;
     }
 
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 59225e1..4ef6b85 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -17,8 +17,8 @@
 #include <utils/String8.h>
 
 #include "Caches.h"
-#include "Dither.h"
 #include "ProgramCache.h"
+#include "Properties.h"
 
 namespace android {
 namespace uirenderer {
@@ -69,22 +69,16 @@
         "varying highp vec2 outBitmapTexCoords;\n";
 const char* gVS_Header_Varyings_HasGradient[6] = {
         // Linear
-        "varying highp vec2 linear;\n"
-        "varying vec2 ditherTexCoords;\n",
-        "varying float linear;\n"
-        "varying vec2 ditherTexCoords;\n",
+        "varying highp vec2 linear;\n",
+        "varying float linear;\n",
 
         // Circular
-        "varying highp vec2 circular;\n"
-        "varying vec2 ditherTexCoords;\n",
-        "varying highp vec2 circular;\n"
-        "varying vec2 ditherTexCoords;\n",
+        "varying highp vec2 circular;\n",
+        "varying highp vec2 circular;\n",
 
         // Sweep
-        "varying highp vec2 sweep;\n"
-        "varying vec2 ditherTexCoords;\n",
-        "varying highp vec2 sweep;\n"
-        "varying vec2 ditherTexCoords;\n",
+        "varying highp vec2 sweep;\n",
+        "varying highp vec2 sweep;\n",
 };
 const char* gVS_Header_Varyings_HasRoundRectClip =
         "varying highp vec2 roundRectPos;\n";
@@ -98,22 +92,16 @@
         "    outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n";
 const char* gVS_Main_OutGradient[6] = {
         // Linear
-        "    linear = vec2((screenSpace * position).x, 0.5);\n"
-        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
-        "    linear = (screenSpace * position).x;\n"
-        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
+        "    linear = vec2((screenSpace * position).x, 0.5);\n",
+        "    linear = (screenSpace * position).x;\n",
 
         // Circular
-        "    circular = (screenSpace * position).xy;\n"
-        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
-        "    circular = (screenSpace * position).xy;\n"
-        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
+        "    circular = (screenSpace * position).xy;\n",
+        "    circular = (screenSpace * position).xy;\n",
 
         // Sweep
+        "    sweep = (screenSpace * position).xy;\n",
         "    sweep = (screenSpace * position).xy;\n"
-        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
-        "    sweep = (screenSpace * position).xy;\n"
-        "    ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n",
 };
 const char* gVS_Main_OutBitmapTexCoords =
         "    outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n";
@@ -147,12 +135,11 @@
         "uniform sampler2D baseSampler;\n";
 const char* gFS_Uniforms_ExternalTextureSampler =
         "uniform samplerExternalOES baseSampler;\n";
-const char* gFS_Uniforms_Dither =
-        "uniform sampler2D ditherSampler;";
 const char* gFS_Uniforms_GradientSampler[2] = {
-        "%s\n"
+        "uniform vec2 screenSize;\n"
         "uniform sampler2D gradientSampler;\n",
-        "%s\n"
+
+        "uniform vec2 screenSize;\n"
         "uniform vec4 startColor;\n"
         "uniform vec4 endColor;\n"
 };
@@ -172,18 +159,57 @@
         "uniform vec4 roundRectInnerRectLTRB;\n"
         "uniform float roundRectRadius;\n";
 
+// Dithering must be done in the quantization space
+// When we are writing to an sRGB framebuffer, we must do the following:
+//     EOCF(OECF(color) + dither)
+// We approximate the transfer functions with gamma 2.0 to avoid branches and pow()
+// The dithering pattern is generated with a triangle noise generator in the range [-0.0,1.0]
+// TODO: Handle linear fp16 render targets
+const char* gFS_Gradient_Functions =
+        "\nfloat triangleNoise(const highp vec2 n) {\n"
+        "    highp vec2 p = fract(n * vec2(5.3987, 5.4421));\n"
+        "    p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));\n"
+        "    highp float xy = p.x * p.y;\n"
+        "    return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;\n"
+        "}\n";
+const char* gFS_Gradient_Preamble[2] = {
+        // Linear framebuffer
+        "\nvec4 dither(const vec4 color) {\n"
+        "    return vec4(color.rgb + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0), color.a);"
+        "}\n"
+        "\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
+        "    return pow(mix(a, b, v), vec4(vec3(1.0 / 2.2), 1.0));"
+        "}\n",
+        // sRGB framebuffer
+        "\nvec4 dither(const vec4 color) {\n"
+        "    vec3 dithered = sqrt(color.rgb) + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);\n"
+        "    return vec4(dithered * dithered, color.a);\n"
+        "}\n"
+        "\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
+        "    return mix(a, b, v);"
+        "}\n"
+};
+
+// Uses luminance coefficients from Rec.709 to choose the appropriate gamma
+// The gamma() function assumes that bright text will be displayed on a dark
+// background and that dark text will be displayed on bright background
+// The gamma coefficient is chosen to thicken or thin the text accordingly
+// The dot product used to compute the luminance could be approximated with
+// a simple max(color.r, color.g, color.b)
+const char* gFS_Gamma_Preamble =
+        "\n#define GAMMA (%.2f)\n"
+        "#define GAMMA_INV (%.2f)\n"
+        "\nfloat gamma(float a, const vec3 color) {\n"
+        "    float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));\n"
+        "    return pow(a, luminance < 0.5 ? GAMMA_INV : GAMMA);\n"
+        "}\n";
+
 const char* gFS_Main =
         "\nvoid main(void) {\n"
-        "    lowp vec4 fragColor;\n";
+        "    vec4 fragColor;\n";
 
-const char* gFS_Main_Dither[2] = {
-        // ES 2.0
-        "texture2D(ditherSampler, ditherTexCoords).a * " STR(DITHER_KERNEL_SIZE_INV_SQUARE),
-        // ES 3.0
-        "texture2D(ditherSampler, ditherTexCoords).a"
-};
-const char* gFS_Main_AddDitherToGradient =
-        "    gradientColor += %s;\n";
+const char* gFS_Main_AddDither =
+        "    fragColor = dither(fragColor);\n";
 
 // Fast cases
 const char* gFS_Fast_SingleColor =
@@ -202,24 +228,32 @@
         "\nvoid main(void) {\n"
         "    gl_FragColor = texture2D(baseSampler, outTexCoords);\n"
         "}\n\n";
+const char* gFS_Fast_SingleA8Texture_ApplyGamma =
+        "\nvoid main(void) {\n"
+        "    gl_FragColor = vec4(0.0, 0.0, 0.0, pow(texture2D(baseSampler, outTexCoords).a, GAMMA));\n"
+        "}\n\n";
 const char* gFS_Fast_SingleModulateA8Texture =
         "\nvoid main(void) {\n"
         "    gl_FragColor = color * texture2D(baseSampler, outTexCoords).a;\n"
         "}\n\n";
+const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma =
+        "\nvoid main(void) {\n"
+        "    gl_FragColor = color * gamma(texture2D(baseSampler, outTexCoords).a, color.rgb);\n"
+        "}\n\n";
 const char* gFS_Fast_SingleGradient[2] = {
         "\nvoid main(void) {\n"
-        "    gl_FragColor = %s + texture2D(gradientSampler, linear);\n"
+        "    gl_FragColor = dither(texture2D(gradientSampler, linear));\n"
         "}\n\n",
         "\nvoid main(void) {\n"
-        "    gl_FragColor = %s + mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+        "    gl_FragColor = dither(gammaMix(startColor, endColor, clamp(linear, 0.0, 1.0)));\n"
         "}\n\n",
 };
 const char* gFS_Fast_SingleModulateGradient[2] = {
         "\nvoid main(void) {\n"
-        "    gl_FragColor = %s + color.a * texture2D(gradientSampler, linear);\n"
+        "    gl_FragColor = dither(color.a * texture2D(gradientSampler, linear));\n"
         "}\n\n",
         "\nvoid main(void) {\n"
-        "    gl_FragColor = %s + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n"
+        "    gl_FragColor = dither(color.a * gammaMix(startColor, endColor, clamp(linear, 0.0, 1.0)));\n"
         "}\n\n"
 };
 
@@ -239,29 +273,31 @@
         // Modulate
         "    fragColor = color * texture2D(baseSampler, outTexCoords);\n"
 };
-const char* gFS_Main_FetchA8Texture[2] = {
+const char* gFS_Main_FetchA8Texture[4] = {
         // Don't modulate
         "    fragColor = texture2D(baseSampler, outTexCoords);\n",
+        "    fragColor = texture2D(baseSampler, outTexCoords);\n",
         // Modulate
         "    fragColor = color * texture2D(baseSampler, outTexCoords).a;\n",
+        "    fragColor = color * gamma(texture2D(baseSampler, outTexCoords).a, color.rgb);\n",
 };
 const char* gFS_Main_FetchGradient[6] = {
         // Linear
         "    vec4 gradientColor = texture2D(gradientSampler, linear);\n",
 
-        "    vec4 gradientColor = mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
+        "    vec4 gradientColor = gammaMix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
 
         // Circular
         "    vec4 gradientColor = texture2D(gradientSampler, vec2(length(circular), 0.5));\n",
 
-        "    vec4 gradientColor = mix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
+        "    vec4 gradientColor = gammaMix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
 
         // Sweep
         "    highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
         "    vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n",
 
         "    highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
-        "    vec4 gradientColor = mix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
+        "    vec4 gradientColor = gammaMix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
 };
 const char* gFS_Main_FetchBitmap =
         "    vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n";
@@ -271,29 +307,38 @@
         "    fragColor = blendShaders(gradientColor, bitmapColor)";
 const char* gFS_Main_BlendShadersGB =
         "    fragColor = blendShaders(bitmapColor, gradientColor)";
-const char* gFS_Main_BlendShaders_Modulate[3] = {
+const char* gFS_Main_BlendShaders_Modulate[6] = {
         // Don't modulate
         ";\n",
+        ";\n",
         // Modulate
         " * color.a;\n",
+        " * color.a;\n",
         // Modulate with alpha 8 texture
         " * texture2D(baseSampler, outTexCoords).a;\n",
+        " * gamma(texture2D(baseSampler, outTexCoords).a, color.rgb);\n",
 };
-const char* gFS_Main_GradientShader_Modulate[3] = {
+const char* gFS_Main_GradientShader_Modulate[6] = {
         // Don't modulate
         "    fragColor = gradientColor;\n",
+        "    fragColor = gradientColor;\n",
         // Modulate
         "    fragColor = gradientColor * color.a;\n",
+        "    fragColor = gradientColor * color.a;\n",
         // Modulate with alpha 8 texture
         "    fragColor = gradientColor * texture2D(baseSampler, outTexCoords).a;\n",
+        "    fragColor = gradientColor * gamma(texture2D(baseSampler, outTexCoords).a, gradientColor.rgb);\n",
     };
-const char* gFS_Main_BitmapShader_Modulate[3] = {
+const char* gFS_Main_BitmapShader_Modulate[6] = {
         // Don't modulate
         "    fragColor = bitmapColor;\n",
+        "    fragColor = bitmapColor;\n",
         // Modulate
         "    fragColor = bitmapColor * color.a;\n",
+        "    fragColor = bitmapColor * color.a;\n",
         // Modulate with alpha 8 texture
         "    fragColor = bitmapColor * texture2D(baseSampler, outTexCoords).a;\n",
+        "    fragColor = bitmapColor * gamma(texture2D(baseSampler, outTexCoords).a, bitmapColor.rgb);\n",
     };
 const char* gFS_Main_FragColor =
         "    gl_FragColor = fragColor;\n";
@@ -385,7 +430,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 ProgramCache::ProgramCache(Extensions& extensions)
-        : mHasES3(extensions.getMajorGlVersion() >= 3) {
+        : mHasES3(extensions.getMajorGlVersion() >= 3)
+        , mHasSRGB(extensions.hasSRGB()) {
 }
 
 ProgramCache::~ProgramCache() {
@@ -518,6 +564,7 @@
 static bool shaderOp(const ProgramDescription& description, String8& shader,
         const int modulateOp, const char** snippets) {
     int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp;
+    op = op * 2 + description.hasGammaCorrection;
     shader.append(snippets[op]);
     return description.hasAlpha8Texture;
 }
@@ -570,13 +617,16 @@
         shader.append(gFS_Uniforms_ExternalTextureSampler);
     }
     if (description.hasGradient) {
-        shader.appendFormat(gFS_Uniforms_GradientSampler[description.isSimpleGradient],
-                gFS_Uniforms_Dither);
+        shader.append(gFS_Uniforms_GradientSampler[description.isSimpleGradient]);
     }
     if (description.hasRoundRectClip) {
         shader.append(gFS_Uniforms_HasRoundRectClip);
     }
 
+    if (description.hasGammaCorrection) {
+        shader.appendFormat(gFS_Gamma_Preamble, Properties::textGamma, 1.0f / Properties::textGamma);
+    }
+
     // Optimization for common cases
     if (!description.hasVertexAlpha
             && !blendFramebuffer
@@ -607,18 +657,26 @@
             fast = true;
         } else if (singleA8Texture) {
             if (!description.modulate) {
-                shader.append(gFS_Fast_SingleA8Texture);
+                if (description.hasGammaCorrection) {
+                    shader.append(gFS_Fast_SingleA8Texture_ApplyGamma);
+                } else {
+                    shader.append(gFS_Fast_SingleA8Texture);
+                }
             } else {
-                shader.append(gFS_Fast_SingleModulateA8Texture);
+                if (description.hasGammaCorrection) {
+                    shader.append(gFS_Fast_SingleModulateA8Texture_ApplyGamma);
+                } else {
+                    shader.append(gFS_Fast_SingleModulateA8Texture);
+                }
             }
             fast = true;
         } else if (singleGradient) {
+            shader.append(gFS_Gradient_Functions);
+            shader.append(gFS_Gradient_Preamble[mHasSRGB]);
             if (!description.modulate) {
-                shader.appendFormat(gFS_Fast_SingleGradient[description.isSimpleGradient],
-                        gFS_Main_Dither[mHasES3]);
+                shader.append(gFS_Fast_SingleGradient[description.isSimpleGradient]);
             } else {
-                shader.appendFormat(gFS_Fast_SingleModulateGradient[description.isSimpleGradient],
-                        gFS_Main_Dither[mHasES3]);
+                shader.append(gFS_Fast_SingleModulateGradient[description.isSimpleGradient]);
             }
             fast = true;
         }
@@ -652,6 +710,10 @@
     if (description.isBitmapNpot) {
         generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT);
     }
+    if (description.hasGradient) {
+        shader.append(gFS_Gradient_Functions);
+        shader.append(gFS_Gradient_Preamble[mHasSRGB]);
+    }
 
     // Begin the shader
     shader.append(gFS_Main); {
@@ -659,7 +721,8 @@
         if (description.hasTexture || description.hasExternalTexture) {
             if (description.hasAlpha8Texture) {
                 if (!description.hasGradient && !description.hasBitmap) {
-                    shader.append(gFS_Main_FetchA8Texture[modulateOp]);
+                    shader.append(
+                            gFS_Main_FetchA8Texture[modulateOp * 2 + description.hasGammaCorrection]);
                 }
             } else {
                 shader.append(gFS_Main_FetchTexture[modulateOp]);
@@ -671,7 +734,6 @@
         }
         if (description.hasGradient) {
             shader.append(gFS_Main_FetchGradient[gradientIndex(description)]);
-            shader.appendFormat(gFS_Main_AddDitherToGradient, gFS_Main_Dither[mHasES3]);
         }
         if (description.hasBitmap) {
             if (!description.isBitmapNpot) {
@@ -715,6 +777,10 @@
             }
         }
 
+        if (description.hasGradient) {
+            shader.append(gFS_Main_AddDither);
+        }
+
         // Output the fragment
         if (!blendFramebuffer) {
             shader.append(gFS_Main_FragColor);
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 9ac885b..292ecdf 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -59,6 +59,7 @@
     std::map<programid, std::unique_ptr<Program>> mCache;
 
     const bool mHasES3;
+    const bool mHasSRGB;
 }; // class ProgramCache
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 93b2e15..848161e 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -214,7 +214,7 @@
     property_get(PROPERTY_DEFAULT_RENDERER, prop, "opengl");
     if (!strcmp(prop, "skiagl") ) {
         sRenderPipelineType = RenderPipelineType::SkiaGL;
-    } else if (!strcmp(prop, "skiavulkan") ) {
+    } else if (!strcmp(prop, "skiavk") ) {
         sRenderPipelineType = RenderPipelineType::SkiaVulkan;
     } else { //"opengl"
         sRenderPipelineType = RenderPipelineType::OpenGL;
@@ -222,5 +222,11 @@
     return sRenderPipelineType;
 }
 
+bool Properties::isSkiaEnabled() {
+    auto renderType = getRenderPipelineType();
+    return RenderPipelineType::SkiaGL == renderType
+            || RenderPipelineType::SkiaVulkan == renderType;
+}
+
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index eedc9e7..b4a3118 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -203,7 +203,7 @@
 #define PROPERTY_TEXT_LARGE_CACHE_WIDTH "ro.hwui.text_large_cache_width"
 #define PROPERTY_TEXT_LARGE_CACHE_HEIGHT "ro.hwui.text_large_cache_height"
 
-// Gamma (>= 1.0, <= 10.0)
+// Gamma (>= 1.0, <= 3.0)
 #define PROPERTY_TEXT_GAMMA "hwui.text_gamma"
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -222,7 +222,7 @@
 
 #define DEFAULT_TEXTURE_CACHE_FLUSH_RATE 0.6f
 
-#define DEFAULT_TEXT_GAMMA 1.4f
+#define DEFAULT_TEXT_GAMMA 1.45f // Match design tools
 
 // cap to 256 to limite paths in the path cache
 #define DEFAULT_PATH_TEXTURE_CAP 256
@@ -308,6 +308,7 @@
 
     static ProfileType getProfileType();
     static RenderPipelineType getRenderPipelineType();
+    static bool isSkiaEnabled();
 
     // Should be used only by test apps
     static bool waitForGpuCompletion;
diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp
index 38fb70a..e3258e3 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.cpp
+++ b/libs/hwui/PropertyValuesAnimatorSet.cpp
@@ -46,8 +46,17 @@
 
 void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) {
     if (mOneShotListener.get()) {
-        mOneShotListener->onAnimationFinished(animator);
+        sp<AnimationListener> listener = std::move(mOneShotListener);
+        // Set the listener to nullptr before the onAnimationFinished callback, rather than after,
+        // for two reasons:
+        // 1) We need to prevent changes to mOneShotListener during the onAnimationFinished
+        // callback (specifically in AnimationListenerBridge::onAnimationFinished(...) from
+        // triggering dtor of the bridge and potentially unsafely re-entering
+        // AnimationListenerBridge::onAnimationFinished(...).
+        // 2) It's possible that there are changes to the listener during the callback, therefore
+        // we need to reset the listener before the callback rather than afterwards.
         mOneShotListener = nullptr;
+        listener->onAnimationFinished(animator);
     }
 }
 
diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp
index 6ba0ab5..2a03e6a 100644
--- a/libs/hwui/PropertyValuesHolder.cpp
+++ b/libs/hwui/PropertyValuesHolder.cpp
@@ -16,6 +16,7 @@
 
 #include "PropertyValuesHolder.h"
 
+#include "utils/Color.h"
 #include "utils/VectorDrawableUtils.h"
 
 #include <utils/Log.h>
@@ -25,18 +26,26 @@
 
 using namespace VectorDrawable;
 
-inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) {
-    return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction);
+inline constexpr float lerp(float fromValue, float toValue, float fraction) {
+    return float (fromValue * (1 - fraction) + toValue * fraction);
+}
+
+inline constexpr float linearize(U8CPU component) {
+    return EOCF_sRGB(component / 255.0f);
 }
 
 // TODO: Add a test for this
 void ColorEvaluator::evaluate(SkColor* outColor,
         const SkColor& fromColor, const SkColor& toColor, float fraction) const {
-    U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction);
-    U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction);
-    U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction);
-    U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction);
-    *outColor = SkColorSetARGB(alpha, red, green, blue);
+    float a = lerp(SkColorGetA(fromColor) / 255.0f, SkColorGetA(toColor) / 255.0f, fraction);
+    float r = lerp(linearize(SkColorGetR(fromColor)), linearize(SkColorGetR(toColor)), fraction);
+    float g = lerp(linearize(SkColorGetG(fromColor)), linearize(SkColorGetG(toColor)), fraction);
+    float b = lerp(linearize(SkColorGetB(fromColor)), linearize(SkColorGetB(toColor)), fraction);
+    *outColor = SkColorSetARGB(
+            (U8CPU) roundf(a * 255.0f),
+            (U8CPU) roundf(OECF_sRGB(r) * 255.0f),
+            (U8CPU) roundf(OECF_sRGB(g) * 255.0f),
+            (U8CPU) roundf(OECF_sRGB(b) * 255.0f));
 }
 
 void PathEvaluator::evaluate(PathData* out,
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index ddca122..22c6dfc 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -197,7 +197,7 @@
 
     Texture sourceTexture(caches);
     sourceTexture.wrap(sourceTexId,
-            sourceBuffer->getWidth(), sourceBuffer->getHeight(), 0 /* total lie */);
+            sourceBuffer->getWidth(), sourceBuffer->getHeight(), 0, 0 /* total lie */);
 
     CopyResult copyResult = copyTextureInto(caches, renderThread.renderState(),
             sourceTexture, texTransform, srcRect, bitmap);
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index a65c22c..3b1caa5 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -26,7 +26,6 @@
 #include "Vector.h"
 
 #include <androidfw/ResourceTypes.h>
-#include <SkXfermode.h>
 
 class SkBitmap;
 class SkPaint;
@@ -216,7 +215,6 @@
             : SUPER(BitmapOp)
             , bitmap(bitmap) {}
     const SkBitmap* bitmap;
-    // TODO: asset atlas/texture id lookup?
 };
 
 struct BitmapMeshOp : RecordedOp {
@@ -258,12 +256,12 @@
 
 struct ColorOp : RecordedOp {
     // Note: unbounded op that will fillclip, so no bounds/matrix needed
-    ColorOp(const ClipBase* localClip, int color, SkXfermode::Mode mode)
+    ColorOp(const ClipBase* localClip, int color, SkBlendMode mode)
             : RecordedOp(RecordedOpId::ColorOp, Rect(), Matrix4::identity(), localClip, nullptr)
             , color(color)
             , mode(mode) {}
     const int color;
-    const SkXfermode::Mode mode;
+    const SkBlendMode mode;
 };
 
 struct FunctorOp : RecordedOp {
@@ -505,7 +503,7 @@
             : SUPER_PAINTLESS(LayerOp)
             , layerHandle(layerHandle)
             , alpha(paint ? paint->getAlpha() / 255.0f : 1.0f)
-            , mode(PaintUtils::getXfermodeDirect(paint))
+            , mode(PaintUtils::getBlendModeDirect(paint))
             , colorFilter(paint ? paint->getColorFilter() : nullptr) {}
 
     explicit LayerOp(RenderNode& node)
@@ -519,7 +517,7 @@
     // constructed until after this operation is constructed.
     OffscreenBuffer** layerHandle;
     const float alpha;
-    const SkXfermode::Mode mode;
+    const SkBlendMode mode;
 
     // pointer to object owned by either LayerProperties, or a recorded Paint object in a
     // BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used.
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 27e6a12..09d5252 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -247,7 +247,7 @@
 // ----------------------------------------------------------------------------
 // android/graphics/Canvas draw operations
 // ----------------------------------------------------------------------------
-void RecordingCanvas::drawColor(int color, SkXfermode::Mode mode) {
+void RecordingCanvas::drawColor(int color, SkBlendMode mode) {
     addOp(alloc().create_trivial<ColorOp>(
             getRecordedClip(),
             color,
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index efa6b91..4483e1b 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -144,7 +144,7 @@
 // ----------------------------------------------------------------------------
 // android/graphics/Canvas draw operations
 // ----------------------------------------------------------------------------
-    virtual void drawColor(int color, SkXfermode::Mode mode) override;
+    virtual void drawColor(int color, SkBlendMode mode) override;
     virtual void drawPaint(const SkPaint& paint) override;
 
     // Geometry
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 8c36ab5..a03ded6 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -51,7 +51,7 @@
 RenderNode::~RenderNode() {
     deleteDisplayList(nullptr);
     delete mStagingDisplayList;
-    LOG_ALWAYS_FATAL_IF(mLayer, "layer missed detachment!");
+    LOG_ALWAYS_FATAL_IF(hasLayer(), "layer missed detachment!");
 }
 
 void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* observer) {
@@ -81,7 +81,7 @@
             << (properties().hasShadow() ? ", casting shadow" : "")
             << (isRenderable() ? "" : ", empty")
             << (properties().getProjectBackwards() ? ", projected" : "")
-            << (mLayer != nullptr ? ", on HW Layer" : "")
+            << (hasLayer() ? ", on HW Layer" : "")
             << ")" << std::endl;
 
     properties().debugOutputProperties(output, level + 1);
@@ -237,7 +237,7 @@
             || CC_UNLIKELY(!isRenderable())
             || CC_UNLIKELY(properties().getWidth() == 0)
             || CC_UNLIKELY(properties().getHeight() == 0)) {
-        if (CC_UNLIKELY(mLayer)) {
+        if (CC_UNLIKELY(hasLayer())) {
             renderthread::CanvasContext::destroyLayer(this);
         }
         return;
@@ -247,7 +247,7 @@
         damageSelf(info);
     }
 
-    if (!mLayer) {
+    if (!hasLayer()) {
         Caches::getInstance().dumpMemoryUsage();
         if (info.errorHandler) {
             std::ostringstream err;
@@ -295,9 +295,9 @@
 
     bool willHaveFunctor = false;
     if (info.mode == TreeInfo::MODE_FULL && mStagingDisplayList) {
-        willHaveFunctor = !mStagingDisplayList->getFunctors().empty();
+        willHaveFunctor = mStagingDisplayList->hasFunctor();
     } else if (mDisplayList) {
-        willHaveFunctor = !mDisplayList->getFunctors().empty();
+        willHaveFunctor = mDisplayList->hasFunctor();
     }
     bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence(
             willHaveFunctor, functorsNeedLayer);
@@ -310,15 +310,15 @@
     if (info.mode == TreeInfo::MODE_FULL) {
         pushStagingDisplayListChanges(info);
     }
-    prepareSubTree(info, childFunctorsNeedLayer, mDisplayList);
 
     if (mDisplayList) {
-        for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) {
-            // If any vector drawable in the display list needs update, damage the node.
-            if (vectorDrawable->isDirty()) {
-                damageSelf(info);
-            }
-            vectorDrawable->setPropertyChangeWillBeConsumed(true);
+        info.out.hasFunctors |= mDisplayList->hasFunctor();
+        bool isDirty = mDisplayList->prepareListAndChildren(info, childFunctorsNeedLayer,
+                [](RenderNode* child, TreeInfo& info, bool functorsNeedLayer) {
+            child->prepareTreeImpl(info, functorsNeedLayer);
+        });
+        if (isDirty) {
+            damageSelf(info);
         }
     }
     pushLayerUpdate(info);
@@ -356,20 +356,15 @@
     // Make sure we inc first so that we don't fluctuate between 0 and 1,
     // which would thrash the layer cache
     if (mStagingDisplayList) {
-        for (auto&& child : mStagingDisplayList->getChildren()) {
-            child->renderNode->incParentRefCount();
-        }
+        mStagingDisplayList->updateChildren([](RenderNode* child) {
+            child->incParentRefCount();
+        });
     }
     deleteDisplayList(info ? info->observer : nullptr, info);
     mDisplayList = mStagingDisplayList;
     mStagingDisplayList = nullptr;
     if (mDisplayList) {
-        for (auto& iter : mDisplayList->getFunctors()) {
-            (*iter.functor)(DrawGlInfo::kModeSync, nullptr);
-        }
-        for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) {
-            vectorDrawable->syncProperties();
-        }
+        mDisplayList->syncContents();
     }
 }
 
@@ -386,40 +381,24 @@
 
 void RenderNode::deleteDisplayList(TreeObserver* observer, TreeInfo* info) {
     if (mDisplayList) {
-        for (auto&& child : mDisplayList->getChildren()) {
-            child->renderNode->decParentRefCount(observer, info);
+        mDisplayList->updateChildren([observer, info](RenderNode* child) {
+            child->decParentRefCount(observer, info);
+        });
+        if (!mDisplayList->reuseDisplayList(this, info ? &info->canvasContext : nullptr)) {
+            delete mDisplayList;
         }
     }
-    delete mDisplayList;
     mDisplayList = nullptr;
 }
 
-void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayList* subtree) {
-    if (subtree) {
-        TextureCache& cache = Caches::getInstance().textureCache;
-        info.out.hasFunctors |= subtree->getFunctors().size();
-        for (auto&& bitmapResource : subtree->getBitmapResources()) {
-            void* ownerToken = &info.canvasContext;
-            info.prepareTextures = cache.prefetchAndMarkInUse(ownerToken, bitmapResource);
-        }
-        for (auto&& op : subtree->getChildren()) {
-            RenderNode* childNode = op->renderNode;
-            info.damageAccumulator->pushTransform(&op->localMatrix);
-            bool childFunctorsNeedLayer = functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip;
-            childNode->prepareTreeImpl(info, childFunctorsNeedLayer);
-            info.damageAccumulator->popTransform();
-        }
-    }
-}
-
 void RenderNode::destroyHardwareResources(TreeObserver* observer, TreeInfo* info) {
-    if (mLayer) {
+    if (hasLayer()) {
         renderthread::CanvasContext::destroyLayer(this);
     }
     if (mDisplayList) {
-        for (auto&& child : mDisplayList->getChildren()) {
-            child->renderNode->destroyHardwareResources(observer, info);
-        }
+        mDisplayList->updateChildren([observer, info](RenderNode* child) {
+            child->destroyHardwareResources(observer, info);
+        });
         if (mNeedsDisplayListSync) {
             // Next prepare tree we are going to push a new display list, so we can
             // drop our current one now
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index da93c13..a05c744 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -32,6 +32,7 @@
 #include "DisplayList.h"
 #include "Matrix.h"
 #include "RenderProperties.h"
+#include "SkiaDisplayList.h"
 
 #include <vector>
 
@@ -39,6 +40,7 @@
 class SkPaint;
 class SkPath;
 class SkRegion;
+class SkSurface;
 
 namespace android {
 namespace uirenderer {
@@ -48,6 +50,7 @@
 class FrameBuilder;
 class OffscreenBuffer;
 class Rect;
+class SkiaDisplayList;
 class SkiaShader;
 struct RenderNodeOp;
 
@@ -240,7 +243,6 @@
     void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer);
     void pushStagingPropertiesChanges(TreeInfo& info);
     void pushStagingDisplayListChanges(TreeInfo& info);
-    void prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayList* subtree);
     void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
     void pushLayerUpdate(TreeInfo& info);
     void deleteDisplayList(TreeObserver* observer, TreeInfo* info = nullptr);
@@ -285,6 +287,63 @@
     uint32_t mParentCount;
 
     sp<PositionListener> mPositionListener;
+
+// METHODS & FIELDS ONLY USED BY THE SKIA RENDERER
+public:
+    /**
+     * Detach and transfer ownership of an already allocated displayList for use
+     * in recording updated content for this renderNode
+     */
+    std::unique_ptr<SkiaDisplayList> detachAvailableList() {
+        return std::move(mAvailableDisplayList);
+    }
+
+    /**
+     * Attach unused displayList to this node for potential future reuse.
+     */
+    void attachAvailableList(SkiaDisplayList* skiaDisplayList) {
+        mAvailableDisplayList.reset(skiaDisplayList);
+    }
+
+    /**
+     * Returns true if an offscreen layer from any renderPipeline is attached
+     * to this node.
+     */
+    bool hasLayer() const { return mLayer || mLayerSurface.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; }
+
+
+    /**
+     * If the RenderNode is of type LayerType::RenderLayer then this method will
+     * return the an offscreen rendering surface that is used to both render into
+     * the layer and composite the layer into its parent.  If the type is not
+     * LayerType::RenderLayer then it will return a nullptr.
+     *
+     * NOTE: this function is only guaranteed to return accurate results after
+     *       prepareTree has been run for this RenderNode
+     */
+    SkSurface* getLayerSurface() const { return mLayerSurface.get(); }
+
+private:
+    /**
+     * If this RenderNode has been used in a previous frame then the SkiaDisplayList
+     * from that frame is cached here until one of the following conditions is met:
+     *  1) The RenderNode is deleted (causing this to be deleted)
+     *  2) It is replaced with the displayList from the next completed frame
+     *  3) It is detached and used to to record a new displayList for a later frame
+     */
+    std::unique_ptr<SkiaDisplayList> mAvailableDisplayList;
+
+    /**
+     * 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;
 }; // class RenderNode
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index b0114bc..146fbe7 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -52,7 +52,7 @@
 bool LayerProperties::setFromPaint(const SkPaint* paint) {
     bool changed = false;
     changed |= setAlpha(static_cast<uint8_t>(PaintUtils::getAlphaDirect(paint)));
-    changed |= setXferMode(PaintUtils::getXfermodeDirect(paint));
+    changed |= setXferMode(PaintUtils::getBlendModeDirect(paint));
     changed |= setColorFilter(paint ? paint->getColorFilter() : nullptr);
     return changed;
 }
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 2f5223c..9ee2f9c 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -24,10 +24,10 @@
 #include "utils/MathUtils.h"
 #include "utils/PaintUtils.h"
 
+#include <SkBlendMode.h>
 #include <SkCamera.h>
 #include <SkMatrix.h>
 #include <SkRegion.h>
-#include <SkXfermode.h>
 
 #include <algorithm>
 #include <stddef.h>
@@ -93,11 +93,11 @@
         return mAlpha;
     }
 
-    bool setXferMode(SkXfermode::Mode mode) {
+    bool setXferMode(SkBlendMode mode) {
         return RP_SET(mMode, mode);
     }
 
-    SkXfermode::Mode xferMode() const {
+    SkBlendMode xferMode() const {
         return mMode;
     }
 
@@ -133,7 +133,7 @@
     // Whether or not that Layer's content is opaque, doesn't include alpha
     bool mOpaque;
     uint8_t mAlpha;
-    SkXfermode::Mode mMode;
+    SkBlendMode mMode;
     SkColorFilter* mColorFilter = nullptr;
 };
 
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 9553ab4..7b2fda1 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -386,7 +386,7 @@
 // Canvas draw operations
 // ----------------------------------------------------------------------------
 
-void SkiaCanvas::drawColor(int color, SkXfermode::Mode mode) {
+void SkiaCanvas::drawColor(int color, SkBlendMode mode) {
     mCanvas->drawColor(color, mode);
 }
 
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 0e506f4..aac9036 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -100,7 +100,7 @@
     virtual SkDrawFilter* getDrawFilter() override;
     virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
 
-    virtual void drawColor(int color, SkXfermode::Mode mode) override;
+    virtual void drawColor(int color, SkBlendMode mode) override;
     virtual void drawPaint(const SkPaint& paint) override;
 
     virtual void drawPoint(float x, float y, const SkPaint& paint) override;
diff --git a/libs/hwui/SkiaDisplayList.cpp b/libs/hwui/SkiaDisplayList.cpp
new file mode 100644
index 0000000..d10f306
--- /dev/null
+++ b/libs/hwui/SkiaDisplayList.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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 "SkiaDisplayList.h"
+
+#include "renderthread/CanvasContext.h"
+#include "VectorDrawable.h"
+
+#include <SkImagePriv.h>
+#include <SkMutex.h>
+
+namespace android {
+namespace uirenderer {
+
+SkiaDisplayList::SkiaDisplayList(SkRect bounds) : mDrawable(SkLiteDL::New(bounds)) {
+    SkASSERT(projectionReceiveIndex == -1);
+}
+
+void SkiaDisplayList::syncContents() {
+    for (auto& functor : mChildFunctors) {
+        functor.syncFunctor();
+    }
+    for (auto& vectorDrawable : mVectorDrawables) {
+        vectorDrawable->syncProperties();
+    }
+}
+
+bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) {
+    reset(context ? context->getGrContext() : nullptr, SkRect::MakeEmpty());
+    node->attachAvailableList(this);
+    return true;
+}
+
+void SkiaDisplayList::updateChildren(std::function<void(RenderNode*)> updateFn) {
+    for (auto& child : mChildNodes) {
+        updateFn(child.getRenderNode());
+    }
+}
+
+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());
+
+    for (auto& child : mChildNodes) {
+        RenderNode* childNode = child.getRenderNode();
+        Matrix4 mat4(child.getRecordedMatrix());
+        info.damageAccumulator->pushTransform(&mat4);
+        // TODO: a layer is needed if the canvas is rotated or has a non-rect clip
+        bool childFunctorsNeedLayer = functorsNeedLayer;
+        childFn(childNode, info, childFunctorsNeedLayer);
+        info.damageAccumulator->popTransform();
+    }
+
+    bool isDirty = false;
+    for (auto& vectorDrawable : mVectorDrawables) {
+        // If any vector drawable in the display list needs update, damage the node.
+        if (vectorDrawable->isDirty()) {
+            isDirty = true;
+        }
+        vectorDrawable->setPropertyChangeWillBeConsumed(true);
+    }
+    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);
+    mIsProjectionReceiver = false;
+
+    mDrawable->reset(bounds);
+
+    mMutableImages.clear();
+    mVectorDrawables.clear();
+    mChildFunctors.clear();
+    mChildNodes.clear();
+
+    projectionReceiveIndex = -1;
+    allocator.~LinearAllocator();
+    new (&allocator) LinearAllocator();
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/SkiaDisplayList.h b/libs/hwui/SkiaDisplayList.h
new file mode 100644
index 0000000..c8a82bd
--- /dev/null
+++ b/libs/hwui/SkiaDisplayList.h
@@ -0,0 +1,152 @@
+/*
+ * 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 "DisplayList.h"
+#include "SkiaDrawables.h"
+
+#include <deque>
+#include <SkLiteDL.h>
+#include <SkPictureRecorder.h>
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * This class is intended to be self contained, but still subclasses from
+ * DisplayList to make it easier to support switching between the two at
+ * runtime.  The downside of this inheritance is that we pay for the overhead
+ * of the parent class construction/destruction without any real benefit.
+ */
+class SkiaDisplayList : public DisplayList {
+public:
+    SkiaDisplayList(SkRect bounds);
+    virtual ~SkiaDisplayList() {
+        /* Given that we are using a LinearStdAllocator to store some of the
+         * SkDrawable contents we must ensure that any other object that is
+         * holding a reference to those drawables is destroyed prior to their
+         * deletion.
+         */
+        mDrawable.reset();
+    }
+
+    /**
+     * This resets the DisplayList so that it behaves as if the object were newly
+     * 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);
+
+    /**
+     * Use the linear allocator to create any SkDrawables needed by the display
+     * list. This could be dangerous as these objects are ref-counted, so we
+     * need to monitor that they don't extend beyond the lifetime of the class
+     * that creates them.
+     */
+    template<class T, typename... Params>
+    SkDrawable* allocateDrawable(Params&&... params) {
+        return allocator.create<T>(std::forward<Params>(params)...);
+    }
+
+    bool isSkiaDL() const override { return true; }
+
+    /**
+     * Returns true if the DisplayList does not have any recorded content
+     */
+    bool isEmpty() const override { return mDrawable->empty(); }
+
+    /**
+     * Returns true if this list directly contains a GLFunctor drawing command.
+     */
+    bool hasFunctor() const override { return !mChildFunctors.empty(); }
+
+    /**
+     * Returns true if this list directly contains a VectorDrawable drawing command.
+     */
+    bool hasVectorDrawables() const override { return !mVectorDrawables.empty(); }
+
+    /**
+     * Attempts to reset and reuse this DisplayList.
+     *
+     * @return true if the displayList will be reused and therefore should not be deleted
+     */
+    bool reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) override;
+
+    /**
+     * ONLY to be called by RenderNode::syncDisplayList so that we can notify any
+     * contained VectorDrawables or GLFunctors to sync their state.
+     *
+     * NOTE: This function can be folded into RenderNode when we no longer need
+     *       to subclass from DisplayList
+     */
+    void syncContents() override;
+
+    /**
+     * ONLY to be called by RenderNode::prepareTree in order to prepare this
+     * list while the UI thread is blocked.  Here we can upload mutable bitmaps
+     * and notify our parent if any of our content has been invalidated and in
+     * need of a redraw.  If the renderNode has any children then they are also
+     * call in order to prepare them.
+     *
+     * @return true if any content change requires the node to be invalidated
+     *
+     * NOTE: This function can be folded into RenderNode when we no longer need
+     *       to subclass from DisplayList
+     */
+
+    bool prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
+            std::function<void(RenderNode*, TreeInfo&, bool)> childFn) override;
+
+    /**
+     *  Calls the provided function once for each child of this DisplayList
+     */
+    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.
+     */
+    std::deque<RenderNodeDrawable> mChildNodes;
+    std::deque<GLFunctorDrawable> mChildFunctors;
+    std::vector<SkImage*> mMutableImages;
+    std::vector<VectorDrawableRoot*> mVectorDrawables;
+    sk_sp<SkLiteDL> mDrawable;
+
+    bool mIsProjectionReceiver = false;
+
+private:
+    bool mPinnedImages = false;
+};
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/SkiaDrawables.h b/libs/hwui/SkiaDrawables.h
new file mode 100644
index 0000000..a1ceeaa
--- /dev/null
+++ b/libs/hwui/SkiaDrawables.h
@@ -0,0 +1,102 @@
+/*
+ * 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 "Layer.h"
+#include "RenderNode.h"
+
+#include <SkCanvas.h>
+#include <SkDrawable.h>
+#include <SkMatrix.h>
+
+#include <utils/RefBase.h>
+#include <utils/FatVector.h>
+#include <utils/Functor.h>
+
+namespace android {
+
+class Functor;
+
+namespace uirenderer {
+
+
+class RenderProperties;
+class OffscreenBuffer;
+class GlFunctorLifecycleListener;
+class SkiaDisplayList;
+
+/**
+ * This drawable wraps a RenderNode and enables it to be recorded into a list
+ * of Skia drawing commands.
+ */
+class RenderNodeDrawable : public SkDrawable {
+public:
+    explicit RenderNodeDrawable(RenderNode* node, SkCanvas* canvas)
+            : mRenderNode(node)
+            , mRecordedTransform(canvas->getTotalMatrix()) {}
+
+    /**
+     * The renderNode (and its properties) that is to be drawn
+     */
+    RenderNode* getRenderNode() const { return mRenderNode.get(); }
+
+    /**
+     * Returns the transform on the canvas at time of recording and is used for
+     * computing total transform without rerunning DL contents.
+     */
+    const SkMatrix& getRecordedMatrix() const { return mRecordedTransform; }
+
+protected:
+    virtual SkRect onGetBounds() override {
+        // We don't want to enable a record time quick reject because the properties
+        // of the RenderNode may be updated on subsequent frames.
+        return SkRect::MakeLargest();
+    }
+    virtual void onDraw(SkCanvas* canvas) override { /* TODO */ }
+
+private:
+    sp<RenderNode> mRenderNode;
+    const SkMatrix mRecordedTransform;
+};
+
+/**
+ * This drawable wraps a OpenGL functor enabling it to be recorded into a list
+ * of Skia drawing commands.
+ */
+class GLFunctorDrawable : public SkDrawable {
+public:
+    GLFunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener, SkCanvas* canvas)
+            : mFunctor(functor)
+            , mListener(listener) {
+        canvas->getClipBounds(&mBounds);
+    }
+    virtual ~GLFunctorDrawable() {}
+
+    void syncFunctor() const { (*mFunctor)(DrawGlInfo::kModeSync, nullptr); }
+
+ protected:
+    virtual SkRect onGetBounds() override { return mBounds; }
+    virtual void onDraw(SkCanvas* canvas) override { /* TODO */ }
+
+ private:
+     Functor* mFunctor;
+     sp<GlFunctorLifecycleListener> mListener;
+     SkRect mBounds;
+};
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 6f4a683..5d9e5c0 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -173,15 +173,16 @@
         outData->gradientSampler = 0;
         outData->gradientTexture = nullptr;
 
-        outData->startColor.set(gradInfo.fColors[0]);
-        outData->endColor.set(gradInfo.fColors[1]);
+        outData->startColor.setSRGB(gradInfo.fColors[0]);
+        outData->endColor.setSRGB(gradInfo.fColors[1]);
     }
 
-    outData->ditherSampler = (*textureUnit)++;
     return true;
 }
 
-void applyGradient(Caches& caches, const SkiaShaderData::GradientShaderData& data) {
+void applyGradient(Caches& caches, const SkiaShaderData::GradientShaderData& data,
+        const GLsizei width, const GLsizei height) {
+
     if (CC_UNLIKELY(data.gradientTexture)) {
         caches.textureState().activateTexture(data.gradientSampler);
         bindTexture(&caches, data.gradientTexture, data.wrapST, data.wrapST);
@@ -191,10 +192,7 @@
         bindUniformColor(caches.program().getUniform("endColor"), data.endColor);
     }
 
-    // TODO: remove sampler slot incrementing from dither.setupProgram,
-    // since this assignment of slots is done at store, not apply time
-    GLuint ditherSampler = data.ditherSampler;
-    caches.dither.setupProgram(caches.program(), &ditherSampler);
+    glUniform2f(caches.program().getUniform("screenSize"), 1.0f / width, 1.0f / height);
     glUniformMatrix4fv(caches.program().getUniform("screenSpace"), 1,
             GL_FALSE, &data.screenSpace.data[0]);
 }
@@ -208,13 +206,7 @@
         return false;
     }
 
-    /*
-     * Bypass the AssetAtlas, since those textures:
-     * 1) require UV mapping, which isn't implemented in matrix computation below
-     * 2) can't handle REPEAT simply
-     * 3) are safe to upload here (outside of sync stage), since they're static
-     */
-    outData->bitmapTexture = caches.textureCache.getAndBypassAtlas(&bitmap);
+    outData->bitmapTexture = caches.textureCache.get(&bitmap);
     if (!outData->bitmapTexture) return false;
 
     outData->bitmapSampler = (*textureUnit)++;
@@ -388,11 +380,12 @@
     outData->skiaShaderType = kNone_SkiaShaderType;
 }
 
-void SkiaShader::apply(Caches& caches, const SkiaShaderData& data) {
+void SkiaShader::apply(Caches& caches, const SkiaShaderData& data,
+        const GLsizei width, const GLsizei height) {
     if (!data.skiaShaderType) return;
 
     if (data.skiaShaderType & kGradient_SkiaShaderType) {
-        applyGradient(caches, data.gradientData);
+        applyGradient(caches, data.gradientData, width, height);
     }
     if (data.skiaShaderType & kBitmap_SkiaShaderType) {
         applyBitmap(caches, data.bitmapData);
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 884196d..5854289 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -62,7 +62,6 @@
     } bitmapData;
     struct GradientShaderData {
         Matrix4 screenSpace;
-        GLuint ditherSampler;
 
         // simple gradient
         FloatColor startColor;
@@ -72,7 +71,6 @@
         Texture* gradientTexture;
         GLuint gradientSampler;
         GLenum wrapST;
-
     } gradientData;
     struct LayerShaderData {
         Layer* layer;
@@ -90,7 +88,8 @@
     static void store(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
             GLuint* textureUnit, ProgramDescription* description,
             SkiaShaderData* outData);
-    static void apply(Caches& caches, const SkiaShaderData& data);
+    static void apply(Caches& caches, const SkiaShaderData& data,
+            const GLsizei width, const GLsizei height);
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index e2ee5bf..7b0a1bc 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -927,9 +927,13 @@
         AlphaVertex::set(&shadowVertices[vertexBufferIndex++], newPenumbra[i].x,
                 newPenumbra[i].y, PENUMBRA_ALPHA);
     }
+    // Since the umbra can be a faked one when the occluder is too high, the umbra should be lighter
+    // in this case.
+    float scaledUmbraAlpha = UMBRA_ALPHA * shadowStrengthScale;
+
     for (int i = 0; i < umbraLength; i++) {
         AlphaVertex::set(&shadowVertices[vertexBufferIndex++], umbra[i].x, umbra[i].y,
-                UMBRA_ALPHA);
+                scaledUmbraAlpha);
     }
 
     for (int i = 0; i < verticesPairIndex; i++) {
@@ -969,14 +973,14 @@
             indexBuffer[indexBufferIndex++] = newPenumbraLength + i;
             indexBuffer[indexBufferIndex++] = vertexBufferIndex;
             AlphaVertex::set(&shadowVertices[vertexBufferIndex++],
-                    closerVertex.x, closerVertex.y, UMBRA_ALPHA);
+                    closerVertex.x, closerVertex.y, scaledUmbraAlpha);
         }
     } else {
         // If there is no occluded umbra at all, then draw the triangle fan
         // starting from the centroid to all umbra vertices.
         int lastCentroidIndex = vertexBufferIndex;
         AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid.x,
-                centroid.y, UMBRA_ALPHA);
+                centroid.y, scaledUmbraAlpha);
         for (int i = 0; i < umbraLength; i++) {
             indexBuffer[indexBufferIndex++] = newPenumbraLength + i;
             indexBuffer[indexBufferIndex++] = lastCentroidIndex;
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index 4f49a35..908f572 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -26,19 +26,23 @@
 namespace android {
 namespace uirenderer {
 
+// Number of bytes used by a texture in the given format
 static int bytesPerPixel(GLint glFormat) {
     switch (glFormat) {
     // The wrapped-texture case, usually means a SurfaceTexture
     case 0:
         return 0;
+    case GL_LUMINANCE:
     case GL_ALPHA:
         return 1;
+    case GL_SRGB8:
     case GL_RGB:
         return 3;
+    case GL_SRGB8_ALPHA8:
     case GL_RGBA:
         return 4;
     case GL_RGBA16F:
-        return 16;
+        return 8;
     default:
         LOG_ALWAYS_FATAL("UNKNOWN FORMAT %d", glFormat);
     }
@@ -83,14 +87,16 @@
     mId = 0;
 }
 
-bool Texture::updateSize(uint32_t width, uint32_t height, GLint format) {
-    if (mWidth == width && mHeight == height && mFormat == format) {
+bool Texture::updateSize(uint32_t width, uint32_t height, GLint internalFormat, GLint format) {
+    if (mWidth == width && mHeight == height &&
+            mFormat == format && mInternalFormat == internalFormat) {
         return false;
     }
     mWidth = width;
     mHeight = height;
     mFormat = format;
-    notifySizeChanged(mWidth * mHeight * bytesPerPixel(mFormat));
+    mInternalFormat = internalFormat;
+    notifySizeChanged(mWidth * mHeight * bytesPerPixel(internalFormat));
     return true;
 }
 
@@ -101,10 +107,10 @@
     mMagFilter = GL_LINEAR;
 }
 
-void Texture::upload(GLint internalformat, uint32_t width, uint32_t height,
+void Texture::upload(GLint internalFormat, uint32_t width, uint32_t height,
         GLenum format, GLenum type, const void* pixels) {
     GL_CHECKPOINT(MODERATE);
-    bool needsAlloc = updateSize(width, height, internalformat);
+    bool needsAlloc = updateSize(width, height, internalFormat, format);
     if (!mId) {
         glGenTextures(1, &mId);
         needsAlloc = true;
@@ -112,17 +118,17 @@
     }
     mCaches.textureState().bindTexture(GL_TEXTURE_2D, mId);
     if (needsAlloc) {
-        glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0,
+        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0,
                 format, type, pixels);
     } else if (pixels) {
-        glTexSubImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0,
+        glTexSubImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0,
                 format, type, pixels);
     }
     GL_CHECKPOINT(MODERATE);
 }
 
-static void uploadToTexture(bool resize, GLenum format, GLenum type, GLsizei stride, GLsizei bpp,
-        GLsizei width, GLsizei height, const GLvoid * data) {
+static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GLenum type,
+        GLsizei stride, GLsizei bpp, GLsizei width, GLsizei height, const GLvoid * data) {
 
     const bool useStride = stride != width
             && Caches::getInstance().extensions().hasUnpackRowLength();
@@ -132,7 +138,7 @@
         }
 
         if (resize) {
-            glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data);
+            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, data);
         } else {
             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
         }
@@ -156,7 +162,7 @@
         }
 
         if (resize) {
-            glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, temp);
+            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, temp);
         } else {
             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp);
         }
@@ -166,31 +172,44 @@
 }
 
 static void uploadSkBitmapToTexture(const SkBitmap& bitmap,
-        bool resize, GLenum format, GLenum type) {
-    uploadToTexture(resize, format, type, bitmap.rowBytesAsPixels(), bitmap.bytesPerPixel(),
-            bitmap.width(), bitmap.height(), bitmap.getPixels());
+        bool resize, GLint internalFormat, GLenum format, GLenum type) {
+    uploadToTexture(resize, internalFormat, format, type, bitmap.rowBytesAsPixels(),
+            bitmap.bytesPerPixel(), bitmap.width(), bitmap.height(), bitmap.getPixels());
 }
 
-static void colorTypeToGlFormatAndType(SkColorType colorType,
-        GLint* outFormat, GLint* outType) {
+static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
+        bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType) {
     switch (colorType) {
     case kAlpha_8_SkColorType:
         *outFormat = GL_ALPHA;
+        *outInternalFormat = GL_ALPHA;
         *outType = GL_UNSIGNED_BYTE;
         break;
     case kRGB_565_SkColorType:
-        *outFormat = GL_RGB;
-        *outType = GL_UNSIGNED_SHORT_5_6_5;
+        if (needSRGB) {
+            // We would ideally use a GL_RGB/GL_SRGB8 texture but the
+            // intermediate Skia bitmap needs to be ARGB_8888
+            *outFormat = GL_RGBA;
+            *outInternalFormat = caches.rgbaInternalFormat();
+            *outType = GL_UNSIGNED_BYTE;
+        } else {
+            *outFormat = GL_RGB;
+            *outInternalFormat = GL_RGB;
+            *outType = GL_UNSIGNED_SHORT_5_6_5;
+        }
         break;
     // ARGB_4444 and Index_8 are both upconverted to RGBA_8888
     case kARGB_4444_SkColorType:
     case kIndex_8_SkColorType:
     case kN32_SkColorType:
         *outFormat = GL_RGBA;
+        *outInternalFormat = caches.rgbaInternalFormat(needSRGB);
         *outType = GL_UNSIGNED_BYTE;
         break;
     case kGray_8_SkColorType:
+        // TODO: Handle sRGB
         *outFormat = GL_LUMINANCE;
+        *outInternalFormat = GL_LUMINANCE;
         *outType = GL_UNSIGNED_BYTE;
         break;
     default:
@@ -224,29 +243,36 @@
         setDefaultParams = true;
     }
 
-    GLint format, type;
-    colorTypeToGlFormatAndType(bitmap.colorType(), &format, &type);
+    sk_sp<SkColorSpace> sRGB = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+    bool needSRGB = bitmap.colorSpace() == sRGB.get();
 
-    if (updateSize(bitmap.width(), bitmap.height(), format)) {
+    GLint internalFormat, format, type;
+    colorTypeToGlFormatAndType(mCaches, bitmap.colorType(), needSRGB, &internalFormat, &format, &type);
+
+    if (updateSize(bitmap.width(), bitmap.height(), internalFormat, format)) {
         needsAlloc = true;
     }
 
     blend = !bitmap.isOpaque();
     mCaches.textureState().bindTexture(mId);
 
+    // TODO: Handle sRGB gray bitmaps
+    bool hasSRGB = mCaches.extensions().hasSRGB();
     if (CC_UNLIKELY(bitmap.colorType() == kARGB_4444_SkColorType
-            || bitmap.colorType() == kIndex_8_SkColorType)) {
+            || bitmap.colorType() == kIndex_8_SkColorType
+            || (bitmap.colorType() == kRGB_565_SkColorType && hasSRGB && needSRGB))) {
+
         SkBitmap rgbaBitmap;
-        rgbaBitmap.allocPixels(SkImageInfo::MakeN32(mWidth, mHeight,
-                bitmap.alphaType()));
+        rgbaBitmap.allocPixels(SkImageInfo::MakeN32(
+                mWidth, mHeight, bitmap.alphaType(), hasSRGB ? sRGB : nullptr));
         rgbaBitmap.eraseColor(0);
 
         SkCanvas canvas(rgbaBitmap);
         canvas.drawBitmap(bitmap, 0.0f, 0.0f, nullptr);
 
-        uploadSkBitmapToTexture(rgbaBitmap, needsAlloc, format, type);
+        uploadSkBitmapToTexture(rgbaBitmap, needsAlloc, internalFormat, format, type);
     } else {
-        uploadSkBitmapToTexture(bitmap, needsAlloc, format, type);
+        uploadSkBitmapToTexture(bitmap, needsAlloc, internalFormat, format, type);
     }
 
     if (canMipMap) {
@@ -262,11 +288,12 @@
     }
 }
 
-void Texture::wrap(GLuint id, uint32_t width, uint32_t height, GLint format) {
+void Texture::wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format) {
     mId = id;
     mWidth = width;
     mHeight = height;
     mFormat = format;
+    mInternalFormat = internalFormat;
     // We're wrapping an existing texture, so don't double count this memory
     notifySizeChanged(0);
 }
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index b72742f..aa8a6d3 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -69,8 +69,8 @@
      *
      * The image data is undefined after calling this.
      */
-    void resize(uint32_t width, uint32_t height, GLint format) {
-        upload(format, width, height, format, GL_UNSIGNED_BYTE, nullptr);
+    void resize(uint32_t width, uint32_t height, GLint internalFormat, GLint format) {
+        upload(internalFormat, width, height, format, GL_UNSIGNED_BYTE, nullptr);
     }
 
     /**
@@ -85,13 +85,13 @@
     /**
      * Basically glTexImage2D/glTexSubImage2D.
      */
-    void upload(GLint internalformat, uint32_t width, uint32_t height,
+    void upload(GLint internalFormat, uint32_t width, uint32_t height,
             GLenum format, GLenum type, const void* pixels);
 
     /**
      * Wraps an existing texture.
      */
-    void wrap(GLuint id, uint32_t width, uint32_t height, GLint format);
+    void wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format);
 
     GLuint id() const {
         return mId;
@@ -109,6 +109,10 @@
         return mFormat;
     }
 
+    GLint internalFormat() const {
+        return mInternalFormat;
+    }
+
     /**
      * Generation of the backing bitmap,
      */
@@ -148,13 +152,14 @@
     friend class Layer;
 
     // Returns true if the size changed, false if it was the same
-    bool updateSize(uint32_t width, uint32_t height, GLint format);
+    bool updateSize(uint32_t width, uint32_t height, GLint internalFormat, GLint format);
     void resetCachedParams();
 
     GLuint mId = 0;
     uint32_t mWidth = 0;
     uint32_t mHeight = 0;
     GLint mFormat = 0;
+    GLint mInternalFormat = 0;
 
     /* See GLES spec section 3.8.14
      * "In the initial state, the value assigned to TEXTURE_MIN_FILTER is
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 523924a..5ccdbda 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -18,7 +18,6 @@
 
 #include <utils/Mutex.h>
 
-#include "AssetAtlas.h"
 #include "Caches.h"
 #include "Texture.h"
 #include "TextureCache.h"
@@ -36,8 +35,7 @@
         : mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity)
         , mSize(0)
         , mMaxSize(Properties::textureCacheSize)
-        , mFlushRate(Properties::textureCacheFlushRate)
-        , mAssetAtlas(nullptr) {
+        , mFlushRate(Properties::textureCacheFlushRate) {
     mCache.setOnEntryRemovedListener(this);
 
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
@@ -84,10 +82,6 @@
 // Caching
 ///////////////////////////////////////////////////////////////////////////////
 
-void TextureCache::setAssetAtlas(AssetAtlas* assetAtlas) {
-    mAssetAtlas = assetAtlas;
-}
-
 void TextureCache::resetMarkInUse(void* ownerToken) {
     LruCache<uint32_t, Texture*>::Iterator iter(mCache);
     while (iter.next()) {
@@ -108,14 +102,7 @@
 
 // Returns a prepared Texture* that either is already in the cache or can fit
 // in the cache (and is thus added to the cache)
-Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap, AtlasUsageType atlasUsageType) {
-    if (CC_LIKELY(mAssetAtlas != nullptr) && atlasUsageType == AtlasUsageType::Use) {
-        AssetAtlas::Entry* entry = mAssetAtlas->getEntry(bitmap->pixelRef());
-        if (CC_UNLIKELY(entry)) {
-            return entry->texture;
-        }
-    }
-
+Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
     Texture* texture = mCache.get(bitmap->pixelRef()->getStableID());
 
     if (!texture) {
@@ -160,7 +147,7 @@
 }
 
 bool TextureCache::prefetchAndMarkInUse(void* ownerToken, const SkBitmap* bitmap) {
-    Texture* texture = getCachedTexture(bitmap, AtlasUsageType::Use);
+    Texture* texture = getCachedTexture(bitmap);
     if (texture) {
         texture->isInUse = ownerToken;
     }
@@ -168,11 +155,11 @@
 }
 
 bool TextureCache::prefetch(const SkBitmap* bitmap) {
-    return getCachedTexture(bitmap, AtlasUsageType::Use);
+    return getCachedTexture(bitmap);
 }
 
-Texture* TextureCache::get(const SkBitmap* bitmap, AtlasUsageType atlasUsageType) {
-    Texture* texture = getCachedTexture(bitmap, atlasUsageType);
+Texture* TextureCache::get(const SkBitmap* bitmap) {
+    Texture* texture = getCachedTexture(bitmap);
 
     if (!texture) {
         if (!canMakeTextureFromBitmap(bitmap)) {
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 0a61b6b..88ef771 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -47,8 +47,6 @@
 // Classes
 ///////////////////////////////////////////////////////////////////////////////
 
-class AssetAtlas;
-
 /**
  * A simple LRU texture cache. The cache has a maximum size expressed in bytes.
  * Any texture added to the cache causing the cache to grow beyond the maximum
@@ -85,20 +83,10 @@
     bool prefetch(const SkBitmap* bitmap);
 
     /**
-     * Returns the texture associated with the specified bitmap from either within the cache, or
-     * the AssetAtlas. If the texture cannot be found in the cache, a new texture is generated.
+     * Returns the texture associated with the specified bitmap from within the cache.
+     * If the texture cannot be found in the cache, a new texture is generated.
      */
-    Texture* get(const SkBitmap* bitmap) {
-        return get(bitmap, AtlasUsageType::Use);
-    }
-
-    /**
-     * Returns the texture associated with the specified bitmap. If the texture cannot be found in
-     * the cache, a new texture is generated, even if it resides in the AssetAtlas.
-     */
-    Texture* getAndBypassAtlas(const SkBitmap* bitmap) {
-        return get(bitmap, AtlasUsageType::Bypass);
-    }
+    Texture* get(const SkBitmap* bitmap);
 
     /**
      * Removes the texture associated with the specified pixelRef. This is meant
@@ -130,18 +118,10 @@
      */
     void flush();
 
-    void setAssetAtlas(AssetAtlas* assetAtlas);
-
 private:
-    enum class AtlasUsageType {
-        Use,
-        Bypass,
-    };
-
     bool canMakeTextureFromBitmap(const SkBitmap* bitmap);
 
-    Texture* get(const SkBitmap* bitmap, AtlasUsageType atlasUsageType);
-    Texture* getCachedTexture(const SkBitmap* bitmap, AtlasUsageType atlasUsageType);
+    Texture* getCachedTexture(const SkBitmap* bitmap);
 
     LruCache<uint32_t, Texture*> mCache;
 
@@ -155,8 +135,6 @@
 
     std::vector<uint32_t> mGarbage;
     mutable Mutex mLock;
-
-    AssetAtlas* mAssetAtlas;
 }; // class TextureCache
 
 }; // namespace uirenderer
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 2b79941..715681d 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -201,8 +201,7 @@
     SkPaint paint;
     if (properties.getFillGradient() != nullptr) {
         paint.setColor(applyAlpha(SK_ColorBLACK, properties.getFillAlpha()));
-        SkShader* newShader = properties.getFillGradient()->newWithLocalMatrix(matrix);
-        paint.setShader(newShader);
+        paint.setShader(properties.getFillGradient()->makeWithLocalMatrix(matrix));
         needsFill = true;
     } else if (properties.getFillColor() != SK_ColorTRANSPARENT) {
         paint.setColor(applyAlpha(properties.getFillColor(), properties.getFillAlpha()));
@@ -221,8 +220,7 @@
     bool needsStroke = false;
     if (properties.getStrokeGradient() != nullptr) {
         paint.setColor(applyAlpha(SK_ColorBLACK, properties.getStrokeAlpha()));
-        SkShader* newShader = properties.getStrokeGradient()->newWithLocalMatrix(matrix);
-        paint.setShader(newShader);
+        paint.setShader(properties.getStrokeGradient()->makeWithLocalMatrix(matrix));
         needsStroke = true;
     } else if (properties.getStrokeColor() != SK_ColorTRANSPARENT) {
         paint.setColor(applyAlpha(properties.getStrokeColor(), properties.getStrokeAlpha()));
@@ -530,7 +528,7 @@
     if (prop->getRootAlpha() == 1.0f && prop->getColorFilter() == nullptr) {
         return nullptr;
     } else {
-        outPaint->setColorFilter(prop->getColorFilter());
+        outPaint->setColorFilter(sk_ref_sp(prop->getColorFilter()));
         outPaint->setFilterQuality(kLow_SkFilterQuality);
         outPaint->setAlpha(prop->getRootAlpha() * 255);
         return outPaint;
@@ -561,8 +559,12 @@
 
 bool Tree::allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height) {
     if (!canReuseBitmap(*outCache, width, height)) {
-        SkImageInfo info = SkImageInfo::Make(width, height,
-                kN32_SkColorType, kPremul_SkAlphaType);
+#ifndef ANDROID_ENABLE_LINEAR_BLENDING
+        sk_sp<SkColorSpace> colorSpace = nullptr;
+#else
+        sk_sp<SkColorSpace> colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+#endif
+        SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType, colorSpace);
         outCache->setInfo(info);
         // TODO: Count the bitmap cache against app's java heap
         outCache->allocPixels(info);
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index c1bf980..db982ad 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -19,6 +19,7 @@
 
 #include "Vector.h"
 
+#include "FloatColor.h"
 #include "utils/Macros.h"
 
 namespace android {
@@ -76,21 +77,19 @@
 REQUIRE_COMPATIBLE_LAYOUT(TextureVertex);
 
 /**
- * Simple structure to describe a vertex with a position, texture UV and ARGB color.
+ * Simple structure to describe a vertex with a position, texture UV and an
+ * sRGB color with alpha. The color is stored pre-multiplied in linear space.
  */
 struct ColorTextureVertex {
     float x, y;
     float u, v;
-    float r, g, b, a;
+    float r, g, b, a; // pre-multiplied linear
 
     static inline void set(ColorTextureVertex* vertex, float x, float y,
-            float u, float v, int color) {
-
-        float a =     ((color >> 24) & 0xff) / 255.0f;
-        float r = a * ((color >> 16) & 0xff) / 255.0f;
-        float g = a * ((color >>  8) & 0xff) / 255.0f;
-        float b = a * ((color) & 0xff) / 255.0f;
-        *vertex = { x, y, u, v, r, g, b, a };
+            float u, float v, uint32_t color) {
+        FloatColor c;
+        c.set(color);
+        *vertex = { x, y, u, v, c.r, c.g, c.b, c.a };
     }
 }; // struct ColorTextureVertex
 
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
index 49e9f65..e2844ad 100644
--- a/libs/hwui/font/CacheTexture.cpp
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -180,7 +180,12 @@
         mPixelBuffer = PixelBuffer::create(mFormat, getWidth(), getHeight());
     }
 
-    mTexture.resize(mWidth, mHeight, mFormat);
+    GLint internalFormat = mFormat;
+    if (mFormat == GL_RGBA) {
+        internalFormat = mCaches.rgbaInternalFormat();
+    }
+
+    mTexture.resize(mWidth, mHeight, internalFormat, mFormat);
     mTexture.setFilter(getLinearFiltering() ? GL_LINEAR : GL_NEAREST);
     mTexture.setWrap(GL_CLAMP_TO_EDGE);
 }
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index d76143b..cb9056f 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -174,7 +174,7 @@
 // ----------------------------------------------------------------------------
 // Canvas draw operations
 // ----------------------------------------------------------------------------
-    virtual void drawColor(int color, SkXfermode::Mode mode) = 0;
+    virtual void drawColor(int color, SkBlendMode mode) = 0;
     virtual void drawPaint(const SkPaint& paint) = 0;
 
     // Geometry
diff --git a/libs/hwui/hwui/PixelRef.cpp b/libs/hwui/hwui/PixelRef.cpp
new file mode 100644
index 0000000..795de6b
--- /dev/null
+++ b/libs/hwui/hwui/PixelRef.cpp
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+#include "PixelRef.h"
+
+#include "Caches.h"
+
+#include <cutils/log.h>
+#include <sys/mman.h>
+#include <cutils/ashmem.h>
+
+namespace android {
+
+void PixelRef::reconfigure(const SkImageInfo& newInfo, size_t rowBytes, SkColorTable* ctable) {
+    if (kIndex_8_SkColorType != newInfo.colorType()) {
+        ctable = nullptr;
+    }
+    mRowBytes = rowBytes;
+    if (mColorTable.get() != ctable) {
+        mColorTable.reset(ctable);
+    }
+
+    // Need to validate the alpha type to filter against the color type
+    // to prevent things like a non-opaque RGB565 bitmap
+    SkAlphaType alphaType;
+    LOG_ALWAYS_FATAL_IF(!SkColorTypeValidateAlphaType(
+            newInfo.colorType(), newInfo.alphaType(), &alphaType),
+            "Failed to validate alpha type!");
+
+    // Dirty hack is dirty
+    // TODO: Figure something out here, Skia's current design makes this
+    // really hard to work with. Skia really, really wants immutable objects,
+    // but with the nested-ref-count hackery going on that's just not
+    // feasible without going insane trying to figure it out
+    SkImageInfo* myInfo = const_cast<SkImageInfo*>(&this->info());
+    *myInfo = newInfo;
+    changeAlphaType(alphaType);
+
+    // Docs say to only call this in the ctor, but we're going to call
+    // it anyway even if this isn't always the ctor.
+    // TODO: Fix this too as part of the above TODO
+    setPreLocked(getStorage(), mRowBytes, mColorTable.get());
+}
+
+PixelRef::PixelRef(void* address, size_t size, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
+            : SkPixelRef(info)
+            , mPixelStorageType(PixelStorageType::Heap) {
+    mPixelStorage.heap.address = address;
+    mPixelStorage.heap.size = size;
+    reconfigure(info, rowBytes, ctable);
+}
+
+PixelRef::PixelRef(void* address, void* context, FreeFunc freeFunc,
+                const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
+            : SkPixelRef(info)
+            , mPixelStorageType(PixelStorageType::External) {
+    mPixelStorage.external.address = address;
+    mPixelStorage.external.context = context;
+    mPixelStorage.external.freeFunc = freeFunc;
+    reconfigure(info, rowBytes, ctable);
+}
+
+PixelRef::PixelRef(void* address, int fd, size_t mappedSize,
+                const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
+            : SkPixelRef(info)
+            , mPixelStorageType(PixelStorageType::Ashmem) {
+    mPixelStorage.ashmem.address = address;
+    mPixelStorage.ashmem.fd = fd;
+    mPixelStorage.ashmem.size = mappedSize;
+    reconfigure(info, rowBytes, ctable);
+}
+
+PixelRef::~PixelRef() {
+    switch (mPixelStorageType) {
+    case PixelStorageType::External:
+        mPixelStorage.external.freeFunc(mPixelStorage.external.address,
+                mPixelStorage.external.context);
+        break;
+    case PixelStorageType::Ashmem:
+        munmap(mPixelStorage.ashmem.address, mPixelStorage.ashmem.size);
+        close(mPixelStorage.ashmem.fd);
+        break;
+    case PixelStorageType::Heap:
+        free(mPixelStorage.heap.address);
+        break;
+    }
+
+    if (android::uirenderer::Caches::hasInstance()) {
+        android::uirenderer::Caches::getInstance().textureCache.releaseTexture(getStableID());
+    }
+}
+
+bool PixelRef::hasHardwareMipMap() const {
+    return mHasHardwareMipMap;
+}
+
+void PixelRef::setHasHardwareMipMap(bool hasMipMap) {
+    mHasHardwareMipMap = hasMipMap;
+}
+
+void* PixelRef::getStorage() const {
+    switch (mPixelStorageType) {
+    case PixelStorageType::External:
+        return mPixelStorage.external.address;
+    case PixelStorageType::Ashmem:
+        return mPixelStorage.ashmem.address;
+    case PixelStorageType::Heap:
+        return mPixelStorage.heap.address;
+    }
+}
+
+bool PixelRef::onNewLockPixels(LockRec* rec) {
+    rec->fPixels = getStorage();
+    rec->fRowBytes = mRowBytes;
+    rec->fColorTable = mColorTable.get();
+    return true;
+}
+
+size_t PixelRef::getAllocatedSizeInBytes() const {
+    return info().getSafeSize(mRowBytes);
+}
+
+int PixelRef::getAshmemFd() const {
+    switch (mPixelStorageType) {
+    case PixelStorageType::Ashmem:
+        return mPixelStorage.ashmem.fd;
+    default:
+        return -1;
+    }
+}
+
+size_t PixelRef::getAllocationByteCount() const {
+    switch (mPixelStorageType) {
+    case PixelStorageType::Heap:
+        return mPixelStorage.heap.size;
+    default:
+        return rowBytes() * height();
+    }
+}
+
+void PixelRef::reconfigure(const SkImageInfo& info) {
+    reconfigure(info, info.minRowBytes(), nullptr);
+}
+
+void PixelRef::setAlphaType(SkAlphaType alphaType) {
+    if (!SkColorTypeValidateAlphaType(info().colorType(), alphaType, &alphaType)) {
+        return;
+    }
+
+    changeAlphaType(alphaType);
+}
+
+void PixelRef::getSkBitmap(SkBitmap* outBitmap) {
+    outBitmap->setInfo(info(), rowBytes());
+    outBitmap->setPixelRef(this);
+    outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/hwui/hwui/PixelRef.h b/libs/hwui/hwui/PixelRef.h
new file mode 100644
index 0000000..3f8aea6
--- /dev/null
+++ b/libs/hwui/hwui/PixelRef.h
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <SkBitmap.h>
+#include <SkColorTable.h>
+#include <SkImageInfo.h>
+#include <SkPixelRef.h>
+#include <cutils/compiler.h>
+
+namespace android {
+
+enum class PixelStorageType {
+    External,
+    Heap,
+    Ashmem,
+};
+
+typedef void (*FreeFunc)(void* addr, void* context);
+
+class ANDROID_API PixelRef : public SkPixelRef {
+public:
+    PixelRef(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes,
+            SkColorTable* ctable);
+    PixelRef(void* address, void* context, FreeFunc freeFunc,
+            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
+    PixelRef(void* address, int fd, size_t mappedSize, const SkImageInfo& info,
+            size_t rowBytes, SkColorTable* ctable);
+
+    int width() const { return info().width(); }
+    int height() const { return info().height(); }
+
+    // Can't mark as override since SkPixelRef::rowBytes isn't virtual
+    // but that's OK since we just want Bitmap to be able to rely
+    // on calling rowBytes() on an unlocked pixelref, which it will be
+    // doing on a PixelRef type, not a SkPixelRef, so static
+    // dispatching will do what we want.
+    size_t rowBytes() const { return mRowBytes; }
+    void reconfigure(const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
+    void reconfigure(const SkImageInfo& info);
+    void setAlphaType(SkAlphaType alphaType);
+
+    void getSkBitmap(SkBitmap* outBitmap);
+
+    int getAshmemFd() const;
+    size_t getAllocationByteCount() const;
+
+protected:
+    virtual bool onNewLockPixels(LockRec* rec) override;
+    virtual void onUnlockPixels() override { };
+    virtual size_t getAllocatedSizeInBytes() const override;
+private:
+    friend class Bitmap;
+    virtual ~PixelRef();
+    void doFreePixels();
+    void* getStorage() const;
+    void setHasHardwareMipMap(bool hasMipMap);
+    bool hasHardwareMipMap() const;
+
+    PixelStorageType mPixelStorageType;
+
+    size_t mRowBytes = 0;
+    sk_sp<SkColorTable> mColorTable;
+    bool mHasHardwareMipMap = false;
+
+    union {
+        struct {
+            void* address;
+            void* context;
+            FreeFunc freeFunc;
+        } external;
+        struct {
+            void* address;
+            int fd;
+            size_t size;
+        } ashmem;
+        struct {
+            void* address;
+            size_t size;
+        } heap;
+    } mPixelStorage;
+};
+
+} //namespace android
\ No newline at end of file
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index 18c35b3..33ee108 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -22,6 +22,8 @@
 
 #include "Typeface.h"
 
+#include <pthread.h>
+
 #include "MinikinSkia.h"
 #include "SkTypeface.h"
 #include "SkPaint.h"
diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp
index 93f787d..8865c6e 100644
--- a/libs/hwui/renderstate/Blend.cpp
+++ b/libs/hwui/renderstate/Blend.cpp
@@ -25,70 +25,70 @@
  * Structure mapping Skia xfermodes to OpenGL blending factors.
  */
 struct Blender {
-    SkXfermode::Mode mode;
+    SkBlendMode mode;
     GLenum src;
     GLenum dst;
 };
 
 // assumptions made by lookup tables in either this file or ProgramCache
-static_assert(0 == SkXfermode::kClear_Mode, "SkXfermode enums have changed");
-static_assert(1 == SkXfermode::kSrc_Mode, "SkXfermode enums have changed");
-static_assert(2 == SkXfermode::kDst_Mode, "SkXfermode enums have changed");
-static_assert(3 == SkXfermode::kSrcOver_Mode, "SkXfermode enums have changed");
-static_assert(4 == SkXfermode::kDstOver_Mode, "SkXfermode enums have changed");
-static_assert(5 == SkXfermode::kSrcIn_Mode, "SkXfermode enums have changed");
-static_assert(6 == SkXfermode::kDstIn_Mode, "SkXfermode enums have changed");
-static_assert(7 == SkXfermode::kSrcOut_Mode, "SkXfermode enums have changed");
-static_assert(8 == SkXfermode::kDstOut_Mode, "SkXfermode enums have changed");
-static_assert(9 == SkXfermode::kSrcATop_Mode, "SkXfermode enums have changed");
-static_assert(10 == SkXfermode::kDstATop_Mode, "SkXfermode enums have changed");
-static_assert(11 == SkXfermode::kXor_Mode, "SkXfermode enums have changed");
-static_assert(12 == SkXfermode::kPlus_Mode, "SkXfermode enums have changed");
-static_assert(13 == SkXfermode::kModulate_Mode, "SkXfermode enums have changed");
-static_assert(14 == SkXfermode::kScreen_Mode, "SkXfermode enums have changed");
-static_assert(15 == SkXfermode::kOverlay_Mode, "SkXfermode enums have changed");
-static_assert(16 == SkXfermode::kDarken_Mode, "SkXfermode enums have changed");
-static_assert(17 == SkXfermode::kLighten_Mode, "SkXfermode enums have changed");
+static_assert(0 == static_cast<int>(SkBlendMode::kClear), "SkBlendMode enums have changed");
+static_assert(1 == static_cast<int>(SkBlendMode::kSrc), "SkBlendMode enums have changed");
+static_assert(2 == static_cast<int>(SkBlendMode::kDst), "SkBlendMode enums have changed");
+static_assert(3 == static_cast<int>(SkBlendMode::kSrcOver), "SkBlendMode enums have changed");
+static_assert(4 == static_cast<int>(SkBlendMode::kDstOver), "SkBlendMode enums have changed");
+static_assert(5 == static_cast<int>(SkBlendMode::kSrcIn), "SkBlendMode enums have changed");
+static_assert(6 == static_cast<int>(SkBlendMode::kDstIn), "SkBlendMode enums have changed");
+static_assert(7 == static_cast<int>(SkBlendMode::kSrcOut), "SkBlendMode enums have changed");
+static_assert(8 == static_cast<int>(SkBlendMode::kDstOut), "SkBlendMode enums have changed");
+static_assert(9 == static_cast<int>(SkBlendMode::kSrcATop), "SkBlendMode enums have changed");
+static_assert(10 == static_cast<int>(SkBlendMode::kDstATop), "SkBlendMode enums have changed");
+static_assert(11 == static_cast<int>(SkBlendMode::kXor), "SkBlendMode enums have changed");
+static_assert(12 == static_cast<int>(SkBlendMode::kPlus), "SkBlendMode enums have changed");
+static_assert(13 == static_cast<int>(SkBlendMode::kModulate), "SkBlendMode enums have changed");
+static_assert(14 == static_cast<int>(SkBlendMode::kScreen), "SkBlendMode enums have changed");
+static_assert(15 == static_cast<int>(SkBlendMode::kOverlay), "SkBlendMode enums have changed");
+static_assert(16 == static_cast<int>(SkBlendMode::kDarken), "SkBlendMode enums have changed");
+static_assert(17 == static_cast<int>(SkBlendMode::kLighten), "SkBlendMode enums have changed");
 
 // In this array, the index of each Blender equals the value of the first
-// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
+// entry. For instance, gBlends[1] == gBlends[SkBlendMode::kSrc]
 const Blender kBlends[] = {
-    { SkXfermode::kClear_Mode,    GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
-    { SkXfermode::kSrc_Mode,      GL_ONE,                 GL_ZERO },
-    { SkXfermode::kDst_Mode,      GL_ZERO,                GL_ONE },
-    { SkXfermode::kSrcOver_Mode,  GL_ONE,                 GL_ONE_MINUS_SRC_ALPHA },
-    { SkXfermode::kDstOver_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_ONE },
-    { SkXfermode::kSrcIn_Mode,    GL_DST_ALPHA,           GL_ZERO },
-    { SkXfermode::kDstIn_Mode,    GL_ZERO,                GL_SRC_ALPHA },
-    { SkXfermode::kSrcOut_Mode,   GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
-    { SkXfermode::kDstOut_Mode,   GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
-    { SkXfermode::kSrcATop_Mode,  GL_DST_ALPHA,           GL_ONE_MINUS_SRC_ALPHA },
-    { SkXfermode::kDstATop_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
-    { SkXfermode::kXor_Mode,      GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
-    { SkXfermode::kPlus_Mode,     GL_ONE,                 GL_ONE },
-    { SkXfermode::kModulate_Mode, GL_ZERO,                GL_SRC_COLOR },
-    { SkXfermode::kScreen_Mode,   GL_ONE,                 GL_ONE_MINUS_SRC_COLOR }
+    { SkBlendMode::kClear,    GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
+    { SkBlendMode::kSrc,      GL_ONE,                 GL_ZERO },
+    { SkBlendMode::kDst,      GL_ZERO,                GL_ONE },
+    { SkBlendMode::kSrcOver,  GL_ONE,                 GL_ONE_MINUS_SRC_ALPHA },
+    { SkBlendMode::kDstOver,  GL_ONE_MINUS_DST_ALPHA, GL_ONE },
+    { SkBlendMode::kSrcIn,    GL_DST_ALPHA,           GL_ZERO },
+    { SkBlendMode::kDstIn,    GL_ZERO,                GL_SRC_ALPHA },
+    { SkBlendMode::kSrcOut,   GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
+    { SkBlendMode::kDstOut,   GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
+    { SkBlendMode::kSrcATop,  GL_DST_ALPHA,           GL_ONE_MINUS_SRC_ALPHA },
+    { SkBlendMode::kDstATop,  GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
+    { SkBlendMode::kXor,      GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
+    { SkBlendMode::kPlus,     GL_ONE,                 GL_ONE },
+    { SkBlendMode::kModulate, GL_ZERO,                GL_SRC_COLOR },
+    { SkBlendMode::kScreen,   GL_ONE,                 GL_ONE_MINUS_SRC_COLOR }
 };
 
-// This array contains the swapped version of each SkXfermode. For instance
+// This array contains the swapped version of each SkBlendMode. For instance
 // this array's SrcOver blending mode is actually DstOver. You can refer to
 // createLayer() for more information on the purpose of this array.
 const Blender kBlendsSwap[] = {
-    { SkXfermode::kClear_Mode,    GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
-    { SkXfermode::kSrc_Mode,      GL_ZERO,                GL_ONE },
-    { SkXfermode::kDst_Mode,      GL_ONE,                 GL_ZERO },
-    { SkXfermode::kSrcOver_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_ONE },
-    { SkXfermode::kDstOver_Mode,  GL_ONE,                 GL_ONE_MINUS_SRC_ALPHA },
-    { SkXfermode::kSrcIn_Mode,    GL_ZERO,                GL_SRC_ALPHA },
-    { SkXfermode::kDstIn_Mode,    GL_DST_ALPHA,           GL_ZERO },
-    { SkXfermode::kSrcOut_Mode,   GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
-    { SkXfermode::kDstOut_Mode,   GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
-    { SkXfermode::kSrcATop_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
-    { SkXfermode::kDstATop_Mode,  GL_DST_ALPHA,           GL_ONE_MINUS_SRC_ALPHA },
-    { SkXfermode::kXor_Mode,      GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
-    { SkXfermode::kPlus_Mode,     GL_ONE,                 GL_ONE },
-    { SkXfermode::kModulate_Mode, GL_DST_COLOR,           GL_ZERO },
-    { SkXfermode::kScreen_Mode,   GL_ONE_MINUS_DST_COLOR, GL_ONE }
+    { SkBlendMode::kClear,    GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
+    { SkBlendMode::kSrc,      GL_ZERO,                GL_ONE },
+    { SkBlendMode::kDst,      GL_ONE,                 GL_ZERO },
+    { SkBlendMode::kSrcOver,  GL_ONE_MINUS_DST_ALPHA, GL_ONE },
+    { SkBlendMode::kDstOver,  GL_ONE,                 GL_ONE_MINUS_SRC_ALPHA },
+    { SkBlendMode::kSrcIn,    GL_ZERO,                GL_SRC_ALPHA },
+    { SkBlendMode::kDstIn,    GL_DST_ALPHA,           GL_ZERO },
+    { SkBlendMode::kSrcOut,   GL_ZERO,                GL_ONE_MINUS_SRC_ALPHA },
+    { SkBlendMode::kDstOut,   GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
+    { SkBlendMode::kSrcATop,  GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
+    { SkBlendMode::kDstATop,  GL_DST_ALPHA,           GL_ONE_MINUS_SRC_ALPHA },
+    { SkBlendMode::kXor,      GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
+    { SkBlendMode::kPlus,     GL_ONE,                 GL_ONE },
+    { SkBlendMode::kModulate, GL_DST_COLOR,           GL_ZERO },
+    { SkBlendMode::kScreen,   GL_ONE_MINUS_DST_COLOR, GL_ONE }
 };
 
 Blend::Blend()
@@ -111,9 +111,10 @@
     }
 }
 
-void Blend::getFactors(SkXfermode::Mode mode, ModeOrderSwap modeUsage, GLenum* outSrc, GLenum* outDst) {
-    *outSrc = (modeUsage == ModeOrderSwap::Swap) ? kBlendsSwap[mode].src : kBlends[mode].src;
-    *outDst = (modeUsage == ModeOrderSwap::Swap) ? kBlendsSwap[mode].dst : kBlends[mode].dst;
+void Blend::getFactors(SkBlendMode mode, ModeOrderSwap modeUsage, GLenum* outSrc, GLenum* outDst) {
+    int index = static_cast<int>(mode);
+    *outSrc = (modeUsage == ModeOrderSwap::Swap) ? kBlendsSwap[index].src : kBlends[index].src;
+    *outDst = (modeUsage == ModeOrderSwap::Swap) ? kBlendsSwap[index].dst : kBlends[index].dst;
 }
 
 void Blend::setFactors(GLenum srcMode, GLenum dstMode) {
diff --git a/libs/hwui/renderstate/Blend.h b/libs/hwui/renderstate/Blend.h
index df9e5a8..ec0e114 100644
--- a/libs/hwui/renderstate/Blend.h
+++ b/libs/hwui/renderstate/Blend.h
@@ -20,7 +20,7 @@
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
-#include <SkXfermode.h>
+#include <SkBlendMode.h>
 #include <memory>
 
 namespace android {
@@ -36,7 +36,7 @@
     };
     void syncEnabled();
 
-    static void getFactors(SkXfermode::Mode mode, ModeOrderSwap modeUsage,
+    static void getFactors(SkBlendMode mode, ModeOrderSwap modeUsage,
             GLenum* outSrc, GLenum* outDst);
     void setFactors(GLenum src, GLenum dst);
 
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index 10a26e0..a9bbb27 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -22,6 +22,7 @@
 #include "utils/FatVector.h"
 #include "utils/TraceUtils.h"
 
+#include <utils/Color.h>
 #include <utils/Log.h>
 
 #include <GLES2/gl2.h>
@@ -44,7 +45,7 @@
     uint32_t height = computeIdealDimension(viewportHeight);
     ATRACE_FORMAT("Allocate %ux%u HW Layer", width, height);
     caches.textureState().activateTexture(0);
-    texture.resize(width, height, GL_RGBA);
+    texture.resize(width, height, caches.rgbaInternalFormat(), GL_RGBA);
     texture.blend = true;
     texture.setWrap(GL_CLAMP_TO_EDGE);
     // not setting filter on texture, since it's set when drawing, based on transform
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index ee4619d..84ab3f3 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -52,7 +52,6 @@
         mCaches = &Caches::createInstance(*this);
     }
     mCaches->init();
-    mCaches->textureCache.setAssetAtlas(&mAssetAtlas);
 }
 
 static void layerLostGlContext(Layer* layer) {
@@ -64,7 +63,6 @@
 
     // TODO: reset all cached state in state objects
     std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext);
-    mAssetAtlas.terminate();
 
     mCaches->terminate();
 
@@ -147,9 +145,17 @@
     meshState().resetVertexPointers();
     meshState().disableTexCoordsVertexArray();
     debugOverdraw(false, false);
+    // TODO: We need a way to know whether the functor is sRGB aware (b/32072673)
+    if (mCaches->extensions().hasSRGBWriteControl()) {
+        glDisable(GL_FRAMEBUFFER_SRGB_EXT);
+    }
 }
 
 void RenderState::resumeFromFunctorInvoke() {
+    if (mCaches->extensions().hasSRGBWriteControl()) {
+        glEnable(GL_FRAMEBUFFER_SRGB_EXT);
+    }
+
     glViewport(0, 0, mViewportWidth, mViewportHeight);
     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
     debugOverdraw(false, false);
@@ -308,7 +314,7 @@
         glVertexAttribPointer(alphaLocation, 1, GL_FLOAT, GL_FALSE, vertices.stride, alphaCoords);
     }
     // Shader uniforms
-    SkiaShader::apply(*mCaches, fill.skiaShaderData);
+    SkiaShader::apply(*mCaches, fill.skiaShaderData, mViewportWidth, mViewportHeight);
 
     GL_CHECKPOINT(MODERATE);
     Texture* texture = (fill.skiaShaderData.skiaShaderType & kBitmap_SkiaShaderType) ?
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index 9e0fb12..3d119dc 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -16,7 +16,6 @@
 #ifndef RENDERSTATE_H
 #define RENDERSTATE_H
 
-#include "AssetAtlas.h"
 #include "Caches.h"
 #include "Glop.h"
 #include "renderstate/Blend.h"
@@ -92,7 +91,6 @@
 
     void render(const Glop& glop, const Matrix4& orthoMatrix);
 
-    AssetAtlas& assetAtlas() { return mAssetAtlas; }
     Blend& blend() { return *mBlend; }
     MeshState& meshState() { return *mMeshState; }
     Scissor& scissor() { return *mScissor; }
@@ -120,7 +118,6 @@
 
     OffscreenBufferPool mLayerPool;
 
-    AssetAtlas mAssetAtlas;
     std::set<Layer*> mActiveLayers;
     std::set<renderthread::CanvasContext*> mRegisteredContexts;
 
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 0f2d55b..fe0f56a 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -545,11 +545,6 @@
     return mRenderPipeline->createTextureLayer();
 }
 
-void CanvasContext::setTextureAtlas(RenderThread& thread,
-        const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize) {
-    thread.eglManager().setTextureAtlas(buffer, map, mapSize);
-}
-
 void CanvasContext::dumpFrames(int fd) {
     FILE* file = fdopen(fd, "a");
     fprintf(file, "\n\n---PROFILEDATA---\n");
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 652cddd..559ac87 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -85,6 +85,12 @@
      */
     static void destroyLayer(RenderNode* node);
 
+    /*
+     * If Properties::isSkiaEnabled() is true then this will return the Skia
+     * grContext associated with the current RenderPipeline.
+     */
+    GrContext* getGrContext() const { return mRenderPipeline->getGrContext(); }
+
     // Won't take effect until next EGLSurface creation
     void setSwapBehavior(SwapBehavior swapBehavior);
 
@@ -119,9 +125,6 @@
 
     DeferredLayerUpdater* createTextureLayer();
 
-    ANDROID_API static void setTextureAtlas(RenderThread& thread,
-            const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
-
     void stopDrawing();
     void notifyFramePending();
 
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 86731c9..beda045 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -91,9 +91,7 @@
         , mEglConfig(nullptr)
         , mEglContext(EGL_NO_CONTEXT)
         , mPBufferSurface(EGL_NO_SURFACE)
-        , mCurrentSurface(EGL_NO_SURFACE)
-        , mAtlasMap(nullptr)
-        , mAtlasMapSize(0) {
+        , mCurrentSurface(EGL_NO_SURFACE) {
 }
 
 void EglManager::initialize() {
@@ -128,7 +126,6 @@
     makeCurrent(mPBufferSurface);
     DeviceInfo::initialize();
     mRenderThread.renderState().onGLContextCreated();
-    initAtlas();
 }
 
 void EglManager::initExtensions() {
@@ -191,32 +188,6 @@
         "Failed to create context, error = %s", egl_error_str());
 }
 
-void EglManager::setTextureAtlas(const sp<GraphicBuffer>& buffer,
-        int64_t* map, size_t mapSize) {
-
-    // Already initialized
-    if (mAtlasBuffer.get()) {
-        ALOGW("Multiple calls to setTextureAtlas!");
-        delete map;
-        return;
-    }
-
-    mAtlasBuffer = buffer;
-    mAtlasMap = map;
-    mAtlasMapSize = mapSize;
-
-    if (hasEglContext()) {
-        initAtlas();
-    }
-}
-
-void EglManager::initAtlas() {
-    if (mAtlasBuffer.get()) {
-        mRenderThread.renderState().assetAtlas().init(mAtlasBuffer,
-                mAtlasMap, mAtlasMapSize);
-    }
-}
-
 void EglManager::createPBufferSurface() {
     LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
             "usePBufferSurface() called on uninitialized GlobalContext!");
@@ -229,7 +200,16 @@
 
 EGLSurface EglManager::createSurface(EGLNativeWindowType window) {
     initialize();
-    EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, nullptr);
+
+    EGLint attribs[] = {
+#ifdef ANDROID_ENABLE_LINEAR_BLENDING
+            EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR,
+            EGL_COLORSPACE, EGL_COLORSPACE_sRGB,
+#endif
+            EGL_NONE
+    };
+
+    EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, attribs);
     LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
             "Failed to create EGLSurface for window %p, eglErr = %s",
             (void*) window, egl_error_str());
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 41047fe..ba4a3e1 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -79,8 +79,6 @@
     // Returns true iff the surface is now preserving buffers.
     bool setPreserveBuffer(EGLSurface surface, bool preserve);
 
-    void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
-
     void fence();
 
 private:
@@ -94,7 +92,6 @@
     void createPBufferSurface();
     void loadConfig();
     void createContext();
-    void initAtlas();
     EGLint queryBufferAge(EGLSurface surface);
 
     RenderThread& mRenderThread;
@@ -106,10 +103,6 @@
 
     EGLSurface mCurrentSurface;
 
-    sp<GraphicBuffer> mAtlasBuffer;
-    int64_t* mAtlasMap;
-    size_t mAtlasMapSize;
-
     enum class SwapBehavior {
         Discard,
         Preserved,
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 97cdf7f..f96c2fd 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -22,6 +22,8 @@
 #include <SkRect.h>
 #include <utils/RefBase.h>
 
+class GrContext;
+
 namespace android {
 
 class Surface;
@@ -43,6 +45,8 @@
     Succeeded
 };
 
+class Frame;
+
 class IRenderPipeline {
 public:
     virtual MakeCurrentResult makeCurrent() = 0;
@@ -69,6 +73,7 @@
     virtual TaskManager* getTaskManager() = 0;
     virtual bool createOrUpdateLayer(RenderNode* node,
             const DamageAccumulator& damageAccumulator) = 0;
+    virtual GrContext* getGrContext() = 0;
 
     virtual ~IRenderPipeline() {}
 };
diff --git a/libs/hwui/renderthread/OpenGLPipeline.h b/libs/hwui/renderthread/OpenGLPipeline.h
index 34d9bc0..d024aec 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.h
+++ b/libs/hwui/renderthread/OpenGLPipeline.h
@@ -26,9 +26,6 @@
 namespace uirenderer {
 namespace renderthread {
 
-class Frame;
-
-
 class OpenGLPipeline : public IRenderPipeline {
 public:
     OpenGLPipeline(RenderThread& thread);
@@ -59,6 +56,7 @@
     bool createOrUpdateLayer(RenderNode* node,
             const DamageAccumulator& damageAccumulator) override;
     static void destroyLayer(RenderNode* node);
+    GrContext* getGrContext() override { return nullptr; }
 
 private:
     EglManager& mEglManager;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index dcbc980..c2ed864 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -480,23 +480,6 @@
     staticPostAndWait(task);
 }
 
-CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map,
-               size_t size) {
-    CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size);
-    args->buffer->decStrong(nullptr);
-    return nullptr;
-}
-
-void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) {
-    SETUP_TASK(setTextureAtlas);
-    args->thread = &mRenderThread;
-    args->buffer = buffer.get();
-    args->buffer->incStrong(nullptr);
-    args->map = map;
-    args->size = size;
-    post(task);
-}
-
 CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
     args->thread->jankTracker().switchStorageToAshmem(args->fd);
     close(args->fd);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d4aaea6..50a6f64 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -112,7 +112,6 @@
     uint32_t frameTimePercentile(int p);
     ANDROID_API static void dumpGraphicsMemory(int fd);
 
-    ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
     ANDROID_API void setProcessStatsBuffer(int fd);
     ANDROID_API int getRenderThreadTid();
 
diff --git a/libs/hwui/tests/common/TestListViewSceneBase.cpp b/libs/hwui/tests/common/TestListViewSceneBase.cpp
index b8484b9..6d2e8599 100644
--- a/libs/hwui/tests/common/TestListViewSceneBase.cpp
+++ b/libs/hwui/tests/common/TestListViewSceneBase.cpp
@@ -47,7 +47,7 @@
         }
     });
 
-    canvas.drawColor(Color::Grey_500, SkXfermode::kSrcOver_Mode);
+    canvas.drawColor(Color::Grey_500, SkBlendMode::kSrcOver);
     canvas.drawRenderNode(mListView.get());
 }
 
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 78e9bc4..51c0a05 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -124,8 +124,9 @@
     static SkBitmap createSkBitmap(int width, int height,
             SkColorType colorType = kN32_SkColorType) {
         SkBitmap bitmap;
+        sk_sp<SkColorSpace> colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
         SkImageInfo info = SkImageInfo::Make(width, height,
-                colorType, kPremul_SkAlphaType);
+                colorType, kPremul_SkAlphaType, colorSpace);
         bitmap.setInfo(info);
         bitmap.allocPixels(info);
         return bitmap;
diff --git a/libs/hwui/tests/common/scenes/ClippingAnimation.cpp b/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
index 47f40a1..8f2ba2d 100644
--- a/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
@@ -29,7 +29,7 @@
 public:
     sp<RenderNode> card;
     void createContent(int width, int height, Canvas& canvas) override {
-        canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
         card = TestUtils::createNode(0, 0, 200, 400,
                 [](RenderProperties& props, Canvas& canvas) {
             canvas.save(SaveFlags::MatrixClip);
@@ -39,7 +39,7 @@
                 canvas.rotate(45);
                 canvas.translate(-100, -100);
                 canvas.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
-                canvas.drawColor(Color::Blue_500, SkXfermode::kSrcOver_Mode);
+                canvas.drawColor(Color::Blue_500, SkBlendMode::kSrcOver);
             }
             canvas.restore();
 
@@ -48,7 +48,7 @@
                 SkPath clipCircle;
                 clipCircle.addCircle(100, 300, 100);
                 canvas.clipPath(&clipCircle, SkRegion::kIntersect_Op);
-                canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode);
+                canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
             }
             canvas.restore();
 
diff --git a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
index 9d6aa53..c0d9450 100644
--- a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
@@ -37,7 +37,7 @@
         container = TestUtils::createNode(0, 0, width, height, nullptr);
         doFrame(0); // update container
 
-        canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
         canvas.drawRenderNode(container.get());
     }
 
diff --git a/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp b/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
index 00dba78..3a230ae 100644
--- a/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
@@ -32,9 +32,9 @@
         card = TestUtils::createNode(0, 0, 200, 200,
                 [](RenderProperties& props, Canvas& canvas) {
             props.mutateLayerProperties().setType(LayerType::RenderLayer);
-            canvas.drawColor(0xFF0000FF, SkXfermode::kSrcOver_Mode);
+            canvas.drawColor(0xFF0000FF, SkBlendMode::kSrcOver);
         });
-        canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode); // background
+        canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver); // background
         canvas.drawRenderNode(card.get());
     }
     void doFrame(int frameNr) override {
diff --git a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
index a5e91e4..b7357e1 100644
--- a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
@@ -31,7 +31,7 @@
 class ListOfFadedTextAnimation : public TestListViewSceneBase {
     void createListItem(RenderProperties& props, Canvas& canvas, int id,
             int itemWidth, int itemHeight)  override {
-        canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
         int length = dp(100);
         canvas.saveLayer(0, 0, length, itemHeight, nullptr, SaveFlags::HasAlphaLayer);
         SkPaint textPaint;
@@ -44,16 +44,15 @@
         pts[1].set(0, 1);
 
         SkColor colors[2] = {Color::Black, Color::Transparent};
-        SkAutoTUnref<SkShader> s(SkGradientShader::CreateLinear(pts, colors, NULL, 2,
+        sk_sp<SkShader> s(SkGradientShader::MakeLinear(pts, colors, NULL, 2,
                 SkShader::kClamp_TileMode));
 
         SkMatrix matrix;
         matrix.setScale(1, length);
         matrix.postRotate(-90);
         SkPaint fadingPaint;
-        fadingPaint.setShader(s->newWithLocalMatrix(matrix))->unref();
-        SkXfermode* mode = SkXfermode::Create(SkXfermode::kDstOut_Mode);
-        fadingPaint.setXfermode(mode);
+        fadingPaint.setShader(s->makeWithLocalMatrix(matrix));
+        fadingPaint.setBlendMode(SkBlendMode::kDstOut);
         canvas.drawRect(0, 0, length, itemHeight, fadingPaint);
         canvas.restore();
     }
diff --git a/libs/hwui/tests/common/scenes/OpPropAnimation.cpp b/libs/hwui/tests/common/scenes/OpPropAnimation.cpp
index c8e124c..68051d6 100644
--- a/libs/hwui/tests/common/scenes/OpPropAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/OpPropAnimation.cpp
@@ -53,7 +53,7 @@
             mCircleX->value = width * 0.75;
             mCircleY->value = height * 0.75;
 
-            canvas.drawColor(Color::White, SkXfermode::Mode::kSrcOver_Mode);
+            canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
             canvas.drawRoundRect(mRoundRectLeft.get(), mRoundRectTop.get(),
                     mRoundRectRight.get(), mRoundRectBottom.get(),
                     mRoundRectRx.get(), mRoundRectRy.get(), mPaint.get());
diff --git a/libs/hwui/tests/common/scenes/OvalAnimation.cpp b/libs/hwui/tests/common/scenes/OvalAnimation.cpp
index f37c00c..d6fd604 100644
--- a/libs/hwui/tests/common/scenes/OvalAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/OvalAnimation.cpp
@@ -29,7 +29,7 @@
 public:
     sp<RenderNode> card;
     void createContent(int width, int height, Canvas& canvas) override {
-        canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
         card = TestUtils::createNode(0, 0, 200, 200,
                 [](RenderProperties& props, Canvas& canvas) {
             SkPaint paint;
diff --git a/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp b/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
index bc2dc75..bc04d81 100644
--- a/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
@@ -37,7 +37,7 @@
                 0xFF4CAF50,
         };
 
-        canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
 
         for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
             for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
@@ -45,7 +45,7 @@
                 sp<RenderNode> card = TestUtils::createNode(x, y,
                         x + dp(100), y + dp(100),
                         [color](RenderProperties& props, Canvas& canvas) {
-                    canvas.drawColor(color, SkXfermode::kSrcOver_Mode);
+                    canvas.drawColor(color, SkBlendMode::kSrcOver);
                 });
                 canvas.drawRenderNode(card.get());
                 cards.push_back(card);
@@ -61,7 +61,7 @@
         TestUtils::recordNode(*cards[0], [curFrame](Canvas& canvas) {
             SkColor color = TestUtils::interpolateColor(
                     curFrame / 150.0f, 0xFFF44336, 0xFFF8BBD0);
-            canvas.drawColor(color, SkXfermode::kSrcOver_Mode);
+            canvas.drawColor(color, SkBlendMode::kSrcOver);
         });
     }
 };
diff --git a/libs/hwui/tests/common/scenes/RecentsAnimation.cpp b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
index 3d4397a..584f684 100644
--- a/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
@@ -39,7 +39,7 @@
         thumbnailSize = std::min(std::min(width, height) / 2, 720);
         int cardsize = std::min(width, height) - dp(64);
 
-        renderer.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
+        renderer.drawColor(Color::White, SkBlendMode::kSrcOver);
         renderer.insertReorderBarrier(true);
 
         int x = dp(32);
@@ -76,7 +76,7 @@
             props.mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
             props.mutableOutline().setShouldClip(true);
 
-            canvas.drawColor(Color::Grey_200, SkXfermode::kSrcOver_Mode);
+            canvas.drawColor(Color::Grey_200, SkBlendMode::kSrcOver);
             canvas.drawBitmap(thumb, 0, 0, thumb.width(), thumb.height(),
                     0, 0, width, height, nullptr);
         });
diff --git a/libs/hwui/tests/common/scenes/RectGridAnimation.cpp b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
index e1d323e..668eec6 100644
--- a/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
@@ -30,12 +30,12 @@
 public:
     sp<RenderNode> card;
     void createContent(int width, int height, Canvas& canvas) override {
-        canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
         canvas.insertReorderBarrier(true);
 
         card = TestUtils::createNode(50, 50, 250, 250,
                 [](RenderProperties& props, Canvas& canvas) {
-            canvas.drawColor(0xFFFF00FF, SkXfermode::kSrcOver_Mode);
+            canvas.drawColor(0xFFFF00FF, SkBlendMode::kSrcOver);
 
             SkRegion region;
             for (int xOffset = 0; xOffset < 200; xOffset+=2) {
diff --git a/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp b/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp
index 0f8906e..4b6632d 100644
--- a/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp
@@ -28,7 +28,7 @@
 
     std::vector< sp<RenderNode> > cards;
     void createContent(int width, int height, Canvas& canvas) override {
-        canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
         canvas.insertReorderBarrier(true);
         int ci = 0;
 
@@ -37,7 +37,7 @@
                 auto color = BrightColors[ci++ % BrightColorsCount];
                 auto card = TestUtils::createNode(x, y, x + mSize, y + mSize,
                         [&](RenderProperties& props, Canvas& canvas) {
-                    canvas.drawColor(color, SkXfermode::kSrcOver_Mode);
+                    canvas.drawColor(color, SkBlendMode::kSrcOver);
                     props.mutableOutline().setRoundRect(0, 0,
                             props.getWidth(), props.getHeight(), mSize * .25, 1);
                     props.mutableOutline().setShouldClip(true);
diff --git a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
index cd00ed3..3630935 100644
--- a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
@@ -29,16 +29,16 @@
 public:
     sp<RenderNode> card;
     void createContent(int width, int height, Canvas& canvas) override {
-        canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode); // background
+        canvas.drawColor(Color::White, SkBlendMode::kSrcOver); // background
 
         card = TestUtils::createNode(0, 0, 400, 800,
                 [](RenderProperties& props, Canvas& canvas) {
             // nested clipped saveLayers
             canvas.saveLayerAlpha(0, 0, 400, 400, 200, SaveFlags::ClipToLayer);
-            canvas.drawColor(Color::Green_700, SkXfermode::kSrcOver_Mode);
+            canvas.drawColor(Color::Green_700, SkBlendMode::kSrcOver);
             canvas.clipRect(50, 50, 350, 350, SkRegion::kIntersect_Op);
             canvas.saveLayerAlpha(100, 100, 300, 300, 128, SaveFlags::ClipToLayer);
-            canvas.drawColor(Color::Blue_500, SkXfermode::kSrcOver_Mode);
+            canvas.drawColor(Color::Blue_500, SkBlendMode::kSrcOver);
             canvas.restore();
             canvas.restore();
 
diff --git a/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp b/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
index d7d0c512..0a69b62 100644
--- a/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
+++ b/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
@@ -29,7 +29,7 @@
 public:
     std::vector< sp<RenderNode> > cards;
     void createContent(int width, int height, Canvas& canvas) override {
-        canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
         canvas.insertReorderBarrier(true);
 
         for (int x = dp(8); x < (width - dp(58)); x += dp(58)) {
@@ -57,7 +57,7 @@
             props.setElevation(dp(16));
             props.mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
             props.mutableOutline().setShouldClip(true);
-            canvas.drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
+            canvas.drawColor(0xFFEEEEEE, SkBlendMode::kSrcOver);
         });
     }
 };
diff --git a/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp b/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
index 75362dd..4a02429 100644
--- a/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
@@ -29,7 +29,7 @@
 public:
     std::vector< sp<RenderNode> > cards;
     void createContent(int width, int height, Canvas& canvas) override {
-        canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
         canvas.insertReorderBarrier(true);
 
         for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
@@ -57,7 +57,7 @@
             props.setElevation(dp(16));
             props.mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
             props.mutableOutline().setShouldClip(true);
-            canvas.drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
+            canvas.drawColor(0xFFEEEEEE, SkBlendMode::kSrcOver);
         });
     }
 };
diff --git a/libs/hwui/tests/common/scenes/ShapeAnimation.cpp b/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
index e2370f7..5ef8773 100644
--- a/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
@@ -83,7 +83,7 @@
                     for (auto op : ops) {
                         int innerCount = canvas.save(SaveFlags::MatrixClip);
                         canvas.clipRect(0, 0, cellSize, cellSize, SkRegion::kIntersect_Op);
-                        canvas.drawColor(Color::White, SkXfermode::Mode::kSrcOver_Mode);
+                        canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
                         op(canvas, cellSize, paint);
                         canvas.restoreToCount(innerCount);
                         canvas.translate(cellSize + cellSpace, 0);
@@ -94,7 +94,7 @@
             }
             canvas.restoreToCount(outerCount);
         });
-        canvas.drawColor(Color::Grey_500, SkXfermode::Mode::kSrcOver_Mode);
+        canvas.drawColor(Color::Grey_500, SkBlendMode::kSrcOver);
         canvas.drawRenderNode(card.get());
     }
 
diff --git a/libs/hwui/tests/common/scenes/TextAnimation.cpp b/libs/hwui/tests/common/scenes/TextAnimation.cpp
index 2933402..438f877 100644
--- a/libs/hwui/tests/common/scenes/TextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/TextAnimation.cpp
@@ -29,7 +29,7 @@
 public:
     sp<RenderNode> card;
     void createContent(int width, int height, Canvas& canvas) override {
-        canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
         card = TestUtils::createNode(0, 0, width, height,
                 [](RenderProperties& props, Canvas& canvas) {
             SkPaint paint;
diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index 2787fba..10cf05a 100644
--- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -163,7 +163,7 @@
 void BM_DisplayListCanvas_basicViewGroupDraw(benchmark::State& benchState) {
     sp<RenderNode> child = TestUtils::createNode(50, 50, 100, 100,
             [](auto& props, auto& canvas) {
-        canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
     });
 
     std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
diff --git a/libs/hwui/tests/scripts/prep_ryu.sh b/libs/hwui/tests/scripts/prep_ryu.sh
new file mode 100644
index 0000000..7c6c0df
--- /dev/null
+++ b/libs/hwui/tests/scripts/prep_ryu.sh
@@ -0,0 +1,31 @@
+adb root
+adb wait-for-device
+adb shell stop thermal-engine
+adb shell stop perfd
+
+# 51000 102000 204000 306000 408000 510000 612000 714000 816000 918000
+# 1020000 1122000 1224000 1326000 1428000 1530000 1632000 1734000 1836000 1912500
+S=1326000
+echo "set cpu to $S hz";
+adb shell "echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
+adb shell "echo $S > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"
+adb shell "echo $S > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"
+
+#01: core 76 MHz emc 408 MHz
+#02: core 153 MHz emc 665 MHz
+#03: core 230 MHz emc 800 MHz *
+#04: core 307 MHz emc 1065 MHz
+#05: core 384 MHz emc 1331 MHz
+#06: core 460 MHz emc 1600 MHz
+#07: core 537 MHz emc 1600 MHz
+#08: core 614 MHz emc 1600 MHz
+#09: core 691 MHz emc 1600 MHz
+#0a: core 768 MHz emc 1600 MHz
+#0b: core 844 MHz emc 1600 MHz
+#0c: core 921 MHz emc 1600 MHz
+#0d: core 998 MHz emc 1600 MHz
+#AC: core 230 MHz emc 800 MHz a A d D
+
+echo "set gpu to core 307 MHz emc 1065 MHz"
+# it will lock gpu until you touch a screen
+adb shell "echo 04 > /sys/devices/57000000.gpu/pstate"
diff --git a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
index 9deb441..d44be7d 100644
--- a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
@@ -86,9 +86,7 @@
     strokePaint.setStrokeWidth(4);
 
     float intervals[] = {1.0f, 1.0f};
-    auto dashEffect = SkDashPathEffect::Create(intervals, 2, 0);
-    strokePaint.setPathEffect(dashEffect);
-    dashEffect->unref();
+    strokePaint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
 
     auto textureGlopVerifier = [] (const Glop& glop) {
         // validate glop produced by renderPathTexture (so texture, unit quad)
@@ -167,7 +165,7 @@
         shadowPaint.setColor(SK_ColorRED);
 
         SkScalar sigma = Blur::convertRadiusToSigma(5);
-        shadowPaint.setLooper(SkBlurDrawLooper::Create(SK_ColorWHITE, sigma, 3, 3))->unref();
+        shadowPaint.setLooper(SkBlurDrawLooper::Make(SK_ColorWHITE, sigma, 3, 3));
 
         TestUtils::drawUtf8ToCanvas(&canvas, "A", shadowPaint, 25, 25);
         TestUtils::drawUtf8ToCanvas(&canvas, "B", shadowPaint, 50, 50);
@@ -202,8 +200,8 @@
         props.mutateLayerProperties().setType(LayerType::RenderLayer);
 
         // provide different blend mode, so decoration draws contrast
-        props.mutateLayerProperties().setXferMode(SkXfermode::Mode::kSrc_Mode);
-        canvas.drawColor(Color::Black, SkXfermode::Mode::kSrcOver_Mode);
+        props.mutateLayerProperties().setXferMode(SkBlendMode::kSrc);
+        canvas.drawColor(Color::Black, SkBlendMode::kSrcOver);
     });
     OffscreenBuffer** layerHandle = node->getLayerHandle();
 
@@ -287,4 +285,4 @@
         EXPECT_EQ(1, reinterpret_cast<PathTexture*>(texture)->left);
         EXPECT_EQ(3, reinterpret_cast<PathTexture*>(texture)->top);
     });
-}
\ No newline at end of file
+}
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 259686b..818c29c 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -477,6 +477,35 @@
     EXPECT_EQ(4, renderer.getIndex());
 }
 
+RENDERTHREAD_TEST(FrameBuilder, regionClipStopsMerge) {
+    class RegionClipStopsMergeTestRenderer : public TestRendererBase {
+    public:
+        void onTextOp(const TextOp& op, const BakedOpState& state) override { mIndex++; }
+    };
+    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        SkPath path;
+        path.addCircle(200, 200, 200, SkPath::kCW_Direction);
+        canvas.save(SaveFlags::MatrixClip);
+        canvas.clipPath(&path, SkRegion::kIntersect_Op);
+        SkPaint paint;
+        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+        paint.setAntiAlias(true);
+        paint.setTextSize(50);
+        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
+        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 200);
+        canvas.restore();
+    });
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
+
+    RegionClipStopsMergeTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(2, renderer.getIndex());
+}
+
 RENDERTHREAD_TEST(FrameBuilder, textMerging) {
     class TextMergingTestRenderer : public TestRendererBase {
     public:
@@ -721,7 +750,7 @@
     auto unclippedColorView = TestUtils::createNode<RecordingCanvas>(0, 0, 10, 10,
             [](RenderProperties& props, RecordingCanvas& canvas) {
         props.setClipToBounds(false);
-        canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode);
+        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
     });
 
     FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
@@ -974,7 +1003,7 @@
         void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
             EXPECT_EQ(1, mIndex++);
             ASSERT_NE(nullptr, op.paint);
-            ASSERT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint));
+            ASSERT_EQ(SkBlendMode::kClear, PaintUtils::getBlendModeDirect(op.paint));
         }
         void onRectOp(const RectOp& op, const BakedOpState& state) override {
             EXPECT_EQ(2, mIndex++);
@@ -1108,7 +1137,7 @@
         void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
             EXPECT_EQ(1, mIndex++);
             ASSERT_NE(nullptr, op.paint);
-            EXPECT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint));
+            EXPECT_EQ(SkBlendMode::kClear, PaintUtils::getBlendModeDirect(op.paint));
             EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds)
                     << "Expect dirty rect as clip";
             ASSERT_NE(nullptr, state.computedState.clipState);
@@ -1433,7 +1462,7 @@
     auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
             [](RenderProperties& props, RecordingCanvas& canvas) {
         props.mutateLayerProperties().setType(LayerType::RenderLayer);
-        canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode);
+        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
     });
     OffscreenBuffer** layerHandle = node->getLayerHandle();
 
@@ -2196,7 +2225,7 @@
     auto node = TestUtils::createNode<RecordingCanvas>(20, 20, 30, 30,
             [](RenderProperties& props, RecordingCanvas& canvas) {
         canvas.clipRect(0, -20, 10, 30, SkRegion::kReplace_Op);
-        canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode);
+        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
     });
 
     FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 40, 40), 50, 50,
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index edc7191..46e685c 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -249,7 +249,7 @@
 
 TEST(RecordingCanvas, drawColor) {
     auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
-        canvas.drawColor(Color::Black, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(Color::Black, SkBlendMode::kSrcOver);
     });
 
     ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
@@ -639,7 +639,7 @@
     auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [](RecordingCanvas& canvas) {
         canvas.save(SaveFlags::MatrixClip);
         canvas.clipRect(-10, -10, 110, 110, SkRegion::kReplace_Op);
-        canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode);
+        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
         canvas.restore();
     });
     ASSERT_EQ(1u, dl->getOps().size()) << "Must have one op";
@@ -773,7 +773,7 @@
                 SkShader::TileMode::kRepeat_TileMode);
 
         sk_sp<SkShader> composeShader = SkShader::MakeComposeShader(std::move(shader1), std::move(shader2),
-                SkXfermode::Mode::kMultiply_Mode);
+                SkXfermode::kMultiply_Mode);
         paint.setShader(std::move(composeShader));
         canvas.drawRoundRect(0, 0, 100, 100, 20.0f, 20.0f, paint);
     });
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index 0d90afa..331a6ac 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -41,7 +41,7 @@
 TEST(RenderNode, hasParents) {
     auto child = TestUtils::createNode(0, 0, 200, 400,
             [](RenderProperties& props, Canvas& canvas) {
-        canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
     });
     auto parent = TestUtils::createNode(0, 0, 200, 400,
             [&child](RenderProperties& props, Canvas& canvas) {
@@ -54,7 +54,7 @@
     EXPECT_FALSE(parent->hasParents()) << "Root node shouldn't have any parents";
 
     TestUtils::recordNode(*parent, [](Canvas& canvas) {
-        canvas.drawColor(Color::Amber_500, SkXfermode::kSrcOver_Mode);
+        canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver);
     });
 
     EXPECT_TRUE(child->hasParents()) << "Child should still have a parent";
@@ -117,7 +117,7 @@
     {
         auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400,
                 [](RenderProperties& props, Canvas& canvas) {
-            canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode);
+            canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
         });
         TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode);
         EXPECT_TRUE(nonNullDLNode->getDisplayList());
@@ -160,7 +160,7 @@
 
     // Check that the VD is in the dislay list, and the layer update queue contains the correct
     // damage rect.
-    EXPECT_FALSE(rootNode->getDisplayList()->getVectorDrawables().empty());
+    EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables());
     EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
     EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode);
     EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
index a30ada0..1f4788a 100644
--- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
+++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
@@ -18,6 +18,7 @@
 
 #include <gtest/gtest.h>
 #include <SkColorMatrixFilter.h>
+#include <SkColorSpace.h>
 #include <SkImagePriv.h>
 #include <SkShader.h>
 
@@ -56,8 +57,8 @@
 
 TEST(SkiaBehavior, lightingColorFilter_simplify) {
     {
-        SkAutoTUnref<SkColorFilter> filter(
-                SkColorMatrixFilter::CreateLightingFilter(0x11223344, 0));
+        sk_sp<SkColorFilter> filter(
+                SkColorMatrixFilter::MakeLightingFilter(0x11223344, 0));
 
         SkColor observedColor;
         SkXfermode::Mode observedMode;
@@ -67,18 +68,24 @@
     }
 
     {
-        SkAutoTUnref<SkColorFilter> failFilter(
-                SkColorMatrixFilter::CreateLightingFilter(0x11223344, 0x1));
+        sk_sp<SkColorFilter> failFilter(
+                SkColorMatrixFilter::MakeLightingFilter(0x11223344, 0x1));
         EXPECT_FALSE(failFilter->asColorMode(nullptr, nullptr));
     }
 }
 
 TEST(SkiaBehavior, porterDuffCreateIsCached) {
     SkPaint paint;
-    paint.setXfermodeMode(SkXfermode::kOverlay_Mode);
-    auto expected = paint.getXfermode();
-    paint.setXfermodeMode(SkXfermode::kClear_Mode);
-    ASSERT_NE(expected, paint.getXfermode());
-    paint.setXfermodeMode(SkXfermode::kOverlay_Mode);
-    ASSERT_EQ(expected, paint.getXfermode());
+    paint.setBlendMode(SkBlendMode::kOverlay);
+    auto expected = paint.getBlendMode();
+    paint.setBlendMode(SkBlendMode::kClear);
+    ASSERT_NE(expected, paint.getBlendMode());
+    paint.setBlendMode(SkBlendMode::kOverlay);
+    ASSERT_EQ(expected, paint.getBlendMode());
+}
+
+TEST(SkiaBehavior, srgbColorSpaceIsSingleton) {
+    sk_sp<SkColorSpace> sRGB1 = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+    sk_sp<SkColorSpace> sRGB2 = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+    ASSERT_EQ(sRGB1.get(), sRGB2.get());
 }
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index 5a01193..451596d 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -45,7 +45,7 @@
         SkCanvas* skCanvas = recorder.beginRecording(200, 200, NULL, 0);
         std::unique_ptr<Canvas> pictCanvas(Canvas::create_canvas(skCanvas));
         TestUtils::drawUtf8ToCanvas(pictCanvas.get(), text, paint, 25, 25);
-        SkAutoTUnref<const SkPicture> picture(recorder.endRecording());
+        sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
 
         canvas.asSkCanvas()->drawPicture(picture);
     });
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
new file mode 100644
index 0000000..7f622eb
--- /dev/null
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -0,0 +1,189 @@
+/*
+ * 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 "SkiaDisplayList.h"
+#include "renderthread/CanvasContext.h"
+#include "tests/common/TestUtils.h"
+
+
+using namespace android;
+using namespace android::uirenderer;
+using namespace android::uirenderer::renderthread;
+
+TEST(SkiaDisplayList, create) {
+    SkRect bounds = SkRect::MakeWH(200, 200);
+    SkiaDisplayList skiaDL(bounds);
+    ASSERT_TRUE(skiaDL.isEmpty());
+    ASSERT_FALSE(skiaDL.mIsProjectionReceiver);
+    ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
+}
+
+TEST(SkiaDisplayList, reset) {
+    SkRect bounds = SkRect::MakeWH(200, 200);
+    SkiaDisplayList skiaDL(bounds);
+
+    SkCanvas dummyCanvas;
+    skiaDL.mChildNodes.emplace_back(nullptr, &dummyCanvas);
+    skiaDL.mChildFunctors.emplace_back(nullptr, nullptr, &dummyCanvas);
+    skiaDL.mMutableImages.push_back(nullptr);
+    skiaDL.mVectorDrawables.push_back(nullptr);
+    skiaDL.mDrawable->drawAnnotation(bounds, "testAnnotation", nullptr);
+    skiaDL.mIsProjectionReceiver = true;
+
+    ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
+    ASSERT_FALSE(skiaDL.mChildNodes.empty());
+    ASSERT_FALSE(skiaDL.mChildFunctors.empty());
+    ASSERT_FALSE(skiaDL.mMutableImages.empty());
+    ASSERT_FALSE(skiaDL.mVectorDrawables.empty());
+    ASSERT_FALSE(skiaDL.isEmpty());
+    ASSERT_TRUE(skiaDL.mIsProjectionReceiver);
+
+    bounds = SkRect::MakeWH(100, 100);
+    skiaDL.reset(nullptr, bounds);
+
+    ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
+    ASSERT_TRUE(skiaDL.mChildNodes.empty());
+    ASSERT_TRUE(skiaDL.mChildFunctors.empty());
+    ASSERT_TRUE(skiaDL.mMutableImages.empty());
+    ASSERT_TRUE(skiaDL.mVectorDrawables.empty());
+    ASSERT_TRUE(skiaDL.isEmpty());
+    ASSERT_FALSE(skiaDL.mIsProjectionReceiver);
+}
+
+TEST(SkiaDisplayList, reuseDisplayList) {
+    sp<RenderNode> renderNode = new RenderNode();
+    std::unique_ptr<SkiaDisplayList> availableList;
+
+    // no list has been attached so it should return a nullptr
+    availableList = renderNode->detachAvailableList();
+    ASSERT_EQ(availableList.get(), nullptr);
+
+    // attach a displayList for reuse
+    SkiaDisplayList skiaDL(SkRect::MakeWH(200, 200));
+    ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get(), nullptr));
+
+    // detach the list that you just attempted to reuse
+    availableList = renderNode->detachAvailableList();
+    ASSERT_EQ(availableList.get(), &skiaDL);
+    availableList.release(); // prevents an invalid free since our DL is stack allocated
+
+    // after detaching there should return no available list
+    availableList = renderNode->detachAvailableList();
+    ASSERT_EQ(availableList.get(), nullptr);
+}
+
+class TestFunctor : public Functor {
+public:
+    bool didSync = false;
+
+    virtual status_t operator ()(int what, void* data) {
+        if (what == DrawGlInfo::kModeSync) { didSync = true; }
+        return DrawGlInfo::kStatusDone;
+    }
+};
+
+TEST(SkiaDisplayList, syncContexts) {
+    SkRect bounds = SkRect::MakeWH(200, 200);
+    SkiaDisplayList skiaDL(bounds);
+
+    SkCanvas dummyCanvas;
+    TestFunctor functor;
+    skiaDL.mChildFunctors.emplace_back(&functor, nullptr, &dummyCanvas);
+
+    VectorDrawableRoot vectorDrawable(new VectorDrawable::Group());
+    vectorDrawable.mutateStagingProperties()->setBounds(bounds);
+    skiaDL.mVectorDrawables.push_back(&vectorDrawable);
+
+    // ensure that the functor and vectorDrawable are properly synced
+    skiaDL.syncContents();
+
+    ASSERT_TRUE(functor.didSync);
+    ASSERT_EQ(vectorDrawable.mutateProperties()->getBounds(), bounds);
+}
+
+class ContextFactory : public IContextFactory {
+public:
+    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
+        return new AnimationContext(clock);
+    }
+};
+
+RENDERTHREAD_TEST(SkiaDisplayList, prepareListAndChildren) {
+    auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
+    ContextFactory contextFactory;
+    std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
+            renderThread, false, rootNode.get(), &contextFactory));
+    TreeInfo info(TreeInfo::MODE_FULL, *canvasContext.get());
+    DamageAccumulator damageAccumulator;
+    info.damageAccumulator = &damageAccumulator;
+    info.observer = nullptr;
+
+    SkiaDisplayList skiaDL(SkRect::MakeWH(200, 200));
+
+    // prepare with a clean VD
+    VectorDrawableRoot cleanVD(new VectorDrawable::Group());
+    skiaDL.mVectorDrawables.push_back(&cleanVD);
+    cleanVD.getBitmapUpdateIfDirty(); // this clears the dirty bit
+
+    ASSERT_FALSE(cleanVD.isDirty());
+    ASSERT_FALSE(cleanVD.getPropertyChangeWillBeConsumed());
+    ASSERT_FALSE(skiaDL.prepareListAndChildren(info, false, [](RenderNode*, TreeInfo&, bool) {}));
+    ASSERT_TRUE(cleanVD.getPropertyChangeWillBeConsumed());
+
+    // prepare again this time adding a dirty VD
+    VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+    skiaDL.mVectorDrawables.push_back(&dirtyVD);
+
+    ASSERT_TRUE(dirtyVD.isDirty());
+    ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+    ASSERT_TRUE(skiaDL.prepareListAndChildren(info, false, [](RenderNode*, TreeInfo&, bool) {}));
+    ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+    // prepare again this time adding a RenderNode and a callback
+    sp<RenderNode> renderNode = new RenderNode();
+    TreeInfo* infoPtr = &info;
+    SkCanvas dummyCanvas;
+    skiaDL.mChildNodes.emplace_back(renderNode.get(), &dummyCanvas);
+    bool hasRun = false;
+    ASSERT_TRUE(skiaDL.prepareListAndChildren(info, false,
+            [&hasRun, renderNode, infoPtr](RenderNode* n, TreeInfo& i, bool r) {
+        hasRun = true;
+        ASSERT_EQ(renderNode.get(), n);
+        ASSERT_EQ(infoPtr, &i);
+        ASSERT_FALSE(r);
+    }));
+    ASSERT_TRUE(hasRun);
+
+    canvasContext->destroy(nullptr);
+}
+
+TEST(SkiaDisplayList, updateChildren) {
+    SkRect bounds = SkRect::MakeWH(200, 200);
+    SkiaDisplayList skiaDL(bounds);
+
+    sp<RenderNode> renderNode = new RenderNode();
+    SkCanvas dummyCanvas;
+    skiaDL.mChildNodes.emplace_back(renderNode.get(), &dummyCanvas);
+    skiaDL.updateChildren([renderNode](RenderNode* n) {
+        ASSERT_EQ(renderNode.get(), n);
+    });
+}
diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp
index 83b485f..8e0d3ee 100644
--- a/libs/hwui/tests/unit/VectorDrawableTests.cpp
+++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp
@@ -426,5 +426,49 @@
     EXPECT_EQ(1.0f, properties->getPivotY());
 
 }
+
+static SkShader* createShader(bool* isDestroyed) {
+    class TestShader : public SkShader {
+    public:
+        TestShader(bool* isDestroyed) : SkShader(), mDestroyed(isDestroyed) {
+        }
+        ~TestShader() {
+            *mDestroyed = true;
+        }
+
+        Factory getFactory() const override { return nullptr; }
+    private:
+        bool* mDestroyed;
+    };
+    return new TestShader(isDestroyed);
+}
+
+TEST(VectorDrawable, drawPathWithoutIncrementingShaderRefCount) {
+    VectorDrawable::FullPath path("m1 1", 4);
+    SkBitmap bitmap;
+    SkImageInfo info = SkImageInfo::Make(5, 5, kN32_SkColorType, kPremul_SkAlphaType);
+    bitmap.setInfo(info);
+    bitmap.allocPixels(info);
+    SkCanvas canvas(bitmap);
+
+    bool shaderIsDestroyed = false;
+
+    // Initial ref count is 1
+    SkShader* shader = createShader(&shaderIsDestroyed);
+
+    // Setting the fill gradient increments the ref count of the shader by 1
+    path.mutateStagingProperties()->setFillGradient(shader);
+    path.draw(&canvas, SkMatrix::I(), 1.0f, 1.0f, true);
+    // Resetting the fill gradient decrements the ref count of the shader by 1
+    path.mutateStagingProperties()->setFillGradient(nullptr);
+
+    // Expect ref count to be 1 again, i.e. nothing else to have a ref to the shader now. Unref()
+    // again should bring the ref count to zero and consequently trigger detor.
+    shader->unref();
+
+    // Verify that detor is called.
+    EXPECT_TRUE(shaderIsDestroyed);
+}
+
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index b5157f4..f9cc46d1 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -16,6 +16,8 @@
 #ifndef COLOR_H
 #define COLOR_H
 
+#include <math.h>
+
 #include <SkColor.h>
 
 namespace android {
@@ -80,6 +82,42 @@
     };
     static constexpr int BrightColorsCount = sizeof(BrightColors) / sizeof(Color::Color);
 
+    // Opto-electronic conversion function for the sRGB color space
+    // Takes a gamma-encoded sRGB value and converts it to a linear sRGB value
+    static constexpr float OECF_sRGB(float linear) {
+        // IEC 61966-2-1:1999
+        return linear <= 0.0031308f ?
+                linear * 12.92f : (powf(linear, 1.0f / 2.4f) * 1.055f) - 0.055f;
+    }
+
+    // Opto-electronic conversion function for the sRGB color space
+    // Takes a gamma-encoded sRGB value and converts it to a linear sRGB value
+    // This function returns the input unmodified if linear blending is not enabled
+    static constexpr float OECF(float linear) {
+#ifdef ANDROID_ENABLE_LINEAR_BLENDING
+        return OECF_sRGB(linear);
+#else
+        return linear;
+#endif
+    }
+
+    // Electro-optical conversion function for the sRGB color space
+    // Takes a linear sRGB value and converts it to a gamma-encoded sRGB value
+    static constexpr float EOCF_sRGB(float srgb) {
+        // IEC 61966-2-1:1999
+        return srgb <= 0.04045f ? srgb / 12.92f : powf((srgb + 0.055f) / 1.055f, 2.4f);
+    }
+
+    // Electro-optical conversion function for the sRGB color space
+    // Takes a linear sRGB value and converts it to a gamma-encoded sRGB value
+    // This function returns the input unmodified if linear blending is not enabled
+    static constexpr float EOCF(float srgb) {
+#ifdef ANDROID_ENABLE_LINEAR_BLENDING
+        return EOCF_sRGB(srgb);
+#else
+        return srgb;
+#endif
+    }
 } /* namespace uirenderer */
 } /* namespace android */
 
diff --git a/libs/hwui/utils/NinePatchImpl.cpp b/libs/hwui/utils/NinePatchImpl.cpp
index d37126c..cef214b 100644
--- a/libs/hwui/utils/NinePatchImpl.cpp
+++ b/libs/hwui/utils/NinePatchImpl.cpp
@@ -134,7 +134,7 @@
 
     if (bounds.isEmpty() ||
         bitmap.width() == 0 || bitmap.height() == 0 ||
-        (paint && paint->getXfermode() == NULL && paint->getAlpha() == 0))
+        (paint && paint->isSrcOver() && paint->getAlpha() == 0))
     {
         if (kUseTrace) {
             ALOGV("======== abort ninepatch draw\n");
@@ -149,7 +149,7 @@
     if (bitmap.getPixels() == NULL)
         return;
 
-    const bool hasXfer = paint->getXfermode() != NULL;
+    const bool hasXfer = !paint->isSrcOver();
     SkRect      dst;
     SkIRect     src;
 
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index 4faab9a..710e063 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -33,18 +33,6 @@
 class PaintUtils {
 public:
 
-   /**
-     * Safely retrieves the mode from the specified xfermode. If the specified
-     * xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
-     */
-    static inline SkXfermode::Mode getXfermode(SkXfermode* mode) {
-        SkXfermode::Mode resultMode;
-        if (!SkXfermode::AsMode(mode, &resultMode)) {
-            resultMode = SkXfermode::kSrcOver_Mode;
-        }
-        return resultMode;
-    }
-
     static inline GLenum getFilter(const SkPaint* paint) {
         if (!paint || paint->getFilterQuality() != kNone_SkFilterQuality) {
             return GL_LINEAR;
@@ -56,7 +44,7 @@
     static inline bool paintWillNotDraw(const SkPaint& paint) {
         return paint.getAlpha() == 0
                 && !paint.getColorFilter()
-                && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
+                && paint.getBlendMode() == SkBlendMode::kSrcOver;
     }
 
     // TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()?
@@ -64,7 +52,7 @@
         return paint.getAlpha() == 0
                 && paint.getLooper() == nullptr
                 && !paint.getColorFilter()
-                && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
+                && paint.getBlendMode() == SkBlendMode::kSrcOver;
     }
 
     static bool isOpaquePaint(const SkPaint* paint) {
@@ -77,9 +65,9 @@
         }
 
         // Only let simple srcOver / src blending modes declare opaque, since behavior is clear.
-        SkXfermode::Mode mode = getXfermode(paint->getXfermode());
-        return mode == SkXfermode::Mode::kSrcOver_Mode
-                || mode == SkXfermode::Mode::kSrc_Mode;
+        SkBlendMode mode = paint->getBlendMode();
+        return mode == SkBlendMode::kSrcOver
+                || mode == SkBlendMode::kSrc;
     }
 
     static bool isBlendedShader(const SkShader* shader) {
@@ -121,8 +109,8 @@
         return getTextShadow(paint, nullptr);
     }
 
-    static inline SkXfermode::Mode getXfermodeDirect(const SkPaint* paint) {
-        return paint ? getXfermode(paint->getXfermode()) : SkXfermode::kSrcOver_Mode;
+    static inline SkBlendMode getBlendModeDirect(const SkPaint* paint) {
+        return paint ? paint->getBlendMode() : SkBlendMode::kSrcOver;
     }
 
     static inline int getAlphaDirect(const SkPaint* paint) {
diff --git a/libs/hwui/utils/TestWindowContext.cpp b/libs/hwui/utils/TestWindowContext.cpp
index b879f78..624d207 100644
--- a/libs/hwui/utils/TestWindowContext.cpp
+++ b/libs/hwui/utils/TestWindowContext.cpp
@@ -110,9 +110,10 @@
     }
 
     bool capturePixels(SkBitmap* bmp) {
+        sk_sp<SkColorSpace> colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
         SkImageInfo destinationConfig =
             SkImageInfo::Make(mSize.width(), mSize.height(),
-                              kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+                              kRGBA_8888_SkColorType, kPremul_SkAlphaType, colorSpace);
         bmp->allocPixels(destinationConfig);
         android_memset32((uint32_t*) bmp->getPixels(), SK_ColorRED,
                          mSize.width() * mSize.height() * 4);
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 0bc832a..6941dba 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -216,7 +216,7 @@
                 SkCanvas surfaceCanvas(surfaceBitmap);
 
                 SkPaint paint;
-                paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+                paint.setBlendMode(SkBlendMode::kSrc);
                 surfaceCanvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint);
 
                 if (outBuffer.width > update.state.icon.bitmap.width()) {
diff --git a/media/java/android/media/AmrInputStream.java b/media/java/android/media/AmrInputStream.java
index f90f1e2..fb91bbb 100644
--- a/media/java/android/media/AmrInputStream.java
+++ b/media/java/android/media/AmrInputStream.java
@@ -18,45 +18,69 @@
 
 import java.io.InputStream;
 import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import android.media.MediaCodec.BufferInfo;
+import android.util.Log;
 
 
 /**
  * AmrInputStream
  * @hide
  */
-public final class AmrInputStream extends InputStream
-{    
-    static {
-        System.loadLibrary("media_jni");
-    }
-    
+public final class AmrInputStream extends InputStream {
     private final static String TAG = "AmrInputStream";
     
     // frame is 20 msec at 8.000 khz
     private final static int SAMPLES_PER_FRAME = 8000 * 20 / 1000;
-    
+
+    MediaCodec mCodec;
+    BufferInfo mInfo;
+    boolean mSawOutputEOS;
+    boolean mSawInputEOS;
+
     // pcm input stream
     private InputStream mInputStream;
-    
-    // native handle
-    private long mGae;
-    
+
     // result amr stream
     private final byte[] mBuf = new byte[SAMPLES_PER_FRAME * 2];
     private int mBufIn = 0;
     private int mBufOut = 0;
-    
+
     // helper for bytewise read()
     private byte[] mOneByte = new byte[1];
-    
+
     /**
      * Create a new AmrInputStream, which converts 16 bit PCM to AMR
      * @param inputStream InputStream containing 16 bit PCM.
      */
     public AmrInputStream(InputStream inputStream) {
         mInputStream = inputStream;
-        mGae = GsmAmrEncoderNew();
-        GsmAmrEncoderInitialize(mGae);
+
+        MediaFormat format  = new MediaFormat();
+        format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AMR_NB);
+        format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000);
+        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, 12200);
+
+        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+        String name = mcl.findEncoderForFormat(format);
+        if (name != null) {
+            try {
+                mCodec = MediaCodec.createByCodecName(name);
+                mCodec.configure(format,
+                        null /* surface */,
+                        null /* crypto */,
+                        MediaCodec.CONFIGURE_FLAG_ENCODE);
+                mCodec.start();
+            } catch (IOException e) {
+                if (mCodec != null) {
+                    mCodec.release();
+                }
+                mCodec = null;
+            }
+        }
+        mInfo = new BufferInfo();
     }
 
     @Override
@@ -64,7 +88,7 @@
         int rtn = read(mOneByte, 0, 1);
         return rtn == 1 ? (0xff & mOneByte[0]) : -1;
     }
-    
+
     @Override
     public int read(byte[] b) throws IOException {
         return read(b, 0, b.length);
@@ -72,67 +96,100 @@
 
     @Override
     public int read(byte[] b, int offset, int length) throws IOException {
-        if (mGae == 0) throw new IllegalStateException("not open");
-        
-        // local buffer of amr encoded audio empty
-        if (mBufOut >= mBufIn) {
-            // reset the buffer
+        if (mCodec == null) {
+            throw new IllegalStateException("not open");
+        }
+
+        if (mBufOut >= mBufIn && !mSawOutputEOS) {
+            // no data left in buffer, refill it
             mBufOut = 0;
             mBufIn = 0;
-            
-            // fetch a 20 msec frame of pcm
-            for (int i = 0; i < SAMPLES_PER_FRAME * 2; ) {
-                int n = mInputStream.read(mBuf, i, SAMPLES_PER_FRAME * 2 - i);
-                if (n == -1) return -1;
-                i += n;
+
+            // first push as much data into the encoder as possible
+            while (!mSawInputEOS) {
+                int index = mCodec.dequeueInputBuffer(0);
+                if (index < 0) {
+                    // no input buffer currently available
+                    break;
+                } else {
+                    int numRead;
+                    for (numRead = 0; numRead < SAMPLES_PER_FRAME * 2; ) {
+                        int n = mInputStream.read(mBuf, numRead, SAMPLES_PER_FRAME * 2 - numRead);
+                        if (n == -1) {
+                            mSawInputEOS = true;
+                            break;
+                        }
+                        numRead += n;
+                    }
+                    ByteBuffer buf = mCodec.getInputBuffer(index);
+                    buf.put(mBuf, 0, numRead);
+                    mCodec.queueInputBuffer(index,
+                            0 /* offset */,
+                            numRead,
+                            0 /* presentationTimeUs */,
+                            mSawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0 /* flags */);
+                }
             }
-            
-            // encode it
-            mBufIn = GsmAmrEncoderEncode(mGae, mBuf, 0, mBuf, 0);
+
+            // now read encoded data from the encoder (blocking, since we just filled up the
+            // encoder's input with data it should be able to output at least one buffer)
+            while (true) {
+                int index = mCodec.dequeueOutputBuffer(mInfo, -1);
+                if (index >= 0) {
+                    mBufIn = mInfo.size;
+                    ByteBuffer out = mCodec.getOutputBuffer(index);
+                    out.get(mBuf, 0 /* offset */, mBufIn /* length */);
+                    mCodec.releaseOutputBuffer(index,  false /* render */);
+                    if ((mInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                        mSawOutputEOS = true;
+                    }
+                    break;
+                }
+            }
         }
-        
-        // return encoded audio to user
-        if (length > mBufIn - mBufOut) length = mBufIn - mBufOut;
-        System.arraycopy(mBuf, mBufOut, b, offset, length);
-        mBufOut += length;
-        
-        return length;
+
+        if (mBufOut < mBufIn) {
+            // there is data in the buffer
+            if (length > mBufIn - mBufOut) {
+                length = mBufIn - mBufOut;
+            }
+            System.arraycopy(mBuf, mBufOut, b, offset, length);
+            mBufOut += length;
+            return length;
+        }
+
+        if (mSawInputEOS && mSawOutputEOS) {
+            // no more data available in buffer, codec or input stream
+            return -1;
+        }
+
+        // caller should try again
+        return 0;
     }
 
     @Override
     public void close() throws IOException {
         try {
-            if (mInputStream != null) mInputStream.close();
+            if (mInputStream != null) {
+                mInputStream.close();
+            }
         } finally {
             mInputStream = null;
             try {
-                if (mGae != 0) GsmAmrEncoderCleanup(mGae);
-            } finally {
-                try {
-                    if (mGae != 0) GsmAmrEncoderDelete(mGae);
-                } finally {
-                    mGae = 0;
+                if (mCodec != null) {
+                    mCodec.release();
                 }
+            } finally {
+                mCodec = null;
             }
         }
     }
 
     @Override
     protected void finalize() throws Throwable {
-        if (mGae != 0) {
-            close();
-            throw new IllegalStateException("someone forgot to close AmrInputStream");
+        if (mCodec != null) {
+            Log.w(TAG, "AmrInputStream wasn't closed");
+            mCodec.release();
         }
     }
-    
-    //
-    // AudioRecord JNI interface
-    //
-    private static native long GsmAmrEncoderNew();
-    private static native void GsmAmrEncoderInitialize(long gae);
-    private static native int GsmAmrEncoderEncode(long gae,
-            byte[] pcm, int pcmOffset, byte[] amr, int amrOffset) throws IOException;
-    private static native void GsmAmrEncoderCleanup(long gae);
-    private static native void GsmAmrEncoderDelete(long gae);
-
 }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 33c1c3f..f24bf09 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -312,29 +312,32 @@
      */
     public static final String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS";
 
-    /** The audio stream for phone calls */
+    /** Used to identify the volume of audio streams for phone calls */
     public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
-    /** The audio stream for system sounds */
+    /** Used to identify the volume of audio streams for system sounds */
     public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
-    /** The audio stream for the phone ring */
+    /** Used to identify the volume of audio streams for the phone ring */
     public static final int STREAM_RING = AudioSystem.STREAM_RING;
-    /** The audio stream for music playback */
+    /** Used to identify the volume of audio streams for music playback */
     public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
-    /** The audio stream for alarms */
+    /** Used to identify the volume of audio streams for alarms */
     public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;
-    /** The audio stream for notifications */
+    /** Used to identify the volume of audio streams for notifications */
     public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;
-    /** @hide The audio stream for phone calls when connected to bluetooth */
+    /** @hide Used to identify the volume of audio streams for phone calls when connected
+     *        to bluetooth */
     public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;
-    /** @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */
+    /** @hide Used to identify the volume of audio streams for enforced system sounds
+     *        in certain countries (e.g camera in Japan) */
     public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED;
-    /** The audio stream for DTMF Tones */
+    /** Used to identify the volume of audio streams for DTMF Tones */
     public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF;
-    /** @hide The audio stream for text to speech (TTS) */
+    /** @hide Used to identify the volume of audio streams exclusively transmitted through the
+     *        speaker (TTS) of the device */
     public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
     /** Number of audio streams */
     /**
-     * @deprecated Use AudioSystem.getNumStreamTypes() instead
+     * @deprecated Do not iterate on volume stream type values.
      */
     @Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS;
 
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index f9bc95c..384be5c 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -39,27 +39,29 @@
      * If these are modified, please also update Settings.System.VOLUME_SETTINGS
      * and attrs.xml and AudioManager.java.
      */
-    /* The default audio stream */
+    /** Used to identify the default audio stream volume */
     public static final int STREAM_DEFAULT = -1;
-    /* The audio stream for phone calls */
+    /** Used to identify the volume of audio streams for phone calls */
     public static final int STREAM_VOICE_CALL = 0;
-    /* The audio stream for system sounds */
+    /** Used to identify the volume of audio streams for system sounds */
     public static final int STREAM_SYSTEM = 1;
-    /* The audio stream for the phone ring and message alerts */
+    /** Used to identify the volume of audio streams for the phone ring and message alerts */
     public static final int STREAM_RING = 2;
-    /* The audio stream for music playback */
+    /** Used to identify the volume of audio streams for music playback */
     public static final int STREAM_MUSIC = 3;
-    /* The audio stream for alarms */
+    /** Used to identify the volume of audio streams for alarms */
     public static final int STREAM_ALARM = 4;
-    /* The audio stream for notifications */
+    /** Used to identify the volume of audio streams for notifications */
     public static final int STREAM_NOTIFICATION = 5;
-    /* @hide The audio stream for phone calls when connected on bluetooth */
+    /** Used to identify the volume of audio streams for phone calls when connected on bluetooth */
     public static final int STREAM_BLUETOOTH_SCO = 6;
-    /* @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */
+    /** Used to identify the volume of audio streams for enforced system sounds in certain
+     * countries (e.g camera in Japan) */
     public static final int STREAM_SYSTEM_ENFORCED = 7;
-    /* @hide The audio stream for DTMF tones */
+    /** Used to identify the volume of audio streams for DTMF tones */
     public static final int STREAM_DTMF = 8;
-    /* @hide The audio stream for text to speech (TTS) */
+    /** Used to identify the volume of audio streams exclusively transmitted through the
+     *  speaker (TTS) of the device */
     public static final int STREAM_TTS = 9;
     /**
      * @deprecated Use {@link #numStreamTypes() instead}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 69710d6..d77a082 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -1764,16 +1764,13 @@
      * <p>
      * This method is only supported for JPEG files.
      * </p>
-     *
-     * @throws UnsupportedOperationException If this method is called with unsupported files.
      */
     public void saveAttributes() throws IOException {
         if (!mIsSupportedFile || mMimeType != IMAGE_TYPE_JPEG) {
-            throw new UnsupportedOperationException(
-                    "ExifInterface only supports saving attributes on JPEG formats.");
+            throw new IOException("ExifInterface only supports saving attributes on JPEG formats.");
         }
         if (mIsInputStream || (mSeekableFileDescriptor == null && mFilename == null)) {
-            throw new UnsupportedOperationException(
+            throw new IOException(
                     "ExifInterface does not support saving attributes for the current input.");
         }
 
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 8ae6e6b..7767712 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -371,6 +371,7 @@
 
     private void destroyLocalPlayer() {
         if (mLocalPlayer != null) {
+            mLocalPlayer.setOnCompletionListener(null);
             mLocalPlayer.reset();
             mLocalPlayer.release();
             mLocalPlayer = null;
@@ -467,11 +468,12 @@
     }
 
     class MyOnCompletionListener implements MediaPlayer.OnCompletionListener {
-        public void onCompletion(MediaPlayer mp)
-        {
+        @Override
+        public void onCompletion(MediaPlayer mp) {
             synchronized (sActiveRingtones) {
                 sActiveRingtones.remove(Ringtone.this);
             }
+            mp.setOnCompletionListener(null); // Help the Java GC: break the refcount cycle.
         }
     }
 }
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index 4e7551c..d6958b3 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -25,7 +25,9 @@
 import android.os.ParcelFileDescriptor;
 
 import android.os.UserManager;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
+import dalvik.system.CloseGuard;
 
 import java.io.IOException;
 
@@ -45,6 +47,16 @@
         System.loadLibrary("media_jni");
     }
 
+    /** Make sure that MTP device is closed properly */
+    @GuardedBy("mLock")
+    private CloseGuard mCloseGuard = CloseGuard.get();
+
+    /** Current connection to the {@link #mDevice}, or null if device is not connected */
+    @GuardedBy("mLock")
+    private UsbDeviceConnection mConnection;
+
+    private final Object mLock = new Object();
+
     /**
      * MtpClient constructor
      *
@@ -68,17 +80,25 @@
         boolean result = false;
 
         Context context = connection.getContext();
-        if (context != null) {
-            UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
 
-            if (!userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
-                result = native_open(mDevice.getDeviceName(), connection.getFileDescriptor());
+        synchronized (mLock) {
+            if (context != null) {
+                UserManager userManager = (UserManager) context
+                        .getSystemService(Context.USER_SERVICE);
+
+                if (!userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
+                    result = native_open(mDevice.getDeviceName(), connection.getFileDescriptor());
+                }
+            }
+
+            if (!result) {
+                connection.close();
+            } else {
+                mConnection = connection;
+                mCloseGuard.open("close");
             }
         }
 
-        if (!result) {
-            connection.close();
-        }
         return result;
     }
 
@@ -88,13 +108,23 @@
      * with a new {@link android.hardware.usb.UsbDeviceConnection}.
      */
     public void close() {
-        native_close();
+        synchronized (mLock) {
+            if (mConnection != null) {
+                mCloseGuard.close();
+
+                native_close();
+
+                mConnection.close();
+                mConnection = null;
+            }
+        }
     }
 
     @Override
     protected void finalize() throws Throwable {
         try {
-            native_close();
+            mCloseGuard.warnIfOpen();
+            close();
         } finally {
             super.finalize();
         }
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index dcd5057..44f7e56 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -2,7 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    android_media_AmrInputStream.cpp \
     android_media_ImageWriter.cpp \
     android_media_ImageReader.cpp \
     android_media_MediaCrypto.cpp \
@@ -44,11 +43,9 @@
     libmtp \
     libusbhost \
     libexif \
-    libpiex \
-    libstagefright_amrnb_common
+    libpiex
 
 LOCAL_STATIC_LIBRARIES := \
-    libstagefright_amrnbenc
 
 LOCAL_C_INCLUDES += \
     external/libexif/ \
@@ -58,9 +55,6 @@
     frameworks/base/libs/hwui \
     frameworks/av/media/libmedia \
     frameworks/av/media/libstagefright \
-    frameworks/av/media/libstagefright/codecs/amrnb/enc/src \
-    frameworks/av/media/libstagefright/codecs/amrnb/common \
-    frameworks/av/media/libstagefright/codecs/amrnb/common/include \
     frameworks/av/media/mtp \
     frameworks/native/include/media/openmax \
     $(call include-path-for, libhardware)/hardware \
diff --git a/media/jni/android_media_AmrInputStream.cpp b/media/jni/android_media_AmrInputStream.cpp
deleted file mode 100644
index b56a364..0000000
--- a/media/jni/android_media_AmrInputStream.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-**
-** Copyright 2007, 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.
-*/
-
-#define LOG_TAG "AmrInputStream"
-#include "utils/Log.h"
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "gsmamr_enc.h"
-
-// ----------------------------------------------------------------------------
-
-using namespace android;
-
-// Corresponds to max bit rate of 12.2 kbps.
-static const int MAX_OUTPUT_BUFFER_SIZE = 32;
-static const int FRAME_DURATION_MS = 20;
-static const int SAMPLING_RATE_HZ = 8000;
-static const int SAMPLES_PER_FRAME = ((SAMPLING_RATE_HZ * FRAME_DURATION_MS) / 1000);
-static const int BYTES_PER_SAMPLE = 2;  // Assume 16-bit PCM samples
-static const int BYTES_PER_FRAME = (SAMPLES_PER_FRAME * BYTES_PER_SAMPLE);
-
-struct GsmAmrEncoderState {
-    GsmAmrEncoderState()
-        : mEncState(NULL),
-          mSidState(NULL),
-          mLastModeUsed(0) {
-    }
-
-    ~GsmAmrEncoderState() {}
-
-    void*   mEncState;
-    void*   mSidState;
-    int32_t mLastModeUsed;
-};
-
-static jlong android_media_AmrInputStream_GsmAmrEncoderNew
-        (JNIEnv *env, jclass /* clazz */) {
-    GsmAmrEncoderState* gae = new GsmAmrEncoderState();
-    if (gae == NULL) {
-        jniThrowRuntimeException(env, "Out of memory");
-    }
-    return (jlong)gae;
-}
-
-static void android_media_AmrInputStream_GsmAmrEncoderInitialize
-        (JNIEnv *env, jclass /* clazz */, jlong gae) {
-    GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
-    int32_t nResult = AMREncodeInit(&state->mEncState, &state->mSidState, false);
-    if (nResult != OK) {
-        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
-                "GsmAmrEncoder initialization failed %d", nResult);
-    }
-}
-
-static jint android_media_AmrInputStream_GsmAmrEncoderEncode
-        (JNIEnv *env, jclass /* clazz */,
-         jlong gae, jbyteArray pcm, jint pcmOffset, jbyteArray amr, jint amrOffset) {
-
-    jbyte inBuf[BYTES_PER_FRAME];
-    jbyte outBuf[MAX_OUTPUT_BUFFER_SIZE];
-
-    env->GetByteArrayRegion(pcm, pcmOffset, sizeof(inBuf), inBuf);
-    GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
-    int32_t length = AMREncode(state->mEncState, state->mSidState,
-                                (Mode) MR122,
-                                (int16_t *) inBuf,
-                                (unsigned char *) outBuf,
-                                (Frame_Type_3GPP*) &state->mLastModeUsed,
-                                AMR_TX_WMF);
-    if (length < 0) {
-        jniThrowExceptionFmt(env, "java/io/IOException",
-                "Failed to encode a frame with error code: %d", length);
-        return (jint)-1;
-    }
-
-    // The 1st byte of PV AMR frames are WMF (Wireless Multimedia Forum)
-    // bitpacked, i.e.;
-    //    [P(4) + FT(4)]. Q=1 for good frame, P=padding bit, 0
-    // Here we are converting the header to be as specified in Section 5.3 of
-    // RFC 3267 (AMR storage format) i.e.
-    //    [P(1) + FT(4) + Q(1) + P(2)].
-    if (length > 0) {
-      outBuf[0] = (outBuf[0] << 3) | 0x4;
-    }
-
-    env->SetByteArrayRegion(amr, amrOffset, length, outBuf);
-
-    return (jint)length;
-}
-
-static void android_media_AmrInputStream_GsmAmrEncoderCleanup
-        (JNIEnv* /* env */, jclass /* clazz */, jlong gae) {
-    GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
-    AMREncodeExit(&state->mEncState, &state->mSidState);
-    state->mEncState = NULL;
-    state->mSidState = NULL;
-}
-
-static void android_media_AmrInputStream_GsmAmrEncoderDelete
-        (JNIEnv* /* env */, jclass /* clazz */, jlong gae) {
-    delete (GsmAmrEncoderState*)gae;
-}
-
-// ----------------------------------------------------------------------------
-
-static const JNINativeMethod gMethods[] = {
-    {"GsmAmrEncoderNew",        "()J",        (void*)android_media_AmrInputStream_GsmAmrEncoderNew},
-    {"GsmAmrEncoderInitialize", "(J)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderInitialize},
-    {"GsmAmrEncoderEncode",     "(J[BI[BI)I", (void*)android_media_AmrInputStream_GsmAmrEncoderEncode},
-    {"GsmAmrEncoderCleanup",    "(J)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderCleanup},
-    {"GsmAmrEncoderDelete",     "(J)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderDelete},
-};
-
-
-int register_android_media_AmrInputStream(JNIEnv *env)
-{
-    const char* const kClassPathName = "android/media/AmrInputStream";
-
-    return AndroidRuntime::registerNativeMethods(env,
-            kClassPathName, gMethods, NELEM(gMethods));
-}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index ecf733f..c825702 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1105,7 +1105,6 @@
 extern int register_android_media_MediaSync(JNIEnv *env);
 extern int register_android_media_ResampleInputStream(JNIEnv *env);
 extern int register_android_media_MediaProfiles(JNIEnv *env);
-extern int register_android_media_AmrInputStream(JNIEnv *env);
 extern int register_android_mtp_MtpDatabase(JNIEnv *env);
 extern int register_android_mtp_MtpDevice(JNIEnv *env);
 extern int register_android_mtp_MtpServer(JNIEnv *env);
@@ -1151,11 +1150,6 @@
         goto bail;
     }
 
-    if (register_android_media_AmrInputStream(env) < 0) {
-        ALOGE("ERROR: AmrInputStream native registration failed\n");
-        goto bail;
-    }
-
     if (register_android_media_ResampleInputStream(env) < 0) {
         ALOGE("ERROR: ResampleInputStream native registration failed\n");
         goto bail;
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 8bcc85f..768ac1d 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -194,6 +194,9 @@
         return JNI_FALSE;
     }
 
+    // The passed in fd is maintained by the UsbDeviceConnection
+    fd = dup(fd);
+
     MtpDevice* device = MtpDevice::open(deviceNameStr, fd);
     env->ReleaseStringUTFChars(deviceName, deviceNameStr);
 
diff --git a/media/jni/audioeffect/Android.mk b/media/jni/audioeffect/Android.mk
index 5c22c9b..91dd8a5 100644
--- a/media/jni/audioeffect/Android.mk
+++ b/media/jni/audioeffect/Android.mk
@@ -13,9 +13,6 @@
     libnativehelper \
     libmedia
 
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-effects)
-
 LOCAL_MODULE:= libaudioeffect_jni
 
 LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index a9b7062..401012f 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -352,7 +352,7 @@
                                     effectCallback,
                                     &lpJniStorage->mCallbackData,
                                     (audio_session_t) sessionId,
-                                    0);
+                                    AUDIO_IO_HANDLE_NONE);
     if (lpAudioEffect == 0) {
         ALOGE("Error creating AudioEffect");
         goto setup_failure;
diff --git a/media/tests/MediaFrameworkTest/Android.mk b/media/tests/MediaFrameworkTest/Android.mk
index 20575e0..308c665 100644
--- a/media/tests/MediaFrameworkTest/Android.mk
+++ b/media/tests/MediaFrameworkTest/Android.mk
@@ -7,8 +7,6 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
-
 LOCAL_STATIC_JAVA_LIBRARIES := \
     mockito-target-minus-junit4 \
     android-support-test \
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
index cdd4065..195df78 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
@@ -415,7 +415,7 @@
             in = getContext().getAssets().open(imageFile.getName());
             ExifInterface exifInterface = new ExifInterface(in);
             exifInterface.saveAttributes();
-        } catch (UnsupportedOperationException e) {
+        } catch (IOException e) {
             // Expected. saveAttributes is not supported with an ExifInterface object which was
             // created with InputStream.
             return;
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 33d6b9a..662a1cd 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.externalstorage;
 
+import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +41,7 @@
 import android.os.storage.VolumeInfo;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Path;
 import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsProvider;
 import android.provider.MediaStore;
@@ -48,6 +50,7 @@
 import android.util.ArrayMap;
 import android.util.DebugUtils;
 import android.util.Log;
+import android.util.Pair;
 import android.webkit.MimeTypeMap;
 
 import com.android.internal.annotations.GuardedBy;
@@ -183,7 +186,8 @@
             root.rootId = rootId;
             root.volumeId = volume.id;
             root.flags = Root.FLAG_LOCAL_ONLY
-                    | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
+                    | Root.FLAG_SUPPORTS_SEARCH
+                    | Root.FLAG_SUPPORTS_IS_CHILD;
 
             final DiskInfo disk = volume.getDisk();
             if (DEBUG) Log.d(TAG, "Disk for root " + rootId + " is " + disk);
@@ -270,7 +274,6 @@
         return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
     }
 
-
     private String getDocIdForFile(File file) throws FileNotFoundException {
         return getDocIdForFileMaybeCreate(file, false);
     }
@@ -323,9 +326,19 @@
     }
 
     private File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
+        RootInfo root = getRootFromDocId(docId);
+        return buildFile(root, docId, visible);
+    }
+
+    private Pair<RootInfo, File> resolveDocId(String docId, boolean visible)
+            throws FileNotFoundException {
+        RootInfo root = getRootFromDocId(docId);
+        return Pair.create(root, buildFile(root, docId, visible));
+    }
+
+    private RootInfo getRootFromDocId(String docId) throws FileNotFoundException {
         final int splitIndex = docId.indexOf(':', 1);
         final String tag = docId.substring(0, splitIndex);
-        final String path = docId.substring(splitIndex + 1);
 
         RootInfo root;
         synchronized (mRootsLock) {
@@ -335,6 +348,14 @@
             throw new FileNotFoundException("No root for " + tag);
         }
 
+        return root;
+    }
+
+    private File buildFile(RootInfo root, String docId, boolean visible)
+            throws FileNotFoundException {
+        final int splitIndex = docId.indexOf(':', 1);
+        final String path = docId.substring(splitIndex + 1);
+
         File target = visible ? root.visiblePath : root.path;
         if (target == null) {
             return null;
@@ -423,6 +444,36 @@
     }
 
     @Override
+    public Path findPath(String childDocId, @Nullable String parentDocId)
+            throws FileNotFoundException {
+        LinkedList<String> path = new LinkedList<>();
+
+        final Pair<RootInfo, File> resolvedDocId = resolveDocId(childDocId, false);
+        final RootInfo root = resolvedDocId.first;
+        File child = resolvedDocId.second;
+
+        final File parent = TextUtils.isEmpty(parentDocId)
+                        ? root.path
+                        : getFileForDocId(parentDocId);
+
+        if (!child.exists()) {
+            throw new FileNotFoundException(childDocId + " is not found.");
+        }
+
+        if (!child.getAbsolutePath().startsWith(parent.getAbsolutePath())) {
+            throw new FileNotFoundException(childDocId + " is not found under " + parentDocId);
+        }
+
+        while (child != null && child.getAbsolutePath().startsWith(parent.getAbsolutePath())) {
+            path.addFirst(getDocIdForFile(child));
+
+            child = child.getParentFile();
+        }
+
+        return new Path(parentDocId == null ? root.rootId : null, path);
+    }
+
+    @Override
     public String createDocument(String docId, String mimeType, String displayName)
             throws FileNotFoundException {
         displayName = FileUtils.buildValidFatFilename(displayName);
diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk
index f9e2686..38cf559 100644
--- a/packages/Keyguard/Android.mk
+++ b/packages/Keyguard/Android.mk
@@ -14,6 +14,17 @@
 #
 
 LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := SystemUI-tags
+
+LOCAL_SRC_FILES := src/com/android/systemui/EventLogTags.logtags
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# ------------------
+
 include $(CLEAR_VARS)
 
 LOCAL_USE_AAPT2 := true
@@ -26,6 +37,8 @@
 
 LOCAL_JAVA_LIBRARIES := SettingsLib
 
+LOCAL_STATIC_JAVA_LIBRARIES = SystemUI-tags
+
 LOCAL_PRIVILEGED_MODULE := true
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
diff --git a/packages/Keyguard/res/values-b+sr+Latn/strings.xml b/packages/Keyguard/res/values-b+sr+Latn/strings.xml
index 570f4bc..8006125 100644
--- a/packages/Keyguard/res/values-b+sr+Latn/strings.xml
+++ b/packages/Keyguard/res/values-b+sr+Latn/strings.xml
@@ -56,7 +56,7 @@
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Pogrešan šablon"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"Pogrešna lozinka"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Pogrešan PIN"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekunde(i)."</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Probajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekunde(i)."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Nacrtajte šablon"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Unesite PIN SIM kartice"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="7818515973197201434">"Unesite PIN za SIM „<xliff:g id="CARRIER">%1$s</xliff:g>“"</string>
@@ -72,9 +72,9 @@
     <string name="kg_invalid_puk" msgid="3638289409676051243">"Ponovo unesite ispravni PUK kôd. Ponovljeni pokušaji će trajno onemogućiti SIM."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN kodovi se ne podudaraju"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Previše pokušaja unosa šablona"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Uneli ste netačni PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Uneli ste netačnu lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Uneli ste netačni PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Uneli ste netačnu lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="8774056606869646621">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> put(a). Imate još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaj(a), nakon čega se tablet resetuje i svi podaci sa njega brišu."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="1843331751334128428">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> put(a). Imate još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaj(a), nakon čega se telefon resetuje i svi podaci sa njega brišu."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="258925501999698032">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER">%d</xliff:g> put(a). Tablet će biti resetovan i svi podaci sa njega će biti izbrisani."</string>
@@ -87,8 +87,8 @@
     <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="6853071165802933545">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> put(a). Imate još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaj(a), nakon čega se poslovni profil uklanja i svi podaci sa profila brišu."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4686386497449912146">"Pogrešno ste pokušali da otključate tablet <xliff:g id="NUMBER">%d</xliff:g> put(a). Poslovni profil će biti uklonjen i svi podaci sa njega će biti izbrisani."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4951507352869831265">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER">%d</xliff:g> put(a). Poslovni profil će biti uklonjen i svi podaci sa njega će biti izbrisani."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate tablet pomoću naloga e-pošte.\n\nPokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću naloga e-pošte.\n\nPokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate tablet pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Netačan SIM PIN kôd. Sada morate da kontaktirate mobilnog operatera da biste otključali uređaj."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
       <item quantity="one">Netačan SIM PIN kôd. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj.</item>
diff --git a/packages/Keyguard/res/values-sr/strings.xml b/packages/Keyguard/res/values-sr/strings.xml
index 840cae7..23c0b50 100644
--- a/packages/Keyguard/res/values-sr/strings.xml
+++ b/packages/Keyguard/res/values-sr/strings.xml
@@ -56,7 +56,7 @@
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Погрешан шаблон"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"Погрешна лозинка"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Погрешан PIN"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Покушајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Пробајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунде(и)."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Нацртајте шаблон"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Унесите PIN SIM картице"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="7818515973197201434">"Унесите PIN за SIM „<xliff:g id="CARRIER">%1$s</xliff:g>“"</string>
@@ -72,9 +72,9 @@
     <string name="kg_invalid_puk" msgid="3638289409676051243">"Поново унесите исправни PUK кôд. Поновљени покушаји ће трајно онемогућити SIM."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN кодови се не подударају"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Превише покушаја уноса шаблона"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Унели сте нетачни PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПокушајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Унели сте нетачну лозинку <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПокушајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПокушајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Унели сте нетачни PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Унели сте нетачну лозинку <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="8774056606869646621">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER_0">%1$d</xliff:g> пут(а). Имате још <xliff:g id="NUMBER_1">%2$d</xliff:g> покушај(а), након чега се таблет ресетује и сви подаци са њега бришу."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="1843331751334128428">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER_0">%1$d</xliff:g> пут(а). Имате још <xliff:g id="NUMBER_1">%2$d</xliff:g> покушај(а), након чега се телефон ресетује и сви подаци са њега бришу."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="258925501999698032">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER">%d</xliff:g> пут(а). Таблет ће бити ресетован и сви подаци са њега ће бити избрисани."</string>
@@ -87,8 +87,8 @@
     <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="6853071165802933545">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER_0">%1$d</xliff:g> пут(а). Имате још <xliff:g id="NUMBER_1">%2$d</xliff:g> покушај(а), након чега се пословни профил уклања и сви подаци са профила бришу."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4686386497449912146">"Погрешно сте покушали да откључате таблет <xliff:g id="NUMBER">%d</xliff:g> пут(а). Пословни профил ће бити уклоњен и сви подаци са њега ће бити избрисани."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4951507352869831265">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER">%d</xliff:g> пут(а). Пословни профил ће бити уклоњен и сви подаци са њега ће бити избрисани."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште.\n\nПокушајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПокушајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Нетачан SIM PIN кôд. Сада морате да контактирате мобилног оператера да бисте откључали уређај."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
       <item quantity="one">Нетачан SIM PIN кôд. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушај.</item>
diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml
index 0723ab1..e15950f 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -36,7 +36,7 @@
     <string name="keyguard_low_battery" msgid="8143808018719173859">"请连接充电器。"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"按“菜单”键解锁。"</string>
     <string name="keyguard_network_locked_message" msgid="9169717779058037168">"网络已锁定"</string>
-    <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"无 SIM 卡"</string>
+    <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"没有 SIM 卡"</string>
     <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"平板电脑中没有SIM卡。"</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"手机中没有SIM卡。"</string>
     <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"请插入SIM卡。"</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 766eab7..94286ec 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -16,6 +16,9 @@
 
 package com.android.keyguard;
 
+import static com.android.keyguard.LatencyTracker.ACTION_CHECK_CREDENTIAL;
+import static com.android.keyguard.LatencyTracker.ACTION_CHECK_CREDENTIAL_UNLOCKED;
+
 import android.content.Context;
 import android.os.AsyncTask;
 import android.os.CountDownTimer;
@@ -132,6 +135,10 @@
             return;
         }
 
+        if (LatencyTracker.isEnabled(mContext)) {
+            LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);
+            LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
+        }
         mPendingLockCheck = LockPatternChecker.checkPassword(
                 mLockPatternUtils,
                 entry,
@@ -140,12 +147,20 @@
 
                     @Override
                     public void onEarlyMatched() {
+                        if (LatencyTracker.isEnabled(mContext)) {
+                            LatencyTracker.getInstance(mContext).onActionEnd(
+                                    ACTION_CHECK_CREDENTIAL);
+                        }
                         onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */,
                                 true /* isValidPassword */);
                     }
 
                     @Override
                     public void onChecked(boolean matched, int timeoutMs) {
+                        if (LatencyTracker.isEnabled(mContext)) {
+                            LatencyTracker.getInstance(mContext).onActionEnd(
+                                    ACTION_CHECK_CREDENTIAL_UNLOCKED);
+                        }
                         setPasswordEntryInputEnabled(true);
                         mPendingLockCheck = null;
                         if (!matched) {
@@ -153,6 +168,16 @@
                                     true /* isValidPassword */);
                         }
                     }
+
+                    @Override
+                    public void onCancelled() {
+                        // We already got dismissed with the early matched callback, so we cancelled
+                        // the check. However, we still need to note down the latency.
+                        if (LatencyTracker.isEnabled(mContext)) {
+                            LatencyTracker.getInstance(mContext).onActionEnd(
+                                    ACTION_CHECK_CREDENTIAL_UNLOCKED);
+                        }
+                    }
                 });
     }
 
@@ -175,7 +200,7 @@
                 }
             }
             if (timeoutMs == 0) {
-                mSecurityMessageDisplay.setMessage(getWrongPasswordStringId(), true);
+                mSecurityMessageDisplay.setMessage(getWrongPasswordStringId());
             }
         }
         resetPasswordText(true /* animate */, !matched /* announce deletion if no match */);
@@ -195,13 +220,13 @@
             @Override
             public void onTick(long millisUntilFinished) {
                 int secondsRemaining = (int) (millisUntilFinished / 1000);
-                mSecurityMessageDisplay.setMessage(
-                        R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining);
+                mSecurityMessageDisplay.formatMessage(
+                        R.string.kg_too_many_failed_attempts_countdown, secondsRemaining);
             }
 
             @Override
             public void onFinish() {
-                mSecurityMessageDisplay.setMessage("", false);
+                mSecurityMessageDisplay.setMessage("");
                 resetState();
             }
         }.start();
@@ -211,7 +236,7 @@
         if (mCallback != null) {
             mCallback.userActivity();
         }
-        mSecurityMessageDisplay.setMessage("", false);
+        mSecurityMessageDisplay.setMessage("");
     }
 
     @Override
@@ -248,8 +273,7 @@
         if (reason != PROMPT_REASON_NONE) {
             int promtReasonStringRes = getPromtReasonStringRes(reason);
             if (promtReasonStringRes != 0) {
-                mSecurityMessageDisplay.setMessage(promtReasonStringRes,
-                        true /* important */);
+                mSecurityMessageDisplay.setMessage(promtReasonStringRes);
             }
         }
     }
@@ -257,7 +281,7 @@
     @Override
     public void showMessage(String message, int color) {
         mSecurityMessageDisplay.setNextMessageColor(color);
-        mSecurityMessageDisplay.setMessage(message, true /* important */);
+        mSecurityMessageDisplay.setMessage(message);
     }
 
     protected abstract int getPromtReasonStringRes(int reason);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
index c8adf64..caeb74c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
@@ -41,14 +41,10 @@
     private static final long ANNOUNCEMENT_DELAY = 250;
     private static final int DEFAULT_COLOR = -1;
 
-    private static final int SECURITY_MESSAGE_DURATION = 5000;
-
     private final KeyguardUpdateMonitor mUpdateMonitor;
     private final Handler mHandler;
     private final int mDefaultColor;
 
-    // Timeout before we reset the message to show charging/owner info
-    long mTimeout = SECURITY_MESSAGE_DURATION;
     CharSequence mMessage;
     private int mNextMessageColor = DEFAULT_COLOR;
 
@@ -91,8 +87,8 @@
     }
 
     @Override
-    public void setMessage(CharSequence msg, boolean important) {
-        if (!TextUtils.isEmpty(msg) && important) {
+    public void setMessage(CharSequence msg) {
+        if (!TextUtils.isEmpty(msg)) {
             securityMessageChanged(msg);
         } else {
             clearMessage();
@@ -100,28 +96,21 @@
     }
 
     @Override
-    public void setMessage(int resId, boolean important) {
-        if (resId != 0 && important) {
-            CharSequence message = getContext().getResources().getText(resId);
-            securityMessageChanged(message);
-        } else {
-            clearMessage();
+    public void setMessage(int resId) {
+        CharSequence message = null;
+        if (resId != 0) {
+            message = getContext().getResources().getText(resId);
         }
+        setMessage(message);
     }
 
     @Override
-    public void setMessage(int resId, boolean important, Object... formatArgs) {
-        if (resId != 0 && important) {
-            String message = getContext().getString(resId, formatArgs);
-            securityMessageChanged(message);
-        } else {
-            clearMessage();
+    public void formatMessage(int resId, Object... formatArgs) {
+        CharSequence message = null;
+        if (resId != 0) {
+            message = getContext().getString(resId, formatArgs);
         }
-    }
-
-    @Override
-    public void setTimeout(int timeoutMs) {
-        mTimeout = timeoutMs;
+        setMessage(message);
     }
 
     public static SecurityMessageDisplay findSecurityMessageDisplay(View v) {
@@ -142,10 +131,6 @@
     private void securityMessageChanged(CharSequence message) {
         mMessage = message;
         update();
-        mHandler.removeCallbacks(mClearMessageRunnable);
-        if (mTimeout > 0) {
-            mHandler.postDelayed(mClearMessageRunnable, mTimeout);
-        }
         mHandler.removeCallbacksAndMessages(ANNOUNCE_TOKEN);
         mHandler.postAtTime(new AnnounceRunnable(this, getText()), ANNOUNCE_TOKEN,
                 (SystemClock.uptimeMillis() + ANNOUNCEMENT_DELAY));
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
index 285b1ae..590d8d5 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
@@ -67,7 +67,7 @@
     @Override
     protected void resetState() {
         super.resetState();
-        mSecurityMessageDisplay.setMessage(R.string.kg_pin_instructions, false);
+        mSecurityMessageDisplay.setMessage("");
     }
 
     @Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index ddccc14..d49ff97 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -79,7 +79,7 @@
 
     @Override
     protected void resetState() {
-        mSecurityMessageDisplay.setMessage(R.string.kg_password_instructions, false);
+        mSecurityMessageDisplay.setMessage("");
         final boolean wasDisabled = mPasswordEntry.isEnabled();
         setPasswordEntryEnabled(true);
         setPasswordEntryInputEnabled(true);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 7d1a6fb..330632b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -15,6 +15,9 @@
  */
 package com.android.keyguard;
 
+import static com.android.keyguard.LatencyTracker.ACTION_CHECK_CREDENTIAL;
+import static com.android.keyguard.LatencyTracker.ACTION_CHECK_CREDENTIAL_UNLOCKED;
+
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.AsyncTask;
@@ -197,7 +200,7 @@
     }
 
     private void displayDefaultSecurityMessage() {
-        mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions, false);
+        mSecurityMessageDisplay.setMessage("");
     }
 
     @Override
@@ -216,7 +219,7 @@
         @Override
         public void onPatternStart() {
             mLockPatternView.removeCallbacks(mCancelPatternRunnable);
-            mSecurityMessageDisplay.setMessage("", false);
+            mSecurityMessageDisplay.setMessage("");
         }
 
         @Override
@@ -242,6 +245,10 @@
                 return;
             }
 
+            if (LatencyTracker.isEnabled(mContext)) {
+                LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);
+                LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
+            }
             mPendingLockCheck = LockPatternChecker.checkPattern(
                     mLockPatternUtils,
                     pattern,
@@ -250,12 +257,20 @@
 
                         @Override
                         public void onEarlyMatched() {
+                            if (LatencyTracker.isEnabled(mContext)) {
+                                LatencyTracker.getInstance(mContext).onActionEnd(
+                                        ACTION_CHECK_CREDENTIAL);
+                            }
                             onPatternChecked(userId, true /* matched */, 0 /* timeoutMs */,
                                     true /* isValidPattern */);
                         }
 
                         @Override
                         public void onChecked(boolean matched, int timeoutMs) {
+                            if (LatencyTracker.isEnabled(mContext)) {
+                                LatencyTracker.getInstance(mContext).onActionEnd(
+                                        ACTION_CHECK_CREDENTIAL_UNLOCKED);
+                            }
                             mLockPatternView.enableInput();
                             mPendingLockCheck = null;
                             if (!matched) {
@@ -263,6 +278,16 @@
                                         true /* isValidPattern */);
                             }
                         }
+
+                        @Override
+                        public void onCancelled() {
+                            // We already got dismissed with the early matched callback, so we
+                            // cancelled the check. However, we still need to note down the latency.
+                            if (LatencyTracker.isEnabled(mContext)) {
+                                LatencyTracker.getInstance(mContext).onActionEnd(
+                                        ACTION_CHECK_CREDENTIAL_UNLOCKED);
+                            }
+                        }
                     });
             if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
                 mCallback.userActivity();
@@ -289,7 +314,7 @@
                     }
                 }
                 if (timeoutMs == 0) {
-                    mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern, true);
+                    mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern);
                     mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS);
                 }
             }
@@ -306,8 +331,8 @@
             @Override
             public void onTick(long millisUntilFinished) {
                 final int secondsRemaining = (int) (millisUntilFinished / 1000);
-                mSecurityMessageDisplay.setMessage(
-                        R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining);
+                mSecurityMessageDisplay.formatMessage(
+                        R.string.kg_too_many_failed_attempts_countdown, secondsRemaining);
             }
 
             @Override
@@ -350,26 +375,21 @@
     public void showPromptReason(int reason) {
         switch (reason) {
             case PROMPT_REASON_RESTART:
-                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_restart_pattern,
-                        true /* important */);
+                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_restart_pattern);
                 break;
             case PROMPT_REASON_TIMEOUT:
-                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern,
-                        true /* important */);
+                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern);
                 break;
             case PROMPT_REASON_DEVICE_ADMIN:
-                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_device_admin,
-                        true /* important */);
+                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_device_admin);
                 break;
             case PROMPT_REASON_USER_REQUEST:
-                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_user_request,
-                        true /* important */);
+                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_user_request);
                 break;
             case PROMPT_REASON_NONE:
                 break;
             default:
-                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern,
-                        true /* important */);
+                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern);
                 break;
         }
     }
@@ -377,7 +397,7 @@
     @Override
     public void showMessage(String message, int color) {
         mSecurityMessageDisplay.setNextMessageColor(color);
-        mSecurityMessageDisplay.setMessage(message, true /* important */);
+        mSecurityMessageDisplay.setMessage(message);
     }
 
     @Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 04f32a1..91c943d 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -174,6 +174,7 @@
         final AlertDialog dialog = new AlertDialog.Builder(mContext)
             .setTitle(title)
             .setMessage(message)
+            .setCancelable(false)
             .setNeutralButton(R.string.ok, null)
             .create();
         if (!(mContext instanceof Activity)) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index d48cc94..839d3ce 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -92,7 +92,7 @@
                     color = info.getIconTint();
                 }
             }
-            mSecurityMessageDisplay.setMessage(msg, true);
+            mSecurityMessageDisplay.setMessage(msg);
             mSimImageView.setImageTintList(ColorStateList.valueOf(color));
         }
     }
@@ -141,7 +141,6 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
         if (mEcaView instanceof EmergencyCarrierArea) {
             ((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true);
         }
@@ -252,7 +251,7 @@
 
         if (entry.length() < 4) {
             // otherwise, display a message to the user, and don't submit.
-            mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint, true);
+            mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint);
             resetPasswordText(true /* animate */, true /* announce */);
             mCallback.userActivity();
             return;
@@ -284,13 +283,13 @@
                                     } else {
                                         // show message
                                         mSecurityMessageDisplay.setMessage(
-                                                getPinPasswordErrorMessage(attemptsRemaining), true);
+                                                getPinPasswordErrorMessage(attemptsRemaining));
                                     }
                                 } else {
                                     // "PIN operation failed!" - no idea what this was and no way to
                                     // find out. :/
                                     mSecurityMessageDisplay.setMessage(getContext().getString(
-                                            R.string.kg_password_pin_failed), true);
+                                            R.string.kg_password_pin_failed));
                                 }
                                 if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock "
                                         + " CheckSimPin.onSimCheckResponse: " + result
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index 249dde8..3871448 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -108,7 +108,7 @@
             }
             resetPasswordText(true /* animate */, true /* announce */);
             if (msg != 0) {
-                mSecurityMessageDisplay.setMessage(msg, true);
+                mSecurityMessageDisplay.setMessage(msg);
             }
         }
 
@@ -133,7 +133,7 @@
                         color = info.getIconTint();
                     }
                 }
-                mSecurityMessageDisplay.setMessage(msg, true);
+                mSecurityMessageDisplay.setMessage(msg);
                 mSimImageView.setImageTintList(ColorStateList.valueOf(color));
             }
             mPasswordEntry.requestFocus();
@@ -184,7 +184,6 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
         if (mEcaView instanceof EmergencyCarrierArea) {
             ((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true);
         }
@@ -341,11 +340,11 @@
                                     } else {
                                         // show message
                                         mSecurityMessageDisplay.setMessage(
-                                                getPukPasswordErrorMessage(attemptsRemaining), true);
+                                                getPukPasswordErrorMessage(attemptsRemaining));
                                     }
                                 } else {
                                     mSecurityMessageDisplay.setMessage(getContext().getString(
-                                            R.string.kg_password_puk_failed), true);
+                                            R.string.kg_password_puk_failed));
                                 }
                                 if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock "
                                         + " UpdateSim.onSimCheckResponse: "
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 288b954..66e56e0 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -16,6 +16,7 @@
 
 package com.android.keyguard;
 
+import static android.content.Intent.ACTION_USER_UNLOCKED;
 import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
 import static android.os.BatteryManager.BATTERY_STATUS_FULL;
 import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
@@ -136,6 +137,7 @@
     private static final int MSG_SCREEN_TURNED_ON = 331;
     private static final int MSG_SCREEN_TURNED_OFF = 332;
     private static final int MSG_DREAMING_STATE_CHANGED = 333;
+    private static final int MSG_USER_UNLOCKED = 334;
 
     /** Fingerprint state: Not listening to fingerprint. */
     private static final int FINGERPRINT_STATE_STOPPED = 0;
@@ -291,6 +293,9 @@
                 case MSG_DREAMING_STATE_CHANGED:
                     handleDreamingStateChanged(msg.arg1);
                     break;
+                case MSG_USER_UNLOCKED:
+                    handleUserUnlocked();
+                    break;
             }
         }
     };
@@ -723,6 +728,8 @@
             } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
                     .equals(action)) {
                 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
+            } else if (ACTION_USER_UNLOCKED.equals(action)) {
+                mHandler.sendEmptyMessage(MSG_USER_UNLOCKED);
             }
         }
     };
@@ -1025,6 +1032,16 @@
         }
     }
 
+    private void handleUserUnlocked() {
+        mNeedsSlowUnlockTransition = resolveNeedsSlowUnlockTransition();
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onUserUnlocked();
+            }
+        }
+    }
+
     private KeyguardUpdateMonitor(Context context) {
         mContext = context;
         mSubscriptionManager = SubscriptionManager.from(context);
@@ -1065,6 +1082,7 @@
         allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED);
         allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED);
         allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+        allUserFilter.addAction(ACTION_USER_UNLOCKED);
         context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter,
                 null, null);
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index eb29d9b..14d6b59 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -128,6 +128,11 @@
     public void onUserInfoChanged(int userId) { }
 
     /**
+     * Called when a user got unlocked.
+     */
+    public void onUserUnlocked() { }
+
+    /**
      * Called when boot completed.
      *
      * Note, this callback will only be received if boot complete occurs after registering with
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTracker.java b/packages/Keyguard/src/com/android/keyguard/LatencyTracker.java
similarity index 80%
rename from packages/SystemUI/src/com/android/systemui/LatencyTracker.java
rename to packages/Keyguard/src/com/android/keyguard/LatencyTracker.java
index 0196815..cee0afc 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTracker.java
+++ b/packages/Keyguard/src/com/android/keyguard/LatencyTracker.java
@@ -14,14 +14,13 @@
  * limitations under the License
  */
 
-package com.android.systemui;
+package com.android.keyguard;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Build;
-import android.os.Handler;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
@@ -29,9 +28,15 @@
 import android.util.Log;
 import android.util.SparseLongArray;
 
+import com.android.systemui.EventLogTags;
+
 /**
  * Class to track various latencies in SystemUI. It then outputs the latency to logcat so these
  * latencies can be captured by tests and then used for dashboards.
+ * <p>
+ * This is currently only in Keyguard so it can be shared between SystemUI and Keyguard, but
+ * eventually we'd want to merge these two packages together so Keyguard can use common classes
+ * that are shared with SystemUI.
  */
 public class LatencyTracker {
 
@@ -55,10 +60,29 @@
      */
     public static final int ACTION_FINGERPRINT_WAKE_AND_UNLOCK = 2;
 
+    /**
+     * Time it takes to check PIN/Pattern/Password.
+     */
+    public static final int ACTION_CHECK_CREDENTIAL = 3;
+
+    /**
+     * Time it takes to check fully PIN/Pattern/Password, i.e. that's the time spent including the
+     * actions to unlock a user.
+     */
+    public static final int ACTION_CHECK_CREDENTIAL_UNLOCKED = 4;
+
+    /**
+     * Time it takes to turn on the screen.
+     */
+    public static final int ACTION_TURN_ON_SCREEN = 5;
+
     private static final String[] NAMES = new String[] {
             "expand panel",
             "toggle recents",
-            "fingerprint wake-and-unlock" };
+            "fingerprint wake-and-unlock",
+            "check credential",
+            "check credential unlocked",
+            "turn on screen" };
 
     private static LatencyTracker sLatencyTracker;
 
@@ -117,6 +141,7 @@
         if (startRtc == -1) {
             return;
         }
+        mStartRtc.delete(action);
         Trace.asyncTraceEnd(Trace.TRACE_TAG_APP, NAMES[action], 0);
         long duration = endRtc - startRtc;
         Log.i(TAG, "action=" + action + " latency=" + duration);
diff --git a/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java b/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java
index ddb1f6e..6977b51 100644
--- a/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java
+++ b/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java
@@ -20,11 +20,9 @@
 
     void setNextMessageColor(int color);
 
-    void setMessage(CharSequence msg, boolean important);
+    void setMessage(CharSequence msg);
 
-    void setMessage(int resId, boolean important);
+    void setMessage(int resId);
 
-    void setMessage(int resId, boolean important, Object... formatArgs);
-
-    void setTimeout(int timeout_ms);
+    void formatMessage(int resId, Object... formatArgs);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/EventLogTags.logtags b/packages/Keyguard/src/com/android/systemui/EventLogTags.logtags
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/EventLogTags.logtags
rename to packages/Keyguard/src/com/android/systemui/EventLogTags.logtags
diff --git a/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp b/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp
index a2e9e94..e948cf7 100644
--- a/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp
+++ b/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp
@@ -23,6 +23,7 @@
 
 #include <linux/fuse.h>
 #include <sys/stat.h>
+#include <sys/uio.h>
 
 #include <map>
 
diff --git a/packages/MtpDocumentsProvider/perf_tests/Android.mk b/packages/MtpDocumentsProvider/perf_tests/Android.mk
new file mode 100644
index 0000000..f0d4878
--- /dev/null
+++ b/packages/MtpDocumentsProvider/perf_tests/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := MtpDocumentsProviderPerfTests
+LOCAL_INSTRUMENTATION_FOR := MtpDocumentsProvider
+LOCAL_CERTIFICATE := media
+
+include $(BUILD_PACKAGE)
diff --git a/packages/MtpDocumentsProvider/perf_tests/AndroidManifest.xml b/packages/MtpDocumentsProvider/perf_tests/AndroidManifest.xml
new file mode 100644
index 0000000..26e109d
--- /dev/null
+++ b/packages/MtpDocumentsProvider/perf_tests/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.mtp.perftests"
+    android:sharedUserId="android.media">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.mtp"
+        android:label="Performance tests for MtpDocumentsProvider." />
+</manifest>
diff --git a/packages/MtpDocumentsProvider/perf_tests/src/com/android/mtp/AppFusePerfTest.java b/packages/MtpDocumentsProvider/perf_tests/src/com/android/mtp/AppFusePerfTest.java
new file mode 100644
index 0000000..0762571
--- /dev/null
+++ b/packages/MtpDocumentsProvider/perf_tests/src/com/android/mtp/AppFusePerfTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.mtp;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.os.storage.StorageManager;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.support.test.filters.LargeTest;
+import android.support.test.InstrumentationRegistry;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Arrays;
+import libcore.io.IoUtils;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.junit.Test;
+
+@RunWith(JUnit4.class)
+public class AppFusePerfTest {
+    @Test
+    @LargeTest
+    public void testReadWriteFile() throws IOException {
+        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        final StorageManager storageManager = context.getSystemService(StorageManager.class);
+        final int INODE = 10;
+        final int SIZE = 10 * 1024 * 1024;  // 10MB
+        final AppFuse appFuse = new AppFuse(
+                "test",
+                new TestCallback() {
+                    @Override
+                    public long getFileSize(int inode) throws FileNotFoundException {
+                        if (inode != INODE) {
+                            throw new FileNotFoundException();
+                        }
+                        return SIZE;
+                    }
+
+                    @Override
+                    public long readObjectBytes(int inode, long offset, long size, byte[] bytes)
+                            throws IOException {
+                        return size;
+                    }
+
+                    @Override
+                    public int writeObjectBytes(
+                            long fileHandle, int inode, long offset, int size, byte[] bytes) {
+                        return size;
+                    }
+                });
+
+        appFuse.mount(storageManager);
+
+        final byte[] bytes = new byte[SIZE];
+        final int SAMPLES = 100;
+        final double[] readTime = new double[SAMPLES];
+        final double[] writeTime = new double[SAMPLES];
+
+        for (int i = 0; i < SAMPLES; i++) {
+            final ParcelFileDescriptor fd = appFuse.openFile(
+                    INODE,
+                    ParcelFileDescriptor.MODE_READ_ONLY);
+            try (final ParcelFileDescriptor.AutoCloseInputStream stream =
+                    new ParcelFileDescriptor.AutoCloseInputStream(fd)) {
+                final long startTime = System.nanoTime();
+                stream.read(bytes);
+                readTime[i] = (System.nanoTime() - startTime) / 1000.0 / 1000.0;
+            }
+
+        }
+
+        for (int i = 0; i < SAMPLES; i++) {
+            final ParcelFileDescriptor fd = appFuse.openFile(
+                    INODE,
+                    ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_TRUNCATE);
+            try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
+                    new ParcelFileDescriptor.AutoCloseOutputStream(fd)) {
+                final long startTime = System.nanoTime();
+                stream.write(bytes);
+                writeTime[i] = (System.nanoTime() - startTime) / 1000.0 / 1000.0;
+            }
+        }
+
+        appFuse.close();
+
+        double readAverage = 0;
+        double writeAverage = 0;
+        double readSquaredAverage = 0;
+        double writeSquaredAverage = 0;
+        for (int i = 0; i < SAMPLES; i++) {
+            readAverage += readTime[i];
+            writeAverage += writeTime[i];
+            readSquaredAverage += readTime[i] * readTime[i];
+            writeSquaredAverage += writeTime[i] * writeTime[i];
+        }
+
+        readAverage /= SAMPLES;
+        writeAverage /= SAMPLES;
+        readSquaredAverage /= SAMPLES;
+        writeSquaredAverage /= SAMPLES;
+
+        final Bundle results = new Bundle();
+        results.putDouble("readAverage", readAverage);
+        results.putDouble("readStandardDeviation",
+                Math.sqrt(readSquaredAverage - readAverage * readAverage));
+        results.putDouble("writeAverage", writeAverage);
+        results.putDouble("writeStandardDeviation",
+                Math.sqrt(writeSquaredAverage - writeAverage * writeAverage));
+        InstrumentationRegistry.getInstrumentation().sendStatus(Activity.RESULT_OK, results);
+    }
+
+    private static class TestCallback implements AppFuse.Callback {
+        @Override
+        public long getFileSize(int inode) throws FileNotFoundException {
+            throw new FileNotFoundException();
+        }
+
+        @Override
+        public long readObjectBytes(int inode, long offset, long size, byte[] bytes)
+                throws IOException {
+            throw new IOException();
+        }
+
+        @Override
+        public int writeObjectBytes(long fileHandle, int inode, long offset, int size, byte[] bytes)
+                throws IOException {
+            throw new IOException();
+        }
+
+        @Override
+        public void flushFileHandle(long fileHandle) throws IOException {}
+
+        @Override
+        public void closeFileHandle(long fileHandle) {}
+    }
+}
diff --git a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
index ce8a81e..2b1b8ca 100644
--- a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
+++ b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
@@ -103,8 +103,8 @@
     <item msgid="3199660090246166812">"Vodoravno"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"Upisivanje u datoteku nije moguće"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"Žao nam je, ovo nije uspelo. Pokušajte ponovo."</string>
-    <string name="print_error_retry" msgid="1426421728784259538">"Pokušajte ponovo"</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"Žao nam je, ovo nije uspelo. Probajte ponovo."</string>
+    <string name="print_error_retry" msgid="1426421728784259538">"Probajte ponovo"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Ovaj štampač trenutno nije dostupan."</string>
     <string name="print_cannot_load_page" msgid="6179560924492912009">"Nije uspeo prikaz pregleda"</string>
     <string name="print_preparing_preview" msgid="3939930735671364712">"Priprema pregleda..."</string>
diff --git a/packages/PrintSpooler/res/values-kn-rIN/strings.xml b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
index ef3ea16..c6e36d2 100644
--- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
@@ -47,7 +47,7 @@
     <string name="savetopdf_button" msgid="2976186791686924743">"PDF ಗೆ ಉಳಿಸು"</string>
     <string name="print_options_expanded" msgid="6944679157471691859">"ಪ್ರಿಂಟ್ ಆಯ್ಕೆಗಳನ್ನು ವಿಸ್ತರಿಸಲಾಗಿದೆ"</string>
     <string name="print_options_collapsed" msgid="7455930445670414332">"ಪ್ರಿಂಟ್ ಆಯ್ಕೆಗಳನ್ನು ಮುಚ್ಚಲಾಗಿದೆ"</string>
-    <string name="search" msgid="5421724265322228497">"ಹುಡುಕು"</string>
+    <string name="search" msgid="5421724265322228497">"ಹುಡುಕಿ"</string>
     <string name="all_printers_label" msgid="3178848870161526399">"ಎಲ್ಲಾ ಪ್ರಿಂಟರ್‌ಗಳು"</string>
     <string name="add_print_service_label" msgid="5356702546188981940">"ಸೇವೆಯನ್ನು ಸೇರಿಸು"</string>
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ಹುಡುಕಾಟ ಪೆಟ್ಟಿಗೆಯನ್ನು ತೋರಿಸಲಾಗಿದೆ"</string>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index 012bbbc..9283d77 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -103,8 +103,8 @@
     <item msgid="3199660090246166812">"Водоравно"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"Уписивање у датотеку није могуће"</string>
-    <string name="print_error_default_message" msgid="8602678405502922346">"Жао нам је, ово није успело. Покушајте поново."</string>
-    <string name="print_error_retry" msgid="1426421728784259538">"Покушајте поново"</string>
+    <string name="print_error_default_message" msgid="8602678405502922346">"Жао нам је, ово није успело. Пробајте поново."</string>
+    <string name="print_error_retry" msgid="1426421728784259538">"Пробајте поново"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Овај штампач тренутно није доступан."</string>
     <string name="print_cannot_load_page" msgid="6179560924492912009">"Није успео приказ прегледа"</string>
     <string name="print_preparing_preview" msgid="3939930735671364712">"Припрема прегледа..."</string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index b3cfea5..23c6615 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -46,7 +46,6 @@
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.os.UserManager;
 import android.print.IPrintDocumentAdapter;
 import android.print.PageRange;
@@ -760,8 +759,11 @@
                 mPrintJob.setPrinterId(printerInfo.getId());
                 mPrintJob.setPrinterName(printerInfo.getName());
 
-                if (printerInfo.getCapabilities() != null) {
+                if (canPrint(printerInfo)) {
                     updatePrintAttributesFromCapabilities(printerInfo.getCapabilities());
+                    onPrinterAvailable(printerInfo);
+                } else {
+                    onPrinterUnavailable(printerInfo);
                 }
 
                 mDestinationSpinnerAdapter.ensurePrinterInVisibleAdapterPosition(printerInfo);
@@ -2050,7 +2052,7 @@
     }
 
     public void onPrinterUnavailable(PrinterInfo printer) {
-        if (mCurrentPrinter.getId().equals(printer.getId())) {
+        if (mCurrentPrinter == null || mCurrentPrinter.getId().equals(printer.getId())) {
             setState(STATE_PRINTER_UNAVAILABLE);
             mPrintedDocument.cancel(false);
             ensureErrorUiShown(getString(R.string.print_error_printer_unavailable),
@@ -2309,8 +2311,7 @@
         public int getPrinterIndex(PrinterId printerId) {
             for (int i = 0; i < getCount(); i++) {
                 PrinterHolder printerHolder = (PrinterHolder) getItem(i);
-                if (printerHolder != null && !printerHolder.removed
-                        && printerHolder.printer.getId().equals(printerId)) {
+                if (printerHolder != null && printerHolder.printer.getId().equals(printerId)) {
                     return i;
                 }
             }
@@ -2539,7 +2540,11 @@
                 if (updatedPrinter != null) {
                     printerHolder.printer = updatedPrinter;
                     printerHolder.removed = false;
-                    onPrinterAvailable(printerHolder.printer);
+                    if (canPrint(printerHolder.printer)) {
+                        onPrinterAvailable(printerHolder.printer);
+                    } else {
+                        onPrinterUnavailable(printerHolder.printer);
+                    }
                     newPrinterHolders.add(printerHolder);
                 } else if (mCurrentPrinter != null && mCurrentPrinter.getId().equals(oldPrinterId)){
                     printerHolder.removed = true;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index cc69089..293665a 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -17,6 +17,7 @@
 package com.android.printspooler.ui;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.LoaderManager;
 import android.content.ComponentName;
@@ -24,13 +25,17 @@
 import android.content.Intent;
 import android.content.IntentSender.SendIntentException;
 import android.content.Loader;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.database.DataSetObserver;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.os.Bundle;
 import android.print.PrintManager;
 import android.print.PrintServicesLoader;
 import android.print.PrinterId;
 import android.print.PrinterInfo;
+import android.printservice.PrintService;
 import android.printservice.PrintServiceInfo;
 import android.provider.Settings;
 import android.text.TextUtils;
@@ -76,6 +81,8 @@
     private static final int LOADER_ID_PRINT_REGISTRY_INT = 2;
     private static final int LOADER_ID_ENABLED_PRINT_SERVICES = 3;
 
+    private static final int INFO_INTENT_REQUEST_CODE = 1;
+
     public static final String INTENT_EXTRA_PRINTER = "INTENT_EXTRA_PRINTER";
 
     private static final String EXTRA_PRINTER = "EXTRA_PRINTER";
@@ -83,6 +90,7 @@
 
     private static final String KEY_NOT_FIRST_CREATE = "KEY_NOT_FIRST_CREATE";
     private static final String KEY_DID_SEARCH = "DID_SEARCH";
+    private static final String KEY_PRINTER_FOR_INFO_INTENT = "KEY_PRINTER_FOR_INFO_INTENT";
 
     // Constants for MetricsLogger.count and MetricsLogger.histo
     private static final String PRINTERS_LISTED_COUNT = "printers_listed";
@@ -100,6 +108,12 @@
 
     private boolean mDidSearch;
 
+    /**
+     * Printer we are currently in the info intent for. This is only non-null while this activity
+     * started an info intent that has not yet returned
+     */
+    private @Nullable PrinterInfo mPrinterForInfoIntent;
+
     private void startAddPrinterActivity() {
         MetricsLogger.action(this, MetricsEvent.ACTION_PRINT_SERVICE_ADD);
         startActivity(new Intent(this, AddPrinterActivity.class));
@@ -200,6 +214,7 @@
 
         if (savedInstanceState != null) {
             mDidSearch = savedInstanceState.getBoolean(KEY_DID_SEARCH);
+            mPrinterForInfoIntent = savedInstanceState.getParcelable(KEY_PRINTER_FOR_INFO_INTENT);
         }
     }
 
@@ -208,6 +223,7 @@
         super.onSaveInstanceState(outState);
         outState.putBoolean(KEY_NOT_FIRST_CREATE, true);
         outState.putBoolean(KEY_DID_SEARCH, mDidSearch);
+        outState.putParcelable(KEY_PRINTER_FOR_INFO_INTENT, mPrinterForInfoIntent);
     }
 
     @Override
@@ -353,6 +369,24 @@
         super.onDestroy();
     }
 
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        switch (requestCode) {
+            case INFO_INTENT_REQUEST_CODE:
+                if (resultCode == RESULT_OK &&
+                        data != null &&
+                        data.getBooleanExtra(PrintService.EXTRA_SELECT_PRINTER, false) &&
+                        mPrinterForInfoIntent != null &&
+                        mPrinterForInfoIntent.getStatus() != PrinterInfo.STATUS_UNAVAILABLE) {
+                    onPrinterSelected(mPrinterForInfoIntent);
+                }
+                mPrinterForInfoIntent = null;
+                break;
+            default:
+                // not reached
+        }
+    }
+
     private void onPrinterSelected(PrinterInfo printer) {
         Intent intent = new Intent();
         intent.putExtra(INTENT_EXTRA_PRINTER, printer);
@@ -418,6 +452,26 @@
         }
     }
 
+    /**
+     * Return the target SDK of the package that defined the printer.
+     *
+     * @param printer The printer
+     *
+     * @return The target SDK that defined a printer.
+     */
+    private int getTargetSDKOfPrintersService(@NonNull PrinterInfo printer) {
+        ApplicationInfo serviceAppInfo;
+        try {
+            serviceAppInfo = getPackageManager().getApplicationInfo(
+                    printer.getId().getServiceName().getPackageName(), 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(LOG_TAG, "Could not find package that defined the printer", e);
+            return Build.VERSION_CODES.KITKAT;
+        }
+
+        return serviceAppInfo.targetSdkVersion;
+    }
+
     private final class DestinationAdapter extends BaseAdapter implements Filterable {
 
         private final Object mLock = new Object();
@@ -638,15 +692,17 @@
             LinearLayout moreInfoView = (LinearLayout) convertView.findViewById(R.id.more_info);
             if (printer.getInfoIntent() != null) {
                 moreInfoView.setVisibility(View.VISIBLE);
-                moreInfoView.setOnClickListener(new OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        try {
-                            startIntentSender(printer.getInfoIntent().getIntentSender(), null, 0, 0,
-                                    0);
-                        } catch (SendIntentException e) {
-                            Log.e(LOG_TAG, "Could not execute pending info intent: %s", e);
-                        }
+                moreInfoView.setOnClickListener(v -> {
+                    Intent fillInIntent = new Intent();
+                    fillInIntent.putExtra(PrintService.EXTRA_CAN_SELECT_PRINTER, true);
+
+                    try {
+                        mPrinterForInfoIntent = printer;
+                        startIntentSenderForResult(printer.getInfoIntent().getIntentSender(),
+                                INFO_INTENT_REQUEST_CODE, fillInIntent, 0, 0, 0);
+                    } catch (SendIntentException e) {
+                        mPrinterForInfoIntent = null;
+                        Log.e(LOG_TAG, "Could not execute pending info intent: %s", e);
                     }
                 });
             } else {
diff --git a/packages/PrintSpooler/tests/Android.mk b/packages/PrintSpooler/tests/Android.mk
new file mode 100644
index 0000000..83e00ce
--- /dev/null
+++ b/packages/PrintSpooler/tests/Android.mk
@@ -0,0 +1,19 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.mk b/packages/PrintSpooler/tests/outofprocess/Android.mk
new file mode 100644
index 0000000..d1d0ee4
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/Android.mk
@@ -0,0 +1,28 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator mockito-target-minus-junit4
+
+LOCAL_PACKAGE_NAME := PrintSpoolerOutOfProcessTests
+
+include $(BUILD_PACKAGE)
diff --git a/packages/PrintSpooler/tests/outofprocess/AndroidManifest.xml b/packages/PrintSpooler/tests/outofprocess/AndroidManifest.xml
new file mode 100644
index 0000000..4a05f6f
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?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"
+        package="com.android.printspooler.outofprocess.tests">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name=".PrintTestActivity"/>
+
+        <service
+                android:name=".mockservice.MockPrintService"
+                android:permission="android.permission.BIND_PRINT_SERVICE">
+
+            <intent-filter>
+                <action android:name="android.printservice.PrintService" />
+            </intent-filter>
+            <meta-data
+                    android:name="android.printservice"
+                    android:resource="@xml/printservice">
+            </meta-data>
+        </service>
+
+        <activity
+                android:name=".mockservice.SettingsActivity"
+                android:permission="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY"
+                android:exported="true">
+        </activity>
+
+        <activity
+                android:name=".mockservice.AddPrintersActivity"
+                android:exported="true">
+        </activity>
+
+    </application>
+
+    <!-- This runs in its own process, hence it instruments itself -->
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.printspooler.outofprocess.tests"
+            android:label="PrintSpooler Out of Process Test Cases">
+    </instrumentation>
+
+</manifest>
diff --git a/packages/PrintSpooler/tests/outofprocess/res/xml/printservice.xml b/packages/PrintSpooler/tests/outofprocess/res/xml/printservice.xml
new file mode 100644
index 0000000..9eecf45
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/res/xml/printservice.xml
@@ -0,0 +1,20 @@
+<?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.
+  -->
+
+<print-service  xmlns:android="http://schemas.android.com/apk/res/android"
+        android:addPrintersActivity="com.android.printspooler.outofprocess.tests.mockservice.AddPrintersActivity" />
diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/BasePrintTest.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/BasePrintTest.java
new file mode 100644
index 0000000..4de3570
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/BasePrintTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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.printspooler.outofprocess.tests;
+
+import android.annotation.NonNull;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+import android.print.PrintAttributes;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintManager;
+import android.print.PrinterId;
+import com.android.printspooler.outofprocess.tests.mockservice.PrintServiceCallbacks;
+import com.android.printspooler.outofprocess.tests.mockservice.PrinterDiscoverySessionCallbacks;
+import com.android.printspooler.outofprocess.tests.mockservice.StubbablePrinterDiscoverySession;
+import android.printservice.CustomPrinterIconCallback;
+import android.printservice.PrintJob;
+import android.printservice.PrintService;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.uiautomator.UiDevice;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.mockito.stubbing.Answer;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.List;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * This is the base class for print tests.
+ */
+abstract class BasePrintTest {
+    protected static final long OPERATION_TIMEOUT = 30000;
+    private static final String PM_CLEAR_SUCCESS_OUTPUT = "Success";
+    private static final int CURRENT_USER_ID = -2; // Mirrors UserHandle.USER_CURRENT
+
+    private android.print.PrintJob mPrintJob;
+
+    private static Instrumentation sInstrumentation;
+    private static UiDevice sUiDevice;
+
+    @Rule
+    public ActivityTestRule<PrintTestActivity> mActivityRule =
+            new ActivityTestRule<>(PrintTestActivity.class, false, true);
+
+    /**
+     * Return the UI device
+     *
+     * @return the UI device
+     */
+    public UiDevice getUiDevice() {
+        return sUiDevice;
+    }
+
+    protected static Instrumentation getInstrumentation() {
+        return sInstrumentation;
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        sInstrumentation = InstrumentationRegistry.getInstrumentation();
+        assumeTrue(sInstrumentation.getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_PRINTING));
+
+        sUiDevice = UiDevice.getInstance(sInstrumentation);
+
+        // Make sure we start with a clean slate.
+        clearPrintSpoolerData();
+
+        // Workaround for dexmaker bug: https://code.google.com/p/dexmaker/issues/detail?id=2
+        // Dexmaker is used by mockito.
+        System.setProperty("dexmaker.dexcache", getInstrumentation()
+                .getTargetContext().getCacheDir().getPath());
+    }
+
+    @After
+    public void exitActivities() throws Exception {
+        // Exit print spooler
+        getUiDevice().pressBack();
+        getUiDevice().pressBack();
+    }
+
+    protected android.print.PrintJob print(@NonNull final PrintDocumentAdapter adapter,
+            final PrintAttributes attributes) {
+        // Initiate printing as if coming from the app.
+        getInstrumentation().runOnMainSync(() -> {
+            PrintManager printManager = (PrintManager) getActivity()
+                    .getSystemService(Context.PRINT_SERVICE);
+            mPrintJob = printManager.print("Print job", adapter, attributes);
+        });
+
+        return mPrintJob;
+    }
+
+    protected PrintTestActivity getActivity() {
+        return mActivityRule.getActivity();
+    }
+
+    public static String runShellCommand(Instrumentation instrumentation, String cmd)
+            throws IOException {
+        ParcelFileDescriptor pfd = instrumentation.getUiAutomation().executeShellCommand(cmd);
+        byte[] buf = new byte[512];
+        int bytesRead;
+        FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+        StringBuilder stdout = new StringBuilder();
+        while ((bytesRead = fis.read(buf)) != -1) {
+            stdout.append(new String(buf, 0, bytesRead));
+        }
+        fis.close();
+        return stdout.toString();
+    }
+
+    protected static void clearPrintSpoolerData() throws Exception {
+        assertTrue("failed to clear print spooler data",
+                runShellCommand(getInstrumentation(), String.format(
+                        "pm clear --user %d %s", CURRENT_USER_ID,
+                        PrintManager.PRINT_SPOOLER_PACKAGE_NAME))
+                        .contains(PM_CLEAR_SUCCESS_OUTPUT));
+    }
+
+    @SuppressWarnings("unchecked")
+    protected PrinterDiscoverySessionCallbacks createMockPrinterDiscoverySessionCallbacks(
+            Answer<Void> onStartPrinterDiscovery, Answer<Void> onStopPrinterDiscovery,
+            Answer<Void> onValidatePrinters, Answer<Void> onStartPrinterStateTracking,
+            Answer<Void> onRequestCustomPrinterIcon, Answer<Void> onStopPrinterStateTracking,
+            Answer<Void> onDestroy) {
+        PrinterDiscoverySessionCallbacks callbacks = mock(PrinterDiscoverySessionCallbacks.class);
+
+        doCallRealMethod().when(callbacks).setSession(any(StubbablePrinterDiscoverySession.class));
+        when(callbacks.getSession()).thenCallRealMethod();
+
+        if (onStartPrinterDiscovery != null) {
+            doAnswer(onStartPrinterDiscovery).when(callbacks).onStartPrinterDiscovery(
+                    any(List.class));
+        }
+        if (onStopPrinterDiscovery != null) {
+            doAnswer(onStopPrinterDiscovery).when(callbacks).onStopPrinterDiscovery();
+        }
+        if (onValidatePrinters != null) {
+            doAnswer(onValidatePrinters).when(callbacks).onValidatePrinters(
+                    any(List.class));
+        }
+        if (onStartPrinterStateTracking != null) {
+            doAnswer(onStartPrinterStateTracking).when(callbacks).onStartPrinterStateTracking(
+                    any(PrinterId.class));
+        }
+        if (onRequestCustomPrinterIcon != null) {
+            doAnswer(onRequestCustomPrinterIcon).when(callbacks).onRequestCustomPrinterIcon(
+                    any(PrinterId.class), any(CancellationSignal.class),
+                    any(CustomPrinterIconCallback.class));
+        }
+        if (onStopPrinterStateTracking != null) {
+            doAnswer(onStopPrinterStateTracking).when(callbacks).onStopPrinterStateTracking(
+                    any(PrinterId.class));
+        }
+        if (onDestroy != null) {
+            doAnswer(onDestroy).when(callbacks).onDestroy();
+        }
+
+        return callbacks;
+    }
+
+    protected PrintServiceCallbacks createMockPrintServiceCallbacks(
+            Answer<PrinterDiscoverySessionCallbacks> onCreatePrinterDiscoverySessionCallbacks,
+            Answer<Void> onPrintJobQueued, Answer<Void> onRequestCancelPrintJob) {
+        final PrintServiceCallbacks service = mock(PrintServiceCallbacks.class);
+
+        doCallRealMethod().when(service).setService(any(PrintService.class));
+        when(service.getService()).thenCallRealMethod();
+
+        if (onCreatePrinterDiscoverySessionCallbacks != null) {
+            doAnswer(onCreatePrinterDiscoverySessionCallbacks).when(service)
+                    .onCreatePrinterDiscoverySessionCallbacks();
+        }
+        if (onPrintJobQueued != null) {
+            doAnswer(onPrintJobQueued).when(service).onPrintJobQueued(any(PrintJob.class));
+        }
+        if (onRequestCancelPrintJob != null) {
+            doAnswer(onRequestCancelPrintJob).when(service).onRequestCancelPrintJob(
+                    any(PrintJob.class));
+        }
+
+        return service;
+    }
+}
diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/PrintTestActivity.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/PrintTestActivity.java
new file mode 100644
index 0000000..4905a0b
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/PrintTestActivity.java
@@ -0,0 +1,32 @@
+/*
+ * 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.printspooler.outofprocess.tests;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+public class PrintTestActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+    }
+}
diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java
new file mode 100644
index 0000000..184e559
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java
@@ -0,0 +1,460 @@
+/*
+ * 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.printspooler.outofprocess.tests;
+
+import android.graphics.pdf.PdfDocument;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintDocumentInfo;
+import android.print.PrinterCapabilitiesInfo;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import com.android.printspooler.outofprocess.tests.mockservice.AddPrintersActivity;
+import com.android.printspooler.outofprocess.tests.mockservice.MockPrintService;
+import com.android.printspooler.outofprocess.tests.mockservice.PrinterDiscoverySessionCallbacks;
+import com.android.printspooler.outofprocess.tests.mockservice.StubbablePrinterDiscoverySession;
+import android.print.pdf.PrintedPdfDocument;
+import android.support.test.filters.LargeTest;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+import android.util.Log;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Supplier;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests for the basic printing workflows
+ */
+@RunWith(Parameterized.class)
+public class WorkflowTest extends BasePrintTest {
+    private static final String LOG_TAG = WorkflowTest.class.getSimpleName();
+
+    private static float sWindowAnimationScaleBefore;
+    private static float sTransitionAnimationScaleBefore;
+    private static float sAnimatiorDurationScaleBefore;
+
+    private PrintAttributes.MediaSize mFirst;
+    private boolean mSelectPrinter;
+    private PrintAttributes.MediaSize mSecond;
+
+    public WorkflowTest(PrintAttributes.MediaSize first, boolean selectPrinter,
+            PrintAttributes.MediaSize second) {
+        mFirst = first;
+        mSelectPrinter = selectPrinter;
+        mSecond = second;
+    }
+
+    interface InterruptableConsumer<T> {
+        void accept(T t) throws InterruptedException;
+    }
+
+    /**
+     * Execute {@code waiter} until {@code condition} is met.
+     *
+     * @param condition Conditions to wait for
+     * @param waiter    Code to execute while waiting
+     */
+    private void waitWithTimeout(Supplier<Boolean> condition, InterruptableConsumer<Long> waiter)
+            throws TimeoutException, InterruptedException {
+        long startTime = System.currentTimeMillis();
+        while (condition.get()) {
+            long timeLeft = OPERATION_TIMEOUT - (System.currentTimeMillis() - startTime);
+            if (timeLeft < 0) {
+                throw new TimeoutException();
+            }
+
+            waiter.accept(timeLeft);
+        }
+    }
+
+    /**
+     * Executes a shell command using shell user identity, and return the standard output in
+     * string.
+     *
+     * @param cmd the command to run
+     *
+     * @return the standard output of the command
+     */
+    private static String runShellCommand(String cmd) throws IOException {
+        try (FileInputStream is = new ParcelFileDescriptor.AutoCloseInputStream(
+                getInstrumentation().getUiAutomation().executeShellCommand(cmd))) {
+            byte[] buf = new byte[64];
+            int bytesRead;
+
+            StringBuilder stdout = new StringBuilder();
+            while ((bytesRead = is.read(buf)) != -1) {
+                stdout.append(new String(buf, 0, bytesRead));
+            }
+
+            return stdout.toString();
+        }
+    }
+
+    @BeforeClass
+    public static void disableAnimations() throws Exception {
+        try {
+            sWindowAnimationScaleBefore = Float.parseFloat(runShellCommand(
+                    "settings get global window_animation_scale"));
+
+            runShellCommand("settings put global window_animation_scale 0");
+        } catch (NumberFormatException e) {
+            sWindowAnimationScaleBefore = Float.NaN;
+        }
+        try {
+            sTransitionAnimationScaleBefore = Float.parseFloat(runShellCommand(
+                    "settings get global transition_animation_scale"));
+
+            runShellCommand("settings put global transition_animation_scale 0");
+        } catch (NumberFormatException e) {
+            sTransitionAnimationScaleBefore = Float.NaN;
+        }
+        try {
+            sAnimatiorDurationScaleBefore = Float.parseFloat(runShellCommand(
+                    "settings get global animator_duration_scale"));
+
+            runShellCommand("settings put global animator_duration_scale 0");
+        } catch (NumberFormatException e) {
+            sAnimatiorDurationScaleBefore = Float.NaN;
+        }
+    }
+
+    @AfterClass
+    public static void enableAnimations() throws Exception {
+        if (sWindowAnimationScaleBefore != Float.NaN) {
+            runShellCommand(
+                    "settings put global window_animation_scale " + sWindowAnimationScaleBefore);
+        }
+        if (sTransitionAnimationScaleBefore != Float.NaN) {
+            runShellCommand(
+                    "settings put global transition_animation_scale " +
+                            sTransitionAnimationScaleBefore);
+        }
+        if (sAnimatiorDurationScaleBefore != Float.NaN) {
+            runShellCommand(
+                    "settings put global animator_duration_scale " + sAnimatiorDurationScaleBefore);
+        }
+    }
+
+    /** Add a printer with a given name and supported mediasize to a session */
+    private void addPrinter(StubbablePrinterDiscoverySession session,
+            String name, PrintAttributes.MediaSize mediaSize) {
+        PrinterId printerId = session.getService().generatePrinterId(name);
+        List<PrinterInfo> printers = new ArrayList<>(1);
+
+        PrinterCapabilitiesInfo.Builder builder =
+                new PrinterCapabilitiesInfo.Builder(printerId);
+
+        PrinterInfo printerInfo;
+        if (mediaSize != null) {
+            builder.setMinMargins(new PrintAttributes.Margins(0, 0, 0, 0))
+                    .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                            PrintAttributes.COLOR_MODE_COLOR)
+                    .addMediaSize(mediaSize, true)
+                    .addResolution(new PrintAttributes.Resolution("300x300", "300x300", 300, 300),
+                            true);
+
+            printerInfo = new PrinterInfo.Builder(printerId, name,
+                    PrinterInfo.STATUS_IDLE).setCapabilities(builder.build()).build();
+        } else {
+            printerInfo = (new PrinterInfo.Builder(printerId, name,
+                    PrinterInfo.STATUS_IDLE)).build();
+        }
+
+        printers.add(printerInfo);
+        session.addPrinters(printers);
+    }
+
+    /** Find a certain element in the UI and click on it */
+    private void clickOn(UiSelector selector) throws UiObjectNotFoundException {
+        Log.i(LOG_TAG, "Click on " + selector);
+        UiObject view = getUiDevice().findObject(selector);
+        view.click();
+        getUiDevice().waitForIdle();
+    }
+
+    /** Find a certain text in the UI and click on it */
+    private void clickOnText(String text) throws UiObjectNotFoundException {
+        clickOn(new UiSelector().text(text));
+    }
+
+    /** Set the printer in the print activity */
+    private void setPrinter(String printerName) throws UiObjectNotFoundException {
+        clickOn(new UiSelector().resourceId("com.android.printspooler:id/destination_spinner"));
+
+        clickOnText(printerName);
+    }
+
+    /**
+     * Init mock print servic that returns a single printer by default.
+     *
+     * @param sessionRef Where to store the reference to the session once started
+     */
+    private void setMockPrintServiceCallbacks(StubbablePrinterDiscoverySession[] sessionRef,
+            ArrayList<String> trackedPrinters, PrintAttributes.MediaSize mediaSize) {
+        MockPrintService.setCallbacks(createMockPrintServiceCallbacks(
+                inv -> createMockPrinterDiscoverySessionCallbacks(inv2 -> {
+                            synchronized (sessionRef) {
+                                sessionRef[0] = ((PrinterDiscoverySessionCallbacks) inv2.getMock())
+                                        .getSession();
+
+                                addPrinter(sessionRef[0], "1st printer", mediaSize);
+
+                                sessionRef.notifyAll();
+                            }
+                            return null;
+                        },
+                        null, null, inv2 -> {
+                            synchronized (trackedPrinters) {
+                                trackedPrinters
+                                        .add(((PrinterId) inv2.getArguments()[0]).getLocalId());
+                                trackedPrinters.notifyAll();
+                            }
+                            return null;
+                        }, null, inv2 -> {
+                            synchronized (trackedPrinters) {
+                                trackedPrinters
+                                        .remove(((PrinterId) inv2.getArguments()[0]).getLocalId());
+                                trackedPrinters.notifyAll();
+                            }
+                            return null;
+                        }, inv2 -> {
+                            synchronized (sessionRef) {
+                                sessionRef[0] = null;
+                                sessionRef.notifyAll();
+                            }
+                            return null;
+                        }
+                ), null, null));
+    }
+
+    /**
+     * Start print operation that just prints a single empty page
+     *
+     * @param printAttributesRef Where to store the reference to the print attributes once started
+     */
+    private void print(PrintAttributes[] printAttributesRef) {
+        print(new PrintDocumentAdapter() {
+            @Override
+            public void onStart() {
+            }
+
+            @Override
+            public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
+                    CancellationSignal cancellationSignal, LayoutResultCallback callback,
+                    Bundle extras) {
+                callback.onLayoutFinished((new PrintDocumentInfo.Builder("doc")).build(),
+                        !newAttributes.equals(printAttributesRef[0]));
+
+                synchronized (printAttributesRef) {
+                    printAttributesRef[0] = newAttributes;
+                    printAttributesRef.notifyAll();
+                }
+            }
+
+            @Override
+            public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
+                    CancellationSignal cancellationSignal, WriteResultCallback callback) {
+                try {
+                    try {
+                        PrintedPdfDocument document = new PrintedPdfDocument(getActivity(),
+                                printAttributesRef[0]);
+                        try {
+                            PdfDocument.Page page = document.startPage(0);
+                            document.finishPage(page);
+                            try (FileOutputStream os = new FileOutputStream(
+                                    destination.getFileDescriptor())) {
+                                document.writeTo(os);
+                                os.flush();
+                            }
+                        } finally {
+                            document.close();
+                        }
+                    } finally {
+                        destination.close();
+                    }
+
+                    callback.onWriteFinished(pages);
+                } catch (IOException e) {
+                    callback.onWriteFailed(e.getMessage());
+                }
+            }
+        }, null);
+    }
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> getParameters() {
+        ArrayList<Object[]> tests = new ArrayList<>();
+
+        for (PrintAttributes.MediaSize first : new PrintAttributes.MediaSize[]{
+                PrintAttributes.MediaSize.ISO_A0, null}) {
+            for (Boolean selectPrinter : new Boolean[]{true, false}) {
+                for (PrintAttributes.MediaSize second : new PrintAttributes.MediaSize[]{
+                        PrintAttributes.MediaSize.ISO_A1, null}) {
+                    // If we do not use the second printer, no need to try various options
+                    if (!selectPrinter && second == null) {
+                        continue;
+                    }
+                    tests.add(new Object[]{first, selectPrinter, second});
+                }
+            }
+        }
+
+        return tests;
+    }
+
+    @Test
+    @LargeTest
+    public void addAndSelectPrinter() throws Exception {
+        final StubbablePrinterDiscoverySession session[] = new StubbablePrinterDiscoverySession[1];
+        final PrintAttributes printAttributes[] = new PrintAttributes[1];
+        ArrayList<String> trackedPrinters = new ArrayList<>();
+
+        Log.i(LOG_TAG, "Running " + mFirst + " " + mSelectPrinter + " " + mSecond);
+
+        setMockPrintServiceCallbacks(session, trackedPrinters, mFirst);
+        print(printAttributes);
+
+        // We are now in the PrintActivity
+        Log.i(LOG_TAG, "Waiting for session");
+        synchronized (session) {
+            waitWithTimeout(() -> session[0] == null, session::wait);
+        }
+
+        setPrinter("1st printer");
+
+        Log.i(LOG_TAG, "Waiting for 1st printer to be tracked");
+        synchronized (trackedPrinters) {
+            waitWithTimeout(() -> !trackedPrinters.contains("1st printer"), trackedPrinters::wait);
+        }
+
+        if (mFirst != null) {
+            Log.i(LOG_TAG, "Waiting for print attributes to change");
+            synchronized (printAttributes) {
+                waitWithTimeout(
+                        () -> printAttributes[0] == null ||
+                                !printAttributes[0].getMediaSize().equals(
+                                        mFirst), printAttributes::wait);
+            }
+        } else {
+            Log.i(LOG_TAG, "Waiting for error message");
+            assertNotNull(getUiDevice().wait(Until.findObject(
+                    By.text("This printer isn't available right now.")), OPERATION_TIMEOUT));
+        }
+
+        setPrinter("All printers\u2026");
+
+        // We are now in the SelectPrinterActivity
+        clickOnText("Add printer");
+
+        // We are now in the AddPrinterActivity
+        AddPrintersActivity.addObserver(
+                () -> addPrinter(session[0], "2nd printer", mSecond));
+
+        // This executes the observer registered above
+        clickOn(new UiSelector().text(MockPrintService.class.getCanonicalName())
+                .resourceId("com.android.printspooler:id/title"));
+
+        getUiDevice().pressBack();
+        AddPrintersActivity.clearObservers();
+
+        if (mSelectPrinter) {
+            // We are now in the SelectPrinterActivity
+            clickOnText("2nd printer");
+        } else {
+            getUiDevice().pressBack();
+        }
+
+        // We are now in the PrintActivity
+        if (mSelectPrinter) {
+            if (mSecond != null) {
+                Log.i(LOG_TAG, "Waiting for print attributes to change");
+                synchronized (printAttributes) {
+                    waitWithTimeout(
+                            () -> printAttributes[0] == null ||
+                                    !printAttributes[0].getMediaSize().equals(
+                                            mSecond), printAttributes::wait);
+                }
+            } else {
+                Log.i(LOG_TAG, "Waiting for error message");
+                assertNotNull(getUiDevice().wait(Until.findObject(
+                        By.text("This printer isn't available right now.")), OPERATION_TIMEOUT));
+            }
+
+            Log.i(LOG_TAG, "Waiting for 1st printer to be not tracked");
+            synchronized (trackedPrinters) {
+                waitWithTimeout(() -> trackedPrinters.contains("1st printer"),
+                        trackedPrinters::wait);
+            }
+
+            Log.i(LOG_TAG, "Waiting for 2nd printer to be tracked");
+            synchronized (trackedPrinters) {
+                waitWithTimeout(() -> !trackedPrinters.contains("2nd printer"),
+                        trackedPrinters::wait);
+            }
+        } else {
+            Thread.sleep(100);
+
+            if (mFirst != null) {
+                Log.i(LOG_TAG, "Waiting for print attributes to change");
+                synchronized (printAttributes) {
+                    waitWithTimeout(
+                            () -> printAttributes[0] == null ||
+                                    !printAttributes[0].getMediaSize().equals(
+                                            mFirst), printAttributes::wait);
+                }
+            } else {
+                Log.i(LOG_TAG, "Waiting for error message");
+                assertNotNull(getUiDevice().wait(Until.findObject(
+                        By.text("This printer isn't available right now.")), OPERATION_TIMEOUT));
+            }
+
+            Log.i(LOG_TAG, "Waiting for 1st printer to be tracked");
+            synchronized (trackedPrinters) {
+                waitWithTimeout(() -> !trackedPrinters.contains("1st printer"),
+                        trackedPrinters::wait);
+            }
+        }
+
+        getUiDevice().pressBack();
+
+        // We are back in the test activity
+        Log.i(LOG_TAG, "Waiting for session to end");
+        synchronized (session) {
+            waitWithTimeout(() -> session[0] != null, session::wait);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/print/mockservice/AddPrintersActivity.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/AddPrintersActivity.java
similarity index 95%
rename from core/tests/coretests/src/android/print/mockservice/AddPrintersActivity.java
rename to packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/AddPrintersActivity.java
index 8f1a9ed..2ea4e7d 100644
--- a/core/tests/coretests/src/android/print/mockservice/AddPrintersActivity.java
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/AddPrintersActivity.java
@@ -14,7 +14,7 @@
  *  limitations under the License.
  */
 
-package android.print.mockservice;
+package com.android.printspooler.outofprocess.tests.mockservice;
 
 import android.app.Activity;
 import android.os.Bundle;
diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/MockPrintService.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/MockPrintService.java
new file mode 100644
index 0000000..3a23113
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/MockPrintService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.printspooler.outofprocess.tests.mockservice;
+
+public class MockPrintService extends StubbablePrintService {
+
+    private static final Object sLock = new Object();
+
+    private static PrintServiceCallbacks sCallbacks;
+
+    public static void setCallbacks(PrintServiceCallbacks callbacks) {
+        synchronized (sLock) {
+            sCallbacks = callbacks;
+        }
+    }
+
+    @Override
+    protected PrintServiceCallbacks getCallbacks() {
+        synchronized (sLock) {
+            if (sCallbacks != null) {
+                sCallbacks.setService(this);
+            }
+            return sCallbacks;
+        }
+    }
+}
diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/PrintServiceCallbacks.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/PrintServiceCallbacks.java
new file mode 100644
index 0000000..07baa0f
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/PrintServiceCallbacks.java
@@ -0,0 +1,39 @@
+/*
+ * 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.printspooler.outofprocess.tests.mockservice;
+
+import android.printservice.PrintJob;
+import android.printservice.PrintService;
+
+public abstract class PrintServiceCallbacks {
+
+    private PrintService mService;
+
+    public PrintService getService() {
+        return mService;
+    }
+
+    public void setService(PrintService service) {
+        mService = service;
+    }
+
+    public abstract PrinterDiscoverySessionCallbacks onCreatePrinterDiscoverySessionCallbacks();
+
+    public abstract void onRequestCancelPrintJob(PrintJob printJob);
+
+    public abstract void onPrintJobQueued(PrintJob printJob);
+}
diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/PrinterDiscoverySessionCallbacks.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/PrinterDiscoverySessionCallbacks.java
new file mode 100644
index 0000000..5c1260c
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/PrinterDiscoverySessionCallbacks.java
@@ -0,0 +1,51 @@
+/*
+ * 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.printspooler.outofprocess.tests.mockservice;
+
+import android.os.CancellationSignal;
+import android.print.PrinterId;
+import android.printservice.CustomPrinterIconCallback;
+
+import java.util.List;
+
+public abstract class PrinterDiscoverySessionCallbacks {
+
+    private StubbablePrinterDiscoverySession mSession;
+
+    public void setSession(StubbablePrinterDiscoverySession session) {
+        mSession = session;
+    }
+
+    public StubbablePrinterDiscoverySession getSession() {
+        return mSession;
+    }
+
+    public abstract void onStartPrinterDiscovery(List<PrinterId> priorityList);
+
+    public abstract void onStopPrinterDiscovery();
+
+    public abstract void onValidatePrinters(List<PrinterId> printerIds);
+
+    public abstract void onStartPrinterStateTracking(PrinterId printerId);
+
+    public abstract void onRequestCustomPrinterIcon(PrinterId printerId,
+            CancellationSignal cancellationSignal, CustomPrinterIconCallback callback);
+
+    public abstract void onStopPrinterStateTracking(PrinterId printerId);
+
+    public abstract void onDestroy();
+}
diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/StubbablePrintService.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/StubbablePrintService.java
new file mode 100644
index 0000000..be9d19b
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/StubbablePrintService.java
@@ -0,0 +1,52 @@
+/*
+ * 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.printspooler.outofprocess.tests.mockservice;
+
+import android.printservice.PrintJob;
+import android.printservice.PrintService;
+import android.printservice.PrinterDiscoverySession;
+
+public abstract class StubbablePrintService extends PrintService {
+
+    @Override
+    public PrinterDiscoverySession onCreatePrinterDiscoverySession() {
+        PrintServiceCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            return new StubbablePrinterDiscoverySession(this,
+                    getCallbacks().onCreatePrinterDiscoverySessionCallbacks());
+        }
+        return null;
+    }
+
+    @Override
+    public void onRequestCancelPrintJob(PrintJob printJob) {
+        PrintServiceCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            callbacks.onRequestCancelPrintJob(printJob);
+        }
+    }
+
+    @Override
+    public void onPrintJobQueued(PrintJob printJob) {
+        PrintServiceCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            callbacks.onPrintJobQueued(printJob);
+        }
+    }
+
+    protected abstract PrintServiceCallbacks getCallbacks();
+}
diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/StubbablePrinterDiscoverySession.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/StubbablePrinterDiscoverySession.java
new file mode 100644
index 0000000..a828cd6
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/mockservice/StubbablePrinterDiscoverySession.java
@@ -0,0 +1,95 @@
+/*
+ * 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.printspooler.outofprocess.tests.mockservice;
+
+import android.os.CancellationSignal;
+import android.print.PrinterId;
+import android.printservice.CustomPrinterIconCallback;
+import android.printservice.PrintService;
+import android.printservice.PrinterDiscoverySession;
+import android.support.annotation.NonNull;
+
+import java.util.List;
+
+public class StubbablePrinterDiscoverySession extends PrinterDiscoverySession {
+    private final PrintService mService;
+    private final PrinterDiscoverySessionCallbacks mCallbacks;
+
+    public StubbablePrinterDiscoverySession(PrintService service,
+            PrinterDiscoverySessionCallbacks callbacks) {
+        mService = service;
+        mCallbacks = callbacks;
+        if (mCallbacks != null) {
+            mCallbacks.setSession(this);
+        }
+    }
+
+    public PrintService getService() {
+        return mService;
+    }
+
+    @Override
+    public void onStartPrinterDiscovery(@NonNull List<PrinterId> priorityList) {
+        if (mCallbacks != null) {
+            mCallbacks.onStartPrinterDiscovery(priorityList);
+        }
+    }
+
+    @Override
+    public void onStopPrinterDiscovery() {
+        if (mCallbacks != null) {
+            mCallbacks.onStopPrinterDiscovery();
+        }
+    }
+
+    @Override
+    public void onValidatePrinters(@NonNull List<PrinterId> printerIds) {
+        if (mCallbacks != null) {
+            mCallbacks.onValidatePrinters(printerIds);
+        }
+    }
+
+    @Override
+    public void onStartPrinterStateTracking(@NonNull PrinterId printerId) {
+        if (mCallbacks != null) {
+            mCallbacks.onStartPrinterStateTracking(printerId);
+        }
+    }
+
+    @Override
+    public void onRequestCustomPrinterIcon(@NonNull PrinterId printerId,
+            @NonNull CancellationSignal cancellationSignal,
+            @NonNull CustomPrinterIconCallback callback) {
+        if (mCallbacks != null) {
+            mCallbacks.onRequestCustomPrinterIcon(printerId, cancellationSignal, callback);
+        }
+    }
+
+    @Override
+    public void onStopPrinterStateTracking(@NonNull PrinterId printerId) {
+        if (mCallbacks != null) {
+            mCallbacks.onStopPrinterStateTracking(printerId);
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mCallbacks != null) {
+            mCallbacks.onDestroy();
+        }
+    }
+}
diff --git a/packages/SettingsLib/res/layout/restricted_switch_preference.xml b/packages/SettingsLib/res/layout/restricted_switch_preference.xml
index 89dc10b..bb1d906 100644
--- a/packages/SettingsLib/res/layout/restricted_switch_preference.xml
+++ b/packages/SettingsLib/res/layout/restricted_switch_preference.xml
@@ -20,7 +20,7 @@
     android:gravity="center_vertical"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-    android:background="?android:attr/activatedBackgroundIndicator"
+    android:background="?android:attr/selectableItemBackground"
     android:clipToPadding="false">
 
     <LinearLayout
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 20e3f6f..295248c 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Wys snitgrense, kantlyne, ens."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Dwing RTL-uitlegrigting"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Dwing skermuitlegrigting na RTL vir alle locales"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Wys CPU-verbruik"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Skermlaag wys huidige CPU-gebruik"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forseer GPU-lewering"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Dwing gebruik van GPU vir 2D-tekening"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Dwing 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index e4455a4..bb50087 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"የቅንጥብ ገደቦች፣ ጠርዞች፣ ወዘተ አሳይ"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"የቀኝ-ወደ-ግራ አቀማመጥ አቅጣጫ አስገድድ"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"ለሁሉም አካባቢዎች የማያ ገጽ አቀማመጥ ከቀኝ-ወደ-ግራ እንዲሆን አስገድድ"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"የCPU አጠቃቀም አሳይ"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"የማያ ተደራቢ የአሁኑን የCPU አጠቃቀም  እያሳየ ነው።"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU ምላሽ መስጠትን አስገድድ"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"ለ2-ልኬት መሳል የGPU ስራ አስገድድ"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA አስገድድ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 24b51ec..829123c 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"عرض حدود وهوامش المقطع وما إلى ذلك."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"فرض اتجاه التنسيق ليكون من اليمين إلى اليسار"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"فرض اتجاه تنسيق الشاشة ليكون من اليمين إلى اليسار لجميع اللغات"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"‏عرض استخدام CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"‏عرض تراكب الشاشة لاستخدام CPU الحالي"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"‏فرض عرض رسومات GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"فرض استخدام وحدة معالجة الرسومات للرسم ثنائي الأبعاد"</string>
     <string name="force_msaa" msgid="7920323238677284387">"‏فرض 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index 5eb7a00..483770f 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Klip sərhədləri, boşluqları və s. göstər"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL düzən istiqamətinə məcbur edin"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Ekran düzən istiqamətini RTL üzərinə bütün yerli variantlar üçün məcbur edin"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU istifadəsini göstər"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Ekran örtüşməsi cari CPU istifadəsini göstərir"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU renderə məcbur edin"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d rəsm üçün GPU məcburi istifadə"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA məcbur edin"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 1acc445..5498580a 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Prikaži granice klipa, margine itd."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Nametni smer rasporeda zdesna nalevo"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Nametni smer rasporeda ekrana zdesna nalevo za sve lokalitete"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Prik. upotrebu procesora"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Postav. element sa trenutnom upotrebom procesora"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Prinudni prikaz pom. GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Prinudno koristi GPU za 2D crtanje"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Nametni 4x MSAA"</string>
@@ -283,7 +281,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="2485604010404197724">"Pokrećite WebView prikazivače zasebno"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Primena WebView-a"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Podesite primenu WebView-a"</string>
-    <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Ovaj izbor više nije važeći. Pokušajte ponovo."</string>
+    <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Ovaj izbor više nije važeći. Probajte ponovo."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertuj u šifrovanje datoteka"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertuj..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Već se koristi šifrovanje datoteka"</string>
diff --git a/packages/SettingsLib/res/values-be-rBY/strings.xml b/packages/SettingsLib/res/values-be-rBY/strings.xml
index 0e3faca..f233db9 100644
--- a/packages/SettingsLib/res/values-be-rBY/strings.xml
+++ b/packages/SettingsLib/res/values-be-rBY/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Паказаць межы кліпу, палі і г. д."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Прымусовая раскладка справа налева"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Прымусовая раскладка экрана справа налева для ўсіх рэгіянальных налад"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Паказаць выкарыстанне ЦП"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Наклад на экран з бягучым выкарыстаннем працэсара"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Прымусовае адлюстраванне GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Прымусовае выкарыстанне GPU для 2-мерных чарцяжоў"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Прымусовае выкананне 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 1d618d7..cd77792 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Показв. на границите на изрязване, полетата и др."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Принуд. оформл. отдясно наляво"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Принуд. оформл. на екрана отдясно наляво за вс. локали"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Употреба на процесора"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Наслагване на екрана показва употр. на процесора"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Принудително изобразяване"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Принуд. използв. на GPU за двуизмерно начертаване"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Задаване на 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index c094d27..a011fcf 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"ক্লিপ বাউন্ড, মার্জিন ইত্যাদি দেখান"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL লেআউট দিকনির্দেশ জোর দিন"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"সমস্ত স্থানের জন্য RTL এ স্ক্রীন লেআউট দিকনির্দেশে জোর দেয়"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU এর ব্যবহার দেখান"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"স্ক্রীন ওভারলে বর্তমান CPU ব্যবহার দেখাচ্ছে"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"জোর করে GPU রেন্ডারিং করুন"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2D অঙ্কনের জন্য GPU-এর ব্যবহারে জোর দিন"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA এ জোর দিন"</string>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index b7a7d29..1df5ec9 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Prikaži granice isječka, margine itd."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Prisilno postavi raspored s desna u lijevo"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Prisilno postavi raspored ekrana s desna u lijevo za sve regije"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Prikaži korištenje CPU-a"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Trenutno korištenje CPU-a prikazuje se u nadsloju preko ekrana"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Prisili GPU iscrtavanje"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Prisilno koristite GPU za 2d crtanje"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Prinudno primjeni 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 0d696d5..92e9005 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Mostra els límits de clips, els marges, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Força direcció dreta-esquerra"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Força direcció de pantalla dreta-esquerra en totes les llengües"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Mostra l\'ús de la CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Superposa l\'ús de la CPU a la pantalla"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Força acceleració GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Força l\'ús de GPU per a dibuixos en 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Força MSAA  4x"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 486819a..8ec531c 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Zobrazit u výstřižku ohraničení, okraje atd."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Vynutit rozvržení zprava doleva"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Vynutit ve všech jazycích rozvržení obrazovky zprava doleva"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Zobrazit využití CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Překryvná vrstva s aktuálním využitím procesoru"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Vykreslování pomocí GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Vynutit použití GPU pro 2D vykreslování"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Vynutit 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index af4bf05..a65c58f 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -152,7 +152,7 @@
     <string name="clear_adb_keys" msgid="4038889221503122743">"Tilbagekald tilladelser for USB-fejlfinding"</string>
     <string name="bugreport_in_power" msgid="7923901846375587241">"Genvej til fejlrapporting"</string>
     <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Vis en knap til oprettelse af fejlrapporter i menu for slukknap"</string>
-    <string name="keep_screen_on" msgid="1146389631208760344">"Undgå dvale"</string>
+    <string name="keep_screen_on" msgid="1146389631208760344">"Lås ikke"</string>
     <string name="keep_screen_on_summary" msgid="2173114350754293009">"Skærmen går ikke i dvale under opladning"</string>
     <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Aktivér Bluetooth HCI snoop log"</string>
     <string name="bt_hci_snoop_log_summary" msgid="730247028210113851">"Gem alle Bluetooth HCI-pakker i en fil"</string>
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Vis grænser for klip, margener osv."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Tving læsning mod venstre"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Tving til højre mod venstre-layout for alle sprog"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Vis CPU-forbrug"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Skærmoverlejring viser det aktuelle CPU-forbrug"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Tving gengivelse af GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Gennemtving brug af GPU til 2D-tegning"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Tving 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index e4da20d..923eca1 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -39,7 +39,7 @@
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Verbindung wird getrennt..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Verbindung wird hergestellt..."</string>
     <string name="bluetooth_connected" msgid="6038755206916626419">"Verbunden"</string>
-    <string name="bluetooth_pairing" msgid="1426882272690346242">"Pairing läuft…"</string>
+    <string name="bluetooth_pairing" msgid="1426882272690346242">"Kopplung läuft…"</string>
     <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Verbunden (kein Telefon)"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Verbunden (außer Audiomedien)"</string>
     <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Verbunden (ohne Nachrichtenzugriff)"</string>
@@ -70,12 +70,12 @@
     <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Für Audiosystem des Telefons verwenden"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Für Dateiübertragung verwenden"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Für Eingabe verwenden"</string>
-    <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pairing durchführen"</string>
-    <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"Pairing durchführen"</string>
+    <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Koppeln"</string>
+    <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOPPELN"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Abbrechen"</string>
-    <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Über das Pairing kann auf deine Kontakte und auf deinen Anrufverlauf zugegriffen werden, wenn eine Verbindung besteht."</string>
-    <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Pairing mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> war nicht möglich."</string>
-    <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Pairing mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> war nicht möglich, weil die eingegebene PIN oder der Zugangscode falsch ist."</string>
+    <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Über die Kopplung kann auf deine Kontakte und auf deinen Anrufverlauf zugegriffen werden, wenn eine Verbindung besteht."</string>
+    <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Kopplung mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> war nicht möglich."</string>
+    <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Kopplung mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> war nicht möglich, weil die eingegebene PIN oder der Zugangscode falsch ist."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Kommunikation mit <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ist nicht möglich."</string>
     <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Verbindung wurde von <xliff:g id="DEVICE_NAME">%1$s</xliff:g> abgelehnt."</string>
     <string name="accessibility_wifi_off" msgid="1166761729660614716">"WLAN: aus"</string>
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Clip-Begrenzungen, Ränder usw. anzeigen"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL-Layout erzwingen"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"RTL-Bildschirmlayout für alle Sprachen erzwingen"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU-Auslastung anzeigen"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Bildschirm-Overlay mit aktueller CPU-Auslastung"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU-Rendering erzwingen"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Einsatz von GPU für 2D-Zeichnung erzwingen"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA erzwingen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 715b6c4..3c0247d 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Εμφάνιση ορίων κλιπ, περιθωρίων, κλπ."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Επιβολή κατ. διάταξης RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Επιβολή διάταξης οθόν. RTL για όλες τις τοπ. ρυθμ."</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Προβολή χρήσης CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Επικάλυψη οθόνης για προβολή τρέχουσας χρήσης CPU"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Αναγκαστική απόδοση GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Αναγκαστική χρήση του GPU για σχέδιο 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Αναγκαστικά 4x MSAA"</string>
@@ -288,8 +286,8 @@
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Μετατροπή…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Με κρυπτογράφηση αρχείου"</string>
     <string name="title_convert_fbe" msgid="1263622876196444453">"Μετατροπή σε κρυπτογράφηση βάσει αρχείου…"</string>
-    <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Μετατροπή τμήματος δεδομένων σε κρυπτογράφηση βάσει αρχείου.\n !!Προσοχή!! Με αυτήν την ενέργεια, θα διαγραφούν όλα τα δεδομένα σας.\n Αυτή η λειτουργία βρίσκεται σε δοκιμαστικό στάδιο alpha και ενδέχεται να μην λειτουργεί σωστά.\n Πατήστε \"Εκκαθάριση και μετατροπή…\" για να συνεχίσετε."</string>
-    <string name="button_convert_fbe" msgid="5152671181309826405">"Εκκαθάριση και μετατροπή…"</string>
+    <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Μετατροπή τμήματος δεδομένων σε κρυπτογράφηση βάσει αρχείου.\n !!Προσοχή!! Με αυτήν την ενέργεια, θα διαγραφούν όλα τα δεδομένα σας.\n Αυτή η λειτουργία βρίσκεται σε δοκιμαστικό στάδιο alpha και ενδέχεται να μην λειτουργεί σωστά.\n Πατήστε \"Διαγραφή και μετατροπή…\" για να συνεχίσετε."</string>
+    <string name="button_convert_fbe" msgid="5152671181309826405">"Διαγραφή και μετατροπή…"</string>
     <string name="picture_color_mode" msgid="4560755008730283695">"Λειτουργία χρώματος εικόνας"</string>
     <string name="picture_color_mode_desc" msgid="1141891467675548590">"Χρήση sRGB"</string>
     <string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Απενεργοποιημένο"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index f3bc540..8ed7444 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Show clip bounds, margins, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Force RTL layout direction"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Force screen layout direction to RTL for all locales"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Show CPU usage"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Screen overlay showing current CPU usage"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Force GPU rendering"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Force use of GPU for 2D drawing"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Force 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index f3bc540..8ed7444 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Show clip bounds, margins, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Force RTL layout direction"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Force screen layout direction to RTL for all locales"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Show CPU usage"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Screen overlay showing current CPU usage"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Force GPU rendering"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Force use of GPU for 2D drawing"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Force 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index f3bc540..8ed7444 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Show clip bounds, margins, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Force RTL layout direction"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Force screen layout direction to RTL for all locales"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Show CPU usage"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Screen overlay showing current CPU usage"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Force GPU rendering"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Force use of GPU for 2D drawing"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Force 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 8f91cb7..cdfbc01 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Mostrar límites de recortes, márgenes, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forzar diseño der. a izq."</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Forzar diseño pantalla der.&gt;izq., cualquier idioma"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Mostrar el uso de CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Mostrar superposición en pantalla con uso actual de la CPU"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forzar representación GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Forzar uso de GPU para dibujar en 2d"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Forzar MSAA 4x"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index fc8da79..2a21d22 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Mostrar límites de vídeo, márgenes, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forzar dirección diseño RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Forzar dirección (RTL) para todas configuraciones"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Mostrar uso de la CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Suporponer el uso de la CPU en la pantalla"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forzar aceleración GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Forzar uso de GPU para dibujos en 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Forzar MSAA 4x"</string>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index d28818b..644bf59 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Kuva klipi piirid, veerised jms"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Paremalt vasakule paig."</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Määra lokaatides ekraanipaig. paremalt vasakule"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU-kasutuse kuvamine"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Praegust CPU-kasutust kuvav ekraani ülekate"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Jõusta GPU renderdamine"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Jõusta GPU kasutam. kahemõõtmeliste jooniste puhul"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Jõusta 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index a975971..2217611 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Erakutsi kliparen mugak, marjinak, etab."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Behartu eskuin-ezker norabidea."</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Behartu pantaila-diseinuaren norabidea eskuin-ezker izatera eskualdeko ezarpen guztiekin."</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Erakutsi PUZ erabilera"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"PUZ erabilera erakusten duen pantaila-gainjartzea"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Behartu GPU errendatzea"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Behartu GPUa erabiltzera 2 dimentsioko marrazkietan."</string>
     <string name="force_msaa" msgid="7920323238677284387">"Behartu 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 8f613aa..88ed7fa 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"نمایش مرزها، حاشیه‌ها و ویژگی‌های دیگر کلیپ."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"‏اجباری کردن چیدمان RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"‏اجباری کردن چیدمان RTL صفحه برای همه زبان‌ها"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"‏نمایش میزان استفاده از CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"‏هم‌پوشانی صفحه‌نمایش میزان استفاده از CPU فعلی"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"‏پردازش اجباری GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"‏استفاده اجباری از GPU برای طراحی دوم"</string>
     <string name="force_msaa" msgid="7920323238677284387">"‏اجبار 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index ea2a17f..d26fc05 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Näytä leikkeiden rajat, marginaalit jne."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Pakota RTL-ulkoasun suunta"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Pakota kaikkien kielten näytön ulkoasun suunnaksi RTL"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Näytä suorittimen käyttö"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Näytön peittokuva näyttää nykyisen suoritinkäytön"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Pakota GPU-hahmonnus"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Käytä GPU:ta 2d-piirtämiseen"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Pakota 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 3001a69..caad889 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Afficher les limites, les marges de clip, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forcer orient. : g. à d."</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Forcer l\'orientation: g. à droite (toutes langues)"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Afficher mém. CPU utilisée"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Superposition écran indiquant mémoire CPU utilisée"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forcer le rendu GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Forcer l\'utilisation du GPU pour le dessin 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Forcer MSAA 4x"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index c00a030..91bbaf0 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Afficher les limites de coupe, les marges, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forcer droite à gauche"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Forcer orient. droite à gauche pour toutes langues"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Afficher mém. CPU utilisée"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Superposition écran indiquant mémoire CPU utilisée"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forcer le rendu GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Forcer l\'utilisation du GPU pour le dessin 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Forcer MSAA 4x"</string>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 03cf223..b717382 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Mostra os límites dos clips, as marxes, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forzar dirección do deseño RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Forza a dirección de pantalla a RTL (dereita a esquerda) para todas as configuración rexionais"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Mostrar uso da CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Superpoñer o uso da CPU na pantalla"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forzar procesamento GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Forzar o uso de GPU para o debuxo en 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Forzar MSAA 4x"</string>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 737af54..5605189 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"ક્લિપ બાઉન્ડ્સ, હાંસિયાં વગેરે બતાવો."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL લેઆઉટ દિશા નિર્દેશની ફરજ પાડો"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"તમામ લૉકેલ્સ માટે સ્ક્રીન લેઆઉટ દિશા નિર્દેશને RTL ની ફરજ પાડો"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU સંગ્રહ બતાવો"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"વર્તમાન CPU વપરાશ દર્શાવતું સ્ક્રીન ઓવરલે"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU રેન્ડરિંગની ફરજ પાડો"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2જા રેખાંકન માટે GPU ના ઉપયોગની ફરજ પાડો"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA ને ફરજ પાડો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index efefca3..d579ec4 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"क्लिप सीमाएं, मार्जिन, आदि दिखाएं."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL लेआउट दिशा लागू करें"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"सभी भाषाओं के लिए स्क्रीन लेआउट दिशा को RTL रखें"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU उपयोग दिखाएं"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"स्‍क्रीन ओवरले वर्तमान CPU उपयोग को दिखा रहा है"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"बलपूर्वक GPU रेंडर करें"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d ड्रॉइंग के लिए GPU का बलपूर्वक उपयोग करें"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA को बाध्य करें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 8990536..94229b1 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Prikazuju se obrubi, margine itd. isječaka."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Nametni zdesna ulijevo"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Nametni smjer zdesna ulijevo za sve zemlje/jezike"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Prikaži upotrebu procesora"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Na zaslonu se prikazuje iskorištenost procesora."</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Nametni GPU renderiranje"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Nametni upotrebu GPU-a za 2D crteže"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Nametni 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index c557161..34f06e5 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Kliphatárok, margók stb. megjelenítése."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Elrendezés jobbról balra"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Elrendezés jobbról balra minden nyelvnél"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU-használat mutatása"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Képernyőfedvény a jelenlegi CPU-használattal"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU-megjelenítés"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"GPU használatának kényszerítése 2D rajzhoz"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA kényszerítése"</string>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 41556dc..9428e17 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi կապի ձախողում"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Նույնականացման խնդիր"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ընդգրկույթից դուրս է"</string>
-    <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Ավտոմատ միացում չի կատարվի"</string>
+    <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Չի միանա ավտոմատ"</string>
     <string name="wifi_no_internet" msgid="3880396223819116454">"Ինտերնետ կապ չկա"</string>
     <string name="saved_network" msgid="4352716707126620811">"Պահել է հետևյալ օգտվողը՝ <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Կապակցված է Wi‑Fi Օգնականի միջոցով"</string>
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Ցույց տալ կտրվածքի սահմանները, լուսանցքները և այլն"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Փոխել RTL-ի դասավորության ուղղությունը"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Դարձնել էկրանի դասավորության ուղղությունը դեպի RTL բոլոր լեզուների համար"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Ցույց տալ CPU-ի աշխատանքը"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Էկրանի վերադրումը ցույց է տալիս ընթացիկ CPU օգտագործումը"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Ստիպել GPU-ին մատուցել"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Ստիպողաբար GPU-ի օգտագործում 2-րդ պատկերի համար"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Ստիպել  4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 039457d..a382e37 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Tampilkan batas klip, margin, dll."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Paksa arah tata letak RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Paksa arah tata letak layar RTL untuk semua lokal"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Tampilkan penggunaan CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Hamparan layar menampilkan penggunaan CPU saat ini"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Paksa perenderan GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Paksa penggunaan GPU untuk gambar 2d"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Force 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index a3126bf..44517a8 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Sýna skurðlínur, spássíur o.s.frv."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Þvinga umbrot frá hægri til vinstri"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Þvinga umbrot skjás frá hægri til vinstri fyrir alla tungumálskóða"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Sýna örgjörvanotkun"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Skjáyfirlögn sem sýnir núverandi örgjörvanotkun"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Þvinga skjákortsteiknun"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Þvinga notkun skjákorts fyrir tvívíða teikningu"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Þvinga 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index bff3bb7..7a32827 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Mostra limiti, margini dei clip e così via"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forza direzione layout RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Direzione layout schermo RTL per tutte le lingue"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Mostra utilizzo CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Overlay schermo che mostra l\'uso corrente della CPU"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forza rendering GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Forza l\'uso della GPU per i disegni 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Forza MSAA 4x"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 4d794fc..2e85770 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"הצג גבולות קליפ, שוליים וכו\'"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"אלץ כיוון פריסה מימין לשמאל"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"אלץ כיוון פריסת מסך מימין לשמאל עבור כל השפות בכל המקומות"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"‏הצג את השימוש ב-CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"‏שכבת-על של מסך שמציגה את השימוש הנוכחי ב-CPU"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"‏אלץ עיבוד ב-GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"‏אכוף שימוש ב-GPU לשרטוט דו-מימדי"</string>
     <string name="force_msaa" msgid="7920323238677284387">"‏אלץ הפעלת 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 4c4eed0..00e323c 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"クリップの境界線、マージンなどを表示"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTLレイアウト方向を使用"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"すべての言語/地域で画面レイアウト方向をRTLに設定"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU使用状況を表示"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"現在のCPU使用状況をオーバーレイ表示する"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPUレンダリングを使用"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2D描画にGPUを常に使用する"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAAを適用"</string>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 2142fa3..2b9e8cb 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"კლიპის საზღვრების, მინდვრების ჩვენება და ა.შ."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"მარჯვნიდან მარცხნივ განლაგების მიმართულების იძულება"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"ეკრანის RTL მიმართულებაზე იძულება ყველა ლოკალისათვის"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"ცენტრალური პროცესორის ჩატვირთვის ჩვენება"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"ეკრანის გადაფარვა აჩვენებს CPU ამჟამინდელ გამოყენებას"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU-აჩქარება"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"GPU-ის ძალით გამოყენება 2d drawing-თვის"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA-ს ჩართვა"</string>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index e00e820..0037c11 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Қию шектерін, жиектерін, т.б көрсету."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Оңнан солға орналасу бағытына реттеу"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Экранның орналасу бағытын барлық тілдер үшін оңнан солға қарату"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU (орталық өңдеу бірлігі) қолданысы"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Экран бетіне ағымдағы CPU қолданысы көрсетіледі"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU рендерингін жылдамдату"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Графикалық процессорды 2d сызбаларына қолдану"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA қолдану"</string>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 3593c4a..235ea6a 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -28,10 +28,8 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"ការ​ភ្ជាប់​ WiFi បរាជ័យ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"បញ្ហា​ក្នុង​ការ​ផ្ទៀងផ្ទាត់"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"នៅ​ក្រៅ​តំបន់"</string>
-    <!-- no translation found for wifi_no_internet_no_reconnect (5724903347310541706) -->
-    <skip />
-    <!-- no translation found for wifi_no_internet (3880396223819116454) -->
-    <skip />
+    <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"នឹងមិនភ្ជាប់ដោយស្វ័យប្រវត្តិទេ"</string>
+    <string name="wifi_no_internet" msgid="3880396223819116454">"មិនមានអ៊ីនធឺណិតទេ"</string>
     <string name="saved_network" msgid="4352716707126620811">"បានរក្សាទុកដោយ <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"បានភ្ជាប់តាមរយៈជំនួយការ Wi‑Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"បានភ្ជាប់តាមរយៈ %1$s"</string>
@@ -236,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"បង្ហាញ​ការ​ភ្ជាប់​អត្ថបទ​សម្រង់ រឹម ។ល។"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"បង្ខំ​ទិស​ប្លង់ RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"បង្ខំ​ទិស​ប្លង់​អេក្រង់​ទៅកាន់ RTL សម្រាប់​មូលដ្ឋាន​ទាំងអស់"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"បង្ហាញ​​ការ​ប្រើ CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"អេក្រង់​ត្រួត​គ្នា​បង្ហាញ​​ការ​ប្រើ CPU បច្ចុប្បន្ន"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"បង្ខំ​ឲ្យ​បង្ហាញ GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"បង្ខំ​ប្រើ GPU សម្រាប់​ការ​គូរ​លើក​ទី​ពីរ"</string>
     <string name="force_msaa" msgid="7920323238677284387">"បង្ខំ 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index 312beae..b89bad8 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"ಕ್ಲಿಪ್‌ನ ಗಡಿಗಳು, ಅಂಚುಗಳು, ಇತ್ಯಾದಿ ತೋರಿಸು."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL ಲೇಔಟ್‌ ಪರಿಮಿತಿ ಬಲಗೊಳಿಸಿ"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"ಎಲ್ಲ ಸ್ಥಳಗಳಿಗಾಗಿ RTL ಗೆ ಸ್ಕ್ರೀನ್‌ ಲೇಔಟ್‌ ದಿಕ್ಕನ್ನು ಪ್ರಬಲಗೊಳಿಸಿ"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU ಬಳಕೆಯನ್ನು ತೋರಿಸು"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"ಪ್ರಸ್ತುತ CPU ಬಳಕೆಯನ್ನು ತೋರಿಸುತ್ತಿರುವ ಪರದೆಯ ಓವರ್‌ಲೇ"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU ನೀಡುವಿಕೆ ಬಲಗೊಳಿಸು"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d ಚಿತ್ರಕಲೆಗಾಗಿ GPU ಬಳಕೆ ಬಲಗೊಳಿಸಿ"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA ಪ್ರಬಲಗೊಳಿಸಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 72b5fe3..21bbc3f 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"클립 경계, 여백 등을 표시"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL 레이아웃 방향 강제 적용"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"모든 언어에 대해 화면 레이아웃 방향을 RTL로 강제 적용"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU 사용량 표시"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"현재 CPU 사용량 오버레이 표시"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU 렌더링 강제 설정"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2D 드로잉용으로 GPU 강제 사용"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA 강제 사용"</string>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index a5386c8..ca716cae 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Клиптин чектерин, талааларын ж.б. көргөзүү"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Солдон оңго багытына мажбурлоо"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Экрандын жайгашуу багытын бардык тилдер үчүн Оңдон-солго кылуу"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU колдонулушун көрсөтүү"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Учурдагы CPU колдонулушун көрсөтүүчү экран катмары"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU иштетүүсүн мажбурлоо"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d тартуу үчүн GPU\'ну колдонууга мажбурлоо"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA мажбурлоо"</string>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 2dc4fd7..0108c2c 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"ສະແດງໜ້າປົກຄລິບ, ຂອບ ແລະອື່ນໆ."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"ບັງ​ຄັບ​ໃຫ້ຮູບຮ່າງຂຽນຈາກຂວາຫາຊ້າຍ"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"ບັງຄັບໃຫ້ຮູບຮ່າງໜ້າຈໍ ຂຽນຈາກຂວາໄປຊ້າຍ ສຳລັບທຸກພາສາ"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"ສະແດງການນຳໃຊ້ CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"ການວາງຊ້ອນໜ້າຈໍທີ່ສະແດງການນຳໃຊ້ CPU ໃນປັດຈຸບັນ"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"ບັງຄັບໃຊ້ GPU ປະມວນພາບ"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"ບັງຄັບໃຊ້ GPU ເພື່ອການແຕ້ມພາບ 2 ມິຕິ"</string>
     <string name="force_msaa" msgid="7920323238677284387">"ບັງຄັບໃຊ້ 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 51fb7fa..154864f 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Rodyti iškarpų ribas, kraštines ir t. t."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Išdėst. iš dešin. į kairę"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Nust. visų lokalių ekran. išdėst. iš deš. į kairę"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Rodyti centr. proc. naud."</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Ekrano perdanga rodo dabartinį centr. proc. naud."</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Priverst. GPU atvaizd."</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Priverstinai naudoti GPU atvaizduojant 2D formatą"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Priverst. vykdyti 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 9d4d055..df91cb1 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Rādīt klipu robežas, malas utt."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Virziens no labās uz kreiso (Obligāts) WL: 295"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Obl. izkārt. virz. no labās uz kr. pusi visām lok."</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Rādīt CPU lietojumu"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Ekrāna pārklājums ar aktuālo CPU lietojumu"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Piespiedu GPU render."</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Izmantot GPU atveidi divdimensiju zīmējumiem"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA piespiedu palaiš."</string>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index 7521250..42bc33f 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Прикажи граници на клип, маргини, итн."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Сила на RTL за насока на слој"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Присилно постави насока на распоред на екран во РТЛ за сите локални стандарди"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Прикажи употреба на ЦПУ"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Прекривка на екран прикаж. употреба на тековен ЦПУ"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Присили рендерирање на GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Присилно користење на GPU за цртеж 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Сила 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index fed05c9..a6017d5 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -28,10 +28,8 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi കണക്ഷൻ പരാജയം"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ആധികാരികമാക്കുന്നതിലെ പ്രശ്‌നം"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"പരിധിയിലില്ല"</string>
-    <!-- no translation found for wifi_no_internet_no_reconnect (5724903347310541706) -->
-    <skip />
-    <!-- no translation found for wifi_no_internet (3880396223819116454) -->
-    <skip />
+    <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"സ്വയമേവ കണക്‌റ്റുചെയ്യില്ല"</string>
+    <string name="wifi_no_internet" msgid="3880396223819116454">"ഇന്റർനെറ്റ് ആക്‌സസ്സ് ഇല്ല"</string>
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> സംരക്ഷിച്ചത്"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"വൈഫൈ അസിസ്റ്റന്റ് മുഖേന കണക്‌റ്റുചെയ്തു"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s വഴി ബന്ധിപ്പിച്ചു"</string>
@@ -236,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"ക്ലിപ്പ് ബൗണ്ടുകൾ, മാർജിനുകൾ തുടങ്ങിയവ ദൃശ്യമാക്കുക"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL ലേഔട്ട് ഡയറക്ഷൻ നിർബന്ധമാക്കുക"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"എല്ലാ ഭാഷകൾക്കുമായി സ്‌ക്രീൻ ലേഔട്ട് ഡയറക്ഷൻ RTL-ലേക്ക് നിർബന്ധമാക്കുക"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU ഉപയോഗം ദൃശ്യമാക്കുക"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"സ്ക്രീൻ ഓവർലേ നിലവിലെ CPU ഉപയോഗം ദൃശ്യമാക്കുന്നു"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU റെൻഡറിംഗ് ഫോഴ്സ്ചെയ്യുക"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d ഡ്രോയിംഗിനായുള്ള നിരബന്ധിത GPU ഉപയോഗം"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA നിർബന്ധമാക്കുക"</string>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 3d32aea..cb6327a 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Клипийн зах, хязгаар зэргийг харуулах"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL байрлалын чиглэлийг хүчээр тогтоох"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Бүх локалын хувьд дэлгэцийн байрлалын чиглэлийг хүчээр RTL болгох"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU ашиглалтыг харуулах"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Дэлгэцийн давхцалаар одоогийн CPU ашиглалтыг харуулж байна"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Хүчээр GPU ашиглах"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"GPU-г 2d зурагт хүчээр ашиглах"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Хүчээр 4x MSAA ашиглах"</string>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index e81b5ae..b6adb4f 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"क्लिप सीमा, समास इत्यादी दर्शवा."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL लेआउट दिशानिर्देशाची सक्ती करा"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"सर्व लोकॅलसाठी RTL स्क्रीन लेआउट दिशानिर्देशाची सक्ती करा"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU वापर दर्शवा"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"वर्तमान CPU वापर दर्शविणारे स्क्रीन आच्छादन"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU प्रस्तुतीस सक्ती करा"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d रेखांकनासाठी GPU च्या वापराची सक्ती करा"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA ची सक्ती करा"</string>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 2368d09..9886d3e 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -28,10 +28,8 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Kegagalan Sambungan WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Masalah pengesahan"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Tidak dalam liputan"</string>
-    <!-- no translation found for wifi_no_internet_no_reconnect (5724903347310541706) -->
-    <skip />
-    <!-- no translation found for wifi_no_internet (3880396223819116454) -->
-    <skip />
+    <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Tidak akan menyambung secara automatik"</string>
+    <string name="wifi_no_internet" msgid="3880396223819116454">"Tiada akses Internet"</string>
     <string name="saved_network" msgid="4352716707126620811">"Diselamatkan oleh <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Disambungkan melalui Pembantu Wi-Fi"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Disambungkan melalui %1$s"</string>
@@ -236,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Tunjukkan batas klip, margin dll."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Paksa arah reka letak RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Paksa arah reka letak skrin RTL bagi semua tempat peristiwa"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Tunjukkan penggunaan CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Tindihan skrin menunjukkan penggunaan semasa CPU"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Paksa pemaparan GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Paksa penggunaan GPU untuk lukisan 2d"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Paksa 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 95711a4..935ad40 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"ဖြတ်ပိုင်းအနားသတ်များ၊ အနားများ စသဖြင့် ပြပါ။"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL ဖွဲ့စည်းပုံအညွှန်း မဖြစ်မနေလုပ်ပါ"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"လိုကယ်လ်အားလုံးအတွက် မျက်နှာပြင် ဖွဲ့စည်းပုံအညွှန်း မဖြစ်မနေလုပ်ရန်"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPUအသုံးပြုမှုအား ပြသရန်"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"လက်ရှိCPUအသုံးပြုမှုအားလုံး မျက်နှာပြင်တွင်ပြသမှု"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPUအား အတင်းအကျပ်ဖြစ်စေမည်"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"GPUကို ၂ဖက်မြင်ပုံဆွဲခြင်းအတွက် မဖြစ်မနေအသုံးပြုစေရန်"</string>
     <string name="force_msaa" msgid="7920323238677284387">"တွန်းအား ၄× MSAA"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 1a053e2..18b6f60 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -28,10 +28,8 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-tilkoblingsfeil"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentiseringsproblem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Utenfor område"</string>
-    <!-- no translation found for wifi_no_internet_no_reconnect (5724903347310541706) -->
-    <skip />
-    <!-- no translation found for wifi_no_internet (3880396223819116454) -->
-    <skip />
+    <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Kobler ikke til automatisk"</string>
+    <string name="wifi_no_internet" msgid="3880396223819116454">"Ingen Internett-tilgang"</string>
     <string name="saved_network" msgid="4352716707126620811">"Lagret av <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Koblet til via en Wi-Fi-assistent"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Tilkoblet via %1$s"</string>
@@ -236,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Vis kanter, marger osv."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Tving layoutretning for RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Tving RTL-retning på skjermen for alle språk"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Vis CPU-bruk"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Skjermoverlegg viser gjeldende CPU-bruk"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Tving GPU-gjengivelse"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Tving bruk av GPU for 2D-tegning"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Tving 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 0a7cdab..478e19d 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"क्लिप सीमा, मार्जिन, इत्यादि देखाउनुहोस्।"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL लेआउट दिशामा जबर्जस्ती गर्नुहोस्"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"सबै लोकेलहरूको लागि RTLमा स्क्रिन लेआउट दिशामा जबर्जस्ती गर्नुहोस्"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU उपयोग देखाउनुहोस्"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"स्क्रिन ओभरले वर्तमान CPU प्रयोग देखाउँदै"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU रेन्डर गर्न जोड गर्नुहोस्"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d चित्र कोर्नका लागि GPU को प्रयोगलाई जोड दिनुहोस्"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA जोड गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index e1bc58d..8f73bf9 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -50,12 +50,12 @@
   </string-array>
   <string-array name="hdcp_checking_titles">
     <item msgid="441827799230089869">"Nooit controleren"</item>
-    <item msgid="6042769699089883931">"Alleen controleren op DRM-inhoud"</item>
+    <item msgid="6042769699089883931">"Alleen controleren op DRM-content"</item>
     <item msgid="9174900380056846820">"Altijd controleren"</item>
   </string-array>
   <string-array name="hdcp_checking_summaries">
     <item msgid="505558545611516707">"HDCP-controle nooit gebruiken"</item>
-    <item msgid="3878793616631049349">"HDCP-controle alleen voor DRM-inhoud gebruiken"</item>
+    <item msgid="3878793616631049349">"HDCP-controle alleen voor DRM-content gebruiken"</item>
     <item msgid="45075631231212732">"HDCP-controle altijd gebruiken"</item>
   </string-array>
   <string-array name="select_logd_size_titles">
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 27478a4..78e1ee1 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Clipgrenzen, marges en meer weergeven"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"V.r.n.l.-indelingsrichting afdwingen"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Schermindelingsrichting geforceerd instellen op v.r.n.l. voor alle talen"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU-gebruik weergeven"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Schermoverlay met huidig CPU-gebruik"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU-rendering afdwingen"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Gebruik van GPU voor 2D-tekening forceren"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA forceren"</string>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index d06a88f..b678aac 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"ਕਲਿਪ ਬਾਊਂਡਸ, ਮਾਰਜਿਨ ਆਦਿ ਦਿਖਾਓ"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL ਲੇਆਉਟ ਦਿਸ਼ਾ ਤੇ ਜ਼ੋਰ ਪਾਓ"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"ਸਾਰੇ ਸਥਾਨਾਂ ਲਈ RTL ਵੱਲ ਸਕ੍ਰੀਨ ਲੇਆਉਟ ਦਿਸ਼ਾ ਤੇ ਜ਼ੋਰ ਪਾਓ"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU ਵਰਤੋਂ ਦਿਖਾਓ"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"ਸਕ੍ਰੀਨ ਓਵਰਲੇ ਵਰਤਮਾਨ CPU ਵਰਤੋਂ ਦਿਖਾ ਰਿਹਾ ਹੈ"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU ਪ੍ਰਗਟਾਅ ਤੇ ਜ਼ੋਰ ਪਾਓ"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d ਡ੍ਰਾਇੰਗ ਲਈ GPU ਦੀ ਵਰਤੋਂ ਤੇ ਜ਼ੋਰ ਪਾਓ"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA ਤੇ ਜ਼ੋਰ ਪਾਓ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 3c09335..77a23f2 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Pokaż granice przycięcia, marginesy itd."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Układ od prawej do lewej"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Wymuś wszędzie układ ekranu od prawej do lewej"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Pokaż użycie procesora"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Nakładka na ekranie pokazująca użycie procesora"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Renderowanie na GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Wymuszaj użycie GPU do rysowania 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Wymuś 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 1b46c84..588ca67 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Mostrar limites de corte, margens, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forçar dir. layout (RTL)"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Forçar direção do layout (RTL) p/ todas as local."</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Mostrar o uso da CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Sobreposição de tela que mostra o uso da CPU atual"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forçar renderização GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Forçar uso da GPU para desenho em 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Forçar 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index c8be0da..763cb70 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Apresentar limites de clipes, margens, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forçar dir. do esq. RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Forçar dir. do esq. do ecrã p. RTL tds os locais"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Mostrar utilização da CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Sobrep. de ecrã que mostra a utiliz. atual da CPU"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forçar composição GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Forçar a utilização de GPU para desenho 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Forçar 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 1b46c84..588ca67 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Mostrar limites de corte, margens, etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Forçar dir. layout (RTL)"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Forçar direção do layout (RTL) p/ todas as local."</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Mostrar o uso da CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Sobreposição de tela que mostra o uso da CPU atual"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forçar renderização GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Forçar uso da GPU para desenho em 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Forçar 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index b022163..6a2122a 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Afișați limitele clipului, marginile etc."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Direcție aspect dreapta - stânga"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Direcție obligatorie aspect ecran dreapta - stânga"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Afișați utiliz. procesor"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Suprapunere care indică utilizare curentă procesor"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Forțați redarea cu GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Forțați utilizarea GPU pentru desen în 2D"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Forțați MSAA 4x"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 3a4e85b..a6d0cba 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Показывать границы клипа, поля и т. д."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Написание справа налево"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Включить написание справа налево для всех языков"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Показывать загрузку ЦП"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Экран, показывающий текущую загрузку ЦП"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU-ускорение"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Всегда использовать GPU для двухмерного рисования"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Включить 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index 24779b3..e415544 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"ක්ලිප් සීමා, මායිම්, ආදිය පෙන්වන්න."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"බල RTL පිරිසැලසුම් දිශාව"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"සියලු පෙදෙසි සඳහා RTL වෙත බල තිර පිරිසැලසුම"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU භාවිතය පෙන්වන්න"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"තීර උඩැතිරිය වත්මන් CPU භාවිතය පෙන්නුම් කරයි"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU විදහාපෑම බලකරන්න"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d ඇඳීම් සඳහා GPU බලයෙන් භාවිතා කරන්න"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA බල කරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index e8db85b..7e636fe7 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Zobraziť vo výstrižku ohraničenie, okraje a pod."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Rozloženia sprava doľava"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Vynútiť pre všetky jazyky rozloženie obrazovky sprava doľava"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Zobraziť využitie CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Prekryvná vrstva s aktuálnym využitím procesora"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Vykresľovat pomocou GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Používať GPU na dvojrozmerné vykresľovanie"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Vynútiť 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index d908e6d..78fa3fd 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Pokaži meje obrezovanja, obrobe ipd."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Vsili od desne proti levi"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Vsili smer postavitve na zaslonu od desne proti levi za vse jezike"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Prikaži uporabo CPE-ja"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Prekrivanje zaslona prikazuje tren. uporabo CPE-ja"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Vsili upodabljanje z GPE-jem"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Za risanje 2D vsili uporabo grafičnega procesorja"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Vsili 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 69318a1..ad4cf61 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Shfaq konturet e klipit, hapësirat etj."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Detyro drejtimin e shkrimit nga e djathta në të majtë"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Ndrysho me detyrim drejtimin e planit të ekranit nga e djathta në të majtë për të gjitha vendet"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Shfaq përdorimin e CPU-së"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Mbivendosja e ekranit tregon përdorimin e CPU-së"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Detyro interpretimin e GPU-së"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Detyro përdorimin e GPU-së për vizatimin e dytë"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Detyro 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 459d92e..02eb615 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Прикажи границе клипа, маргине итд."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Наметни смер распореда здесна налево"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Наметни смер распореда екрана здесна налево за све локалитете"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Прик. употребу процесора"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Постав. елемент са тренутном употребом процесора"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Принудни приказ пом. GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Принудно користи GPU за 2D цртање"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Наметни 4x MSAA"</string>
@@ -283,7 +281,7 @@
     <string name="enable_webview_multiprocess_desc" msgid="2485604010404197724">"Покрећите WebView приказиваче засебно"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"Примена WebView-а"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Подесите примену WebView-а"</string>
-    <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Овај избор више није важећи. Покушајте поново."</string>
+    <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Овај избор више није важећи. Пробајте поново."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертуј у шифровање датотека"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертуј..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Већ се користи шифровање датотека"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index d52882a..a936c3e 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Visa gränser för videoklipp, marginaler m.m."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Tvinga fram RTL-layout"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Tvinga fram RTL-skärmlayout (hö–vä) för alla språk"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Visa CPU-användning"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Överlägg på skärmen med aktuell CPU-användning"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Framtvinga GPU-rendering"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Tvingad användning av GPU för 2D-ritning"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Force 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 6f2e0cb..25f79b6 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Onyesha mipaka ya picha, kingo, nk."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Lazimisha uelekezaji wa muundo wa RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Lazimisha uelekezaji wa muundo wa skrini kwa RTL kwa lugha zote"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Onyesha matumizi ya CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Kuegeshwa kwa skrini ikionyesha matumizi ya sasa ya CPU"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Lazimisha kutungiliza  GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Lazimisha matumizi ya GPU kwa uchoraji wa 2d"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Lazimisha 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 5f218e0..9e9e92c 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"கிளிப் எல்லைகள், ஓரங்கள், மேலும் பலவற்றைக் காட்டு"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL தளவமைப்பின் திசையை வலியுறுத்து"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"எல்லா மொழிகளுக்கும் திரையின் தளவமைப்பு திசையை RTL க்கு மாற்று"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU பயன்பாட்டைக் காட்டு"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"தற்போதைய CPU பயன்பாட்டைக் காட்டும் திரை மேலடுக்கு"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU காட்சியாக்கத்தை வலியுறுத்து"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d வரைபடத்திற்கு GPU பயன்பாட்டை வலியுறுத்து"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA ஐ வலியுறுத்து"</string>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 0bd77f7..27f8e09 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"క్లిప్ సరిహద్దులు, అంచులు మొ. చూపు"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"RTL లేఅవుట్ దిశను నిర్భందం చేయండి"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"అన్ని లొకేల్‌ల కోసం RTLకి స్క్రీన్ లేఅవుట్ దిశను నిర్భందించు"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU వినియోగాన్ని చూపు"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"ప్రస్తుత CPU వినియోగాన్ని చూపేలా స్క్రీన్ అతివ్యాప్తి చేయబడుతుంది"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"నిర్బంధంగా GPU భాషాంతరీకరణ"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d డ్రాయింగ్ కోసం GPU నిర్భంద వినియోగం"</string>
     <string name="force_msaa" msgid="7920323238677284387">"నిర్భందం 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index d8ee2f3..6005972 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"แสดงหน้าปกคลิป ขอบ ฯลฯ"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"บังคับทิศทางการจัดวาง RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"บังคับทิศทางการจัดวางหน้าจอเป็น RTL สำหรับทุกภาษา"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"แสดงการใช้ CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"การวางซ้อนหน้าจอที่แสดงการใช้ CPU ในปัจจุบัน"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"เร่งการแสดงผลของ GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"ต้องใช้ GPU สำหรับการวาดภาพ 2 มิติ"</string>
     <string name="force_msaa" msgid="7920323238677284387">"บังคับใช้ 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 9b9d26f..e9feded 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Ipakita ang mga hangganan ng clip, margin, atbp."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Force RTL layout dir."</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Force screen layout dir. sa RTL sa lahat ng lokal"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Ipakita paggamit ng CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Ipinapakita ng screen overlay ang paggamit ng CPU ngayon"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Ipilit ang pag-render ng GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Sapilitang paggamit sa GPU para sa 2d na pagguhit"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Puwersahin ang 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 643b710..0e73b7b 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -28,10 +28,8 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Kablosuz Bağlantı Hatası"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Kimlik doğrulama sorunu"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Kapsama alanı dışında"</string>
-    <!-- no translation found for wifi_no_internet_no_reconnect (5724903347310541706) -->
-    <skip />
-    <!-- no translation found for wifi_no_internet (3880396223819116454) -->
-    <skip />
+    <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Otomatik olarak bağlanma"</string>
+    <string name="wifi_no_internet" msgid="3880396223819116454">"İnternet erişimi yok"</string>
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> tarafından kaydedildi"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"Kablosuz bağlantı yardımcısıyla bağlandı"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s üzerinden bağlı"</string>
@@ -236,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Klip sınırlarını, kenar boşluklarını vb. göster"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Sağdan sola düzenini zorla"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Tüm yerel ayarlar için sağdan sola ekran düzenini zorlar"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"CPU kullanımını göster"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Mevcut CPU kullanımını gösteren yer paylaşımı"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU oluşturmayı zorla"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2D çizimde GPU kullanımını zorla"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA\'yı zorla"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index b1fbef5..1015e1c 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Показувати межі роликів, поля тощо"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Макет письма справа наліво"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Застосовувати макет письма справа наліво для всіх мов"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Показати використання ЦП"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Показувати на екрані поточне використання ЦП"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Примусова візуалізація GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Примусово використовувати GPU для 2D-малювання"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Примус. запустити 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 322b468..61dc5ab 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"کلپ باؤنڈز، حاشیے وغیرہ دکھائیں"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"‏RTL لے آؤٹ سمت زبردستی نافذ کریں"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"‏سبھی زبانوں کیلئے اسکرین لے آؤٹ کی سمت کو RTL پر مجبور کریں"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"‏CPU استعمال دکھائیں"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"‏موجودہ CPU استعمال دکھانے والا اسکرین اوورلے"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"‏GPU رینڈرنگ زبردستی نافذ کریں"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"‏2D ڈرائنگ کیلئے GPU کا استعمال زبردستی نافذ کریں"</string>
     <string name="force_msaa" msgid="7920323238677284387">"‏4x MSAA زبردستی نافذ کریں"</string>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index 09ac4b1..a6f9ab8 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Klip, maydon va h.k. chegaralarini ko‘rsatish"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"O‘ngdan chapga qarab yozish"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Barcha tillarda o‘ngdan chapga qarab yozish"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"MP yuklanishini ko‘rsatish"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Joriy MP yuklanishini ko‘rsatuvchi ekran"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"GPU yordamida tezlatish"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Ikki o‘lchamli chizma uchun doim GPU ishlatilsin"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAAni yoqish"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index fa41b45..f09e0e5 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Hiển thị viền đoạn video, lề, v.v.."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Buộc hướng bố cục RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Buộc hướng bố cục màn hình RTL cho tất cả ngôn ngữ"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Hiển thị mức sử dụng CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Lớp phủ màn hình hiển thị mức sử dụng CPU hiện tại"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Bắt buộc kết xuất GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Bắt buộc sử dụng GPU cho bản vẽ 2d"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Bắt buộc 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 2e515da..7268dcd 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -28,10 +28,8 @@
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WLAN 连接失败"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"身份验证出现问题"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"不在范围内"</string>
-    <!-- no translation found for wifi_no_internet_no_reconnect (5724903347310541706) -->
-    <skip />
-    <!-- no translation found for wifi_no_internet (3880396223819116454) -->
-    <skip />
+    <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"无法自动连接"</string>
+    <string name="wifi_no_internet" msgid="3880396223819116454">"无法连接到互联网"</string>
     <string name="saved_network" msgid="4352716707126620811">"已通过<xliff:g id="NAME">%1$s</xliff:g>保存"</string>
     <string name="connected_via_wfa" msgid="3805736726317410714">"已连接(通过 WLAN 助手)"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"已通过%1$s连接"</string>
@@ -236,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"显示剪辑边界、边距等。"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"强制使用从右到左的布局方向"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"强制将所有语言区域的屏幕布局方向改为从右到左"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"显示 CPU 使用情况"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"屏幕叠加层显示当前 CPU 使用情况"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"强制进行 GPU 渲染"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"强制使用 GPU 进行 2D 绘图"</string>
     <string name="force_msaa" msgid="7920323238677284387">"强制启用 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index f6c2f93..ac9de74 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"顯示剪輯範圍、邊界等"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"強制使用從右至左的版面配置方向"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"強制將所有語言代碼的畫面配置方向改為從右至左"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"顯示 CPU 使用量"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"在螢幕上重疊顯示目前的 CPU 使用量"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"強制使用 GPU 轉譯"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"強制使用 GPU 進行 2D 繪圖"</string>
     <string name="force_msaa" msgid="7920323238677284387">"強制 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index df9238a..f17b523 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"顯示剪輯範圍、邊界等。"</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"強制使用從右至左版面配置方向"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"強制將所有語言代碼的畫面配置方向改為從右至左"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"顯示 CPU 使用量"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"在螢幕上方顯示目前的 CPU 使用量"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"強制使用 GPU 轉譯"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"強制使用 GPU 進行 2D 繪圖"</string>
     <string name="force_msaa" msgid="7920323238677284387">"強制 4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index fc9e81f..1fc551f 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -234,8 +234,6 @@
     <string name="debug_layout_summary" msgid="2001775315258637682">"Bonisa imikhawulo, imiphetho, njll, yesiqeshana."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Phoqelela isikhombisi-ndlela sesakhiwo se-RTL"</string>
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Phoqelela isikhombisi-ndlela sesikrini ku-RTL kuzo zonke izifunda"</string>
-    <string name="show_cpu_usage" msgid="2389212910758076024">"Bonisa ukusebenzisa i-CPU"</string>
-    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Imbondela yesikrini ibonisa ukusetshenziswa kwe-CPU okwamanje"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Phoqa ukunikeza i-GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Phoqelela ukusetshenziswa kwe-GPU ngomdwebo we-2d"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Phoqelela i-4x MSAA"</string>
diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml
index 0cf4a41..e2e721c 100755
--- a/packages/SettingsLib/res/values/config.xml
+++ b/packages/SettingsLib/res/values/config.xml
@@ -37,4 +37,7 @@
 
     <!-- Intent key for package name values -->
     <string name="config_helpIntentNameKey" translatable="false"></string>
-</resources>
+
+    <!-- The apps that need to be hided when they are disabled -->
+    <string-array name="config_hideWhenDisabled_packageNames"></string-array>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 1a1aa57..972fc73 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -582,11 +582,6 @@
     <!-- UI debug setting: force right to left layout summary [CHAR LIMIT=100] -->
     <string name="force_rtl_layout_all_locales_summary">Force screen layout direction to RTL for all locales</string>
 
-    <!-- UI debug setting: show how CPU is being used? [CHAR LIMIT=25] -->
-    <string name="show_cpu_usage">Show CPU usage</string>
-    <!-- UI debug setting: show cpu usage summary [CHAR LIMIT=50] -->
-    <string name="show_cpu_usage_summary">Screen overlay showing current CPU usage</string>
-
     <!-- UI debug setting: force hardware acceleration to render apps [CHAR LIMIT=25] -->
     <string name="force_hw_ui">Force GPU rendering</string>
     <!-- UI debug setting: force hardware acceleration summary [CHAR LIMIT=50] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index a22a051..f0ec107 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -47,6 +47,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.settingslib.R;
 
 import java.io.File;
 import java.text.Collator;
@@ -621,7 +622,7 @@
             }
 
             if (filter != null) {
-                filter.init();
+                filter.init(mContext);
             }
 
             List<AppEntry> apps;
@@ -1280,6 +1281,9 @@
 
     public interface AppFilter {
         void init();
+        default void init(Context context) {
+            init();
+        }
         boolean filterApp(AppEntry info);
     }
 
@@ -1398,6 +1402,33 @@
         }
     };
 
+    public static final AppFilter FILTER_NOT_HIDE = new AppFilter() {
+        private String[] mHidePackageNames;
+
+        public void init(Context context) {
+            mHidePackageNames = context.getResources()
+                .getStringArray(R.array.config_hideWhenDisabled_packageNames);
+        }
+
+        @Override
+        public void init() {
+        }
+
+        @Override
+        public boolean filterApp(AppEntry entry) {
+            if (ArrayUtils.contains(mHidePackageNames, entry.info.packageName)) {
+                if (!entry.info.enabled) {
+                    return false;
+                } else if (entry.info.enabledSetting ==
+                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+    };
+
     public static class VolumeFilter implements AppFilter {
         private final String mVolumeUuid;
 
@@ -1425,6 +1456,12 @@
         }
 
         @Override
+        public void init(Context context) {
+            mFirstFilter.init(context);
+            mSecondFilter.init(context);
+        }
+
+        @Override
         public void init() {
             mFirstFilter.init();
             mSecondFilter.init();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 4bcbea7..a332332 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -268,16 +268,16 @@
             if (cachedDevice == null) {
                 Log.w(TAG, "CachedBluetoothDevice for device " + device +
                         " not found, calling readPairedDevices().");
-                if (!readPairedDevices()) {
-                    Log.e(TAG, "Got bonding state changed for " + device +
-                            ", but we have no record of that device.");
-                    return;
+                if (readPairedDevices()) {
+                    cachedDevice = mDeviceManager.findDevice(device);
                 }
-                cachedDevice = mDeviceManager.findDevice(device);
+
                 if (cachedDevice == null) {
-                    Log.e(TAG, "Got bonding state changed for " + device +
-                            ", but device not added in cache.");
-                    return;
+                    Log.w(TAG, "Got bonding state changed for " + device +
+                            ", but we have no record of that device.");
+
+                    cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
+                    dispatchDeviceAdded(cachedDevice);
                 }
             }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index a879d16f..52e686c9b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -102,9 +102,6 @@
     private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000;
     private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000;
 
-    /** Auto-connect after pairing only if locally initiated. */
-    private boolean mConnectAfterPairing;
-
     /**
      * Describes the current device and profile for logging.
      *
@@ -300,7 +297,6 @@
             return false;
         }
 
-        mConnectAfterPairing = true;  // auto-connect after pairing
         return true;
     }
 
@@ -309,7 +305,7 @@
      * slightly different for local vs. remote initiated pairing dialogs.
      */
     boolean isUserInitiatedPairing() {
-        return mConnectAfterPairing;
+        return mDevice.isBondingInitiatedLocally();
     }
 
     public void unpair() {
@@ -549,7 +545,6 @@
     void onBondingStateChanged(int bondState) {
         if (bondState == BluetoothDevice.BOND_NONE) {
             mProfiles.clear();
-            mConnectAfterPairing = false;  // cancel auto-connect
             setPhonebookPermissionChoice(ACCESS_UNKNOWN);
             setMessagePermissionChoice(ACCESS_UNKNOWN);
             setSimPermissionChoice(ACCESS_UNKNOWN);
@@ -562,10 +557,9 @@
         if (bondState == BluetoothDevice.BOND_BONDED) {
             if (mDevice.isBluetoothDock()) {
                 onBondingDockConnect();
-            } else if (mConnectAfterPairing) {
+            } else if (mDevice.isBondingInitiatedLocally()) {
                 connect(false);
             }
-            mConnectAfterPairing = false;
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
index 26e8303..857ca49 100644
--- a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
@@ -40,23 +40,47 @@
 import java.util.Set;
 import java.util.TimeZone;
 
+/**
+ * ZoneGetter is the utility class to get time zone and zone list, and both of them have display
+ * name in time zone. In this class, we will keep consistency about display names for all
+ * the methods.
+ *
+ * The display name chosen for each zone entry depends on whether the zone is one associated
+ * with the country of the user's chosen locale. For "local" zones we prefer the "long name"
+ * (e.g. "Europe/London" -> "British Summer Time" for people in the UK). For "non-local"
+ * zones we prefer the exemplar location (e.g. "Europe/London" -> "London" for English
+ * speakers from outside the UK). This heuristic is based on the fact that people are
+ * typically familiar with their local timezones and exemplar locations don't always match
+ * modern-day expectations for people living in the country covered. Large countries like
+ * China that mostly use a single timezone (olson id: "Asia/Shanghai") may not live near
+ * "Shanghai" and prefer the long name over the exemplar location. The only time we don't
+ * follow this policy for local zones is when Android supplies multiple olson IDs to choose
+ * from and the use of a zone's long name leads to ambiguity. For example, at the time of
+ * writing Android lists 5 olson ids for Australia which collapse to 2 different zone names
+ * in winter but 4 different zone names in summer. The ambiguity leads to the users
+ * selecting the wrong olson ids.
+ *
+ */
 public class ZoneGetter {
     private static final String TAG = "ZoneGetter";
 
-    private static final String XMLTAG_TIMEZONE = "timezone";
-
     public static final String KEY_ID = "id";  // value: String
     public static final String KEY_DISPLAYNAME = "name";  // value: String
     public static final String KEY_GMT = "gmt";  // value: String
     public static final String KEY_OFFSET = "offset";  // value: int (Integer)
 
-    private ZoneGetter() {}
+    private static final String XMLTAG_TIMEZONE = "timezone";
 
-    public static String getTimeZoneOffsetAndName(TimeZone tz, Date now) {
-        Locale locale = Locale.getDefault();
-        String gmtString = getGmtOffsetString(locale, tz, now);
-        TimeZoneNames timeZoneNames = TimeZoneNames.getInstance(locale);
-        String zoneNameString = getZoneLongName(timeZoneNames, tz, now);
+    public static String getTimeZoneOffsetAndName(Context context, TimeZone tz, Date now) {
+        final Locale locale = Locale.getDefault();
+        final String gmtString = getGmtOffsetString(locale, tz, now);
+        final TimeZoneNames timeZoneNames = TimeZoneNames.getInstance(locale);
+        final ZoneGetterData data = new ZoneGetterData(context);
+
+        final boolean useExemplarLocationForLocalNames =
+                shouldUseExemplarLocationForLocalNames(data, timeZoneNames);
+        final String zoneNameString = getTimeZoneDisplayName(data, timeZoneNames,
+                useExemplarLocationForLocalNames, tz, tz.getID());
         if (zoneNameString == null) {
             return gmtString;
         }
@@ -69,82 +93,20 @@
         final Locale locale = Locale.getDefault();
         final Date now = new Date();
         final TimeZoneNames timeZoneNames = TimeZoneNames.getInstance(locale);
-
-        // The display name chosen for each zone entry depends on whether the zone is one associated
-        // with the country of the user's chosen locale. For "local" zones we prefer the "long name"
-        // (e.g. "Europe/London" -> "British Summer Time" for people in the UK). For "non-local"
-        // zones we prefer the exemplar location (e.g. "Europe/London" -> "London" for English
-        // speakers from outside the UK). This heuristic is based on the fact that people are
-        // typically familiar with their local timezones and exemplar locations don't always match
-        // modern-day expectations for people living in the country covered. Large countries like
-        // China that mostly use a single timezone (olson id: "Asia/Shanghai") may not live near
-        // "Shanghai" and prefer the long name over the exemplar location. The only time we don't
-        // follow this policy for local zones is when Android supplies multiple olson IDs to choose
-        // from and the use of a zone's long name leads to ambiguity. For example, at the time of
-        // writing Android lists 5 olson ids for Australia which collapse to 2 different zone names
-        // in winter but 4 different zone names in summer. The ambiguity leads to the users
-        // selecting the wrong olson ids.
-
-        // Get the list of olson ids to display to the user.
-        List<String> olsonIdsToDisplayList = readTimezonesToDisplay(context);
-
-        // Store the information we are going to need more than once.
-        final int zoneCount = olsonIdsToDisplayList.size();
-        final String[] olsonIdsToDisplay = new String[zoneCount];
-        final TimeZone[] timeZones = new TimeZone[zoneCount];
-        final String[] gmtOffsetStrings = new String[zoneCount];
-        for (int i = 0; i < zoneCount; i++) {
-            String olsonId = olsonIdsToDisplayList.get(i);
-            olsonIdsToDisplay[i] = olsonId;
-            TimeZone tz = TimeZone.getTimeZone(olsonId);
-            timeZones[i] = tz;
-            gmtOffsetStrings[i] = getGmtOffsetString(locale, tz, now);
-        }
-
-        // Create a lookup of local zone IDs.
-        Set<String> localZoneIds = new HashSet<String>();
-        for (String olsonId : libcore.icu.TimeZoneNames.forLocale(locale)) {
-            localZoneIds.add(olsonId);
-        }
+        final ZoneGetterData data = new ZoneGetterData(context);
 
         // Work out whether the display names we would show by default would be ambiguous.
-        Set<String> localZoneNames = new HashSet<String>();
-        boolean useExemplarLocationForLocalNames = false;
-        for (int i = 0; i < zoneCount; i++) {
-            String olsonId = olsonIdsToDisplay[i];
-            if (localZoneIds.contains(olsonId)) {
-                TimeZone tz = timeZones[i];
-                String displayName = getZoneLongName(timeZoneNames, tz, now);
-                if (displayName == null) {
-                    displayName = gmtOffsetStrings[i];
-                }
-                boolean nameIsUnique = localZoneNames.add(displayName);
-                if (!nameIsUnique) {
-                    useExemplarLocationForLocalNames = true;
-                    break;
-                }
-            }
-        }
+        final boolean useExemplarLocationForLocalNames =
+                shouldUseExemplarLocationForLocalNames(data, timeZoneNames);
 
         // Generate the list of zone entries to return.
         List<Map<String, Object>> zones = new ArrayList<Map<String, Object>>();
-        for (int i = 0; i < zoneCount; i++) {
-            String olsonId = olsonIdsToDisplay[i];
-            TimeZone tz = timeZones[i];
-            String gmtOffsetString = gmtOffsetStrings[i];
+        for (int i = 0; i < data.zoneCount; i++) {
+            TimeZone tz = data.timeZones[i];
+            String gmtOffsetString = data.gmtOffsetStrings[i];
 
-            boolean isLocalZoneId = localZoneIds.contains(olsonId);
-            boolean preferLongName = isLocalZoneId && !useExemplarLocationForLocalNames;
-            String displayName;
-            if (preferLongName) {
-                displayName = getZoneLongName(timeZoneNames, tz, now);
-            } else {
-                displayName = timeZoneNames.getExemplarLocationName(tz.getID());
-                if (displayName == null || displayName.isEmpty()) {
-                    // getZoneExemplarLocation can return null. Fall back to the long name.
-                    displayName = getZoneLongName(timeZoneNames, tz, now);
-                }
-            }
+            String displayName = getTimeZoneDisplayName(data, timeZoneNames,
+                    useExemplarLocationForLocalNames, tz, data.olsonIdsToDisplay[i]);
             if (displayName == null  || displayName.isEmpty()) {
                 displayName = gmtOffsetString;
             }
@@ -198,28 +160,103 @@
         return olsonIds;
     }
 
+    private static boolean shouldUseExemplarLocationForLocalNames(ZoneGetterData data,
+            TimeZoneNames timeZoneNames) {
+        final Set<String> localZoneNames = new HashSet<String>();
+        final Date now = new Date();
+        for (int i = 0; i < data.zoneCount; i++) {
+            final String olsonId = data.olsonIdsToDisplay[i];
+            if (data.localZoneIds.contains(olsonId)) {
+                final TimeZone tz = data.timeZones[i];
+                String displayName = getZoneLongName(timeZoneNames, tz, now);
+                if (displayName == null) {
+                    displayName = data.gmtOffsetStrings[i];
+                }
+                final boolean nameIsUnique = localZoneNames.add(displayName);
+                if (!nameIsUnique) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private static String getTimeZoneDisplayName(ZoneGetterData data, TimeZoneNames timeZoneNames,
+            boolean useExemplarLocationForLocalNames, TimeZone tz, String olsonId) {
+        final Date now = new Date();
+        final boolean isLocalZoneId = data.localZoneIds.contains(olsonId);
+        final boolean preferLongName = isLocalZoneId && !useExemplarLocationForLocalNames;
+        String displayName;
+
+        if (preferLongName) {
+            displayName = getZoneLongName(timeZoneNames, tz, now);
+        } else {
+            displayName = timeZoneNames.getExemplarLocationName(tz.getID());
+            if (displayName == null || displayName.isEmpty()) {
+                // getZoneExemplarLocation can return null. Fall back to the long name.
+                displayName = getZoneLongName(timeZoneNames, tz, now);
+            }
+        }
+
+        return displayName;
+    }
+
     /**
      * Returns the long name for the timezone for the given locale at the time specified.
      * Can return {@code null}.
      */
     private static String getZoneLongName(TimeZoneNames names, TimeZone tz, Date now) {
-        TimeZoneNames.NameType nameType =
+        final TimeZoneNames.NameType nameType =
                 tz.inDaylightTime(now) ? TimeZoneNames.NameType.LONG_DAYLIGHT
-                : TimeZoneNames.NameType.LONG_STANDARD;
+                        : TimeZoneNames.NameType.LONG_STANDARD;
         return names.getDisplayName(tz.getID(), nameType, now.getTime());
     }
 
     private static String getGmtOffsetString(Locale locale, TimeZone tz, Date now) {
         // Use SimpleDateFormat to format the GMT+00:00 string.
-        SimpleDateFormat gmtFormatter = new SimpleDateFormat("ZZZZ");
+        final SimpleDateFormat gmtFormatter = new SimpleDateFormat("ZZZZ");
         gmtFormatter.setTimeZone(tz);
         String gmtString = gmtFormatter.format(now);
 
         // Ensure that the "GMT+" stays with the "00:00" even if the digits are RTL.
-        BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+        final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
         boolean isRtl = TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL;
         gmtString = bidiFormatter.unicodeWrap(gmtString,
                 isRtl ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR);
         return gmtString;
     }
-}
+
+    private static final class ZoneGetterData {
+        public final String[] olsonIdsToDisplay;
+        public final String[] gmtOffsetStrings;
+        public final TimeZone[] timeZones;
+        public final Set<String> localZoneIds;
+        public final int zoneCount;
+
+        public ZoneGetterData(Context context) {
+            final Locale locale = Locale.getDefault();
+            final Date now = new Date();
+            final List<String> olsonIdsToDisplayList = readTimezonesToDisplay(context);
+
+            // Load all the data needed to display time zones
+            zoneCount = olsonIdsToDisplayList.size();
+            olsonIdsToDisplay = new String[zoneCount];
+            timeZones = new TimeZone[zoneCount];
+            gmtOffsetStrings = new String[zoneCount];
+            for (int i = 0; i < zoneCount; i++) {
+                final String olsonId = olsonIdsToDisplayList.get(i);
+                olsonIdsToDisplay[i] = olsonId;
+                final TimeZone tz = TimeZone.getTimeZone(olsonId);
+                timeZones[i] = tz;
+                gmtOffsetStrings[i] = getGmtOffsetString(locale, tz, now);
+            }
+
+            // Create a lookup of local zone IDs.
+            localZoneIds = new HashSet<String>();
+            for (String olsonId : libcore.icu.TimeZoneNames.forLocale(locale)) {
+                localZoneIds.add(olsonId);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
index 812d33a..a51ad76 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
@@ -21,6 +21,8 @@
 import android.util.Log;
 import android.util.Pair;
 
+import com.android.settingslib.applications.InterestingConfigChanges;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -30,6 +32,7 @@
     private static final String TAG = "CategoryManager";
 
     private static CategoryManager sInstance;
+    private final InterestingConfigChanges mInterestingConfigChanges;
 
     // Tile cache (key: <packageName, activityName>, value: tile)
     private final Map<Pair<String, String>, Tile> mTileByComponentCache;
@@ -39,26 +42,24 @@
 
     private List<DashboardCategory> mCategories;
 
-    public static CategoryManager get() {
+    public static CategoryManager get(Context context) {
         if (sInstance == null) {
-            sInstance = new CategoryManager();
+            sInstance = new CategoryManager(context);
         }
         return sInstance;
     }
 
-    CategoryManager() {
+    CategoryManager(Context context) {
         mTileByComponentCache = new ArrayMap<>();
         mCategoryByKeyMap = new ArrayMap<>();
+        mInterestingConfigChanges = new InterestingConfigChanges();
+        mInterestingConfigChanges.applyNewConfig(context.getResources());
     }
 
     public synchronized DashboardCategory getTilesByCategory(Context context, String categoryKey) {
         tryInitCategories(context);
 
-        final DashboardCategory category = mCategoryByKeyMap.get(categoryKey);
-        if (category == null) {
-            throw new IllegalStateException("Can't find category with key " + categoryKey);
-        }
-        return category;
+        return mCategoryByKeyMap.get(categoryKey);
     }
 
     public synchronized List<DashboardCategory> getCategories(Context context) {
@@ -67,8 +68,10 @@
     }
 
     public synchronized void reloadAllCategories(Context context) {
+        final boolean forceClearCache = mInterestingConfigChanges.applyNewConfig(
+                context.getResources());
         mCategories = null;
-        tryInitCategories(context);
+        tryInitCategories(context, forceClearCache);
     }
 
     public synchronized void updateCategoryFromBlacklist(Set<ComponentName> tileBlacklist) {
@@ -87,8 +90,16 @@
     }
 
     private synchronized void tryInitCategories(Context context) {
+        // Keep cached tiles by default. The cache is only invalidated when InterestingConfigChange
+        // happens.
+        tryInitCategories(context, false /* forceClearCache */);
+    }
+
+    private synchronized void tryInitCategories(Context context, boolean forceClearCache) {
         if (mCategories == null) {
-            mTileByComponentCache.clear();
+            if (forceClearCache) {
+                mTileByComponentCache.clear();
+            }
             mCategoryByKeyMap.clear();
             mCategories = TileUtils.getCategories(context, mTileByComponentCache,
                     false /* categoryDefinedInManifest */);
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index bb6c558..bad7ba4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -185,7 +185,7 @@
             return false;
         }
         if (isDashboardFeatureEnabled()) {
-            final DashboardCategory homepageCategories = CategoryManager.get()
+            final DashboardCategory homepageCategories = CategoryManager.get(this)
                     .getTilesByCategory(this, CategoryKey.CATEGORY_HOMEPAGE);
             return homepageCategories.containsComponent(componentName);
         } else {
@@ -429,7 +429,7 @@
         private final CategoryManager mCategoryManager;
 
         public CategoriesUpdateTask() {
-            mCategoryManager = CategoryManager.get();
+            mCategoryManager = CategoryManager.get(SettingsDrawerActivity.this);
         }
 
         @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
index e1216a1..602d135 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
@@ -69,8 +69,8 @@
     }
 
     public void updateHomepageCategories() {
-        DashboardCategory category =
-                CategoryManager.get().getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE);
+        final DashboardCategory category = CategoryManager.get(mActivity)
+                        .getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE);
         mItems.clear();
         // Spacer.
         mItems.add(null);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index a514ebb..c2161ae 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -288,7 +288,7 @@
 
     public boolean matches(WifiConfiguration config) {
         if (config.isPasspoint() && mConfig != null && mConfig.isPasspoint()) {
-            return config.FQDN.equals(mConfig.providerFriendlyName);
+            return config.FQDN.equals(mConfig.FQDN);
         } else {
             return ssid.equals(removeDoubleQuotes(config.SSID))
                     && security == getSecurity(config)
@@ -407,7 +407,11 @@
     }
 
     public DetailedState getDetailedState() {
-        return mNetworkInfo != null ? mNetworkInfo.getDetailedState() : null;
+        if (mNetworkInfo != null) {
+            return mNetworkInfo.getDetailedState();
+        }
+        Log.w(TAG, "NetworkInfo is null, cannot return detailed state");
+        return null;
     }
 
     public String getSavedNetworkSummary() {
@@ -847,7 +851,10 @@
                 return context.getString(R.string.wifi_connected_no_internet);
             }
         }
-
+        if (state == null) {
+            Log.w(TAG, "state is null, returning empty summary");
+            return "";
+        }
         String[] formats = context.getResources().getStringArray((ssid == null)
                 ? R.array.wifi_status : R.array.wifi_status_with_ssid);
         int index = state.ordinal();
diff --git a/packages/SettingsLib/tests/AndroidManifest.xml b/packages/SettingsLib/tests/AndroidManifest.xml
index 18bbbed..9fd5a41 100644
--- a/packages/SettingsLib/tests/AndroidManifest.xml
+++ b/packages/SettingsLib/tests/AndroidManifest.xml
@@ -20,6 +20,7 @@
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY"/>
+    <uses-permission android:name="android.permission.SET_TIME_ZONE" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/utils/ZoneGetterTest.java b/packages/SettingsLib/tests/src/com/android/settingslib/utils/ZoneGetterTest.java
new file mode 100644
index 0000000..57e06dd
--- /dev/null
+++ b/packages/SettingsLib/tests/src/com/android/settingslib/utils/ZoneGetterTest.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.settingslib.utils;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.*;
+import com.android.settingslib.datetime.ZoneGetter;
+
+import static junit.framework.Assert.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ZoneGetterTest {
+    private static final String TIME_ZONE_LONDON_ID = "Europe/London";
+    private static final String TIME_ZONE_LA_ID = "America/Los_Angeles";
+    private Locale mLocaleEnUs;
+    private Calendar mCalendar;
+
+    @Before
+    public void setUp() {
+        mLocaleEnUs = new Locale("en", "us");
+        Locale.setDefault(mLocaleEnUs);
+        mCalendar = new GregorianCalendar(2016, 9, 1);
+    }
+
+    @Test
+    public void getTimeZoneOffsetAndName_setLondon_returnLondon() {
+        // Check it will ends with 'London', not 'British Summer Time' or sth else
+        testTimeZoneOffsetAndNameInner(TIME_ZONE_LONDON_ID, "London");
+    }
+
+    @Test
+    public void getTimeZoneOffsetAndName_setLosAngeles_returnPacificDaylightTime() {
+        // Check it will ends with 'Pacific Daylight Time', not 'Los_Angeles'
+        testTimeZoneOffsetAndNameInner(TIME_ZONE_LA_ID, "Pacific Daylight Time");
+    }
+
+    private void testTimeZoneOffsetAndNameInner(String timeZoneId, String expectedName) {
+        final Context context = InstrumentationRegistry.getContext();
+        final TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);
+
+        String timeZoneString = ZoneGetter.getTimeZoneOffsetAndName(context, timeZone,
+                mCalendar.getTime());
+
+        assertTrue(timeZoneString.endsWith(expectedName));
+    }
+
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 7338a9c..c1a1f84 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1483,7 +1483,6 @@
                             Settings.Global.CALL_AUTO_RETRY,
                             Settings.Global.DEBUG_APP,
                             Settings.Global.WAIT_FOR_DEBUGGER,
-                            Settings.Global.SHOW_PROCESSES,
                             Settings.Global.ALWAYS_FINISH_ACTIVITIES,
                     };
                     String[] secureToGlobal = {
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index dde71eb..b4bfb01 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -201,7 +201,12 @@
     @After
     public void tearDown() throws Exception {
         Log.i(TAG, getName() + ".tearDown()");
-        cancelExistingNotifications();
+        try {
+            cancelExistingNotifications();
+        } finally {
+            // Collapses just in case, so a failure here does not compromise tests on other classes.
+            mUiBot.collapseStatusBar();
+        }
     }
 
     @Test
@@ -362,7 +367,7 @@
         detailsUi.assertName(NAME);  // Sanity check
 
         cancelFromNotification();
-        mUiBot.closeNotifications();
+        mUiBot.collapseStatusBar();
 
         assertDetailsUiClosed();
         assertServiceNotRunning();
diff --git a/packages/Shell/tests/src/com/android/shell/UiBot.java b/packages/Shell/tests/src/com/android/shell/UiBot.java
index deab7da..e839765 100644
--- a/packages/Shell/tests/src/com/android/shell/UiBot.java
+++ b/packages/Shell/tests/src/com/android/shell/UiBot.java
@@ -62,7 +62,7 @@
         return getObject(text);
     }
 
-    public void closeNotifications() throws Exception {
+    public void collapseStatusBar() throws Exception {
         // TODO: mDevice should provide such method..
         StatusBarManager sbm =
                 (StatusBarManager) mInstrumentation.getContext().getSystemService("statusbar");
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 71bfe85..ffddf02 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -2,10 +2,9 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := SystemUI-proto-tags
+LOCAL_MODULE := SystemUI-proto
 
-LOCAL_SRC_FILES := $(call all-proto-files-under,src) \
-    src/com/android/systemui/EventLogTags.logtags
+LOCAL_SRC_FILES := $(call all-proto-files-under,src)
 
 LOCAL_PROTOC_OPTIMIZE_TYPE := nano
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
@@ -33,7 +32,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     framework-protos \
-    SystemUI-proto-tags
+    SystemUI-proto
 
 LOCAL_JAVA_LIBRARIES := telephony-common
 LOCAL_JAVA_LIBRARIES += android.car
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 8ed1be5..02518f2 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -219,19 +219,10 @@
             </intent-filter>
         </receiver>
 
-        <service android:name=".LoadAverageService"
-                android:exported="true" />
-
         <service android:name=".ImageWallpaper"
                 android:permission="android.permission.BIND_WALLPAPER"
                 android:exported="true" />
 
-        <receiver android:name=".BootReceiver" androidprv:systemUserOnly="true">
-            <intent-filter android:priority="1000">
-                <action android:name="android.intent.action.BOOT_COMPLETED" />
-            </intent-filter>
-        </receiver>
-
         <activity android:name=".tuner.TunerActivity"
                   android:enabled="false"
                   android:icon="@drawable/tuner"
@@ -247,6 +238,18 @@
                     android:value="com.android.settings.category.system" />
         </activity>
 
+        <activity-alias android:name=".tuner.TunerSettingLink"
+                        android:targetActivity=".tuner.TunerActivity"
+                        android:enabled="false"
+                        android:process=":tuner">
+            <intent-filter android:priority="1">
+                <action android:name="com.android.settings.action.EXTRA_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.category"
+                       android:value="com.android.settings.category.ia.system" />
+        </activity-alias>
+
         <activity-alias android:name=".DemoMode"
                   android:targetActivity=".tuner.TunerActivity"
                   android:icon="@drawable/tuner"
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
index 495771a..75a5434 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
@@ -14,12 +14,10 @@
 
 package com.android.systemui.plugins;
 
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -33,12 +31,10 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
-import dalvik.system.PathClassLoader;
-
 import java.util.ArrayList;
 import java.util.List;
 
-public class PluginInstanceManager<T extends Plugin> extends BroadcastReceiver {
+public class PluginInstanceManager<T extends Plugin> {
 
     private static final boolean DEBUG = false;
 
@@ -57,20 +53,21 @@
     final PluginHandler mPluginHandler;
     private final boolean isDebuggable;
     private final PackageManager mPm;
-    private final ClassLoaderFactory mClassLoaderFactory;
+    private final PluginManager mManager;
 
     PluginInstanceManager(Context context, String action, PluginListener<T> listener,
-            boolean allowMultiple, Looper looper, int version) {
+            boolean allowMultiple, Looper looper, int version, PluginManager manager) {
         this(context, context.getPackageManager(), action, listener, allowMultiple, looper, version,
-                Build.IS_DEBUGGABLE, new ClassLoaderFactory());
+                manager, Build.IS_DEBUGGABLE);
     }
 
     @VisibleForTesting
     PluginInstanceManager(Context context, PackageManager pm, String action,
             PluginListener<T> listener, boolean allowMultiple, Looper looper, int version,
-            boolean debuggable, ClassLoaderFactory classLoaderFactory) {
+            PluginManager manager, boolean debuggable) {
         mMainHandler = new MainHandler(Looper.getMainLooper());
         mPluginHandler = new PluginHandler(looper);
+        mManager = manager;
         mContext = context;
         mPm = pm;
         mAction = action;
@@ -78,44 +75,29 @@
         mAllowMultiple = allowMultiple;
         mVersion = version;
         isDebuggable = debuggable;
-        mClassLoaderFactory = classLoaderFactory;
     }
 
-    public void startListening() {
+    public void loadAll() {
         if (DEBUG) Log.d(TAG, "startListening");
         mPluginHandler.sendEmptyMessage(PluginHandler.QUERY_ALL);
-        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
-        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        filter.addDataScheme("package");
-        mContext.registerReceiver(this, filter);
-        filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
-        mContext.registerReceiver(this, filter);
     }
 
-    public void stopListening() {
+    public void destroy() {
         if (DEBUG) Log.d(TAG, "stopListening");
         ArrayList<PluginInfo> plugins = new ArrayList<>(mPluginHandler.mPlugins);
         for (PluginInfo plugin : plugins) {
             mMainHandler.obtainMessage(MainHandler.PLUGIN_DISCONNECTED,
                     plugin.mPlugin).sendToTarget();
         }
-        mContext.unregisterReceiver(this);
     }
 
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (DEBUG) Log.d(TAG, "onReceive " + intent);
-        if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
-            mPluginHandler.sendEmptyMessage(PluginHandler.QUERY_ALL);
-        } else {
-            Uri data = intent.getData();
-            String pkgName = data.getEncodedSchemeSpecificPart();
-            mPluginHandler.obtainMessage(PluginHandler.REMOVE_PKG, pkgName).sendToTarget();
-            if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
-                mPluginHandler.obtainMessage(PluginHandler.QUERY_PKG, pkgName).sendToTarget();
-            }
-        }
+    public void onPackageRemoved(String pkg) {
+        mPluginHandler.obtainMessage(PluginHandler.REMOVE_PKG, pkg).sendToTarget();
+    }
+
+    public void onPackageChange(String pkg) {
+        mPluginHandler.obtainMessage(PluginHandler.REMOVE_PKG, pkg).sendToTarget();
+        mPluginHandler.obtainMessage(PluginHandler.QUERY_PKG, pkg).sendToTarget();
     }
 
     public boolean checkAndDisable(String className) {
@@ -132,7 +114,9 @@
 
     public void disableAll() {
         ArrayList<PluginInfo> plugins = new ArrayList<>(mPluginHandler.mPlugins);
-        plugins.forEach(this::disable);
+        for (int i = 0; i < plugins.size(); i++) {
+            disable(plugins.get(i));
+        }
     }
 
     private void disable(PluginInfo info) {
@@ -179,12 +163,6 @@
         }
     }
 
-    static class ClassLoaderFactory {
-        public ClassLoader createClassLoader(String path, ClassLoader base) {
-            return new PathClassLoader(path, base);
-        }
-    }
-
     private class PluginHandler extends Handler {
         private static final int QUERY_ALL = 1;
         private static final int QUERY_PKG = 2;
@@ -279,8 +257,7 @@
                     return null;
                 }
                 // Create our own ClassLoader so we can use our own code as the parent.
-                ClassLoader classLoader = mClassLoaderFactory.createClassLoader(info.sourceDir,
-                        getClass().getClassLoader());
+                ClassLoader classLoader = mManager.getClassLoader(info.sourceDir, info.packageName);
                 Context pluginContext = new PluginContextWrapper(
                         mContext.createApplicationContext(info, 0), classLoader);
                 Class<?> pluginClass = Class.forName(cls, true, classLoader);
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
index 4bf6494..686b4d4 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
@@ -14,7 +14,11 @@
 
 package com.android.systemui.plugins;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
 import android.os.Build;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -22,26 +26,31 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import dalvik.system.PathClassLoader;
+
 import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.Map;
 
 /**
  * @see Plugin
  */
-public class PluginManager {
+public class PluginManager extends BroadcastReceiver {
 
     private static PluginManager sInstance;
 
     private final HandlerThread mBackgroundThread;
     private final ArrayMap<PluginListener<?>, PluginInstanceManager> mPluginMap
             = new ArrayMap<>();
+    private final Map<String, ClassLoader> mClassLoaders = new ArrayMap<>();
     private final Context mContext;
     private final PluginInstanceManagerFactory mFactory;
     private final boolean isDebuggable;
     private final PluginPrefs mPluginPrefs;
+    private ClassLoaderFilter mParentClassLoader;
 
     private PluginManager(Context context) {
-        this(context, new PluginInstanceManagerFactory(), Build.IS_DEBUGGABLE,
-                Thread.getDefaultUncaughtExceptionHandler());
+        this(context, new PluginInstanceManagerFactory(),
+                Build.IS_DEBUGGABLE, Thread.getDefaultUncaughtExceptionHandler());
     }
 
     @VisibleForTesting
@@ -72,9 +81,12 @@
         }
         mPluginPrefs.addAction(action);
         PluginInstanceManager p = mFactory.createPluginInstanceManager(mContext, action, listener,
-                allowMultiple, mBackgroundThread.getLooper(), version);
-        p.startListening();
+                allowMultiple, mBackgroundThread.getLooper(), version, this);
+        p.loadAll();
         mPluginMap.put(listener, p);
+        if (mPluginMap.size() == 1) {
+            startListening();
+        }
     }
 
     public void removePluginListener(PluginListener<?> listener) {
@@ -83,7 +95,68 @@
             return;
         }
         if (!mPluginMap.containsKey(listener)) return;
-        mPluginMap.remove(listener).stopListening();
+        mPluginMap.remove(listener).destroy();
+        if (mPluginMap.size() == 0) {
+            stopListening();
+        }
+    }
+
+    private void startListening() {
+        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addDataScheme("package");
+        mContext.registerReceiver(this, filter);
+        filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
+        mContext.registerReceiver(this, filter);
+    }
+
+    private void stopListening() {
+        mContext.unregisterReceiver(this);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
+            for (PluginInstanceManager manager : mPluginMap.values()) {
+                manager.loadAll();
+            }
+        } else {
+            Uri data = intent.getData();
+            String pkg = data.getEncodedSchemeSpecificPart();
+            clearClassLoader(pkg);
+            if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
+                for (PluginInstanceManager manager : mPluginMap.values()) {
+                    manager.onPackageChange(pkg);
+                }
+            } else {
+                for (PluginInstanceManager manager : mPluginMap.values()) {
+                    manager.onPackageRemoved(pkg);
+                }
+            }
+        }
+    }
+
+    public ClassLoader getClassLoader(String sourceDir, String pkg) {
+        if (mClassLoaders.containsKey(pkg)) {
+            return mClassLoaders.get(pkg);
+        }
+        ClassLoader classLoader = new PathClassLoader(sourceDir, getParentClassLoader());
+        mClassLoaders.put(pkg, classLoader);
+        return classLoader;
+    }
+
+    private void clearClassLoader(String pkg) {
+        mClassLoaders.remove(pkg);
+    }
+
+    ClassLoader getParentClassLoader() {
+        if (mParentClassLoader == null) {
+            // Lazily load this so it doesn't have any effect on devices without plugins.
+            mParentClassLoader = new ClassLoaderFilter(getClass().getClassLoader(),
+                    "com.android.systemui.plugin");
+        }
+        return mParentClassLoader;
     }
 
     public static PluginManager getInstance(Context context) {
@@ -97,9 +170,29 @@
     public static class PluginInstanceManagerFactory {
         public <T extends Plugin> PluginInstanceManager createPluginInstanceManager(Context context,
                 String action, PluginListener<T> listener, boolean allowMultiple, Looper looper,
-                int version) {
+                int version, PluginManager manager) {
             return new PluginInstanceManager(context, action, listener, allowMultiple, looper,
-                    version);
+                    version, manager);
+        }
+    }
+
+
+    // This allows plugins to include any libraries or copied code they want by only including
+    // classes from the plugin library.
+    private static class ClassLoaderFilter extends ClassLoader {
+        private final String mPackage;
+        private final ClassLoader mBase;
+
+        public ClassLoaderFilter(ClassLoader base, String pkg) {
+            super(ClassLoader.getSystemClassLoader());
+            mBase = base;
+            mPackage = pkg;
+        }
+
+        @Override
+        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+            if (!name.startsWith(mPackage)) super.loadClass(name, resolve);
+            return mBase.loadClass(name);
         }
     }
 
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java
index 3270587..a616369 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java
@@ -31,7 +31,7 @@
 
     // This should be incremented any time this class or ActivityStarter or BaseStatusBarHeader
     // change in incompatible ways.
-    public static final int VERSION = 1;
+    public static final int VERSION = 2;
 
     public QSContainer(@NonNull Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
@@ -40,6 +40,7 @@
     public abstract void setPanelView(HeightListener notificationPanelView);
     public abstract BaseStatusBarHeader getHeader();
 
+    public abstract void hideImmediately();
     public abstract int getQsMinExpansionHeight();
     public abstract int getDesiredHeight();
     public abstract void setHeightOverride(int desiredHeight);
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
index f63dfb12..b78d3bf 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,17 +15,15 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
+        android:width="32.0dp"
+        android:height="32.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
-    <path
-        android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
-        android:fillColor="#4DFFFFFF"/>
+        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
index 7fb423e..e055de7 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,20 +15,18 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
+        android:width="32.0dp"
+        android:height="32.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/>
+        android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/>
+        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M17.7,8.0l4.299999,0.0 0.0,-6.0 -20.0,20.0 15.700001,0.0z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
+        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
index 3358d65..8a48817 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,20 +15,18 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
+        android:width="32.0dp"
+        android:height="32.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+        android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M13.900000,10.000000l-11.900000,12.000000 11.900000,0.000000z"/>
-    <path
-        android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
-        android:fillColor="#4DFFFFFF"/>
+        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
index 63838a9..39cc94c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,20 +15,18 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
+        android:width="32.0dp"
+        android:height="32.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.700001,19.900000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.700001,9.900000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M16.700001,7.200000l-14.700001,14.700000 14.700001,0.000000z"/>
-    <path
-        android:pathData="M17.700001,7.900000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
-        android:fillColor="#4DFFFFFF"/>
+        android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
index 76690cc..012e95e 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,17 +15,14 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
+        android:width="32.0dp"
+        android:height="32.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M2.000000,22.000000l15.700001,0.000000 0.000000,-14.000000 4.299999,0.000000 0.000000,-6.000000z"/>
+        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
index 50c427e..e6f9292 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -14,17 +14,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="29.5dp"
-        android:viewportWidth="26.0"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.200000,-1.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
index a2d11a0..d423ccb 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -14,20 +14,18 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="29.5dp"
-        android:viewportWidth="26.0"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+        android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M13.000000,22.000000l5.500000,-6.800000c-0.200000,-0.200000 -2.300000,-1.900000 -5.500000,-1.900000s-5.300000,1.800000 -5.500000,1.900000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
index f2043fc..1982130 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -14,20 +14,18 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="29.5dp"
-        android:viewportWidth="26.0"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+        android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.000000,11.600000c-1.300000,-0.700000 -3.400000,-1.600000 -6.000000,-1.600000c-4.400000,0.000000 -7.300000,2.400000 -7.600000,2.700000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,11.600000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.800001,1.9 -1.800001,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
index b7a4f4c..b350111 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -14,20 +14,18 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="29.5dp"
-        android:viewportWidth="26.0"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.000000,8.600000c-1.600000,-0.700000 -3.600000,-1.300000 -6.000000,-1.300000c-5.300000,0.000000 -8.900000,3.000000 -9.200000,3.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.600000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
index 35a9138..136a004 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -14,17 +14,14 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="29.5dp"
-        android:viewportWidth="26.0"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillColor="#FFFFFF"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
index 643c4f9..8bc872a 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,17 +15,14 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
+        android:width="17.0dp"
+        android:height="17.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
-    <path
-        android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
+        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
         android:fillColor="?attr/backgroundColor"/>
+    <path
+        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
index 64781c3..8fa7630 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,20 +15,17 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
+        android:width="17.0dp"
+        android:height="17.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/>
+        android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
+        android:fillColor="?attr/fillColor"/>
     <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/>
+        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+        android:fillColor="?attr/backgroundColor"/>
     <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M17.7,8.0l4.299999,0.0 0.0,-6.0 -20.0,20.0 15.700001,0.0z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
+        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
index eb2be08..2a660a3 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,20 +15,17 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
+        android:width="17.0dp"
+        android:height="17.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+        android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
+        android:fillColor="?attr/fillColor"/>
     <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M13.900000,10.000000l-11.900000,12.000000 11.900000,0.000000z"/>
-    <path
-        android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
+        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
         android:fillColor="?attr/backgroundColor"/>
+    <path
+        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
index 22afad0..9e0a433 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,20 +15,17 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
+        android:width="17.0dp"
+        android:height="17.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.700001,19.900000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.700001,9.900000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M16.700001,7.200000l-14.700001,14.700000 14.700001,0.000000z"/>
-    <path
-        android:pathData="M17.700001,7.900000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
+        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
         android:fillColor="?attr/backgroundColor"/>
+    <path
+        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+        android:fillColor="?attr/fillColor"/>
+    <path
+        android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z"
+        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
index d1e866d..01f6703 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,18 +15,14 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
+        android:width="17.0dp"
+        android:height="17.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
-
     <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+        android:fillColor="?attr/fillColor"/>
     <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M2.000000,22.000000l15.700001,0.000000 0.000000,-14.000000 4.299999,0.000000 0.000000,-6.000000z"/>
+        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
index 7f1b715e..2de2e36 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,16 +15,13 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
-        android:height="17dp"
-        android:viewportWidth="26.0"
+        android:height="18.41dp"
+        android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.200000,-1.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillColor="?attr/backgroundColor"/>
     <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
+        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
index acd89be..144a7c1 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,19 +15,16 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
-        android:height="17dp"
-        android:viewportWidth="26.0"
+        android:height="18.41dp"
+        android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+        android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
+        android:fillColor="?attr/fillColor"/>
     <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M13.000000,22.000000l5.500000,-6.800000c-0.200000,-0.200000 -2.300000,-1.900000 -5.500000,-1.900000s-5.300000,1.800000 -5.500000,1.900000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillColor="?attr/backgroundColor"/>
     <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
+        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
index f33b25c..6b7f712 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,19 +15,16 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
-        android:height="17dp"
-        android:viewportWidth="26.0"
+        android:height="18.41dp"
+        android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+        android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
+        android:fillColor="?attr/fillColor"/>
     <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M19.000000,11.600000c-1.300000,-0.700000 -3.400000,-1.600000 -6.000000,-1.600000c-4.400000,0.000000 -7.300000,2.400000 -7.600000,2.700000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,11.600000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillColor="?attr/backgroundColor"/>
     <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.800001,1.9 -1.800001,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
index 09d2e50..d34b4de 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,19 +15,16 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
-        android:height="17dp"
-        android:viewportWidth="26.0"
+        android:height="18.41dp"
+        android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillColor="?attr/fillColor"/>
     <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M19.000000,8.600000c-1.600000,-0.700000 -3.600000,-1.300000 -6.000000,-1.300000c-5.300000,0.000000 -8.900000,3.000000 -9.200000,3.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.600000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillColor="?attr/backgroundColor"/>
     <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
index fb1f584..5701356 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
@@ -1,7 +1,7 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-   Licensed under the Apache License, Version 2.0 (the "License");
+    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
 
@@ -15,16 +15,13 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
-        android:height="17dp"
-        android:viewportWidth="26.0"
+        android:height="18.41dp"
+        android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+        android:fillColor="?attr/fillColor"/>
     <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
-    <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+        android:fillColor="?attr/fillColor"/>
 </vector>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 7d3eb8d..b8be190 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> waarskuwing"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Werkmodus"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Aandbeligting"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Aandbeligting is aan, tik om af te skakel"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Aandbeligting is af, tik om aan te skakel"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Geen onlangse items nie"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Jy het alles toegemaak"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Programinligting"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Blaaier"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakte"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pos"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Kitsboodskappe"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiek"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index fb73729..6cbb5c6 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"የ<xliff:g id="DATA_LIMIT">%s</xliff:g> ማስጠንቀቂያ"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"የሥራ ሁነታ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"የምሽት ብርሃን"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"የምሽት ብርሃን በርቷል፣ ለማጥፋት መታ ያድርጉ"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"የምሽት ብርሃን ጠፍቷል፣ ለማብራት መታ ያድርጉ"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ምንም የቅርብ ጊዜ ንጥሎች የሉም"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ሁሉንም ነገር አጽድተዋል"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"የመተግበሪያ መረጃ"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"አሳሽ"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"እውቂያዎች"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ኢሜይል"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"ፈጣን መልዕክት"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ሙዚቃ"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"የቀን መቁጠሪያ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index b7bb97e..cc41f0f 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -327,8 +327,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"تحذير <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"وضع العمل"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"إضاءة ليلية"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"الإضاءة الليلية قيد العمل، انقر لإيقافها."</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"الإضاءة الليلية قيد الإيقاف، انقر لتشغيلها."</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ليست هناك عناصر تم استخدامها مؤخرًا"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"لقد محوتَ كل شيء"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"معلومات التطبيق"</string>
@@ -572,7 +570,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"المتصفح"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"جهات الاتصال"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"البريد الإلكتروني"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"الرسائل الفورية"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"الموسيقى"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"التقويم"</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index ee98b8f..2e1438c 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> xəbərdarlığı"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"İş rejimi"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Gecə işığı"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Gecə işığı aktivdir, deaktiv etmək üçün tıklayın"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Gecə işığı deaktivdir, aktiv etmək üçün tıklayın"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Son elementlər yoxdur"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Hərşeyi təmizlədiniz"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Tətbiq haqqında"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brauzer"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktlar"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-poçt"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiqi"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Təqvim"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index ac8699b..28d0967 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje za <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Režim rada"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noćno svetlo"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Noćno svetlo je uključeno, dodirnite da biste ga isključili"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Noćno svetlo je isključeno, dodirnite da biste ga uključili"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nema nedavnih stavki"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Obrisali ste sve"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Pregledač"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakti"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Imejl"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Razmena trenutnih poruka"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzika"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index fb43971..9f23d02 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -325,8 +325,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Папярэджанне: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Рэжым працы"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Начная падсветка"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"\"Начная падсветка\" ўключана; дакраніцеся, каб выключыць"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"\"Начная падсветка\" выключана; дакраніцеся, каб уключыць"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Няма нядаўніх элементаў"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Вы ачысцілі усё"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Звесткі аб праграме"</string>
@@ -570,7 +568,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браўзер"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Кантакты"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Электронная пошта"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Iмгненныя паведамленнi"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Каляндар"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 8ef1c85..4ea50cf 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Работен режим"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Нощно осветление"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Функцията за нощно осветление е включена. Докоснете, за да я изключите"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Функцията за нощно осветление е изключена. Докоснете, за да я включите"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Няма скорошни елементи"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Изчистихте всичко"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информация за приложението"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браузър"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Електронна поща"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Незабавни съобщения"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 3ef8892..0d3e57a 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> সতর্কতা"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"কাজের মোড"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"নাইট লাইট"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"নাইট লাইট চালু আছে, বন্ধ করতে আলতো চাপুন"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"নাইট লাইট বন্ধ আছে, চালু করতে আলতো চাপুন"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"কোনো সাম্প্রতিক আইটেম নেই"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"আপনি সবকিছু সাফ করেছেন"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"অ্যাপ্লিকেশানের তথ্য"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ব্রাউজার"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"পরিচিতি"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ইমেল"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"সংগীত"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ক্যালেন্ডার"</string>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 6ce6dbe..1c28298 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Poslovni režim"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noćno svjetlo"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Noćno svjetlo je uključeno, dodirnite da isključite"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Noćno svjetlo je isključeno, dodirnite da uključite"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nema nedavnih stavki"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Sve ste obrisali"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
@@ -568,7 +566,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Preglednik"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakti"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pošta"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzika"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 8810ce3..c4d82e4 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertiment: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Mode de feina"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Llum nocturna"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"La llum nocturna està encesa; toca aquí per apagar-la"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"La llum nocturna està apagada; toca aquí per encendre-la"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"No hi ha cap element recent"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Ho has esborrat tot"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informació de l\'aplicació"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactes"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correu electrònic"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendari"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 4a515a6..9366b00 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -241,7 +241,7 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G jsou pozastavena"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilní data jsou pozastavena"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data jsou pozastavena"</string>
-    <string name="data_usage_disabled_dialog" msgid="1841738975235283398">"Bylo dosaženo limitu dat. Používání mobilních dat bylo vypnuto.\n\nPokud jej obnovíte, mohou vám být účtovány poplatky za využití dat."</string>
+    <string name="data_usage_disabled_dialog" msgid="1841738975235283398">"Byl dosažen limit dat. Používání mobilních dat bylo vypnuto.\n\nPokud jej obnovíte, mohou vám být účtovány poplatky za využití dat."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Pokračovat"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Žádné přip. k internetu"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: připojeno"</string>
@@ -325,8 +325,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozornění při <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Pracovní režim"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noční režim"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Noční režim je zapnut, klepnutím jej vypnete"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Noční režim je vypnut, klepnutím jej zapnete"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Žádné nedávné položky"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Vše je vymazáno"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informace o aplikaci"</string>
@@ -570,7 +568,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Prohlížeč"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakty"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Hudba"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendář"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index d23bd26..a686306 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -303,7 +303,7 @@
     <string name="quick_settings_inversion_label" msgid="8790919884718619648">"Byt om på farver"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Farvekorrigeringstilstand"</string>
     <string name="quick_settings_more_settings" msgid="326112621462813682">"Flere indstillinger"</string>
-    <string name="quick_settings_done" msgid="3402999958839153376">"Udført"</string>
+    <string name="quick_settings_done" msgid="3402999958839153376">"Udfør"</string>
     <string name="quick_settings_connected" msgid="1722253542984847487">"Tilsluttet"</string>
     <string name="quick_settings_connecting" msgid="47623027419264404">"Opretter forbindelse…"</string>
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Netdeling"</string>
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advarsel ved <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Arbejdstilstand"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nattelys"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Nattelys er tændt. Tryk for at slukke"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Nattelys er slukket. Tryk for at tænde"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Ingen nye elementer"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Du har ryddet alt"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Oplysninger om applikationen"</string>
@@ -520,7 +518,7 @@
     <string name="notification_importance_high" msgid="1729480727023990427">"Se altid smugkig. Ingen afbrydelse af fuld skærm."</string>
     <string name="notification_importance_max" msgid="2508384624461849111">"Se altid smugkig, og tillad afbrydelse af fuld skærm."</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Flere indstillinger"</string>
-    <string name="notification_done" msgid="5279426047273930175">"Færdig"</string>
+    <string name="notification_done" msgid="5279426047273930175">"Udfør"</string>
     <string name="notification_gear_accessibility" msgid="94429150213089611">"Kontrolelementer til underretninger for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Batteriforbrug"</string>
     <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparefunktionen er ikke tilgængelig under opladning"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktpersoner"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 3ba8f5dd..8d55230 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -270,7 +270,7 @@
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Geräte)"</string>
     <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth aus"</string>
-    <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Keine Pairing-Geräte verfügbar"</string>
+    <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Keine gekoppelten Geräte verfügbar"</string>
     <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Helligkeit"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatisch drehen"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Bildschirm automatisch drehen"</string>
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Warnung für <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Arbeitsmodus"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nachtlicht"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Nachtlicht an, zum Deaktivieren tippen"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Nachtlicht aus, zum Aktivieren tippen"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Keine kürzlich verwendeten Elemente"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Du hast alles gelöscht"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"App-Info"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakte"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-Mail"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index fc248cf..3dc97e7 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -163,7 +163,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Φόρτιση μπαταρίας, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> τοις εκατό."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Ρυθμίσεις συστήματος."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Ειδοποιήσεις."</string>
-    <string name="accessibility_remove_notification" msgid="3603099514902182350">"Εκκαθάριση ειδοποίησης."</string>
+    <string name="accessibility_remove_notification" msgid="3603099514902182350">"Διαγραφή ειδοποίησης."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"Το GPS ενεργοποιήθηκε."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Προσδιορισμός GPS."</string>
     <string name="accessibility_tty_enabled" msgid="4613200365379426561">"Το TeleTypewriter ενεργοποιήθηκε."</string>
@@ -244,7 +244,7 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Αναζήτηση για GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Ρύθμιση τοποθεσίας με GPS"</string>
     <string name="accessibility_location_active" msgid="2427290146138169014">"Τα αιτήματα τοποθεσίας έχουν ενεργοποιηθεί"</string>
-    <string name="accessibility_clear_all" msgid="5235938559247164925">"Εκκαθάριση όλων των ειδοποιήσεων."</string>
+    <string name="accessibility_clear_all" msgid="5235938559247164925">"Διαγραφή όλων των ειδοποιήσεων."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> επιπλέον ειδοποιήσεις εντός της ομάδας.</item>
@@ -319,10 +319,8 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Προειδοποίηση για <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Λειτουργία εργασίας"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Νυχτερινός φωτισμός"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Ο Νυχτερινός φωτισμός είναι ενεργοποιημένος. Πατήστε για απενεργοποίηση."</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Ο Νυχτερινός φωτισμός είναι απενεργοποιημένος. Πατήστε για ενεργοποίηση."</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Δεν υπάρχουν πρόσφατα στοιχεία"</string>
-    <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Έχει γίνει εκκαθάριση όλων των στοιχείων"</string>
+    <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Έχει γίνει διαγραφή όλων των στοιχείων"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string>
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"καρφίτσωμα οθόνης"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
@@ -437,7 +435,7 @@
     <string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Θα εμφανιστεί ξανά την επόμενη φορά που θα το ενεργοποιήσετε στις ρυθμίσεις."</string>
     <string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Απόκρυψη"</string>
     <string name="volumeui_prompt_message" msgid="918680947433389110">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> θέλει να γίνει το παράθυρο διαλόγου ελέγχου έντασης"</string>
-    <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Να επιτραπεί"</string>
+    <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Να επιτρέπεται"</string>
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Απόρριψη"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> αποτελεί το παράθυρο διαλόγου ελέγχου έντασης"</string>
     <string name="volumeui_notification_text" msgid="8819536904234337445">"Πατήστε για να επαναφέρετε την αρχική μορφή της εικόνας."</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Πρόγραμμα περιήγησης"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Επαφές"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Ηλεκτρονικό ταχυδρομείο"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Άμεσα μηνύματα (ΙΜ)"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Μουσική"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Ημερολόγιο"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 75ec92f..8a3f385f 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work mode"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Night Light on, tap to turn off"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Night Light off, tap to turn on"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"No recent items"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"You\'ve cleared everything"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 75ec92f..8a3f385f 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work mode"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Night Light on, tap to turn off"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Night Light off, tap to turn on"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"No recent items"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"You\'ve cleared everything"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 75ec92f..8a3f385f 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work mode"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Night Light on, tap to turn off"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Night Light off, tap to turn on"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"No recent items"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"You\'ve cleared everything"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 5c98ae7..e74d341 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabajo"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz nocturna"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Presiona para desactivar la Luz nocturna"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Presiona para activar la Luz nocturna"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"No hay elementos recientes"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Todo borrado"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 4da5ba4..0994575 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -232,8 +232,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabajo activado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modo de trabajo desactivado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modo de trabajo activado."</string>
-    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Economizador de Datos desactivado."</string>
-    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Economizador de Datos activado."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Ahorro de datos desactivado."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Ahorro de datos activado."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brillo de la pantalla"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Datos 2G-3G pausados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Datos 4G pausados"</string>
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabajo"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz nocturna"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Luz nocturna activada; toca aquí para desactivarla"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Luz nocturna desactivada; toca aquí para activarla"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"No hay elementos recientes"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Has rechazado todo"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
@@ -579,9 +578,9 @@
     <string name="headset" msgid="4534219457597457353">"Auriculares"</string>
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auriculares conectados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auriculares conectados"</string>
-    <string name="data_saver" msgid="5037565123367048522">"Economizador de Datos"</string>
-    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Economizador de Datos activado"</string>
-    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Economizador de Datos desactivado"</string>
+    <string name="data_saver" msgid="5037565123367048522">"Ahorro de datos"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Ahorro de datos activado"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Ahorro de datos desactivado"</string>
     <string name="switch_bar_on" msgid="1142437840752794229">"Sí"</string>
     <string name="switch_bar_off" msgid="8803270596930432874">"No"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 0a09e48..06145d9 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> hoiatus"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Töörežiim"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Öövalgus"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Öövalgus on sees, puudutage väljalülitamiseks"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Öövalgus on väljas, puudutage sisselülitamiseks"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Hiljutisi üksusi pole"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Olete kõik ära kustutanud"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Rakenduste teave"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brauser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktid"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-post"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM (kiirsuhtlus)"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muusika"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 74b3a61..5c4f7c9 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Abisua: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Lan modua"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Gaueko argia"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Aktibatuta dago gaueko argia. Sakatu desaktibatzeko."</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Desaktibatuta dago gaueko argia. Sakatu aktibatzeko."</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Ez dago azkenaldi honetako ezer"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Dena garbitu duzu"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Aplikazioaren informazioa"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Arakatzailea"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktuak"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Posta"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Istanteko mezularitza"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musika"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 1ccc804..341e942 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"هشدار <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"حالت کار"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"نور شب"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"نور شب روشن است، برای خاموش‌کردن آن ضربه بزنید"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"نور شب خاموش است، برای روشن‌شدن آن ضربه بزنید"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"بدون موارد اخیر"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"همه‌چیز را پاک کرده‌اید"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"اطلاعات برنامه"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"مرورگر"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"مخاطبین"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"رایانامه"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"پیام فوری"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"موسیقی"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"تقویم"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9ec1ffd..3065bee 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> – varoitus"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Työtila"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Yövalo"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Yövalo on käytössä. Poista se käytöstä koskettamalla."</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Yövalo ei ole käytössä. Ota se käyttöön koskettamalla."</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Ei viimeaikaisia kohteita"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Kaikki on hoidettu."</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Sovellustiedot"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Selain"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Yhteystiedot"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Sähköposti"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Pikaviesti"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiikki"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalenteri"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 67e717e..13eb6aa 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertissement : <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Mode Travail"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Éclairage nocturne"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Le mode Éclairage nocturne est activé. Touchez ici pour le désactiver."</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Le mode Éclairage nocturne est désactivé. Touchez ici pour l\'activer."</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Aucun élément récent"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Vous avez tout effacé"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Détails de l\'application"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navigateur"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Courriel"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musique"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7310a47..0b64c62 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertissement : <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Mode Travail"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Éclairage nocturne"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Éclairage nocturne activé, appuyer pour désactiver"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Éclairage nocturne désactivé, appuyer pour activer"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Aucun élément récent"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Vous avez tout effacé."</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Infos application"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navigateur"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Messagerie"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Messagerie instantanée"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musique"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 6152872..54d2816 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de traballo"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz nocturna"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"A función Luz nocturna está activada. Toca para desactivala"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"A función Luz nocturna está desactivada. Toca para activala"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Non hai elementos recentes"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Borraches todo"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información da aplicación"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 26b1c06..e20bb40 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ચેતવણી"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"કાર્ય મોડ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"રાત્રિ પ્રકાશ"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"રાત્રિ પ્રકાશ ચાલુ છે, બંધ કરવા માટે ટપ કરો"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"રાત્રિ પ્રકાશ બંધ છે, ચાલુ કરવા માટે ટૅપ કરો"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"કોઇ તાજેતરની આઇટમ્સ નથી"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"તમે બધું સાફ કર્યું"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ઍપ્લિકેશન માહિતી"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"બ્રાઉઝર"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"સંપર્કો"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ઇમેઇલ"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"સંગીત"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"કૅલેન્ડર"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 42c049d..d4d0e85 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"कार्य मोड"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"नाइट लाइट"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"नाइट लाइट चालू है, बंद करने के लिए टैप करें"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"नाइट लाइट बंद है, चालू करने के लिए टैप करें"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"हाल ही का कोई आइटम नहीं"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"आपने सब कुछ साफ़ कर दिया है"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"एप्‍लिकेशन जानकारी"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउज़र"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"संपर्क"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ईमेल"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"संगीत"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"कैलेंडर"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 58dd92e..ad77975 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Način rada"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noćno svjetlo"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Noćno je svjetlo uključeno, dodirnite da biste ga isključili"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Noćno je svjetlo isključeno, dodirnite da biste ga uključili"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nema nedavnih stavki"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Izbrisali ste sve"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Preglednik"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakti"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pošta"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Izravna poruka"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Glazba"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 0804093..5ddca19 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Figyelem! <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Munka mód"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Éjszakai fény"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Éjszakai fény bekapcsolva, koppintson a kikapcsoláshoz"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Éjszakai fény kikapcsolva, koppintson a bekapcsoláshoz"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nincsenek mostanában használt elemek"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Mindent törölt"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Az alkalmazás adatai"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Böngésző"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Névjegyek"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Azonnali üzenetküldés"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Zene"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Naptár"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 1b0f3d7..1c267d0 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> զգուշացում"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Աշխատանքային ռեժիմ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Գիշերային լույս"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Գիշերային լույսը միացված է, հպեք՝ անջատելու համար"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Գիշերային լույսն անջատված է, հպեք՝ միացնելու համար"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Վերջին տարրեր չկան"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Դուք ջնջել եք ամենը"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Հավելվածի մասին"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Դիտարկիչ"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Կոնտակտներ"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Էլփոստ"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Երաժշտություն"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Օրացույց"</string>
@@ -643,7 +642,7 @@
     <string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"Բացել կարգավորումները:"</string>
     <string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"Բացել արագ կարգավորումները:"</string>
     <string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"Փակել արագ կարգավորումները:"</string>
-    <string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"Զարթուցիչը կարգավորված է:"</string>
+    <string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"Զարթուցիչը դրված է:"</string>
     <string name="accessibility_quick_settings_user" msgid="1567445362870421770">"Մուտք է գործել որպես <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_no_internet" msgid="31890692343084075">"Ինտերնետ կապ չկա:"</string>
     <string name="accessibility_quick_settings_open_details" msgid="4230931801728005194">"Բացել մանրամասները:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index be27eca..b9bbea0 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Peringatan <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Mode kerja"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Cahaya Malam"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Cahaya Malam hidup, ketuk untuk mematikan"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Cahaya Malam mati, ketuk untuk menyalakan"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Tidak ada item baru-baru ini"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Anda sudah menghapus semua"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Info Aplikasi"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontak"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 0b65a95..b74341e 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> viðvörun"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Vinnustilling"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Næturljós"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Kveikt á næturljósi, ýttu til að slökkva"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Slökkt á næturljósi, ýttu til að kveikja"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Engin nýleg atriði"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Þú hefur hreinsað allt"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Forritsupplýsingar"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Vafri"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Tengiliðir"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Tölvupóstur"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Spjall"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Tónlist"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Dagatal"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 5eae72c..100df92 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avviso <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modalità Lavoro"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luminosità notturna"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Luminosità notturna attiva, tocca per disattivarla"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Luminosità notturna disattivata, tocca per attivarla"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nessun elemento recente"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Hai cancellato tutto"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informazioni sull\'applicazione"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contatti"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musica"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ef4d683..93d633a 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -323,8 +323,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"אזהרה - <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"מצב עבודה"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"תאורת לילה"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"תאורת לילה פועלת, הקש כדי לכבות"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"תאורת לילה כבויה, הקש כדי להפעיל"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"אין פריטים אחרונים"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"מחקת הכול"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"מידע על האפליקציה"</string>
@@ -568,7 +566,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"דפדפן"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"אנשי קשר"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"אימייל"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"שליחת הודעות מיידיות"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"מוזיקה"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"‏YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"יומן"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index fcc5ae1..92a35b1 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"警告: 上限は<xliff:g id="DATA_LIMIT">%s</xliff:g>です"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work モード"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"読書灯"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"読書灯 ON: タップすると OFF になります"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"読書灯 OFF: タップすると ON になります"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"最近のタスクはありません"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"すべてのタスクを消去しました"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"アプリ情報"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ブラウザ"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"連絡先"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"メール"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音楽"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"カレンダー"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index b799116..efc3940 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> გაფრთხილება"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"სამსახურის რეჟიმი"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ღამის განათება"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"ღამის განათება ჩართულია, შეეხეთ გამოსართავად"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"ღამის განათება გამორთულია, შეეხეთ ჩასართავად"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ბოლოს გამოყენებული ერთეულები არ არის"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ყველაფერი გასუფთავდა"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"აპლიკაციის შესახებ"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ბრაუზერი"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"კონტაქტები"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ელფოსტა"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"მუსიკა"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"კალენდარი"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 872caa7..271035f 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> туралы ескерту"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Жұмыс режимі"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Түнгі жарық"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Түнгі жарық қосулы, өшіру үшін оны түртіңіз"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Түнгі жарық өшірулі, қосу үшін оны түртіңіз"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Жақындағы элементтер жоқ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Сіз барлығын өшірдіңіз"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Қолданба туралы ақпарат"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браузер"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контактілер"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Электрондық пошта"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Mузыка"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Күнтізбе"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index ee63681..874993f 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -237,7 +237,7 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"ទិន្នន័យ 4G ត្រូវបានផ្អាក"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"ទិន្នន័យចល័តត្រូវបានផ្អាក"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ទិន្នន័យត្រូវបានផ្អាក"</string>
-    <string name="data_usage_disabled_dialog" msgid="1841738975235283398">"បានឈានដល់កម្រិតទិន្នន័យដែលអ្នកបានកំណត់ហើយ។ អ្នកមិនអាចប្រើទិន្នន័យចល័តបានទៀតទេ។\n\nអាចនឹងគិតថ្លៃលើការប្រើទិន្នន័យ ប្រសិនបើអ្នកបន្តប្រើ។"</string>
+    <string name="data_usage_disabled_dialog" msgid="1841738975235283398">"បានឈានដល់កម្រិតទិន្នន័យដែលអ្នកបានកំណត់ហើយ។ ឥឡូវ​អ្នកមិនប្រើទិន្នន័យចល័តទៀតទេ។\n\nអាចនឹងគិតថ្លៃលើការប្រើទិន្នន័យ ប្រសិនបើអ្នកបន្តប្រើឡើងវិញ។"</string>
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"បន្ត"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"គ្មាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"បាន​ភ្ជាប់​វ៉ាយហ្វាយ"</string>
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ការ​ព្រមាន"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"របៀបការងារ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ពន្លឺពេលយប់"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"ពន្លឺពេលយប់បើកហើយ ប៉ះដើម្បីបិទ"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"ពន្លឺពេលយប់បិទហើយ ប៉ះដើម្បីបើក"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"មិនមានធាតុថ្មីៗទេ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"អ្នកបានជម្រះអ្វីៗទាំងអស់"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ព័ត៌មាន​កម្មវិធី"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"កម្មវិធីរុករក"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ទំនាក់ទំនង"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"អ៊ីមែល"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"តន្ត្រី"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ប្រតិទិន"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 189cce0..6f1f28c 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -84,7 +84,7 @@
     <string name="accessibility_home" msgid="8217216074895377641">"ಮುಖಪುಟ"</string>
     <string name="accessibility_menu" msgid="316839303324695949">"ಮೆನು"</string>
     <string name="accessibility_recent" msgid="5208608566793607626">"ಸಮಗ್ರ ನೋಟ"</string>
-    <string name="accessibility_search_light" msgid="1103867596330271848">"ಹುಡುಕು"</string>
+    <string name="accessibility_search_light" msgid="1103867596330271848">"ಹುಡುಕಿ"</string>
     <string name="accessibility_camera_button" msgid="8064671582820358152">"ಕ್ಯಾಮರಾ"</string>
     <string name="accessibility_phone_button" msgid="6738112589538563574">"ಫೋನ್"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ಎಚ್ಚರಿಕೆ"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"ಕೆಲಸದ ಮೋಡ್"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ನೈಟ್ ಲೈಟ್"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"ನೈಟ್ ಲೈಟ್ ಆನ್ ಆಗಿದೆ, ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"ನೈಟ್ ಲೈಟ್ ಆಫ್ ಆಗಿದೆ, ಆನ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ಯಾವುದೇ ಇತ್ತೀಚಿನ ಐಟಂಗಳಿಲ್ಲ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ನೀವು ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿರುವಿರಿ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ಬ್ರೌಸರ್"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ಸಂಪರ್ಕಗಳು"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ಇಮೇಲ್"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ಸಂಗೀತ"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ಕ್ಯಾಲೆಂಡರ್"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index af40128..0a98831 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 경고"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"작업 모드"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"야간 조명"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"야간 조명 사용 설정됨, 사용 중지하려면 탭"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"야간 조명 사용 중지됨, 사용 설정하려면 탭"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"최근 항목이 없습니다."</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"모든 항목을 삭제했습니다."</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"애플리케이션 정보"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"브라우저"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"주소록"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"이메일"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"메신저"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"음악"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"캘린더"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 62775d1..47abacd 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -237,7 +237,7 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G дайындары тындырылды"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Уюлдук дайындар тындырылды"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Дайындар тындырылды"</string>
-    <string name="data_usage_disabled_dialog" msgid="1841738975235283398">"Сиз койгон дайындардын чегине жетти. Сиз мобилдик дайындарды колдонгон жоксуз.\n\nЭгер улантсаңыз, мобилдик дайындарды колдонгонуңуз үчүн акы алынышы мүмкүн."</string>
+    <string name="data_usage_disabled_dialog" msgid="1841738975235283398">"Трафик сиз койгон чекке жетти. Эми мобилдик дайындарды колдоно албайсыз.\n\nЭгер улантсаңыз, мобилдик дайындарды колдонгонуңуз үчүн акы алынышы мүмкүн."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Улантуу"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Интернет байланыш жок"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi байланышта"</string>
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> эскертүү"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Иштөө режими"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Түнкү жарык"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Түнкү жарык күйүк, өчүрүү үчүн таптап коюңуз"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Түнкү жарык өчүк, күйгүзүү үчүн таптап коюңуз"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Акыркы колдонмолор жок"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Баарын тазаладыңыз"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Колдонмо жөнүндө маалымат"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Серепчи"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Байланыштар"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Электрондук почта"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Жылнаама"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 81ee168..7f2e2a0 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"ຄຳ​ເຕືອນ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"ໂໝດການເຮັດວຽກ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ແສງກາງຄືນ"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"ເປີດແສງກາງຄືນຢູ່, ແຕະເພື່ອປິດໄວ້"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"ປິດແສງກາງຄືນຢູ່, ແຕະເພື່ອເປີດໃຊ້"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ບໍ່ມີລາຍການຫຼ້າສຸດ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ທ່ານລຶບລ້າງທຸກຢ່າງແລ້ວ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"​ຂໍ້​ມູນ​ແອັບ​ພ​ລິ​ເຄ​ຊັນ"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ໂປຣແກຣມທ່ອງເວັບ"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ລາຍຊື່ຜູ້ຕິດຕໍ່"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ອີເມວ"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ດົນຕີ"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ປະຕິທິນ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index df1765a..6514008 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -323,8 +323,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> įspėjimas"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Darbo režimas"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nakties šviesa"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Nakties šviesa įjungta. Palieskite, kad išjungtumėte"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Nakties šviesa išjungta. Palieskite, kad įjungtumėte"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nėra jokių naujausių elementų"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Viską išvalėte"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Programos informacija"</string>
@@ -568,7 +566,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Naršyklė"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktai"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"El. paštas"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"TP"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzika"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendorius"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index ffad77b..fb736a0 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> brīdinājums"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Darba režīms"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nakts režīms"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Nakts režīms ir ieslēgts. Pieskarieties, lai to izslēgtu."</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Nakts režīms ir izslēgts. Pieskarieties, lai to ieslēgtu."</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nav nesenu vienumu"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Visi uzdevumi ir notīrīti"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informācija par lietojumprogrammu"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Pārlūkprogramma"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktpersonas"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pasts"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Tūlītējā ziņojumapmaiņa"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Mūzika"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendārs"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 4aa1821..7b65a92 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупредување за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Режим на работа"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ноќно светло"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Ноќното светло е вклучено, допрете за да се исклучи"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Ноќното светло е исклучено, допрете за да се вклучи"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Нема неодамнешни ставки"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Исчистивте сѐ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информации за апликацијата"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Прелистувач"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Е-пошта"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 225a284..b4d085e 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> മുന്നറിയിപ്പ്"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"പ്രവർത്തന മോഡ്"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"നൈറ്റ് ലൈറ്റ്"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"നൈറ്റ് ലൈറ്റ് ഓണാണ്, ഓഫാക്കുന്നതിന് ടാപ്പുചെയ്യുക"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"നൈറ്റ് ലൈറ്റ് ഓഫാണ്, ഓണാക്കുന്നതിന് ടാപ്പുചെയ്യുക"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"സമീപകാല ഇനങ്ങൾ ഒന്നുമില്ല"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"നിങ്ങൾ എല്ലാം മായ്ച്ചിരിക്കുന്നു"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ആപ്പ് വിവരം"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ബ്രൗസർ"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"കോൺടാക്റ്റുകൾ"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ഇമെയിൽ"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"സംഗീതം"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"കലണ്ടർ"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index a84aae6..8f762fb 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -317,8 +317,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> анхааруулга"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Ажлын горим"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Шөнийн гэрэл"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Шөнийн гэрэл асаалттай байна. Унтраахын тулд товшино уу"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Шөнийн гэрэл унтраалттай байна. Асаахын тулд товшино уу"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Сүүлийн үеийн зүйл байхгүй"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Та бүгдийг нь устгасан"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Аппликешны мэдээлэл"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Хөтөч"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Харилцагчид"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Имэйл"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Хөгжим"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Хуанли"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 6c92213..b4d8b1a 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावणी"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"कार्य मोड"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"रात्रीचा प्रकाश"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"रात्रीचा प्रकाश चालू आहे, बंद करण्यासाठी टॅप करा"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"रात्रीचा प्रकाश बंद आहे, चालू करण्यासाठी टॅप करा"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"अलीकडील कोणतेही आयटम नाहीत"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"आपण सर्वकाही साफ केले"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"अनुप्रयोग माहिती"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउझर"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"संपर्क"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ईमेल"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"संगीत"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"कॅलेंडर"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 95e7a4d..ca54993 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Amaran <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Mod kerja"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Cahaya Malam"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Cahaya Malam dihidupkan, ketik untuk mematikannya"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Cahaya Malam dimatikan, ketik untuk menghidupkannya"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Tiada item terbaharu"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Anda telah mengetepikan semua item"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Maklumat Aplikasi"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Penyemak imbas"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kenalan"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mel"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzik"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 905c865..7032677 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> သတိပေးချက်"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"အလုပ် မုဒ်"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ညအလင်းရောင်"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"ညအလင်းရောင်ကို ဖွင့်ထားသည်၊ ပိတ်ရန်တို့ပါ"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"ညအလင်းရောင်ကို ပိတ်ထားသည်၊ ဖွင့်ရန်တို့ပါ"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"မကြာမီကဖွင့်ထားသည်များ မရှိပါ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"သင်အားလုံးကို ရှင်းလင်းပြီးပါပြီ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"အပလီကေးရှင်းအင်ဖို"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ဘရောင်ဇာ"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"အဆက်အသွယ်များ"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"အီးမေးလ်"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"အမြန်စာတိုစနစ်"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 41d70e6..068c2ca 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advarsel for <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Arbeidsmodus"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nattlys"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Nattlys er på, trykk for å slå av"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Nattlys er av, trykk for å slå på"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Ingen nylige elementer"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Du har fjernet alt"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformasjon"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Nettleser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakter"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-post"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musikk"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index d0dfd66..d88f37f 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी दिँदै"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"कार्य मोड"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"रात्रिको प्रकाश"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"रात्रिको प्रकाश सक्रिय छ, निष्क्रिय पार्न ट्याप गर्नुहोस्"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"रात्रिको प्रकाश निष्क्रिय छ, सक्रिय गर्न ट्याप गर्नुहोस्"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"हालका कुनै पनि वस्तुहरू छैनन्"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"तपाईँले सबै कुरा खाली गर्नुभएको छ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"अनुप्रयोग जानकारी"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउजर"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"सम्पर्कहरू"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"इमेल"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"संगीत"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"पात्रो"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 6bcd642..d07de09 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Waarschuwing voor <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Werkmodus"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nachtverlichting"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Nachtverlichting is ingeschakeld. Tik om deze uit te schakelen."</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Nachtverlichting is uitgeschakeld. Tik om deze in te schakelen."</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Geen recente items"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Je hebt alles gewist"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"App-informatie"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacten"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muziek"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index d5b4a5d..32397f6 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ਚਿਤਾਵਨੀ"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"ਕੰਮ ਮੋਡ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ਰਾਤਰੀ ਲਾਈਟ"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"ਰਾਤਰੀ ਲਾਈਟ ਚਾਲੂ ਹੈ, ਬੰਦ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"ਰਾਤਰੀ ਲਾਈਟ ਬੰਦ ਹੈ, ਚਾਲੂ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ਕੋਈ ਹਾਲੀਆ ਆਈਟਮਾਂ ਨਹੀਂ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ਤੁਸੀਂ ਸਭ ਕੁਝ ਸਾਫ਼ ਕਰ ਦਿੱਤਾ ਹੈ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ਐਪਲੀਕੇਸ਼ਨ ਜਾਣਕਾਰੀ"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ਬ੍ਰਾਊਜ਼ਰ"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ਸੰਪਰਕ"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ਈਮੇਲ"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ਸੰਗੀਤ"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ਕੈਲੰਡਰ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 92df542..511872a 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -323,8 +323,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Ostrzeżenie: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Tryb pracy"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Podświetlenie nocne"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Podświetlenie nocne włączone – kliknij, by wyłączyć"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Podświetlenie nocne wyłączone – kliknij, by włączyć"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Brak ostatnich elementów"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Wszystko zostało wyczyszczone"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacje o aplikacji"</string>
@@ -568,7 +566,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Przeglądarka"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakty"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Komunikator"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzyka"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendarz"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 5fe2def..07b0d50 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabalho"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Modo noturno"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Modo noturno ativado. Toque para desativar"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Modo noturno desativado. Toque para ativar"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nenhum item recente"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Você limpou tudo"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações do app"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contatos"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Mensagens instantâneas"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index ff5f566..b9c96b6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabalho"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz noturna"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Luz noturna ativada; toque para desativar"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Luz noturna desativada; toque para ativar"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nenhum item recente"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Limpou tudo"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações da aplicação"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendário"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 5fe2def..07b0d50 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabalho"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Modo noturno"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Modo noturno ativado. Toque para desativar"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Modo noturno desativado. Toque para ativar"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nenhum item recente"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Você limpou tudo"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações do app"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contatos"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Mensagens instantâneas"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0f7a7db..316c7cf 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -323,12 +323,10 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertizare: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modul de lucru"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Lumină de noapte"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Lumina de noapte este activată; atingeți pentru a o dezactiva"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Lumina de noapte este dezactivată; atingeți pentru a o activa"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Niciun element recent"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Ați șters tot"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informații despre aplicație"</string>
-    <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixare pe ecran"</string>
+    <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixarea ecranului"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nu a putut porni."</string>
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplicația <xliff:g id="APP">%s</xliff:g> este dezactivată în modul sigur."</string>
@@ -568,7 +566,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Agendă"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzică"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 0e49132..7264b95 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -325,8 +325,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Рабочий режим"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ночной режим"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Ночной режим включен. Нажмите, чтобы отключить."</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Ночной режим отключен. Нажмите, чтобы включить."</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Недавних приложений нет"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Вы очистили всё"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Сведения о приложении"</string>
@@ -570,7 +568,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браузер"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакты"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Эл. почта"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Чат"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календарь"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index ff8031e..0dc2f9f 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> අවවාද කිරීම"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"වැඩ ප්‍රකාරය"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"රාත්‍රී ආලෝකය"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"රාත්‍රී ආලෝකය ක්‍රියාත්මකයි, ක්‍රියාවිරහිත කිරීමට තට්ටු කරන්න"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"රාත්‍රී ආලෝකය ක්‍රියාවිරහිතයි, ක්‍රියාත්මක කිරීමට තට්ටු කරන්න"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"මෑත අයිතම නැත"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ඔබ සියලු දේ හිස් කර ඇත"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"යෙදුම් තොරතුරු"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"බ්‍රවුසරය"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"සම්බන්ධතා"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ඊ-තැපෑල"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"සංගීතය"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"දින දර්ශනය"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f6e43dd..4cdb97e 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -325,8 +325,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozornenie pri <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Pracovný režim"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nočný režim"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Nočný režim je zapnutý (vypnete ho klepnutím)"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Nočný režim je vypnutý (zapnete ho klepnutím)"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Žiadne nedávne položky"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Vymazali ste všetko"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informácie o aplikácii"</string>
@@ -570,7 +568,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Prehliadač"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakty"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Okamžité správy"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Hudba"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendár"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 9f2f7c4..6df7acc 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -325,8 +325,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Opozorilo – <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Način za delo"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nočna svetloba"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Nočna svetloba je vklopljena. Dotaknite se, če jo želite izklopiti."</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Nočna svetloba je izklopljena. Dotaknite se, če jo želite vklopiti."</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Ni nedavnih elementov"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Vse te počistili"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Podatki o aplikaciji"</string>
@@ -570,7 +568,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brskalnik"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Stiki"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pošta"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Neposredno sporočanje"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Glasba"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Koledar"</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index b07f551..ba4cea0 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Paralajmërim për kufirin prej <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modaliteti i punës"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Drita e natës"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Drita e natës është joaktive, trokit për ta çaktivizuar"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Drita e natës është joaktive, trokit për ta aktivizuar"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nuk ka asnjë artikull të fundit"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"I ke pastruar të gjitha"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacioni i aplikacionit"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Shfletuesi"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktet"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Mail-i"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Mesazh i çastit"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzikë"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendari"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 35d7d52..4fdbb98 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Упозорење за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Режим рада"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ноћно светло"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Ноћно светло је укључено, додирните да бисте га искључили"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Ноћно светло је искључено, додирните да бисте га укључили"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Нема недавних ставки"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Обрисали сте све"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информације о апликацији"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Прегледач"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Имејл"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Размена тренутних порука"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 26b0d9f..7ccf197 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Varning <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Arbetsläge"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nattljus"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Nattljus har aktiverats. Tryck för att inaktivera"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Nattljus har inaktiverats. Tryck för att aktivera"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Listan med de senaste åtgärderna är tom"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Du har tömt listan"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformation"</string>
@@ -330,7 +328,7 @@
     <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> är inaktiverad i säkert läge."</string>
     <string name="recents_stack_action_button_label" msgid="6593727103310426253">"Rensa alla"</string>
     <string name="recents_incompatible_app_message" msgid="5075812958564082451">"Appen har inte stöd för delad skärm."</string>
-    <string name="recents_drag_hint_message" msgid="2649739267073203985">"Dra här om du vill dela upp skärmen"</string>
+    <string name="recents_drag_hint_message" msgid="2649739267073203985">"Dra hit för att dela upp skärmen"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dela horisontellt"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dela vertikalt"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dela anpassad"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Webbläsare"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakter"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-post"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Snabbmeddelanden"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 396731b..0951594 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Onyo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Hali ya kazi"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Mwanga wa Usiku"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Umewasha hali ya Mwanga wa Usiku, gonga ili uizime"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Umezima hali ya Mwanga wa Usiku, gonga ili uiwashe"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Hakuna vipengee vya hivi karibuni"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Umeondoa vipengee vyote"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Maelezo ya Programu"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Kivinjari"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Anwani"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Barua pepe"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Ujumbe wa papo kwa papo"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muziki"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalenda"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 465d70e..7df7ac5 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> எச்சரிக்கை"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"பணிப் பயன்முறை"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"இரவு ஒளி"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"இரவு ஒளி இயக்கப்பட்டுள்ளது. முடக்க, தட்டவும்"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"இரவு ஒளி முடக்கப்பட்டுள்ளது. இயக்க, தட்டவும்"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"சமீபத்திய பணிகள் இல்லை"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"எல்லாவற்றையும் அழித்துவிட்டீர்கள்"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"பயன்பாட்டு தகவல்"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"உலாவி"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"தொடர்புகள்"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"மின்னஞ்சல்"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"மியூசிக்"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"கேலெண்டர்"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 783664d..eff3a03 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> హెచ్చరిక"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"పని మోడ్"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"రాత్రి కాంతి"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"రాత్రి కాంతి ఆన్‌లో ఉంది, ఆఫ్ చేయడానికి నొక్కండి"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"రాత్రి కాంతి ఆఫ్‌లో ఉంది, ఆన్ చేయడానికి నొక్కండి"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ఇటీవలి అంశాలు ఏవీ లేవు"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"మీరు అన్నింటినీ తీసివేసారు"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"అనువర్తన సమాచారం"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"బ్రౌజర్"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"పరిచయాలు"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ఇమెయిల్"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"సంగీతం"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"క్యాలెండర్"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 1fbd6f4..440d02f 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -237,7 +237,7 @@
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"หยุดการใช้ข้อมูล 4G ชั่วคราวแล้ว"</string>
     <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"หยุดการใช้ข้อมูลมือถือชั่วคราวแล้ว"</string>
     <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"หยุดการใช้ข้อมูลชั่วคราวแล้ว"</string>
-    <string name="data_usage_disabled_dialog" msgid="1841738975235283398">"คุณใช้อินเทอร์เน็ตเกินปริมาณที่กำหนดไว้แล้ว คุณจะไม่สามารถใช้ข้อมูลเครือข่ายมือถืออีก\n\nหากใช้ต่อ อาจมีค่าบริการสำหรับปริมาณการใช้อินเทอร์เน็ต"</string>
+    <string name="data_usage_disabled_dialog" msgid="1841738975235283398">"คุณใช้อินเทอร์เน็ตเกินปริมาณที่กำหนดไว้ ระบบจะไม่ใช้เครือข่ายมือถือต่อไป\n\nหากใช้ต่อ อาจมีค่าบริการตามปริมาณการใช้อินเทอร์เน็ต"</string>
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"ทำต่อ"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ไม่มีอินเทอร์เน็ต"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"เชื่อมต่อ WiFi แล้ว"</string>
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"คำเตือน <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"โหมดการทำงาน"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"แสงตอนกลางคืน"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"แสงตอนกลางคืนเปิดอยู่ แตะเพื่อปิด"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"แสงตอนกลางคืนปิดอยู่ แตะเพื่อเปิด"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ไม่มีรายการล่าสุด"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"คุณได้ล้างทุกอย่างแล้ว"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ข้อมูลแอปพลิเคชัน"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"เบราว์เซอร์"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"รายชื่อติดต่อ"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"อีเมล"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"เพลง"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ปฏิทิน"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index acaf86c..30dc7f5 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Babala sa <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work mode"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Night Light"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Naka-on ang Night Light, i-tap upang i-off"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Naka-off ang Night Light, i-tap upang i-on"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Walang mga kamakailang item"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Na-clear mo ang lahat"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Impormasyon ng Application"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Mga Contact"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendaryo"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index b4dc25d..740fdc6 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> uyarısı"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Çalışma modu"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Gece Işığı"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Geçe Işığı açık, kapatmak için dokunun"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Gece Işığı kapalı, açmak için dokunun"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Yeni öğe yok"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Her şeyi sildiniz"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Uygulama Bilgileri"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Tarayıcı"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kişiler"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-posta"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Müzik"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Takvim"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 4d2b6c39..eae7400 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -325,8 +325,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Застереження: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Робочий режим"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Нічний режим"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Нічний режим увімкнено. Торкніться, щоб вимкнути його"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Нічний режим вимкнено. Торкніться, щоб увімкнути його"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Немає нещодавніх завдань"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Ви очистили все"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Інформація про додаток"</string>
@@ -570,7 +568,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Веб-переглядач"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Електронна пошта"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Чат"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index cbe3d23..b8781f5 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> وارننگ"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"کام موڈ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"نائٹ لائٹ"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"نائٹ لائٹ آن ہے، آف کرنے کیلئے تھپتھپائیں"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"نائٹ لائٹ آف ہے، آن کرنے کیلئے تھپتھپائیں"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"کوئی حالیہ آئٹم نہیں"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"آپ نے سب کچھ صاف کر دیا ہے"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ایپلیکیشن کی معلومات"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"براؤزر"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"رابطے"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ای میل"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"موسیقی"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"کیلنڈر"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 3f1bb9b..e022165 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Ogohlantirish: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Ish rejimi"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Tungi rejim"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Tunji rejim yoniq, o‘chirish uchun bosing"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Tunji rejim o‘chiq, yoqish uchun bosing"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Hozircha hech narsa yo‘q"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Hammasi o‘chirildi"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Ilova haqida ma’lumot"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brauzer"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktlar"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pochta"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiqa"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Taqvim"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index ceeaf18..04e1f89 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Cảnh báo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Chế độ làm việc"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Đèn đọc sách"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Đèn đọc sách được bật, nhấn để tắt"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Đèn đọc sách bị tắt, nhấn để bật"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Không có mục gần đây nào"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Bạn đã xóa mọi nội dung"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Thông tin ứng dụng"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Trình duyệt"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Danh bạ"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Nhắn tin nhanh"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Âm nhạc"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Lịch"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 1217318..1982b57 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g>警告"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"工作模式"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"夜间模式"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"夜间模式已开启,点按即可关闭"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"夜间模式已关闭,点按即可开启"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"近期没有任何内容"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"您已清除所有内容"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"应用信息"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"浏览器"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"通讯录"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"电子邮件"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"即时通讯"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音乐"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"日历"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index bb51ebe..31a92ee 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -321,8 +321,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 警告"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"工作模式"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"夜燈模式"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"夜燈模式已開啟,輕按即可關閉"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"夜燈模式已關閉,輕按即可開啟"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"沒有最近項目"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"您已清除所有項目"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資料"</string>
@@ -566,7 +564,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"瀏覽器"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"通訊錄"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"電郵"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"即時通訊"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音樂"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"日曆"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index ac6b002..6aec964 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 警告"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"工作模式"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"夜燈"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"夜燈功能已開啟,輕觸即可關閉"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"夜燈功能已關閉,輕觸即可開啟"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"最近沒有任何項目"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"您已清除所有工作"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資訊"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"瀏覽器"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"聯絡人"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"電子郵件"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"即時訊息"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音樂"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"日曆"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 78e22f1..d85fcbf 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -319,8 +319,6 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> isexwayiso"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Imodi yomsebenzi"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ukukhanya kwasebusuku"</string>
-    <string name="quick_settings_night_display_summary_on" msgid="1814901757887526769">"Ukukhanya kwasebusuku kuvuliwe, thepha ukuze uvale"</string>
-    <string name="quick_settings_night_display_summary_off" msgid="7892102914128777905">"Ukukhanya kwasebusuku kuvaliwe, thepha ukuze uvule"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Azikho izinto zakamuva"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Usule yonke into"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Ulwazi lohlelo lokusebenza"</string>
@@ -564,7 +562,8 @@
     <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Isiphequluli"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Oxhumana nabo"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"I-imeyili"</string>
-    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"I-IM"</string>
+    <!-- no translation found for keyboard_shortcut_group_applications_sms (638701213803242744) -->
+    <skip />
     <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Umculo"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"I-YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Ikhalenda"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index eb1a1eb..9eea375 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -209,9 +209,6 @@
     <!-- Doze: should the significant motion sensor be used as a pulse signal? -->
     <bool name="doze_pulse_on_significant_motion">false</bool>
 
-    <!-- Doze: should the pickup sensor be used as a pulse signal? -->
-    <bool name="doze_pulse_on_pick_up">false</bool>
-
     <!-- Doze: check proximity sensor before pulsing? -->
     <bool name="doze_proximity_check_before_pulse">true</bool>
 
@@ -240,9 +237,6 @@
     -->
     <string name="doze_pickup_subtype_performs_proximity_check"></string>
 
-    <!-- Type of the double tap sensor. Empty if double tap is not supported. -->
-    <string name="doze_double_tap_sensor_type" translatable="false"></string>
-
     <!-- Doze: pulse parameter - how long does it take to fade in? -->
     <integer name="doze_pulse_duration_in">900</integer>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3f485c3..92e10d2 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -755,10 +755,6 @@
     <string name="quick_settings_work_mode_label">Work mode</string>
     <!-- QuickSettings: Label for the toggle to activate Night display (renamed "Night Light" with title caps). [CHAR LIMIT=20] -->
     <string name="quick_settings_night_display_label">Night Light</string>
-    <!-- QuickSettings: Summary for the toggle to deactivate Night display when it's on (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
-    <string name="quick_settings_night_display_summary_on">Night Light on, tap to turn off</string>
-    <!-- QuickSettings: Label for the toggle to activate Night display when it's off (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
-    <string name="quick_settings_night_display_summary_off">Night Light off, tap to turn on</string>
 
     <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
     <string name="recents_empty_message">No recent items</string>
@@ -1438,8 +1434,8 @@
     <string name="keyboard_shortcut_group_applications_contacts">Contacts</string>
     <!-- User visible title for the keyboard shortcut that takes the user to the email app. -->
     <string name="keyboard_shortcut_group_applications_email">Email</string>
-    <!-- User visible title for the keyboard shortcut that takes the user to the instant messaging app. -->
-    <string name="keyboard_shortcut_group_applications_im">IM</string>
+    <!-- User visible title for the keyboard shortcut that takes the user to the SMS messaging app. -->
+    <string name="keyboard_shortcut_group_applications_sms">SMS</string>
     <!-- User visible title for the keyboard shortcut that takes the user to the music app. -->
     <string name="keyboard_shortcut_group_applications_music">Music</string>
     <!-- User visible title for the keyboard shortcut that takes the user to the YouTube app. -->
diff --git a/packages/SystemUI/src/com/android/systemui/BootReceiver.java b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
deleted file mode 100644
index 8e24eeb..0000000
--- a/packages/SystemUI/src/com/android/systemui/BootReceiver.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2011 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;
-
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.provider.Settings;
-import android.util.Log;
-
-/**
- * Performs a number of miscellaneous, non-system-critical actions
- * after the system has finished booting.
- */
-public class BootReceiver extends BroadcastReceiver {
-    private static final String TAG = "SystemUIBootReceiver";
-
-    @Override
-    public void onReceive(final Context context, Intent intent) {
-        try {
-            // Start the load average overlay, if activated
-            ContentResolver res = context.getContentResolver();
-            if (Settings.Global.getInt(res, Settings.Global.SHOW_PROCESSES, 0) != 0) {
-                Intent loadavg = new Intent(context, com.android.systemui.LoadAverageService.class);
-                context.startService(loadavg);
-            }
-        } catch (Exception e) {
-            Log.e(TAG, "Can't start load average service", e);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index f76a68c..a4d78c5 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -173,11 +173,7 @@
                 if (DEBUG) {
                     Log.d(TAG, "trimMemory");
                 }
-                mBackground.recycle();
-                mBackground = null;
-                mBackgroundWidth = -1;
-                mBackgroundHeight = -1;
-                mWallpaperManager.forgetLoadedWallpaper();
+                unloadWallpaper(true /* forgetSize */);
             }
         }
 
@@ -199,7 +195,7 @@
         public void onDestroy() {
             super.onDestroy();
             mBackground = null;
-            mWallpaperManager.forgetLoadedWallpaper();
+            unloadWallpaper(true /* forgetSize */);
         }
 
         boolean updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo,
@@ -209,8 +205,7 @@
             // Load background image dimensions, if we haven't saved them yet
             if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
                 // Need to load the image to get dimensions
-                mWallpaperManager.forgetLoadedWallpaper();
-                loadWallpaper(forDraw);
+                loadWallpaper(forDraw, true /* needsReset */);
                 if (DEBUG) {
                     Log.d(TAG, "Reloading, redoing updateSurfaceSize later.");
                 }
@@ -366,8 +361,7 @@
                                 ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " +
                                 dw + ", " + dh);
                     }
-                    mWallpaperManager.forgetLoadedWallpaper();
-                    loadWallpaper(true /* needDraw */);
+                    loadWallpaper(true /* needDraw */, true /* needReset */);
                     if (DEBUG) {
                         Log.d(TAG, "Reloading, resuming draw later");
                     }
@@ -426,8 +420,7 @@
                     // position it appropriately.  As such, we no longer needed
                     // the loaded bitmap.  Yay!
                     // hw-accelerated renderer retains bitmap for faster rotation
-                    mBackground = null;
-                    mWallpaperManager.forgetLoadedWallpaper();
+                    unloadWallpaper(false /* forgetSize */);
                 }
             }
         }
@@ -438,25 +431,39 @@
          *
          * If loading is already in-flight, subsequent loads are ignored (but needDraw is or-ed to
          * the active request).
+         *
+         * If {@param needsReset} is set also clears the cache in WallpaperManager first.
          */
-        private void loadWallpaper(boolean needsDraw) {
+        private void loadWallpaper(boolean needsDraw, boolean needsReset) {
             mNeedsDrawAfterLoadingWallpaper |= needsDraw;
             if (mLoader != null) {
-                if (DEBUG) {
-                    Log.d(TAG, "Skipping loadWallpaper, already in flight ");
+                if (needsReset) {
+                    mLoader.cancel(false /* interrupt */);
+                    mLoader = null;
+                } else {
+                    if (DEBUG) {
+                        Log.d(TAG, "Skipping loadWallpaper, already in flight ");
+                    }
+                    return;
                 }
-                return;
             }
             mLoader = new AsyncTask<Void, Void, Bitmap>() {
                 @Override
                 protected Bitmap doInBackground(Void... params) {
                     Throwable exception;
                     try {
+                        if (needsReset) {
+                            mWallpaperManager.forgetLoadedWallpaper();
+                        }
                         return mWallpaperManager.getBitmap();
                     } catch (RuntimeException | OutOfMemoryError e) {
                         exception = e;
                     }
 
+                    if (isCancelled()) {
+                        return null;
+                    }
+
                     if (exception != null) {
                         // Note that if we do fail at this, and the default wallpaper can't
                         // be loaded, we will go into a cycle.  Don't do a build where the
@@ -469,6 +476,10 @@
                             Log.w(TAG, "Unable reset to default wallpaper!", ex);
                         }
 
+                        if (isCancelled()) {
+                            return null;
+                        }
+
                         try {
                             return mWallpaperManager.getBitmap();
                         } catch (RuntimeException | OutOfMemoryError e) {
@@ -505,6 +516,26 @@
             }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
         }
 
+        private void unloadWallpaper(boolean forgetSize) {
+            if (mLoader != null) {
+                mLoader.cancel(false);
+                mLoader = null;
+            }
+            mBackground = null;
+            if (forgetSize) {
+                mBackgroundWidth = -1;
+                mBackgroundHeight = -1;
+            }
+
+            mLoader = new AsyncTask<Void, Void, Bitmap>() {
+                @Override
+                protected Bitmap doInBackground(Void... params) {
+                    mWallpaperManager.forgetLoadedWallpaper();
+                    return null;
+                }
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        }
+
         @Override
         protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
             super.dump(prefix, fd, out, args);
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
new file mode 100644
index 0000000..c14b17f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -0,0 +1,81 @@
+/*
+ * 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;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Build;
+import android.os.PowerManager;
+import android.os.SystemClock;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.LatencyTracker;
+import com.android.systemui.statusbar.phone.FingerprintUnlockController;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+
+/**
+ * Class that only runs on debuggable builds that listens to broadcasts that simulate actions in the
+ * system that are used for testing the latency.
+ */
+public class LatencyTester extends SystemUI {
+
+    private static final String ACTION_FINGERPRINT_WAKE =
+            "com.android.systemui.latency.ACTION_FINGERPRINT_WAKE";
+    private static final String ACTION_TURN_ON_SCREEN =
+            "com.android.systemui.latency.ACTION_TURN_ON_SCREEN";
+
+    @Override
+    public void start() {
+        if (!Build.IS_DEBUGGABLE) {
+            return;
+        }
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_FINGERPRINT_WAKE);
+        filter.addAction(ACTION_TURN_ON_SCREEN);
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (ACTION_FINGERPRINT_WAKE.equals(action)) {
+                    fakeWakeAndUnlock();
+                } else if (ACTION_TURN_ON_SCREEN.equals(action)) {
+                    fakeTurnOnScreen();
+                }
+            }
+        }, filter);
+    }
+
+    private void fakeTurnOnScreen() {
+        PowerManager powerManager = mContext.getSystemService(PowerManager.class);
+        if (LatencyTracker.isEnabled(mContext)) {
+            LatencyTracker.getInstance(mContext).onActionStart(
+                    LatencyTracker.ACTION_TURN_ON_SCREEN);
+        }
+        powerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:LATENCY_TESTS");
+    }
+
+    private void fakeWakeAndUnlock() {
+        FingerprintUnlockController fingerprintUnlockController = getComponent(PhoneStatusBar.class)
+                .getFingerprintUnlockController();
+        fingerprintUnlockController.onFingerprintAcquired();
+        fingerprintUnlockController.onFingerprintAuthenticated(
+                KeyguardUpdateMonitor.getCurrentUser());
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/LoadAverageService.java b/packages/SystemUI/src/com/android/systemui/LoadAverageService.java
deleted file mode 100644
index 59ffe03..0000000
--- a/packages/SystemUI/src/com/android/systemui/LoadAverageService.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (C) 2007 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;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.view.Gravity;
-import android.view.View;
-import android.view.WindowManager;
-
-import com.android.internal.os.ProcessCpuTracker;
-
-public class LoadAverageService extends Service {
-    private View mView;
-
-    private static final class CpuTracker extends ProcessCpuTracker {
-        String mLoadText;
-        int mLoadWidth;
-
-        private final Paint mPaint;
-
-        CpuTracker(Paint paint) {
-            super(false);
-            mPaint = paint;
-        }
-
-        @Override
-        public void onLoadChanged(float load1, float load5, float load15) {
-            mLoadText = load1 + " / " + load5 + " / " + load15;
-            mLoadWidth = (int)mPaint.measureText(mLoadText);
-        }
-
-        @Override
-        public int onMeasureProcessName(String name) {
-            return (int)mPaint.measureText(name);
-        }
-    }
-
-    private class LoadView extends View {
-        private Handler mHandler = new Handler() {
-            @Override
-            public void handleMessage(Message msg) {
-                if (msg.what == 1) {
-                    mStats.update();
-                    updateDisplay();
-                    Message m = obtainMessage(1);
-                    sendMessageDelayed(m, 2000);
-                }
-            }
-        };
-
-        private final CpuTracker mStats;
-
-        private Paint mLoadPaint;
-        private Paint mAddedPaint;
-        private Paint mRemovedPaint;
-        private Paint mShadowPaint;
-        private Paint mShadow2Paint;
-        private Paint mIrqPaint;
-        private Paint mSystemPaint;
-        private Paint mUserPaint;
-        private float mAscent;
-        private int mFH;
-
-        private int mNeededWidth;
-        private int mNeededHeight;
-
-        LoadView(Context c) {
-            super(c);
-
-            setPadding(4, 4, 4, 4);
-            //setBackgroundResource(com.android.internal.R.drawable.load_average_background);
-
-            // Need to scale text size by density...  but we won't do it
-            // linearly, because with higher dps it is nice to squeeze the
-            // text a bit to fit more of it.  And with lower dps, trying to
-            // go much smaller will result in unreadable text.
-            int textSize = 10;
-            float density = c.getResources().getDisplayMetrics().density;
-            if (density < 1) {
-                textSize = 9;
-            } else {
-                textSize = (int)(10*density);
-                if (textSize < 10) {
-                    textSize = 10;
-                }
-            }
-            mLoadPaint = new Paint();
-            mLoadPaint.setAntiAlias(true);
-            mLoadPaint.setTextSize(textSize);
-            mLoadPaint.setARGB(255, 255, 255, 255);
-
-            mAddedPaint = new Paint();
-            mAddedPaint.setAntiAlias(true);
-            mAddedPaint.setTextSize(textSize);
-            mAddedPaint.setARGB(255, 128, 255, 128);
-
-            mRemovedPaint = new Paint();
-            mRemovedPaint.setAntiAlias(true);
-            mRemovedPaint.setStrikeThruText(true);
-            mRemovedPaint.setTextSize(textSize);
-            mRemovedPaint.setARGB(255, 255, 128, 128);
-
-            mShadowPaint = new Paint();
-            mShadowPaint.setAntiAlias(true);
-            mShadowPaint.setTextSize(textSize);
-            //mShadowPaint.setFakeBoldText(true);
-            mShadowPaint.setARGB(192, 0, 0, 0);
-            mLoadPaint.setShadowLayer(4, 0, 0, 0xff000000);
-
-            mShadow2Paint = new Paint();
-            mShadow2Paint.setAntiAlias(true);
-            mShadow2Paint.setTextSize(textSize);
-            //mShadow2Paint.setFakeBoldText(true);
-            mShadow2Paint.setARGB(192, 0, 0, 0);
-            mLoadPaint.setShadowLayer(2, 0, 0, 0xff000000);
-
-            mIrqPaint = new Paint();
-            mIrqPaint.setARGB(0x80, 0, 0, 0xff);
-            mIrqPaint.setShadowLayer(2, 0, 0, 0xff000000);
-            mSystemPaint = new Paint();
-            mSystemPaint.setARGB(0x80, 0xff, 0, 0);
-            mSystemPaint.setShadowLayer(2, 0, 0, 0xff000000);
-            mUserPaint = new Paint();
-            mUserPaint.setARGB(0x80, 0, 0xff, 0);
-            mSystemPaint.setShadowLayer(2, 0, 0, 0xff000000);
-
-            mAscent = mLoadPaint.ascent();
-            float descent = mLoadPaint.descent();
-            mFH = (int)(descent - mAscent + .5f);
-
-            mStats = new CpuTracker(mLoadPaint);
-            mStats.init();
-            updateDisplay();
-        }
-
-        @Override
-        protected void onAttachedToWindow() {
-            super.onAttachedToWindow();
-            mHandler.sendEmptyMessage(1);
-        }
-
-        @Override
-        protected void onDetachedFromWindow() {
-            super.onDetachedFromWindow();
-            mHandler.removeMessages(1);
-        }
-
-        @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            setMeasuredDimension(resolveSize(mNeededWidth, widthMeasureSpec),
-                    resolveSize(mNeededHeight, heightMeasureSpec));
-        }
-
-        @Override
-        public void onDraw(Canvas canvas) {
-            super.onDraw(canvas);
-            final int W = mNeededWidth;
-            final int RIGHT = getWidth()-1;
-
-            final CpuTracker stats = mStats;
-            final int userTime = stats.getLastUserTime();
-            final int systemTime = stats.getLastSystemTime();
-            final int iowaitTime = stats.getLastIoWaitTime();
-            final int irqTime = stats.getLastIrqTime();
-            final int softIrqTime = stats.getLastSoftIrqTime();
-            final int idleTime = stats.getLastIdleTime();
-
-            final int totalTime = userTime+systemTime+iowaitTime+irqTime+softIrqTime+idleTime;
-            if (totalTime == 0) {
-                return;
-            }
-            int userW = (userTime*W)/totalTime;
-            int systemW = (systemTime*W)/totalTime;
-            int irqW = ((iowaitTime+irqTime+softIrqTime)*W)/totalTime;
-
-            int paddingRight = getPaddingRight();
-            int x = RIGHT - paddingRight;
-            int top = getPaddingTop() + 2;
-            int bottom = getPaddingTop() + mFH - 2;
-
-            if (irqW > 0) {
-                canvas.drawRect(x-irqW, top, x, bottom, mIrqPaint);
-                x -= irqW;
-            }
-            if (systemW > 0) {
-                canvas.drawRect(x-systemW, top, x, bottom, mSystemPaint);
-                x -= systemW;
-            }
-            if (userW > 0) {
-                canvas.drawRect(x-userW, top, x, bottom, mUserPaint);
-                x -= userW;
-            }
-
-            int y = getPaddingTop() - (int)mAscent;
-            canvas.drawText(stats.mLoadText, RIGHT-paddingRight-stats.mLoadWidth-1,
-                    y-1, mShadowPaint);
-            canvas.drawText(stats.mLoadText, RIGHT-paddingRight-stats.mLoadWidth-1,
-                    y+1, mShadowPaint);
-            canvas.drawText(stats.mLoadText, RIGHT-paddingRight-stats.mLoadWidth+1,
-                    y-1, mShadow2Paint);
-            canvas.drawText(stats.mLoadText, RIGHT-paddingRight-stats.mLoadWidth+1,
-                    y+1, mShadow2Paint);
-            canvas.drawText(stats.mLoadText, RIGHT-paddingRight-stats.mLoadWidth,
-                    y, mLoadPaint);
-
-            int N = stats.countWorkingStats();
-            for (int i=0; i<N; i++) {
-                CpuTracker.Stats st = stats.getWorkingStats(i);
-                y += mFH;
-                top += mFH;
-                bottom += mFH;
-
-                userW = (st.rel_utime*W)/totalTime;
-                systemW = (st.rel_stime*W)/totalTime;
-                x = RIGHT - paddingRight;
-                if (systemW > 0) {
-                    canvas.drawRect(x-systemW, top, x, bottom, mSystemPaint);
-                    x -= systemW;
-                }
-                if (userW > 0) {
-                    canvas.drawRect(x-userW, top, x, bottom, mUserPaint);
-                    x -= userW;
-                }
-
-                canvas.drawText(st.name, RIGHT-paddingRight-st.nameWidth-1,
-                        y-1, mShadowPaint);
-                canvas.drawText(st.name, RIGHT-paddingRight-st.nameWidth-1,
-                        y+1, mShadowPaint);
-                canvas.drawText(st.name, RIGHT-paddingRight-st.nameWidth+1,
-                        y-1, mShadow2Paint);
-                canvas.drawText(st.name, RIGHT-paddingRight-st.nameWidth+1,
-                        y+1, mShadow2Paint);
-                Paint p = mLoadPaint;
-                if (st.added) p = mAddedPaint;
-                if (st.removed) p = mRemovedPaint;
-                canvas.drawText(st.name, RIGHT-paddingRight-st.nameWidth, y, p);
-            }
-        }
-
-        void updateDisplay() {
-            final CpuTracker stats = mStats;
-            final int NW = stats.countWorkingStats();
-
-            int maxWidth = stats.mLoadWidth;
-            for (int i=0; i<NW; i++) {
-                CpuTracker.Stats st = stats.getWorkingStats(i);
-                if (st.nameWidth > maxWidth) {
-                    maxWidth = st.nameWidth;
-                }
-            }
-
-            int neededWidth = getPaddingLeft() + getPaddingRight() + maxWidth;
-            int neededHeight = getPaddingTop() + getPaddingBottom() + (mFH*(1+NW));
-            if (neededWidth != mNeededWidth || neededHeight != mNeededHeight) {
-                mNeededWidth = neededWidth;
-                mNeededHeight = neededHeight;
-                requestLayout();
-            } else {
-                invalidate();
-            }
-        }
-    }
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mView = new LoadView(this);
-        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
-            WindowManager.LayoutParams.MATCH_PARENT,
-            WindowManager.LayoutParams.WRAP_CONTENT,
-            WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
-            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
-            WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
-            PixelFormat.TRANSLUCENT);
-        params.gravity = Gravity.END | Gravity.TOP;
-        params.setTitle("Load Average");
-        WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);
-        wm.addView(mView, params);
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        ((WindowManager)getSystemService(WINDOW_SERVICE)).removeView(mView);
-        mView = null;
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return null;
-    }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index e300aff..bfc8642 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -29,11 +29,22 @@
 import android.os.UserHandle;
 import android.util.Log;
 
+import com.android.systemui.keyboard.KeyboardUI;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.media.RingtonePlayer;
 import com.android.systemui.plugins.OverlayPlugin;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.power.PowerUI;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.shortcut.ShortcutKeyDispatcher;
 import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.SystemBars;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tv.pip.PipUI;
+import com.android.systemui.usb.StorageNotification;
+import com.android.systemui.volume.VolumeUI;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -50,19 +61,20 @@
      * The classes of the stuff to start.
      */
     private final Class<?>[] SERVICES = new Class[] {
-            com.android.systemui.tuner.TunerService.class,
-            com.android.systemui.keyguard.KeyguardViewMediator.class,
-            com.android.systemui.recents.Recents.class,
-            com.android.systemui.volume.VolumeUI.class,
+            TunerService.class,
+            KeyguardViewMediator.class,
+            Recents.class,
+            VolumeUI.class,
             Divider.class,
-            com.android.systemui.statusbar.SystemBars.class,
-            com.android.systemui.usb.StorageNotification.class,
-            com.android.systemui.power.PowerUI.class,
-            com.android.systemui.media.RingtonePlayer.class,
-            com.android.systemui.keyboard.KeyboardUI.class,
-            com.android.systemui.tv.pip.PipUI.class,
-            com.android.systemui.shortcut.ShortcutKeyDispatcher.class,
-            com.android.systemui.VendorServices.class
+            SystemBars.class,
+            StorageNotification.class,
+            PowerUI.class,
+            RingtonePlayer.class,
+            KeyboardUI.class,
+            PipUI.class,
+            ShortcutKeyDispatcher.class,
+            VendorServices.class,
+            LatencyTester.class
     };
 
     /**
@@ -70,8 +82,8 @@
      * above.
      */
     private final Class<?>[] SERVICES_PER_USER = new Class[] {
-            com.android.systemui.recents.Recents.class,
-            com.android.systemui.tv.pip.PipUI.class
+            Recents.class,
+            PipUI.class
     };
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 261d241..6c35243 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -43,6 +43,7 @@
 import android.util.Log;
 import android.view.Display;
 
+import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.SystemUIApplication;
@@ -60,6 +61,11 @@
     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);
@@ -80,6 +86,8 @@
     private boolean mCarMode;
     private long mNotificationPulseTime;
 
+    private AmbientDisplayConfiguration mConfig;
+
     public DozeService() {
         if (DEBUG) Log.d(mTag, "new DozeService()");
         setDebug(DEBUG);
@@ -120,6 +128,7 @@
         setWindowless(true);
 
         mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+        mConfig = new AmbientDisplayConfiguration(mContext);
         mSensors = new TriggerSensor[] {
                 new TriggerSensor(
                         mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
@@ -130,12 +139,12 @@
                 mPickupSensor = new TriggerSensor(
                         mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
                         Settings.Secure.DOZE_PULSE_ON_PICK_UP,
-                        mDozeParameters.getPulseOnPickup(), mDozeParameters.getVibrateOnPickup(),
+                        mConfig.pulseOnPickupAvailable(), mDozeParameters.getVibrateOnPickup(),
                         DozeLog.PULSE_REASON_SENSOR_PICKUP),
                 new TriggerSensor(
-                        findSensorWithType(mDozeParameters.getDoubleTapSensorType()),
-                        Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
-                        mDozeParameters.getPulseOnPickup(), mDozeParameters.getVibrateOnPickup(),
+                        findSensorWithType(mConfig.doubleTapSensorType()),
+                        Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, true,
+                        mDozeParameters.getVibrateOnPickup(),
                         DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP)
         };
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -272,6 +281,9 @@
             public void onPulseFinished() {
                 if (mPulsing && mDreaming) {
                     mPulsing = false;
+                    if (REREGISTER_ALL_SENSORS_ON_SCREEN_OFF) {
+                        reregisterAllSensors();
+                    }
                     turnDisplayOff();
                 }
                 mWakeLock.release(); // needs to be unconditional to balance acquire
@@ -308,6 +320,15 @@
         listenForNotifications(listen);
     }
 
+    private void reregisterAllSensors() {
+        for (TriggerSensor s : mSensors) {
+            s.setListening(false);
+        }
+        for (TriggerSensor s : mSensors) {
+            s.setListening(true);
+        }
+    }
+
     private void listenForBroadcasts(boolean listen) {
         if (listen) {
             final IntentFilter filter = new IntentFilter(PULSE_ACTION);
@@ -342,7 +363,7 @@
 
     private void requestNotificationPulse() {
         if (DEBUG) Log.d(mTag, "requestNotificationPulse");
-        if (!mDozeParameters.getPulseOnNotifications()) return;
+        if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) return;
         mNotificationPulseTime = SystemClock.elapsedRealtime();
         requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index b9e8acb..24247e4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -73,6 +73,7 @@
 import com.android.keyguard.KeyguardSecurityView;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.LatencyTracker;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIFactory;
@@ -1894,6 +1895,9 @@
 
     private void handleNotifyScreenTurnedOn() {
         Trace.beginSection("KeyguardViewMediator#handleNotifyScreenTurnedOn");
+        if (LatencyTracker.isEnabled(mContext)) {
+            LatencyTracker.getInstance(mContext).onActionEnd(LatencyTracker.ACTION_TURN_ON_SCREEN);
+        }
         synchronized (this) {
             if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOn");
             mStatusBarKeyguardViewManager.onScreenTurnedOn();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 2173922..f345172 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -334,4 +334,10 @@
     public int getQsMinExpansionHeight() {
         return mHeader.getHeight();
     }
+
+    @Override
+    public void hideImmediately() {
+        animate().cancel();
+        setY(-mHeader.getHeight());
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 40ef6eb..0cd6490 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -64,7 +64,10 @@
         for (int i = 0; i < possibleTiles.length; i++) {
             final String spec = possibleTiles[i];
             final QSTile<?> tile = host.createTile(spec);
-            if (tile == null || !tile.isAvailable()) {
+            if (tile == null) {
+                continue;
+            } else if (!tile.isAvailable()) {
+                tile.destroy();
                 continue;
             }
             tile.setListening(this, true);
@@ -78,6 +81,7 @@
                     tile.getState().copyTo(state);
                     // Ignore the current state and get the generic label instead.
                     state.label = tile.getTileLabel();
+                    tile.destroy();
                     mainHandler.post(new Runnable() {
                         @Override
                         public void run() {
@@ -126,6 +130,7 @@
         state.label = label;
         state.contentDescription = label;
         state.icon = new DrawableIcon(drawable);
+        state.autoMirrorDrawable = false;
         addTile(spec, appLabel, state, false);
     }
 
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 b36221d..484e008 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -221,7 +221,9 @@
 
     @Override
     public State newTileState() {
-        return new State();
+        State state = new State();
+        state.autoMirrorDrawable = false;
+        return state;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 89bb1d2..ec4ab51 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -69,12 +69,23 @@
 
     private boolean mListening;
     private boolean mShowingDetail;
+    private boolean mReceiverRegistered;
 
     public DndTile(Host host) {
         super(host);
         mController = host.getZenModeController();
         mDetailAdapter = new DndDetailAdapter();
         mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
+        mReceiverRegistered = true;
+    }
+
+    @Override
+    protected void handleDestroy() {
+        super.handleDestroy();
+        if (mReceiverRegistered) {
+            mContext.unregisterReceiver(mReceiver);
+            mReceiverRegistered = false;
+        }
     }
 
     public static void setVisible(Context context, boolean visible) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index 9415b27..c02e5ae 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -75,14 +75,12 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         final boolean isActivated = mController.isActivated();
         state.value = isActivated;
-        state.label = mContext.getString(R.string.quick_settings_night_display_label);
+        state.label = state.contentDescription =
+                mContext.getString(R.string.quick_settings_night_display_label);
         state.icon = ResourceIcon.get(isActivated ? R.drawable.ic_qs_night_display_on
                 : R.drawable.ic_qs_night_display_off);
-        state.contentDescription = mContext.getString(isActivated
-                ? R.string.quick_settings_night_display_summary_on
-                : R.string.quick_settings_night_display_summary_off);
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName =
+                Switch.class.getName();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 7207463..3c245b4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -18,12 +18,10 @@
 
 import android.app.ActivityManager;
 import android.app.UiModeManager;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
@@ -99,7 +97,7 @@
     // and does not reside in the home stack.
     private String mOverrideRecentsPackageName;
 
-    private Handler mHandler = new Handler();
+    private Handler mHandler;
     private RecentsImpl mImpl;
     private int mDraggingInRecentsCurrentUser;
 
@@ -165,20 +163,6 @@
         }
     };
 
-
-    private BroadcastReceiver mSystemUserUnlockedReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
-                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
-                if (userId != UserHandle.USER_NULL) {
-                    mImpl.onUserUnlocked(userId);
-                }
-            }
-        }
-    };
-
-
     /**
      * Returns the callbacks interface that non-system users can call.
      */
@@ -208,7 +192,7 @@
         sSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
         sTaskLoader = new RecentsTaskLoader(mContext);
         sConfiguration = new RecentsConfiguration(mContext);
-
+        mHandler = new Handler();
         UiModeManager uiModeManager = (UiModeManager) mContext.
                 getSystemService(Context.UI_MODE_SERVICE);
         if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
@@ -238,12 +222,6 @@
             // For the system user, initialize an instance of the interface that we can pass to the
             // secondary user
             mSystemToUserCallbacks = new RecentsSystemUser(mContext, mImpl);
-
-            // Listen for user-unlocked to kick off preloading recents
-            IntentFilter filter = new IntentFilter();
-            filter.addAction(Intent.ACTION_USER_UNLOCKED);
-            mContext.registerReceiverAsUser(mSystemUserUnlockedReceiver, UserHandle.SYSTEM, filter,
-                    null /* permission */, null /* scheduler */);
         } else {
             // For the secondary user, bind to the primary user's service to get a persistent
             // interface to register its implementation and to later update its state
@@ -501,6 +479,7 @@
                 return COUNTER_WINDOW_UNSUPPORTED;
             case ActivityInfo.RESIZE_MODE_RESIZEABLE:
             case ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE:
+            case ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION:
                 return COUNTER_WINDOW_SUPPORTED;
             default:
                 return COUNTER_WINDOW_INCOMPATIBLE;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index e5493b6..ec99d20 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -43,7 +43,7 @@
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.Interpolators;
-import com.android.systemui.LatencyTracker;
+import com.android.keyguard.LatencyTracker;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.recents.events.EventBus;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 390ef87..64ef997 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -188,7 +188,7 @@
         reloadResources();
     }
 
-    public void onUserUnlocked(int userId) {
+    public void onBootCompleted() {
         // When we start, preload the data associated with the previous recent tasks.
         // We can use a new plan since the caches will be the same.
         RecentsTaskLoader loader = Recents.getTaskLoader();
@@ -201,10 +201,6 @@
         loader.loadTasks(mContext, plan, launchOpts);
     }
 
-    public void onBootCompleted() {
-        // Do nothing
-    }
-
     public void onConfigurationChanged() {
         Resources res = mContext.getResources();
         reloadResources();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
index 9faaa4b..a673c8c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
@@ -47,12 +47,13 @@
     public void startEnterAnimation(boolean isPipShown) {
         for(int i = 0; i < mGridView.getChildCount(); i++) {
             TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
+            long delay = Math.max(mDelay * i, 0);
             view.setTranslationX(-mTranslationX);
             view.animate()
                     .alpha(isPipShown ? mDimAlpha : 1.0f)
                     .translationX(0)
                     .setDuration(mDuration)
-                    .setStartDelay(mDelay * i)
+                    .setStartDelay(delay)
                     .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
         }
     }
@@ -60,11 +61,12 @@
     public void startExitAnimation(DismissRecentsToHomeAnimationStarted dismissEvent) {
         for(int i = mGridView.getChildCount() - 1; i >= 0; i--) {
             TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
+            long delay = Math.max(mDelay * (mGridView.getChildCount() - 1 - i), 0);
             view.animate()
                     .alpha(0.0f)
                     .translationXBy(-mTranslationX)
                     .setDuration(mDuration)
-                    .setStartDelay(mDelay * (mGridView.getChildCount() - 1 - i))
+                    .setStartDelay(delay)
                     .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
             if(i == 0) {
                 view.animate().setListener(dismissEvent.getAnimationTrigger()
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index cb77d7b..4e34bbc 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -1113,6 +1113,7 @@
 
     public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) {
         if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP
+                && getSnapAlgorithm().getMiddleTarget() != getSnapAlgorithm().getLastSplitTarget()
                 && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) {
             mState.growAfterRecentsDrawn = true;
             startDragging(false /* animate */, false /* touching */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index a7132e5..4cc7a16 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -161,7 +161,7 @@
             "com.android.systemui.statusbar.banner_action_cancel";
     private static final String BANNER_ACTION_SETUP =
             "com.android.systemui.statusbar.banner_action_setup";
-    private static final String WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION
+    private static final String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION
             = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
 
     protected CommandQueue mCommandQueue;
@@ -217,14 +217,14 @@
     protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     // public mode, private notifications, etc
-    private boolean mLockscreenPublicMode = false;
+    private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
     private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
     private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
 
     private UserManager mUserManager;
     private int mDensity;
 
-    private KeyguardManager mKeyguardManager;
+    protected KeyguardManager mKeyguardManager;
     private LockPatternUtils mLockPatternUtils;
 
     // UI-specific methods
@@ -465,11 +465,11 @@
             row.setUserExpanded(true);
 
             if (!mAllowLockscreenRemoteInput) {
-                if (isLockscreenPublicMode()) {
+                final int userId = pendingIntent.getCreatorUserHandle().getIdentifier();
+                if (isLockscreenPublicMode(userId)) {
                     onLockedRemoteInput(row, view);
                     return true;
                 }
-                final int userId = pendingIntent.getCreatorUserHandle().getIdentifier();
                 if (mUserManager.getUserInfo(userId).isManagedProfile()
                         && mKeyguardManager.isDeviceLocked(userId)) {
                     onLockedWorkRemoteInput(userId, row, view);
@@ -560,7 +560,7 @@
 
                     );
                 }
-            } else if (WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION.equals(action)) {
+            } else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) {
                 final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
                 final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
                 if (intentSender != null) {
@@ -577,7 +577,6 @@
                         /* ignore */
                     }
                 }
-                onWorkChallengeUnlocked();
             }
         }
     };
@@ -585,12 +584,18 @@
     private final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
+            final String action = intent.getAction();
+            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+
             if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) &&
                     isCurrentProfile(getSendingUserId())) {
                 mUsersAllowingPrivateNotifications.clear();
                 updateLockscreenNotificationSetting();
                 updateNotifications();
+            } else if (Intent.ACTION_DEVICE_LOCKED_CHANGED.equals(action)) {
+                if (userId != mCurrentUserId && isCurrentProfile(userId)) {
+                    onWorkChallengeChanged();
+                }
             }
         }
     };
@@ -815,7 +820,7 @@
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
         IntentFilter internalFilter = new IntentFilter();
-        internalFilter.addAction(WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
+        internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
         internalFilter.addAction(BANNER_ACTION_CANCEL);
         internalFilter.addAction(BANNER_ACTION_SETUP);
         mContext.registerReceiver(mBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
@@ -823,6 +828,7 @@
         IntentFilter allUsersFilter = new IntentFilter();
         allUsersFilter.addAction(
                 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+        allUsersFilter.addAction(Intent.ACTION_DEVICE_LOCKED_CHANGED);
         mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL, allUsersFilter,
                 null, null);
         updateCurrentProfilesCache();
@@ -1126,9 +1132,10 @@
             @Override
             public void onClick(View v) {
                 // If the user has security enabled, show challenge if the setting is changed.
-                if (guts.hasImportanceChanged() && isLockscreenPublicMode() &&
-                        (mState == StatusBarState.KEYGUARD
-                        || mState == StatusBarState.SHADE_LOCKED)) {
+                if (guts.hasImportanceChanged()
+                            && isLockscreenPublicMode(sbn.getUser().getIdentifier())
+                            && (mState == StatusBarState.KEYGUARD
+                                    || mState == StatusBarState.SHADE_LOCKED)) {
                     OnDismissAction dismissAction = new OnDismissAction() {
                         @Override
                         public boolean onDismiss() {
@@ -1430,15 +1437,15 @@
     /**
      * Save the current "public" (locked and secure) state of the lockscreen.
      */
-    public void setLockscreenPublicMode(boolean publicMode) {
-        mLockscreenPublicMode = publicMode;
+    public void setLockscreenPublicMode(boolean publicMode, int userId) {
+        mLockscreenPublicMode.put(userId, publicMode);
     }
 
-    public boolean isLockscreenPublicMode() {
-        return mLockscreenPublicMode;
+    public boolean isLockscreenPublicMode(int userId) {
+        return mLockscreenPublicMode.get(userId, false);
     }
 
-    protected void onWorkChallengeUnlocked() {}
+    protected void onWorkChallengeChanged() {}
 
     /**
      * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
@@ -1496,8 +1503,9 @@
      * If so, notifications should be hidden.
      */
     @Override  // NotificationData.Environment
-    public boolean shouldHideNotifications(int userid) {
-        return isLockscreenPublicMode() && !userAllowsNotificationsInPublic(userid);
+    public boolean shouldHideNotifications(int userId) {
+        return isLockscreenPublicMode(mCurrentUserId) && !userAllowsNotificationsInPublic(userId)
+                || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId));
     }
 
     /**
@@ -1506,7 +1514,7 @@
      */
     @Override // NotificationDate.Environment
     public boolean shouldHideNotifications(String key) {
-        return isLockscreenPublicMode()
+        return isLockscreenPublicMode(mCurrentUserId)
                 && mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_SECRET;
     }
 
@@ -1514,8 +1522,8 @@
      * Returns true if we're on a secure lockscreen.
      */
     @Override  // NotificationData.Environment
-    public boolean onSecureLockScreen() {
-        return isLockscreenPublicMode();
+    public boolean isSecurelyLocked(int userId) {
+        return isLockscreenPublicMode(userId);
     }
 
     public void onNotificationClear(StatusBarNotification notification) {
@@ -1711,6 +1719,23 @@
                         sbn.getPackageContext(mContext),
                         contentContainerPublic, mOnClickHandler);
             }
+
+            if (contentViewLocal != null) {
+                contentViewLocal.setIsRootNamespace(true);
+                contentContainer.setContractedChild(contentViewLocal);
+            }
+            if (bigContentViewLocal != null) {
+                bigContentViewLocal.setIsRootNamespace(true);
+                contentContainer.setExpandedChild(bigContentViewLocal);
+            }
+            if (headsUpContentViewLocal != null) {
+                headsUpContentViewLocal.setIsRootNamespace(true);
+                contentContainer.setHeadsUpChild(headsUpContentViewLocal);
+            }
+            if (publicViewLocal != null) {
+                publicViewLocal.setIsRootNamespace(true);
+                contentContainerPublic.setContractedChild(publicViewLocal);
+            }
         }
         catch (RuntimeException e) {
             final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
@@ -1718,23 +1743,6 @@
             return false;
         }
 
-        if (contentViewLocal != null) {
-            contentViewLocal.setIsRootNamespace(true);
-            contentContainer.setContractedChild(contentViewLocal);
-        }
-        if (bigContentViewLocal != null) {
-            bigContentViewLocal.setIsRootNamespace(true);
-            contentContainer.setExpandedChild(bigContentViewLocal);
-        }
-        if (headsUpContentViewLocal != null) {
-            headsUpContentViewLocal.setIsRootNamespace(true);
-            contentContainer.setHeadsUpChild(headsUpContentViewLocal);
-        }
-        if (publicViewLocal != null) {
-            publicViewLocal.setIsRootNamespace(true);
-            contentContainerPublic.setContractedChild(publicViewLocal);
-        }
-
         // Extract target SDK version.
         try {
             ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
@@ -2076,8 +2084,7 @@
         if (newIntent == null) {
             return false;
         }
-        final Intent callBackIntent = new Intent(
-                WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
+        final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
         callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
         callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
         callBackIntent.setPackage(mContext.getPackageName());
@@ -2276,14 +2283,16 @@
                 entry.row.setOnKeyguard(false);
                 entry.row.setSystemExpanded(visibleNotifications == 0 && !childNotification);
             }
+            int userId = entry.notification.getUserId();
             boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
                     entry.notification) && !entry.row.isRemoved();
             boolean childWithVisibleSummary = childNotification
                     && mGroupManager.getGroupSummary(entry.notification).getVisibility()
                     == View.VISIBLE;
             boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
-            if (suppressedSummary || (isLockscreenPublicMode() && !mShowLockscreenNotifications) ||
-                    (onKeyguard && !childWithVisibleSummary
+            if (suppressedSummary
+                    || (isLockscreenPublicMode(userId) && !mShowLockscreenNotifications)
+                    || (onKeyguard && !childWithVisibleSummary
                             && (visibleNotifications >= maxNotifications || !showOnKeyguard))) {
                 entry.row.setVisibility(View.GONE);
                 if (onKeyguard && showOnKeyguard && !childNotification && !suppressedSummary) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index e781f1b..f438762 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -488,9 +488,9 @@
         final Icon messagingIcon = getIconForIntentCategory(Intent.CATEGORY_APP_MESSAGING, userId);
         if (messagingIcon != null) {
             keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
-                    mContext.getString(R.string.keyboard_shortcut_group_applications_im),
+                    mContext.getString(R.string.keyboard_shortcut_group_applications_sms),
                     messagingIcon,
-                    KeyEvent.KEYCODE_T,
+                    KeyEvent.KEYCODE_S,
                     KeyEvent.META_META_ON));
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index cf962df..0ef97152 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -95,8 +95,6 @@
         KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitor);
         context.registerReceiverAsUser(mTickReceiver, UserHandle.SYSTEM,
                 new IntentFilter(Intent.ACTION_TIME_TICK), null, null);
-        context.registerReceiverAsUser(mUnlockReceiver, UserHandle.ALL,
-                new IntentFilter(Intent.ACTION_USER_UNLOCKED), null, null);
     }
 
     public void setVisible(boolean visible) {
@@ -322,6 +320,13 @@
             super.onFingerprintAuthFailed();
             mLastSuccessiveErrorMessage = -1;
         }
+
+        @Override
+        public void onUserUnlocked() {
+            if (mVisible) {
+                updateIndication();
+            }
+        }
     };
 
     BroadcastReceiver mTickReceiver = new BroadcastReceiver() {
@@ -333,14 +338,6 @@
         }
     };
 
-    BroadcastReceiver mUnlockReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (mVisible) {
-                updateIndication();
-            }
-        }
-    };
 
     private final Handler mHandler = new Handler() {
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index b6e54af..bae16f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -380,7 +380,7 @@
             return true;
         }
 
-        if (mEnvironment.onSecureLockScreen() &&
+        if (mEnvironment.isSecurelyLocked(sbn.getUserId()) &&
                 (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
                         || mEnvironment.shouldHideNotifications(sbn.getUserId())
                         || mEnvironment.shouldHideNotifications(sbn.getKey()))) {
@@ -463,7 +463,7 @@
      * Provides access to keyguard state and user settings dependent data.
      */
     public interface Environment {
-        public boolean onSecureLockScreen();
+        public boolean isSecurelyLocked(int userId);
         public boolean shouldHideNotifications(int userid);
         public boolean shouldHideNotifications(String key);
         public boolean isDeviceProvisioned();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
index 59e4244..f46fc67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.widget.ImageView;
 import android.widget.RelativeLayout;
 
 import com.android.keyguard.AlphaOptimizedImageButton;
@@ -41,6 +42,7 @@
     public void onFinishInflate() {
         super.onFinishInflate();
         mIcon = (AlphaOptimizedImageButton) findViewById(R.id.car_nav_button_icon);
+        mIcon.setScaleType(ImageView.ScaleType.CENTER);
         mIcon.setClickable(false);
         mIcon.setBackgroundColor(android.R.color.transparent);
         mIcon.setAlpha(UNSELECTED_ALPHA);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index d5bf499..9e9bdd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -18,11 +18,13 @@
 
 import android.content.Context;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.SparseBooleanArray;
 
+import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.R;
 
 import java.io.PrintWriter;
@@ -31,9 +33,6 @@
 import java.util.regex.Pattern;
 
 public class DozeParameters {
-    private static final String TAG = "DozeParameters";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
     private static final int MAX_DURATION = 60 * 1000;
 
     private final Context mContext;
@@ -55,10 +54,8 @@
         pw.print("    getPulseOutDuration(): "); pw.println(getPulseOutDuration());
         pw.print("    getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion());
         pw.print("    getVibrateOnSigMotion(): "); pw.println(getVibrateOnSigMotion());
-        pw.print("    getPulseOnPickup(): "); pw.println(getPulseOnPickup());
         pw.print("    getVibrateOnPickup(): "); pw.println(getVibrateOnPickup());
         pw.print("    getProxCheckBeforePulse(): "); pw.println(getProxCheckBeforePulse());
-        pw.print("    getPulseOnNotifications(): "); pw.println(getPulseOnNotifications());
         pw.print("    getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
         pw.print("    getPickupSubtypePerformsProxCheck(): ");pw.println(
                 dumpPickupSubtypePerformsProxCheck());
@@ -106,26 +103,14 @@
         return SystemProperties.getBoolean("doze.vibrate.sigmotion", false);
     }
 
-    public boolean getPulseOnPickup() {
-        return getBoolean("doze.pulse.pickup", R.bool.doze_pulse_on_pick_up);
-    }
-
     public boolean getVibrateOnPickup() {
         return SystemProperties.getBoolean("doze.vibrate.pickup", false);
     }
 
-    public String getDoubleTapSensorType() {
-        return mContext.getString(R.string.doze_double_tap_sensor_type);
-    }
-
     public boolean getProxCheckBeforePulse() {
         return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse);
     }
 
-    public boolean getPulseOnNotifications() {
-        return getBoolean("doze.pulse.notifications", R.bool.doze_pulse_on_notifications);
-    }
-
     public int getPickupVibrationThreshold() {
         return getInt("doze.pickup.vibration.threshold", R.integer.doze_pickup_vibration_threshold);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 82867c6..42d9433 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -30,7 +30,7 @@
 import com.android.keyguard.KeyguardConstants;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.LatencyTracker;
+import com.android.keyguard.LatencyTracker;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 
 /**
@@ -42,8 +42,6 @@
     private static final boolean DEBUG_FP_WAKELOCK = KeyguardConstants.DEBUG_FP_WAKELOCK;
     private static final long FINGERPRINT_WAKELOCK_TIMEOUT_MS = 15 * 1000;
     private static final String FINGERPRINT_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
-    private static final String ACTION_FINGERPRINT_WAKE_FAKE =
-            "com.android.systemui.ACTION_FINGERPRINT_WAKE_FAKE";
 
     /**
      * Mode in which we don't need to wake up the device when we get a fingerprint.
@@ -123,14 +121,6 @@
         mScrimController = scrimController;
         mPhoneStatusBar = phoneStatusBar;
         mUnlockMethodCache = unlockMethodCache;
-        if (Build.IS_DEBUGGABLE) {
-            context.registerReceiver(new BroadcastReceiver() {
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    fakeWakeAndUnlock();
-                }
-            }, new IntentFilter(ACTION_FINGERPRINT_WAKE_FAKE));
-        }
     }
 
     public void setStatusBarKeyguardViewManager(
@@ -159,11 +149,6 @@
         }
     }
 
-    public void fakeWakeAndUnlock() {
-        onFingerprintAcquired();
-        onFingerprintAuthenticated(KeyguardUpdateMonitor.getCurrentUser());
-    }
-
     @Override
     public void onFingerprintAcquired() {
         Trace.beginSection("FingerprintUnlockController#onFingerprintAcquired");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 4270147..f9b7bb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -122,6 +122,7 @@
     private KeyguardIndicationController mIndicationController;
     private AccessibilityController mAccessibilityController;
     private PhoneStatusBar mPhoneStatusBar;
+    private KeyguardAffordanceHelper mAffordanceHelper;
 
     private boolean mUserSetupComplete;
     private boolean mPrewarmBound;
@@ -308,6 +309,10 @@
         updateCameraVisibility(); // in case onFinishInflate() was called too early
     }
 
+    public void setAffordanceHelper(KeyguardAffordanceHelper affordanceHelper) {
+        mAffordanceHelper = affordanceHelper;
+    }
+
     public void setUserSetupComplete(boolean userSetupComplete) {
         mUserSetupComplete = userSetupComplete;
         updateCameraVisibility();
@@ -620,6 +625,9 @@
             mPreviewContainer.addView(mCameraPreview);
             mCameraPreview.setVisibility(visibleBefore ? View.VISIBLE : View.INVISIBLE);
         }
+        if (mAffordanceHelper != null) {
+            mAffordanceHelper.updatePreviews();
+        }
     }
 
     private void updateLeftPreview() {
@@ -637,6 +645,9 @@
             mPreviewContainer.addView(mLeftPreview);
             mLeftPreview.setVisibility(View.INVISIBLE);
         }
+        if (mAffordanceHelper != null) {
+            mAffordanceHelper.updatePreviews();
+        }
     }
 
     public void startFinishDozeAnimation() {
@@ -720,6 +731,13 @@
                 @Override
                 public void onStrongAuthStateChanged(int userId) {
                     mLockIcon.update();
+        }
+
+                @Override
+                public void onUserUnlocked() {
+                    inflateCameraPreview();
+                    updateCameraVisibility();
+                    updateLeftAffordance();
                 }
             };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 706abdc..34b8371 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -96,9 +96,10 @@
         }
 
         final int activeUserId = ActivityManager.getCurrentUser();
-        final boolean allowDismissKeyguard =
-                !UserManager.isSplitSystemUser()
-                && activeUserId == keyguardUserId;
+        final boolean isSystemUser =
+                UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
+        final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;
+
         // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
         // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
         if (allowDismissKeyguard && mKeyguardView.dismiss(activeUserId)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index fb2c335..7b35cbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -233,6 +233,7 @@
         mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
         mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
         mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
+        mKeyguardBottomArea.setAffordanceHelper(mAfforanceHelper);
         mLastOrientation = getResources().getConfiguration().orientation;
 
         mQsAutoReinflateContainer =
@@ -1001,8 +1002,8 @@
         mKeyguardShowing = keyguardShowing;
         mQsContainer.setKeyguardShowing(mKeyguardShowing);
 
-        if (goingToFullShade || (oldState == StatusBarState.KEYGUARD
-                && statusBarState == StatusBarState.SHADE_LOCKED)) {
+        if (oldState == StatusBarState.KEYGUARD
+                && (goingToFullShade || statusBarState == StatusBarState.SHADE_LOCKED)) {
             animateKeyguardStatusBarOut();
             long delay = mStatusBarState == StatusBarState.SHADE_LOCKED
                     ? 0 : mStatusBar.calculateGoingToFullShadeDelay();
@@ -1016,7 +1017,7 @@
             mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
             if (keyguardShowing && oldState != mStatusBarState) {
                 mKeyguardBottomArea.onKeyguardShowingChanged();
-                mAfforanceHelper.updatePreviews();
+                mQsContainer.hideImmediately();
             }
         }
         if (keyguardShowing) {
@@ -1312,9 +1313,12 @@
             }
             return;
         }
-        boolean belowFalsingThreshold = isFalseTouch();
-        if (belowFalsingThreshold) {
+
+        // If we move in the opposite direction, reset velocity and use a different duration.
+        boolean oppositeDirection = false;
+        if (vel > 0 && !expand || vel < 0 && expand) {
             vel = 0;
+            oppositeDirection = true;
         }
         ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
         if (isClick) {
@@ -1323,7 +1327,7 @@
         } else {
             mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
         }
-        if (belowFalsingThreshold) {
+        if (oppositeDirection) {
             animator.setDuration(350);
         }
         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index c6aec73..3de03b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -23,7 +23,6 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.InputDevice;
@@ -37,7 +36,7 @@
 import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.Interpolators;
-import com.android.systemui.LatencyTracker;
+import com.android.keyguard.LatencyTracker;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.doze.DozeLog;
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 8ee014c..28e5f7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -37,6 +37,7 @@
 import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
 import android.app.IActivityManager;
+import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
@@ -132,7 +133,7 @@
 import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.Interpolators;
-import com.android.systemui.LatencyTracker;
+import com.android.keyguard.LatencyTracker;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SystemUIFactory;
@@ -1765,18 +1766,21 @@
         for (int i=0; i<N; i++) {
             Entry ent = activeNotifications.get(i);
             int vis = ent.notification.getNotification().visibility;
+            int userId = ent.notification.getUserId();
 
             // Display public version of the notification if we need to redact.
-            final boolean hideSensitive =
-                    !userAllowsPrivateNotificationsInPublic(ent.notification.getUserId());
+            boolean deviceSensitive = (isLockscreenPublicMode(mCurrentUserId)
+                    && !userAllowsPrivateNotificationsInPublic(mCurrentUserId));
+            boolean userSensitive = deviceSensitive || (isLockscreenPublicMode(userId)
+                    && !userAllowsPrivateNotificationsInPublic(userId));
             boolean sensitiveNote = vis == Notification.VISIBILITY_PRIVATE;
             boolean sensitivePackage = packageHasVisibilityOverride(ent.notification.getKey());
-            boolean sensitive = (sensitiveNote && hideSensitive) || sensitivePackage;
-            boolean showingPublic = sensitive && isLockscreenPublicMode();
+            boolean sensitive = (sensitiveNote && userSensitive) || sensitivePackage;
+            boolean showingPublic = sensitive && isLockscreenPublicMode(userId);
             if (showingPublic) {
                 updatePublicContentView(ent, ent.notification);
             }
-            ent.row.setSensitive(sensitive, hideSensitive);
+            ent.row.setSensitive(sensitive, deviceSensitive);
             if (ent.autoRedacted && ent.legacy) {
                 // TODO: Also fade this? Or, maybe easier (and better), provide a dark redacted form
                 // for legacy auto redacted notifications.
@@ -2745,7 +2749,7 @@
     public void handleSystemNavigationKey(int key) {
         if (SPEW) Log.d(TAG, "handleSystemNavigationKey: " + key);
         if (!panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive()
-                || mKeyguardMonitor.isShowing()) {
+                || mKeyguardMonitor.isShowing() && !mKeyguardMonitor.isOccluded()) {
             return;
         }
 
@@ -2980,6 +2984,10 @@
         return mGestureRec;
     }
 
+    public FingerprintUnlockController getFingerprintUnlockController() {
+        return mFingerprintUnlockController;
+    }
+
     private void setNavigationIconHints(int hints) {
         if (hints == mNavigationIconHints) return;
 
@@ -3427,6 +3435,9 @@
         if (KeyguardUpdateMonitor.getInstance(mContext) != null) {
             KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
         }
+        if (mFlashlightController != null) {
+            mFlashlightController.dump(fd, pw, args);
+        }
 
         FalsingManager.getInstance(mContext).dump(pw);
         FalsingLog.dump(pw);
@@ -4258,7 +4269,7 @@
         }
         updateKeyguardState(staying, false /* fromShadeLocked */);
 
-        if (viewToClick != null) {
+        if (viewToClick != null && viewToClick.isAttachedToWindow()) {
             viewToClick.callOnClick();
         }
 
@@ -4333,17 +4344,23 @@
     }
 
     private void updatePublicMode() {
-        boolean isPublic = false;
-        if (mStatusBarKeyguardViewManager.isShowing()) {
-            for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
-                UserInfo userInfo = mCurrentProfiles.valueAt(i);
-                if (mStatusBarKeyguardViewManager.isSecure(userInfo.id)) {
-                    isPublic = true;
-                    break;
+        final boolean showingKeyguard = mStatusBarKeyguardViewManager.isShowing();
+        final boolean devicePublic = showingKeyguard
+                && mStatusBarKeyguardViewManager.isSecure(mCurrentUserId);
+
+        // Look for public mode users. Users are considered public in either case of:
+        //   - device keyguard is shown in secure mode;
+        //   - profile is locked with a work challenge.
+        for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
+            final int userId = mCurrentProfiles.valueAt(i).id;
+            boolean isProfilePublic = devicePublic;
+            if (!devicePublic && userId != mCurrentUserId) {
+                if (mStatusBarKeyguardViewManager.isSecure(userId)) {
+                    isProfilePublic = mKeyguardManager.isDeviceLocked(userId);
                 }
             }
+            setLockscreenPublicMode(isProfilePublic, userId);
         }
-        setLockscreenPublicMode(isPublic);
     }
 
     protected void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) {
@@ -4378,7 +4395,8 @@
         checkBarModes();
         updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
         mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
-                mStatusBarKeyguardViewManager.isSecure());
+                mStatusBarKeyguardViewManager.isSecure(),
+                mStatusBarKeyguardViewManager.isOccluded());
         Trace.endSection();
     }
 
@@ -4400,7 +4418,8 @@
     public void updateStackScrollerState(boolean goingToFullShade, boolean fromShadeLocked) {
         if (mStackScroller == null) return;
         boolean onKeyguard = mState == StatusBarState.KEYGUARD;
-        mStackScroller.setHideSensitive(isLockscreenPublicMode(), goingToFullShade);
+        boolean publicMode = isAnyProfilePublicMode();
+        mStackScroller.setHideSensitive(publicMode, goingToFullShade);
         mStackScroller.setDimmed(onKeyguard, fromShadeLocked /* animate */);
         mStackScroller.setExpandingEnabled(!onKeyguard);
         ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild();
@@ -4456,6 +4475,9 @@
             animateCollapsePanels();
             return true;
         }
+        if (mKeyguardUserSwitcher.hideIfNotSimple(true)) {
+            return true;
+        }
         return false;
     }
 
@@ -4650,6 +4672,7 @@
      * @param expandView The view to expand after going to the shade.
      */
     public void goToLockedShade(View expandView) {
+        int userId = mCurrentUserId;
         ExpandableNotificationRow row = null;
         if (expandView instanceof ExpandableNotificationRow) {
             row = (ExpandableNotificationRow) expandView;
@@ -4657,10 +4680,13 @@
             // Indicate that the group expansion is changing at this time -- this way the group
             // and children backgrounds / divider animations will look correct.
             row.setGroupExpansionChanging(true);
+            if (row.getStatusBarNotification() != null) {
+                userId = row.getStatusBarNotification().getUserId();
+            }
         }
         boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId)
                 || !mShowLockscreenNotifications || mFalsingManager.shouldEnforceBouncer();
-        if (isLockscreenPublicMode() && fullShadeNeedsBouncer) {
+        if (isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) {
             mLeaveOpenOnKeyguardHide = true;
             showBouncer();
             mDraggedDownRow = row;
@@ -4705,10 +4731,20 @@
         mPendingWorkRemoteInputView = clicked;
     }
 
+    private boolean isAnyProfilePublicMode() {
+        for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
+            if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
-    protected void onWorkChallengeUnlocked() {
-        if (mPendingWorkRemoteInputView != null) {
-            final View pendingWorkRemoteInputView = mPendingWorkRemoteInputView;
+    protected void onWorkChallengeChanged() {
+        updatePublicMode();
+        updateNotifications();
+        if (mPendingWorkRemoteInputView != null && !isAnyProfilePublicMode()) {
             // Expand notification panel and the notification row, then click on remote input view
             final Runnable clickPendingViewRunnable = new Runnable() {
                 @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index b0b86be..a8b0122 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -350,9 +350,7 @@
             }
         } else if (v == mAlarmStatus && mNextAlarm != null) {
             PendingIntent showIntent = mNextAlarm.getShowIntent();
-            if (showIntent != null && showIntent.isActivity()) {
-                mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
-            }
+            mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
         }
     }
 
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 01609e4..77c60fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -31,7 +31,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.DejankUtils;
-import com.android.systemui.LatencyTracker;
+import com.android.keyguard.LatencyTracker;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.RemoteInputController;
@@ -264,10 +264,12 @@
             }
         }
         mOccluded = occluded;
-        mPhoneStatusBar.updateMediaMetaData(false, animate && !occluded);
+        if (mShowing) {
+            mPhoneStatusBar.updateMediaMetaData(false, animate && !occluded);
+        }
         mStatusBarWindowManager.setKeyguardOccluded(occluded);
         reset();
-        if (animate && !occluded) {
+        if (animate && !occluded && mShowing) {
             mPhoneStatusBar.animateKeyguardUnoccluding();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 91b21ed..4e9fc76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -27,6 +27,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
@@ -80,6 +82,7 @@
     public void setFlashlight(boolean enabled) {
         boolean pendingError = false;
         synchronized (this) {
+            if (mCameraId == null) return;
             if (mFlashlightEnabled != enabled) {
                 mFlashlightEnabled = enabled;
                 try {
@@ -235,6 +238,17 @@
         }
     };
 
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("FlashlightController state:");
+
+        pw.print("  mCameraId=");
+        pw.println(mCameraId);
+        pw.print("  mFlashlightEnabled=");
+        pw.println(mFlashlightEnabled);
+        pw.print("  mTorchAvailable=");
+        pw.println(mTorchAvailable);
+    }
+
     public interface FlashlightListener {
 
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index c175180..44816f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -38,6 +38,7 @@
     private int mCurrentUser;
     private boolean mShowing;
     private boolean mSecure;
+    private boolean mOccluded;
     private boolean mCanSkipBouncer;
 
     private boolean mListening;
@@ -81,6 +82,10 @@
         return mSecure;
     }
 
+    public boolean isOccluded() {
+        return mOccluded;
+    }
+
     public boolean canSkipBouncer() {
         return mCanSkipBouncer;
     }
@@ -99,10 +104,11 @@
         }
     }
 
-    public void notifyKeyguardState(boolean showing, boolean secure) {
-        if (mShowing == showing && mSecure == secure) return;
+    public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
+        if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
         mShowing = showing;
         mSecure = secure;
+        mOccluded = occluded;
         notifyKeyguardChanged();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index 21f3f5e..1cf4050 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -128,7 +128,7 @@
         }
     }
 
-    private void hide(boolean animate) {
+    private boolean hide(boolean animate) {
         if (mUserSwitcher != null && mUserSwitcherContainer.getVisibility() == View.VISIBLE) {
             cancelAnimations();
             if (animate) {
@@ -137,7 +137,9 @@
                 mUserSwitcherContainer.setVisibility(View.GONE);
             }
             mStatusBarView.setKeyguardUserSwitcherShowing(false, animate);
+            return true;
         }
+        return false;
     }
 
     private void cancelAnimations() {
@@ -223,10 +225,11 @@
         }
     }
 
-    public void hideIfNotSimple(boolean animate) {
+    public boolean hideIfNotSimple(boolean animate) {
         if (mUserSwitcherContainer != null && !mUserSwitcherController.isSimpleUserSwitcher()) {
-            hide(animate);
+            return hide(animate);
         }
+        return false;
     }
 
     boolean isAnimating() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 9dc9062..4b46578 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1057,7 +1057,7 @@
     @Override
     public int getMaxExpandHeight(ExpandableView view) {
         int maxContentHeight = view.getMaxContentHeight();
-        if (view.isSummaryWithChildren()) {
+        if (view.isSummaryWithChildren() && view.getParent() == this) {
             // Faking a measure with the group expanded to simulate how the group would look if
             // it was. Doing a calculation here would be highly non-trivial because of the
             // algorithm
@@ -1072,8 +1072,11 @@
                     row.getStatusBarNotification());
             mGroupExpandedForMeasure = false;
             row.setForceUnlocked(false);
-            int height = mCurrentStackScrollState.getViewStateForView(view).height;
-            return Math.min(height, maxContentHeight);
+            StackViewState viewState = mCurrentStackScrollState.getViewStateForView(view);
+            if (viewState != null) {
+                // The view could have been removed
+                return Math.min(viewState.height, maxContentHeight);
+            }
         }
         return maxContentHeight;
     }
@@ -2038,6 +2041,7 @@
         if (!mIsExpanded) {
             mBackgroundBounds.top = 0;
             mBackgroundBounds.bottom = 0;
+            return;
         }
         ActivatableNotificationView firstView = mFirstVisibleBackgroundChild;
         int top = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 5fe9296..3b14e60 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -30,6 +30,8 @@
         PreferenceFragment.OnPreferenceStartFragmentCallback,
         PreferenceFragment.OnPreferenceStartScreenCallback {
 
+    static final String ACTIVITY_ALIAS_NAME = "com.android.systemui.tuner.TunerSettingLink";
+
     private static final String TAG_TUNER = "tuner";
 
     protected void onCreate(Bundle savedInstanceState) {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index e0a1547..ebc962d 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -255,6 +255,12 @@
                 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                         : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                         PackageManager.DONT_KILL_APP);
+
+        userContext(context).getPackageManager().setComponentEnabledSetting(
+                new ComponentName(context, TunerActivity.ACTIVITY_ALIAS_NAME),
+                enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                        : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
     }
 
     public static final boolean isTunerEnabled(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index 085e003..75c2bcd 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -19,13 +19,13 @@
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManager.StackInfo;
 import android.app.ActivityManagerNative;
-import android.app.ActivityOptions;
 import android.app.IActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.media.session.MediaController;
@@ -33,24 +33,27 @@
 import android.media.session.PlaybackState;
 import android.os.Debug;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
-
+import android.view.IWindowManager;
+import android.view.InputChannel;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
+import android.view.WindowManagerGlobal;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
-import com.android.systemui.SystemUIApplication;
-import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.statusbar.tv.TvStatusBar;
+import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.view.WindowManager.INPUT_CONSUMER_PIP;
 import static com.android.systemui.Prefs.Key.TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN;
 
 /**
@@ -160,6 +163,9 @@
     private boolean mOnboardingShown;
     private String[] mLastPackagesResourceGranted;
 
+    private InputChannel mInputChannel;
+    private PipInputEventReceiver mInputEventReceiver;
+
     private final Runnable mResizePinnedStackRunnable = new Runnable() {
         @Override
         public void run() {
@@ -197,6 +203,25 @@
                 }
             };
 
+    /**
+     * Input handler used for Pip windows.  Currently eats all the input events.
+     */
+    private final class PipInputEventReceiver extends InputEventReceiver {
+        public PipInputEventReceiver(InputChannel inputChannel, Looper looper) {
+            super(inputChannel, looper);
+        }
+
+        @Override
+        public void onInputEvent(InputEvent event) {
+            boolean handled = true;
+            try {
+                // To be implemented for input handling over Pip windows
+            } finally {
+                finishInputEvent(event, handled);
+            }
+        }
+    }
+
     private PipManager() { }
 
     /**
@@ -221,6 +246,20 @@
         mPipRecentsOverlayManager = new PipRecentsOverlayManager(context);
         mMediaSessionManager =
                 (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
+
+        PackageManager pm = mContext.getPackageManager();
+        if (!pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
+            // Initialize the Pip input consumer
+            mInputChannel = new InputChannel();
+            try {
+                IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+                wm.destroyInputConsumer(INPUT_CONSUMER_PIP);
+                wm.createInputConsumer(INPUT_CONSUMER_PIP, mInputChannel);
+                mInputEventReceiver = new PipInputEventReceiver(mInputChannel, Looper.myLooper());
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to create Pip input consumer", e);
+            }
+        }
     }
 
     private void loadConfigurationsAndApply() {
@@ -298,6 +337,7 @@
             mListeners.get(i).onMoveToFullscreen();
         }
         resizePinnedStack(mState);
+        updatePipVisibility(false);
     }
 
     /**
@@ -307,7 +347,11 @@
      */
     private void showPipOverlay() {
         if (DEBUG) Log.d(TAG, "showPipOverlay()");
-        PipOverlayActivity.showPipOverlay(mContext);
+        // Temporary workaround to prevent the overlay on phones
+        PackageManager pm = mContext.getPackageManager();
+        if (pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
+            PipOverlayActivity.showPipOverlay(mContext);
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipUI.java
index b3e9f43..3306cb3 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipUI.java
@@ -21,11 +21,10 @@
 
 import com.android.systemui.SystemUI;
 
-import static android.content.pm.PackageManager.FEATURE_LEANBACK;
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
 
 /**
- * Controls the picture-in-picture window for TV devices.
+ * Controls the picture-in-picture window.
  */
 public class PipUI extends SystemUI {
     private boolean mSupportPip;
@@ -33,8 +32,7 @@
     @Override
     public void start() {
         PackageManager pm = mContext.getPackageManager();
-        mSupportPip = pm.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)
-                && pm.hasSystemFeature(FEATURE_LEANBACK);
+        mSupportPip = pm.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
         if (!mSupportPip) {
             return;
         }
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 23967aa..6038171 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -45,7 +45,8 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
     mockito-target-minus-junit4 \
-    SystemUI-proto-tags
+    SystemUI-proto \
+    SystemUI-tags
 
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.car
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
index ab7de39..9050b83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
@@ -33,13 +33,11 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.net.Uri;
 import android.os.HandlerThread;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.PluginInstanceManager.ClassLoaderFactory;
 
 import org.junit.After;
 import org.junit.Before;
@@ -64,6 +62,7 @@
     private PackageManager mMockPm;
     private PluginListener mMockListener;
     private PluginInstanceManager mPluginInstanceManager;
+    private PluginManager mMockManager;
 
     @Before
     public void setup() throws Exception {
@@ -72,9 +71,11 @@
         mContextWrapper = new MyContextWrapper(getContext());
         mMockPm = mock(PackageManager.class);
         mMockListener = mock(PluginListener.class);
+        mMockManager = mock(PluginManager.class);
+        when(mMockManager.getClassLoader(Mockito.any(), Mockito.any()))
+                .thenReturn(getClass().getClassLoader());
         mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction",
-                mMockListener, true, mHandlerThread.getLooper(), 1, true,
-                new TestClassLoaderFactory());
+                mMockListener, true, mHandlerThread.getLooper(), 1, mMockManager, true);
         sMockPlugin = mock(Plugin.class);
         when(sMockPlugin.getVersion()).thenReturn(1);
     }
@@ -89,7 +90,7 @@
     public void testNoPlugins() {
         when(mMockPm.queryIntentServices(Mockito.any(), Mockito.anyInt())).thenReturn(
                 Collections.emptyList());
-        mPluginInstanceManager.startListening();
+        mPluginInstanceManager.loadAll();
 
         waitForIdleSync(mPluginInstanceManager.mPluginHandler);
         waitForIdleSync(mPluginInstanceManager.mMainHandler);
@@ -112,7 +113,7 @@
     public void testPluginDestroy() {
         createPlugin(); // Get into valid created state.
 
-        mPluginInstanceManager.stopListening();
+        mPluginInstanceManager.destroy();
 
         waitForIdleSync(mPluginInstanceManager.mPluginHandler);
         waitForIdleSync(mPluginInstanceManager.mMainHandler);
@@ -127,7 +128,7 @@
         setupFakePmQuery();
         when(sMockPlugin.getVersion()).thenReturn(2);
 
-        mPluginInstanceManager.startListening();
+        mPluginInstanceManager.loadAll();
 
         waitForIdleSync(mPluginInstanceManager.mPluginHandler);
         waitForIdleSync(mPluginInstanceManager.mMainHandler);
@@ -141,10 +142,7 @@
     public void testReloadOnChange() {
         createPlugin(); // Get into valid created state.
 
-        // Send a package changed broadcast.
-        Intent i = new Intent(Intent.ACTION_PACKAGE_CHANGED,
-                Uri.fromParts("package", "com.android.systemui", null));
-        mPluginInstanceManager.onReceive(mContextWrapper, i);
+        mPluginInstanceManager.onPackageChange("com.android.systemui");
 
         waitForIdleSync(mPluginInstanceManager.mPluginHandler);
         waitForIdleSync(mPluginInstanceManager.mMainHandler);
@@ -164,11 +162,10 @@
     public void testNonDebuggable() {
         // Create a version that thinks the build is not debuggable.
         mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction",
-                mMockListener, true, mHandlerThread.getLooper(), 1, false,
-                new TestClassLoaderFactory());
+                mMockListener, true, mHandlerThread.getLooper(), 1, mMockManager, false);
         setupFakePmQuery();
 
-        mPluginInstanceManager.startListening();
+        mPluginInstanceManager.loadAll();
 
         waitForIdleSync(mPluginInstanceManager.mPluginHandler);
         waitForIdleSync(mPluginInstanceManager.mMainHandler);;
@@ -236,19 +233,12 @@
     private void createPlugin() {
         setupFakePmQuery();
 
-        mPluginInstanceManager.startListening();
+        mPluginInstanceManager.loadAll();
 
         waitForIdleSync(mPluginInstanceManager.mPluginHandler);
         waitForIdleSync(mPluginInstanceManager.mMainHandler);
     }
 
-    private static class TestClassLoaderFactory extends ClassLoaderFactory {
-        @Override
-        public ClassLoader createClassLoader(String path, ClassLoader base) {
-            return base;
-        }
-    }
-
     // Real context with no registering/unregistering of receivers.
     private static class MyContextWrapper extends ContextWrapper {
         public MyContextWrapper(Context base) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
index 56e742a..4b1827d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
@@ -51,7 +51,7 @@
         mMockFactory = mock(PluginInstanceManagerFactory.class);
         mMockPluginInstance = mock(PluginInstanceManager.class);
         when(mMockFactory.createPluginInstanceManager(Mockito.any(), Mockito.any(), Mockito.any(),
-                Mockito.anyBoolean(), Mockito.any(), Mockito.anyInt()))
+                Mockito.anyBoolean(), Mockito.any(), Mockito.anyInt(), Mockito.any()))
                 .thenReturn(mMockPluginInstance);
         mPluginManager = new PluginManager(getContext(), mMockFactory, true, mMockExceptionHandler);
         resetExceptionHandler();
@@ -62,7 +62,7 @@
     public void testAddListener() {
         mPluginManager.addPluginListener("myAction", mMockListener, 1);
 
-        verify(mMockPluginInstance).startListening();
+        verify(mMockPluginInstance).loadAll();
     }
 
     @Test
@@ -70,7 +70,7 @@
         mPluginManager.addPluginListener("myAction", mMockListener, 1);
 
         mPluginManager.removePluginListener(mMockListener);
-        verify(mMockPluginInstance).stopListening();
+        verify(mMockPluginInstance).destroy();
     }
 
     @Test
@@ -80,7 +80,7 @@
         resetExceptionHandler();
         mPluginManager.addPluginListener("myAction", mMockListener, 1);
 
-        verify(mMockPluginInstance, Mockito.never()).startListening();
+        verify(mMockPluginInstance, Mockito.never()).loadAll();
     }
 
     @Test
diff --git a/preloaded-classes b/preloaded-classes
index 42f290e..5ddd08b 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -2077,9 +2077,6 @@
 android.view.HandlerActionQueue
 android.view.HandlerActionQueue$HandlerAction
 android.view.HardwareLayer
-android.view.IAssetAtlas
-android.view.IAssetAtlas$Stub
-android.view.IAssetAtlas$Stub$Proxy
 android.view.IGraphicsStats
 android.view.IGraphicsStats$Stub
 android.view.IGraphicsStats$Stub$Proxy
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index da041da..64d8a4c 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2566,6 +2566,15 @@
     // OPEN: Settings > Wireless > Manage wireless plan dialog
     DIALOG_MANAGE_MOBILE_PLAN = 609;
 
+    // ACTION: Logs network type of the device while provisioning
+    PROVISIONING_NETWORK_TYPE = 610;
+
+    // ACTION: Logs action which triggered provisioning.
+    PROVISIONING_ACTION = 611;
+
+    // ACTION: Logs extra passed by the dpc while provisioning.
+    PROVISIONING_EXTRA = 612;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index 0658620..bf3681b 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -28,7 +28,7 @@
     frameworks/base/libs/hwui \
     $(rs_generated_include_dir)
 
-LOCAL_CFLAGS += -Wno-unused-parameter -std=c++11
+LOCAL_CFLAGS += -Wno-unused-parameter
 LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
 
 LOCAL_ADDITIONAL_DEPENDENCIES := $(addprefix $(rs_generated_include_dir)/,rsgApiFuncDecl.h)
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 06c4350..af370ff 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -644,7 +644,7 @@
     in_allocs[2] = (RsAllocation)C;
 
     rsScriptForEachMulti((RsContext)con, (RsScript)id, 0,
-                         in_allocs, sizeof(in_allocs), nullptr,
+                         in_allocs, NELEM(in_allocs), nullptr,
                          &call, sizeof(call), nullptr, 0);
 }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 0b83e66..4819c0a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -64,6 +64,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.UserManagerInternal;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
@@ -498,20 +499,6 @@
     }
 
     @Override
-    public void sendAccessibilityEvents(ParceledListSlice events, int userId) {
-        List<AccessibilityEvent> a11yEvents = events.getList();
-        // Grab the lock once for the entire batch
-        synchronized (mLock) {
-            int numEventsToProcess = Math.min(a11yEvents.size(),
-                    AccessibilityManager.MAX_A11Y_EVENTS_PER_SERVICE_CALL);
-            for (int i = 0; i < numEventsToProcess; i++) {
-                AccessibilityEvent event = a11yEvents.get(i);
-                sendAccessibilityEvent(event, userId);
-            }
-        }
-    }
-
-    @Override
     public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
         synchronized (mLock) {
             // We treat calls from a profile as if made by its parent as profiles
@@ -1315,14 +1302,8 @@
     private void updateServicesLocked(UserState userState) {
         Map<ComponentName, Service> componentNameToServiceMap =
                 userState.mComponentNameToServiceMap;
-        boolean isUnlockingOrUnlocked;
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            isUnlockingOrUnlocked = mContext.getSystemService(UserManager.class)
+        boolean isUnlockingOrUnlocked = LocalServices.getService(UserManagerInternal.class)
                     .isUserUnlockingOrUnlocked(userState.mUserId);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
 
         for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
             AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 497eac9..8424b39 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -6057,7 +6057,11 @@
                                         // the app developer's cert, so they're different on every
                                         // device.
                                         if (signaturesMatch(sigs, pkgInfo)) {
-                                            if (pkgInfo.versionCode >= version) {
+                                            if ((pkgInfo.applicationInfo.flags
+                                                    & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
+                                                Slog.i(TAG, "Package has restoreAnyVersion; taking data");
+                                                policy = RestorePolicy.ACCEPT;
+                                            } else if (pkgInfo.versionCode >= version) {
                                                 Slog.i(TAG, "Sig + version match; taking data");
                                                 policy = RestorePolicy.ACCEPT;
                                             } else {
@@ -7479,7 +7483,11 @@
                                         // the app developer's cert, so they're different on every
                                         // device.
                                         if (signaturesMatch(sigs, pkgInfo)) {
-                                            if (pkgInfo.versionCode >= version) {
+                                            if ((pkgInfo.applicationInfo.flags
+                                                    & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
+                                                Slog.i(TAG, "Package has restoreAnyVersion; taking data");
+                                                policy = RestorePolicy.ACCEPT;
+                                            } else if (pkgInfo.versionCode >= version) {
                                                 Slog.i(TAG, "Sig + version match; taking data");
                                                 policy = RestorePolicy.ACCEPT;
                                             } else {
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 58f2074..9efafb7 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -17,7 +17,12 @@
 LOCAL_AIDL_INCLUDES += \
     system/netd/server/binder
 
-LOCAL_JAVA_LIBRARIES := services.net telephony-common
+LOCAL_JAVA_LIBRARIES := \
+    services.net \
+    telephony-common \
+    android.hardware.power@1.0-java \
+    android.hardware.light@2.0-java
+
 LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
 LOCAL_PROTOC_OPTIMIZE_TYPE := nano
 
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
deleted file mode 100644
index b0f6048..0000000
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * Copyright (C) 2013 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;
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.graphics.Atlas;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.drawable.Drawable;
-import android.os.Environment;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.util.Log;
-import android.util.LongSparseArray;
-import android.view.GraphicBuffer;
-import android.view.IAssetAtlas;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * This service is responsible for packing preloaded bitmaps into a single
- * atlas texture. The resulting texture can be shared across processes to
- * reduce overall memory usage.
- *
- * @hide
- */
-public class AssetAtlasService extends IAssetAtlas.Stub {
-    /**
-     * Name of the <code>AssetAtlasService</code>.
-     */
-    public static final String ASSET_ATLAS_SERVICE = "assetatlas";
-
-    private static final String LOG_TAG = "AssetAtlas";
-
-    // Turns debug logs on/off. Debug logs are kept to a minimum and should
-    // remain on to diagnose issues
-    private static final boolean DEBUG_ATLAS = true;
-
-    // When set to true the content of the atlas will be saved to disk
-    // in /data/system/atlas.png. The shared GraphicBuffer may be empty
-    private static final boolean DEBUG_ATLAS_TEXTURE = false;
-
-    // Minimum size in pixels to consider for the resulting texture
-    private static final int MIN_SIZE = 512;
-    // Maximum size in pixels to consider for the resulting texture
-    private static final int MAX_SIZE = 2048;
-    // Increment in number of pixels between size variants when looking
-    // for the best texture dimensions
-    private static final int STEP = 64;
-
-    // This percentage of the total number of pixels represents the minimum
-    // number of pixels we want to be able to pack in the atlas
-    private static final float PACKING_THRESHOLD = 0.8f;
-
-    // Defines the number of int fields used to represent a single entry
-    // in the atlas map. This number defines the size of the array returned
-    // by the getMap(). See the mAtlasMap field for more information
-    private static final int ATLAS_MAP_ENTRY_FIELD_COUNT = 3;
-
-    // Specifies how our GraphicBuffer will be used. To get proper swizzling
-    // the buffer will be written to using OpenGL (from JNI) so we can leave
-    // the software flag set to "never"
-    private static final int GRAPHIC_BUFFER_USAGE = GraphicBuffer.USAGE_SW_READ_NEVER |
-            GraphicBuffer.USAGE_SW_WRITE_NEVER | GraphicBuffer.USAGE_HW_TEXTURE;
-
-    // This boolean is set to true if an atlas was successfully
-    // computed and rendered
-    private final AtomicBoolean mAtlasReady = new AtomicBoolean(false);
-
-    private final Context mContext;
-
-    // Version name of the current build, used to identify changes to assets list
-    private final String mVersionName;
-
-    // Holds the atlas' data. This buffer can be mapped to
-    // OpenGL using an EGLImage
-    private GraphicBuffer mBuffer;
-
-    // Describes how bitmaps are placed in the atlas. Each bitmap is
-    // represented by several entries in the array:
-    // long0: SkBitmap*, the native bitmap object
-    // long1: x position
-    // long2: y position
-    private long[] mAtlasMap;
-
-    /**
-     * Creates a new service. Upon creating, the service will gather the list of
-     * assets to consider for packing into the atlas and spawn a new thread to
-     * start the packing work.
-     *
-     * @param context The context giving access to preloaded resources
-     */
-    public AssetAtlasService(Context context) {
-        mContext = context;
-        mVersionName = queryVersionName(context);
-
-        Collection<Bitmap> bitmaps = new HashSet<Bitmap>(300);
-        int totalPixelCount = 0;
-
-        // We only care about drawables that hold bitmaps
-        final Resources resources = context.getResources();
-        final LongSparseArray<Drawable.ConstantState> drawables = resources.getPreloadedDrawables();
-
-        final int count = drawables.size();
-        for (int i = 0; i < count; i++) {
-            try {
-                totalPixelCount += drawables.valueAt(i).addAtlasableBitmaps(bitmaps);
-            } catch (Throwable t) {
-                Log.e("AssetAtlas", "Failed to fetch preloaded drawable state", t);
-                throw t;
-            }
-        }
-
-        ArrayList<Bitmap> sortedBitmaps = new ArrayList<Bitmap>(bitmaps);
-        // Our algorithms perform better when the bitmaps are first sorted
-        // The comparator will sort the bitmap by width first, then by height
-        Collections.sort(sortedBitmaps, new Comparator<Bitmap>() {
-            @Override
-            public int compare(Bitmap b1, Bitmap b2) {
-                if (b1.getWidth() == b2.getWidth()) {
-                    return b2.getHeight() - b1.getHeight();
-                }
-                return b2.getWidth() - b1.getWidth();
-            }
-        });
-
-        // Kick off the packing work on a worker thread
-        new Thread(new Renderer(sortedBitmaps, totalPixelCount)).start();
-    }
-
-    /**
-     * Queries the version name stored in framework's AndroidManifest.
-     * The version name can be used to identify possible changes to
-     * framework resources.
-     *
-     * @see #getBuildIdentifier(String)
-     */
-    private static String queryVersionName(Context context) {
-        try {
-            String packageName = context.getPackageName();
-            PackageInfo info = context.getPackageManager().getPackageInfo(packageName,
-                    PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
-            return info.versionName;
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.w(LOG_TAG, "Could not get package info", e);
-        }
-        return null;
-    }
-
-    /**
-     * Callback invoked by the server thread to indicate we can now run
-     * 3rd party code.
-     */
-    public void systemRunning() {
-    }
-
-    /**
-     * The renderer does all the work:
-     */
-    private class Renderer implements Runnable {
-        private final ArrayList<Bitmap> mBitmaps;
-        private final int mPixelCount;
-
-        Renderer(ArrayList<Bitmap> bitmaps, int pixelCount) {
-            mBitmaps = bitmaps;
-            mPixelCount = pixelCount;
-        }
-
-        /**
-         * 1. On first boot or after every update, brute-force through all the
-         *    possible atlas configurations and look for the best one (maximimize
-         *    number of packed assets and minimize texture size)
-         *    a. If a best configuration was computed, write it out to disk for
-         *       future use
-         * 2. Read best configuration from disk
-         * 3. Compute the packing using the best configuration
-         * 4. Allocate a GraphicBuffer
-         * 5. Render assets in the buffer
-         */
-        @Override
-        public void run() {
-            Configuration config = chooseConfiguration(mBitmaps, mPixelCount, mVersionName);
-            if (DEBUG_ATLAS) Log.d(LOG_TAG, "Loaded configuration: " + config);
-
-            if (config != null) {
-                mBuffer = GraphicBuffer.create(config.width, config.height,
-                        PixelFormat.RGBA_8888, GRAPHIC_BUFFER_USAGE);
-
-                if (mBuffer != null) {
-                    Atlas atlas = new Atlas(config.type, config.width, config.height, config.flags);
-                    if (renderAtlas(mBuffer, atlas, config.count)) {
-                        mAtlasReady.set(true);
-                    }
-                }
-            }
-        }
-
-        /**
-         * Renders a list of bitmaps into the atlas. The position of each bitmap
-         * was decided by the packing algorithm and will be honored by this
-         * method.
-         *
-         * @param buffer The buffer to render the atlas entries into
-         * @param atlas The atlas to pack the bitmaps into
-         * @param packCount The number of bitmaps that will be packed in the atlas
-         *
-         * @return true if the atlas was rendered, false otherwise
-         */
-        @SuppressWarnings("MismatchedReadAndWriteOfArray")
-        private boolean renderAtlas(GraphicBuffer buffer, Atlas atlas, int packCount) {
-            // Use a Source blend mode to improve performance, the target bitmap
-            // will be zero'd out so there's no need to waste time applying blending
-            final Paint paint = new Paint();
-            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
-
-            // We always render the atlas into a bitmap. This bitmap is then
-            // uploaded into the GraphicBuffer using OpenGL to swizzle the content
-            final Bitmap atlasBitmap = Bitmap.createBitmap(
-                    buffer.getWidth(), buffer.getHeight(), Bitmap.Config.ARGB_8888);
-            final Canvas canvas = new Canvas(atlasBitmap);
-
-            final Atlas.Entry entry = new Atlas.Entry();
-
-            mAtlasMap = new long[packCount * ATLAS_MAP_ENTRY_FIELD_COUNT];
-            long[] atlasMap = mAtlasMap;
-            int mapIndex = 0;
-
-            boolean result = false;
-            final long startRender = System.nanoTime();
-            final int count = mBitmaps.size();
-
-            for (int i = 0; i < count; i++) {
-                final Bitmap bitmap = mBitmaps.get(i);
-                if (atlas.pack(bitmap.getWidth(), bitmap.getHeight(), entry) != null) {
-                    // We have more bitmaps to pack than the current configuration
-                    // says, we were most likely not able to detect a change in the
-                    // list of preloaded drawables, abort and delete the configuration
-                    if (mapIndex >= mAtlasMap.length) {
-                        deleteDataFile();
-                        break;
-                    }
-
-                    canvas.save();
-                    canvas.translate(entry.x, entry.y);
-                    canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
-                    canvas.restore();
-                    atlasMap[mapIndex++] = bitmap.refSkPixelRef();
-                    atlasMap[mapIndex++] = entry.x;
-                    atlasMap[mapIndex++] = entry.y;
-                }
-            }
-
-            final long endRender = System.nanoTime();
-            releaseCanvas(canvas, atlasBitmap);
-            result = nUploadAtlas(buffer, atlasBitmap);
-            atlasBitmap.recycle();
-            final long endUpload = System.nanoTime();
-
-            if (DEBUG_ATLAS) {
-                float renderDuration = (endRender - startRender) / 1000.0f / 1000.0f;
-                float uploadDuration = (endUpload - endRender) / 1000.0f / 1000.0f;
-                Log.d(LOG_TAG, String.format("Rendered atlas in %.2fms (%.2f+%.2fms)",
-                        renderDuration + uploadDuration, renderDuration, uploadDuration));
-            }
-
-            return result;
-        }
-
-        /**
-         * Releases the canvas used to render into the buffer. Calling this method
-         * will release any resource previously acquired. If {@link #DEBUG_ATLAS_TEXTURE}
-         * is turend on, calling this method will write the content of the atlas
-         * to disk in /data/system/atlas.png for debugging.
-         */
-        private void releaseCanvas(Canvas canvas, Bitmap atlasBitmap) {
-            canvas.setBitmap(null);
-            if (DEBUG_ATLAS_TEXTURE) {
-
-                File systemDirectory = new File(Environment.getDataDirectory(), "system");
-                File dataFile = new File(systemDirectory, "atlas.png");
-
-                try {
-                    FileOutputStream out = new FileOutputStream(dataFile);
-                    atlasBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
-                    out.close();
-                } catch (FileNotFoundException e) {
-                    // Ignore
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-    }
-
-    private static native boolean nUploadAtlas(GraphicBuffer buffer, Bitmap bitmap);
-
-    @Override
-    public boolean isCompatible(int ppid) {
-        return ppid == android.os.Process.myPpid();
-    }
-
-    @Override
-    public GraphicBuffer getBuffer() throws RemoteException {
-        return mAtlasReady.get() ? mBuffer : null;
-    }
-
-    @Override
-    public long[] getMap() throws RemoteException {
-        return mAtlasReady.get() ? mAtlasMap : null;
-    }
-
-    /**
-     * Finds the best atlas configuration to pack the list of supplied bitmaps.
-     * This method takes advantage of multi-core systems by spawning a number
-     * of threads equal to the number of available cores.
-     */
-    private static Configuration computeBestConfiguration(
-            ArrayList<Bitmap> bitmaps, int pixelCount) {
-        if (DEBUG_ATLAS) Log.d(LOG_TAG, "Computing best atlas configuration...");
-
-        long begin = System.nanoTime();
-        List<WorkerResult> results = Collections.synchronizedList(new ArrayList<WorkerResult>());
-
-        // Don't bother with an extra thread if there's only one processor
-        int cpuCount = Runtime.getRuntime().availableProcessors();
-        if (cpuCount == 1) {
-            new ComputeWorker(MIN_SIZE, MAX_SIZE, STEP, bitmaps, pixelCount, results, null).run();
-        } else {
-            int start = MIN_SIZE + (cpuCount - 1) * STEP;
-            int end = MAX_SIZE;
-            int step = STEP * cpuCount;
-
-            final CountDownLatch signal = new CountDownLatch(cpuCount);
-
-            for (int i = 0; i < cpuCount; i++, start -= STEP, end -= STEP) {
-                ComputeWorker worker = new ComputeWorker(start, end, step,
-                        bitmaps, pixelCount, results, signal);
-                new Thread(worker, "Atlas Worker #" + (i + 1)).start();
-            }
-
-            boolean isAllWorkerFinished;
-            try {
-                isAllWorkerFinished = signal.await(10, TimeUnit.SECONDS);
-            } catch (InterruptedException e) {
-                Log.w(LOG_TAG, "Could not complete configuration computation");
-                return null;
-            }
-
-            if (!isAllWorkerFinished) {
-                // We have to abort here, otherwise the async updates on "results" would crash the
-                // sort later.
-                Log.w(LOG_TAG, "Could not complete configuration computation before timeout.");
-                return null;
-            }
-        }
-
-        // Maximize the number of packed bitmaps, minimize the texture size
-        Collections.sort(results, new Comparator<WorkerResult>() {
-            @Override
-            public int compare(WorkerResult r1, WorkerResult r2) {
-                int delta = r2.count - r1.count;
-                if (delta != 0) return delta;
-                return r1.width * r1.height - r2.width * r2.height;
-            }
-        });
-
-        if (DEBUG_ATLAS) {
-            float delay = (System.nanoTime() - begin) / 1000.0f / 1000.0f / 1000.0f;
-            Log.d(LOG_TAG, String.format("Found best atlas configuration (out of %d) in %.2fs",
-                    results.size(), delay));
-        }
-
-        WorkerResult result = results.get(0);
-        return new Configuration(result.type, result.width, result.height, result.count);
-    }
-
-    /**
-     * Returns the path to the file containing the best computed
-     * atlas configuration.
-     */
-    private static File getDataFile() {
-        File systemDirectory = new File(Environment.getDataDirectory(), "system");
-        return new File(systemDirectory, "framework_atlas.config");
-    }
-
-    private static void deleteDataFile() {
-        Log.w(LOG_TAG, "Current configuration inconsistent with assets list");
-        if (!getDataFile().delete()) {
-            Log.w(LOG_TAG, "Could not delete the current configuration");
-        }
-    }
-
-    private File getFrameworkResourcesFile() {
-        return new File(mContext.getApplicationInfo().sourceDir);
-    }
-
-    /**
-     * Returns the best known atlas configuration. This method will either
-     * read the configuration from disk or start a brute-force search
-     * and save the result out to disk.
-     */
-    private Configuration chooseConfiguration(ArrayList<Bitmap> bitmaps, int pixelCount,
-            String versionName) {
-        Configuration config = null;
-
-        final File dataFile = getDataFile();
-        if (dataFile.exists()) {
-            config = readConfiguration(dataFile, versionName);
-        }
-
-        if (config == null) {
-            config = computeBestConfiguration(bitmaps, pixelCount);
-            if (config != null) writeConfiguration(config, dataFile, versionName);
-        }
-
-        return config;
-    }
-
-    /**
-     * Writes the specified atlas configuration to the specified file.
-     */
-    private void writeConfiguration(Configuration config, File file, String versionName) {
-        BufferedWriter writer = null;
-        try {
-            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
-            writer.write(getBuildIdentifier(versionName));
-            writer.newLine();
-            writer.write(config.type.toString());
-            writer.newLine();
-            writer.write(String.valueOf(config.width));
-            writer.newLine();
-            writer.write(String.valueOf(config.height));
-            writer.newLine();
-            writer.write(String.valueOf(config.count));
-            writer.newLine();
-            writer.write(String.valueOf(config.flags));
-            writer.newLine();
-        } catch (FileNotFoundException e) {
-            Log.w(LOG_TAG, "Could not write " + file, e);
-        } catch (IOException e) {
-            Log.w(LOG_TAG, "Could not write " + file, e);
-        } finally {
-            if (writer != null) {
-                try {
-                    writer.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-    }
-
-    /**
-     * Reads an atlas configuration from the specified file. This method
-     * returns null if an error occurs or if the configuration is invalid.
-     */
-    private Configuration readConfiguration(File file, String versionName) {
-        BufferedReader reader = null;
-        Configuration config = null;
-        try {
-            reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
-
-            if (checkBuildIdentifier(reader, versionName)) {
-                Atlas.Type type = Atlas.Type.valueOf(reader.readLine());
-                int width = readInt(reader, MIN_SIZE, MAX_SIZE);
-                int height = readInt(reader, MIN_SIZE, MAX_SIZE);
-                int count = readInt(reader, 0, Integer.MAX_VALUE);
-                int flags = readInt(reader, Integer.MIN_VALUE, Integer.MAX_VALUE);
-
-                config = new Configuration(type, width, height, count, flags);
-            }
-        } catch (IllegalArgumentException e) {
-            Log.w(LOG_TAG, "Invalid parameter value in " + file, e);
-        } catch (FileNotFoundException e) {
-            Log.w(LOG_TAG, "Could not read " + file, e);
-        } catch (IOException e) {
-            Log.w(LOG_TAG, "Could not read " + file, e);
-        } finally {
-            if (reader != null) {
-                try {
-                    reader.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-        return config;
-    }
-
-    private static int readInt(BufferedReader reader, int min, int max) throws IOException {
-        return Math.max(min, Math.min(max, Integer.parseInt(reader.readLine())));
-    }
-
-    /**
-     * Compares the next line in the specified buffered reader to the current
-     * build identifier. Returns whether the two values are equal.
-     *
-     * @see #getBuildIdentifier(String)
-     */
-    private boolean checkBuildIdentifier(BufferedReader reader, String versionName)
-            throws IOException {
-        String deviceBuildId = getBuildIdentifier(versionName);
-        String buildId = reader.readLine();
-        return deviceBuildId.equals(buildId);
-    }
-
-    /**
-     * Returns an identifier for the current build that can be used to detect
-     * likely changes to framework resources. The build identifier is made of
-     * several distinct values:
-     *
-     * build fingerprint/framework version name/file size of framework resources apk
-     *
-     * Only the build fingerprint should be necessary on user builds but
-     * the other values are useful to detect changes on eng builds during
-     * development.
-     *
-     * This identifier does not attempt to be exact: a new identifier does not
-     * necessarily mean the preloaded drawables have changed. It is important
-     * however that whenever the list of preloaded drawables changes, this
-     * identifier changes as well.
-     *
-     * @see #checkBuildIdentifier(java.io.BufferedReader, String)
-     */
-    private String getBuildIdentifier(String versionName) {
-        return SystemProperties.get("ro.build.fingerprint", "") + '/' + versionName + '/' +
-                String.valueOf(getFrameworkResourcesFile().length());
-    }
-
-    /**
-     * Atlas configuration. Specifies the algorithm, dimensions and flags to use.
-     */
-    private static class Configuration {
-        final Atlas.Type type;
-        final int width;
-        final int height;
-        final int count;
-        final int flags;
-
-        Configuration(Atlas.Type type, int width, int height, int count) {
-            this(type, width, height, count, Atlas.FLAG_DEFAULTS);
-        }
-
-        Configuration(Atlas.Type type, int width, int height, int count, int flags) {
-            this.type = type;
-            this.width = width;
-            this.height = height;
-            this.count = count;
-            this.flags = flags;
-        }
-
-        @Override
-        public String toString() {
-            return type.toString() + " (" + width + "x" + height + ") flags=0x" +
-                    Integer.toHexString(flags) + " count=" + count;
-        }
-    }
-
-    /**
-     * Used during the brute-force search to gather information about each
-     * variant of the packing algorithm.
-     */
-    private static class WorkerResult {
-        Atlas.Type type;
-        int width;
-        int height;
-        int count;
-
-        WorkerResult(Atlas.Type type, int width, int height, int count) {
-            this.type = type;
-            this.width = width;
-            this.height = height;
-            this.count = count;
-        }
-
-        @Override
-        public String toString() {
-            return String.format("%s %dx%d", type.toString(), width, height);
-        }
-    }
-
-    /**
-     * A compute worker will try a finite number of variations of the packing
-     * algorithms and save the results in a supplied list.
-     */
-    private static class ComputeWorker implements Runnable {
-        private final int mStart;
-        private final int mEnd;
-        private final int mStep;
-        private final List<Bitmap> mBitmaps;
-        private final List<WorkerResult> mResults;
-        private final CountDownLatch mSignal;
-        private final int mThreshold;
-
-        /**
-         * Creates a new compute worker to brute-force through a range of
-         * packing algorithms variants.
-         *
-         * @param start The minimum texture width to try
-         * @param end The maximum texture width to try
-         * @param step The number of pixels to increment the texture width by at each step
-         * @param bitmaps The list of bitmaps to pack in the atlas
-         * @param pixelCount The total number of pixels occupied by the list of bitmaps
-         * @param results The list of results in which to save the brute-force search results
-         * @param signal Latch to decrement when this worker is done, may be null
-         */
-        ComputeWorker(int start, int end, int step, List<Bitmap> bitmaps, int pixelCount,
-                List<WorkerResult> results, CountDownLatch signal) {
-            mStart = start;
-            mEnd = end;
-            mStep = step;
-            mBitmaps = bitmaps;
-            mResults = results;
-            mSignal = signal;
-
-            // Minimum number of pixels we want to be able to pack
-            int threshold = (int) (pixelCount * PACKING_THRESHOLD);
-            // Make sure we can find at least one configuration
-            while (threshold > MAX_SIZE * MAX_SIZE) {
-                threshold >>= 1;
-            }
-            mThreshold = threshold;
-        }
-
-        @Override
-        public void run() {
-            if (DEBUG_ATLAS) Log.d(LOG_TAG, "Running " + Thread.currentThread().getName());
-
-            Atlas.Entry entry = new Atlas.Entry();
-
-            for (int width = mEnd; width > mStart; width -= mStep) {
-                for (int height = MAX_SIZE; height > MIN_SIZE; height -= STEP) {
-                    // If the atlas is not big enough, skip it
-                    if (width * height <= mThreshold) continue;
-
-                    boolean packSuccess = false;
-
-                    for (Atlas.Type type : Atlas.Type.values()) {
-                        final int count = packBitmaps(type, width, height, entry);
-                        if (count > 0) {
-                            mResults.add(new WorkerResult(type, width, height, count));
-                            if (count == mBitmaps.size()) {
-                                // If we were able to pack everything let's stop here
-                                // Changing the type further won't make things better
-                                packSuccess = true;
-                                break;
-                            }
-                        }
-                    }
-
-                    // If we were not able to pack everything let's stop here
-                    // Decreasing the height further won't make things better
-                    if (!packSuccess) {
-                        break;
-                    }
-                }
-            }
-
-            if (mSignal != null) {
-                mSignal.countDown();
-            }
-        }
-
-        private int packBitmaps(Atlas.Type type, int width, int height, Atlas.Entry entry) {
-            int total = 0;
-            Atlas atlas = new Atlas(type, width, height);
-
-            final int count = mBitmaps.size();
-            for (int i = 0; i < count; i++) {
-                final Bitmap bitmap = mBitmaps.get(i);
-                if (atlas.pack(bitmap.getWidth(), bitmap.getHeight(), entry) != null) {
-                    total++;
-                }
-            }
-
-            return total;
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index fa2f6ac..ae60d1e 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -78,6 +78,7 @@
 import android.net.metrics.DefaultNetworkEvent;
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.NetworkEvent;
+import android.net.util.AvoidBadWifiTracker;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -403,11 +404,6 @@
     private static final int EVENT_REQUEST_LINKPROPERTIES  = 32;
     private static final int EVENT_REQUEST_NETCAPABILITIES = 33;
 
-    /**
-     * Used internally to (re)configure avoid bad wifi setting.
-     */
-    private static final int EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI = 34;
-
     /** Handler thread used for both of the handlers below. */
     @VisibleForTesting
     protected final HandlerThread mHandlerThread;
@@ -501,6 +497,9 @@
 
     private final IpConnectivityLog mMetricsLog;
 
+    @VisibleForTesting
+    final AvoidBadWifiTracker mAvoidBadWifiTracker;
+
     /**
      * Implements support for the legacy "one network per network type" model.
      *
@@ -863,14 +862,8 @@
                 LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
         mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
 
-        intentFilter = new IntentFilter();
-        intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
-        mContext.registerReceiverAsUser(new BroadcastReceiver() {
-            public void onReceive(Context context, Intent intent) {
-                mHandler.sendEmptyMessage(EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI);
-            }
-        }, UserHandle.ALL, intentFilter, null, null);
-        updateAvoidBadWifi();
+        mAvoidBadWifiTracker = createAvoidBadWifiTracker(
+                mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
     }
 
     private NetworkRequest createInternetRequestForTransport(
@@ -921,12 +914,6 @@
         mSettingsObserver.observe(
                 Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
                 EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
-
-        // Watch for whether to automatically switch away from wifi networks that lose Internet
-        // access.
-        mSettingsObserver.observe(
-                Settings.Global.getUriFor(Settings.Global.NETWORK_AVOID_BAD_WIFI),
-                EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI);
     }
 
     private synchronized int nextNetworkRequestId() {
@@ -2794,36 +2781,23 @@
                 PROMPT_UNVALIDATED_DELAY_MS);
     }
 
-    private boolean mAvoidBadWifi = true;
-
     public boolean avoidBadWifi() {
-        return mAvoidBadWifi;
+        return mAvoidBadWifiTracker.currentValue();
     }
 
-    @VisibleForTesting
-    /** Whether the device or carrier configuration disables avoiding bad wifi by default. */
-    public boolean configRestrictsAvoidBadWifi() {
-        return mContext.getResources().getInteger(R.integer.config_networkAvoidBadWifi) == 0;
+    private void rematchForAvoidBadWifiUpdate() {
+        rematchAllNetworksAndRequests(null, 0);
+        for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
+            if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+                sendUpdatedScoreToFactories(nai);
+            }
+        }
     }
 
-    /** Whether we should display a notification when wifi becomes unvalidated. */
-    public boolean shouldNotifyWifiUnvalidated() {
-        return configRestrictsAvoidBadWifi() &&
-                Settings.Global.getString(mContext.getContentResolver(),
-                        Settings.Global.NETWORK_AVOID_BAD_WIFI) == null;
-    }
-
-    private boolean updateAvoidBadWifi() {
-        boolean settingAvoidBadWifi = "1".equals(Settings.Global.getString(
-                mContext.getContentResolver(), Settings.Global.NETWORK_AVOID_BAD_WIFI));
-
-        boolean prev = mAvoidBadWifi;
-        mAvoidBadWifi = settingAvoidBadWifi || !configRestrictsAvoidBadWifi();
-        return mAvoidBadWifi != prev;
-    }
-
+    // TODO: Evaluate whether this is of interest to other consumers of
+    // AvoidBadWifiTracker and worth moving out of here.
     private void dumpAvoidBadWifiSettings(IndentingPrintWriter pw) {
-        boolean configRestrict = configRestrictsAvoidBadWifi();
+        final boolean configRestrict = mAvoidBadWifiTracker.configRestrictsAvoidBadWifi();
         if (!configRestrict) {
             pw.println("Bad Wi-Fi avoidance: unrestricted");
             return;
@@ -2833,8 +2807,7 @@
         pw.increaseIndent();
         pw.println("Config restrict:   " + configRestrict);
 
-        String value = Settings.Global.getString(
-                mContext.getContentResolver(), Settings.Global.NETWORK_AVOID_BAD_WIFI);
+        final String value = mAvoidBadWifiTracker.getSettingsValue();
         String description;
         // Can't use a switch statement because strings are legal case labels, but null is not.
         if ("0".equals(value)) {
@@ -2897,17 +2870,12 @@
         showValidationNotification(nai, NotificationType.NO_INTERNET);
     }
 
-    // TODO: Delete this like updateMobileDataAlwaysOn above.
-    @VisibleForTesting
-    void updateNetworkAvoidBadWifi() {
-        mHandler.sendEmptyMessage(EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI);
-    }
-
     private void handleNetworkUnvalidated(NetworkAgentInfo nai) {
         NetworkCapabilities nc = nai.networkCapabilities;
         if (DBG) log("handleNetworkUnvalidated " + nai.name() + " cap=" + nc);
 
-        if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && shouldNotifyWifiUnvalidated()) {
+        if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
+            mAvoidBadWifiTracker.shouldNotifyWifiUnvalidated()) {
             showValidationNotification(nai, NotificationType.LOST_INTERNET);
         }
     }
@@ -3002,18 +2970,6 @@
                     handleMobileDataAlwaysOn();
                     break;
                 }
-                case EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI: {
-                    if (updateAvoidBadWifi()) {
-                        rematchAllNetworksAndRequests(null, 0);
-                        for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
-                            if (nai.networkCapabilities.hasTransport(
-                                    NetworkCapabilities.TRANSPORT_WIFI)) {
-                                sendUpdatedScoreToFactories(nai);
-                            }
-                        }
-                    }
-                    break;
-                }
                 case EVENT_REQUEST_LINKPROPERTIES:
                     handleRequestLinkProperties((NetworkRequest) msg.obj, msg.arg1);
                     break;
@@ -5577,6 +5533,11 @@
     }
 
     @VisibleForTesting
+    AvoidBadWifiTracker createAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
+        return new AvoidBadWifiTracker(c, h, r);
+    }
+
+    @VisibleForTesting
     public WakeupMessage makeWakeupMessage(Context c, Handler h, String s, int cmd, Object obj) {
         return new WakeupMessage(c, h, s, cmd, 0, 0, obj);
     }
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index dbc1f31..466633a 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -2726,12 +2726,12 @@
                 }
             }
         } else if ("whitelist".equals(cmd)) {
-            long token = Binder.clearCallingIdentity();
-            try {
-                String arg = shell.getNextArg();
-                if (arg != null) {
-                    getContext().enforceCallingOrSelfPermission(
-                            android.Manifest.permission.DEVICE_POWER, null);
+            String arg = shell.getNextArg();
+            if (arg != null) {
+                getContext().enforceCallingOrSelfPermission(
+                        android.Manifest.permission.DEVICE_POWER, null);
+                long token = Binder.clearCallingIdentity();
+                try {
                     do {
                         if (arg.length() < 1 || (arg.charAt(0) != '-'
                                 && arg.charAt(0) != '+' && arg.charAt(0) != '=')) {
@@ -2754,30 +2754,30 @@
                             pw.println(getPowerSaveWhitelistAppInternal(pkg));
                         }
                     } while ((arg=shell.getNextArg()) != null);
-                } else {
-                    synchronized (this) {
-                        for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
-                            pw.print("system-excidle,");
-                            pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
-                            pw.print(",");
-                            pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
-                        }
-                        for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
-                            pw.print("system,");
-                            pw.print(mPowerSaveWhitelistApps.keyAt(j));
-                            pw.print(",");
-                            pw.println(mPowerSaveWhitelistApps.valueAt(j));
-                        }
-                        for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
-                            pw.print("user,");
-                            pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
-                            pw.print(",");
-                            pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
-                        }
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            } else {
+                synchronized (this) {
+                    for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
+                        pw.print("system-excidle,");
+                        pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
+                        pw.print(",");
+                        pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
+                    }
+                    for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
+                        pw.print("system,");
+                        pw.print(mPowerSaveWhitelistApps.keyAt(j));
+                        pw.print(",");
+                        pw.println(mPowerSaveWhitelistApps.valueAt(j));
+                    }
+                    for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
+                        pw.print("user,");
+                        pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
+                        pw.print(",");
+                        pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
                     }
                 }
-            } finally {
-                Binder.restoreCallingIdentity(token);
             }
         } else if ("tempwhitelist".equals(cmd)) {
             String opt;
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 8f16504..e64aa16 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -77,6 +77,7 @@
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.provider.Settings;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.PhoneStateListener;
@@ -1699,6 +1700,7 @@
                 return;
             }
 
+            Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
             try {
                 mConnector.execute("bandwidth", suffix + chain, uid);
                 if (enable) {
@@ -1708,6 +1710,8 @@
                 }
             } catch (NativeDaemonConnectorException e) {
                 throw e.rethrowAsParcelableException();
+            } finally {
+                Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
             }
         }
     }
@@ -1730,6 +1734,7 @@
                 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
                 return true;
             }
+            Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
             try {
                 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
                 if (changed) {
@@ -1741,6 +1746,8 @@
             } catch (RemoteException e) {
                 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
                 return false;
+            } finally {
+                Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
             }
         }
     }
diff --git a/services/core/java/com/android/server/accounts/AccountsDb.java b/services/core/java/com/android/server/accounts/AccountsDb.java
index 1adcf34..cb594f6 100644
--- a/services/core/java/com/android/server/accounts/AccountsDb.java
+++ b/services/core/java/com/android/server/accounts/AccountsDb.java
@@ -913,6 +913,9 @@
         ) > 0;
     }
 
+    /**
+     * Returns list of all grants as {@link Pair pairs} of account name and UID.
+     */
     List<Pair<String, Integer>> findAllAccountGrants() {
         SQLiteDatabase db = mDeDatabase.getReadableDatabase();
         try (Cursor cursor = db.rawQuery(ACCOUNT_ACCESS_GRANTS, null)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c32cac8..097d2a5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1121,21 +1121,29 @@
      */
     final AppOpsService mAppOpsService;
 
-    /**
-     * Current global configuration information. Contains general settings for the entire system,
-     * also corresponds to the merged configuration of the default display.
-     */
-    Configuration mGlobalConfiguration = new Configuration();
-
     /** Current sequencing integer of the configuration, for skipping old configurations. */
     private int mConfigurationSeq;
 
     /**
      * Temp object used when global configuration is updated. It is also sent to outer world
-     * instead of {@link #mGlobalConfiguration} because we don't trust anyone...
+     * instead of {@link #getGlobalConfiguration} because we don't trust anyone...
      */
     private Configuration mTempGlobalConfig = new Configuration();
 
+    private final UpdateConfigurationResult mTmpUpdateConfigurationResult =
+            new UpdateConfigurationResult();
+    private static final class UpdateConfigurationResult {
+        // Configuration changes that were updated.
+        int changes;
+        // If the activity was relaunched to match the new configuration.
+        boolean activityRelaunched;
+
+        void reset() {
+            changes = 0;
+            activityRelaunched = false;
+        }
+    }
+
     boolean mSuppressResizeConfigChanges;
 
     /**
@@ -1568,6 +1576,14 @@
 
     final boolean mPermissionReviewRequired;
 
+    /**
+     * Current global configuration information. Contains general settings for the entire system,
+     * also corresponds to the merged configuration of the default display.
+     */
+    Configuration getGlobalConfiguration() {
+        return mStackSupervisor.getConfiguration();
+    }
+
     final class KillHandler extends Handler {
         static final int KILL_PROCESS_GROUP_MSG = 4000;
 
@@ -2315,7 +2331,7 @@
                     callingPackage = r.info.getComponentName();
                     if (mInVrMode != vrMode) {
                         mInVrMode = vrMode;
-                        mShowDialogs = shouldShowDialogs(mGlobalConfiguration, mInVrMode);
+                        mShowDialogs = shouldShowDialogs(getGlobalConfiguration(), mInVrMode);
                         if (r.app != null) {
                             ProcessRecord proc = r.app;
                             if (proc.vrThreadTid > 0) {
@@ -2691,15 +2707,16 @@
 
         mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));
 
-        mGlobalConfiguration.setToDefaults();
-        mGlobalConfiguration.setLocales(LocaleList.getDefault());
+        mTempGlobalConfig.setToDefaults();
+        mTempGlobalConfig.setLocales(LocaleList.getDefault());
+        mConfigurationSeq = mTempGlobalConfig.seq = 1;
 
-        mConfigurationSeq = mGlobalConfiguration.seq = 1;
         mProcessCpuTracker.init();
 
+        mStackSupervisor = new ActivityStackSupervisor(this);
+        mStackSupervisor.onConfigurationChanged(mTempGlobalConfig);
         mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
         mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
-        mStackSupervisor = new ActivityStackSupervisor(this);
         mActivityStarter = new ActivityStarter(this, mStackSupervisor);
         mRecentTasks = new RecentTasks(this, mStackSupervisor);
 
@@ -3087,7 +3104,7 @@
         synchronized (this) {
             ActivityRecord r = mStackSupervisor.isInAnyStackLocked(token);
             if (r != null) {
-                r.task.stack.notifyActivityDrawnLocked(r);
+                r.getStack().notifyActivityDrawnLocked(r);
             }
         }
     }
@@ -3131,8 +3148,9 @@
     }
 
     final void showUnsupportedZoomDialogIfNeededLocked(ActivityRecord r) {
-        if (mGlobalConfiguration.densityDpi != DisplayMetrics.DENSITY_DEVICE_STABLE
-                && r.appInfo.requiresSmallestWidthDp > mGlobalConfiguration.smallestScreenWidthDp) {
+        final Configuration globalConfig = getGlobalConfiguration();
+        if (globalConfig.densityDpi != DisplayMetrics.DENSITY_DEVICE_STABLE
+                && r.appInfo.requiresSmallestWidthDp > globalConfig.smallestScreenWidthDp) {
             final Message msg = Message.obtain();
             msg.what = SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG;
             msg.obj = r;
@@ -4735,7 +4753,7 @@
                 return;
             }
             TaskRecord task = r.task;
-            if (task != null && (!task.mFullscreen || !task.stack.mFullscreen)) {
+            if (task != null && (!task.mFullscreen || !task.getStack().mFullscreen)) {
                 // Fixed screen orientation isn't supported when activities aren't in full screen
                 // mode.
                 return;
@@ -4743,7 +4761,7 @@
             final long origId = Binder.clearCallingIdentity();
             mWindowManager.setAppOrientation(r.appToken, requestedOrientation);
             Configuration config = mWindowManager.updateOrientationFromAppTokens(
-                    mGlobalConfiguration, r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
+                    getGlobalConfiguration(), r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
             if (config != null) {
                 r.frozenBeforeDestroy = true;
                 if (!updateConfigurationLocked(config, r, false)) {
@@ -4775,7 +4793,8 @@
             final long origId = Binder.clearCallingIdentity();
             try {
                 r.forceNewConfig = true;
-                r.task.stack.ensureActivityConfigurationLocked(r, 0, false);
+                r.ensureActivityConfigurationLocked(0 /* globalChanges */,
+                        false /* preserveWindow */);
             } finally {
                 Binder.restoreCallingIdentity(origId);
             }
@@ -4821,7 +4840,7 @@
             }
             if (mController != null) {
                 // Find the first activity that is not finishing.
-                ActivityRecord next = r.task.stack.topRunningActivityLocked(token, 0);
+                ActivityRecord next = r.getStack().topRunningActivityLocked(token, 0);
                 if (next != null) {
                     // ask watcher if this is allowed
                     boolean resumeOK = true;
@@ -4855,7 +4874,7 @@
                         Slog.i(TAG, "Removing task failed to finish activity");
                     }
                 } else {
-                    res = tr.stack.requestFinishActivityLocked(token, resultCode,
+                    res = tr.getStack().requestFinishActivityLocked(token, resultCode,
                             resultData, "app-request", true);
                     if (!res) {
                         Slog.i(TAG, "Failed to finish by app-request");
@@ -4889,7 +4908,7 @@
             for (int i = 0; i < activities.size(); i++) {
                 ActivityRecord r = activities.get(i);
                 if (!r.finishing && r.isInStackLocked()) {
-                    r.task.stack.finishActivityLocked(r, Activity.RESULT_CANCELED,
+                    r.getStack().finishActivityLocked(r, Activity.RESULT_CANCELED,
                             null, "finish-heavy", true);
                 }
             }
@@ -4925,7 +4944,7 @@
             final long origId = Binder.clearCallingIdentity();
             ActivityRecord r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
-                r.task.stack.finishSubActivityLocked(r, resultWho, requestCode);
+                r.getStack().finishSubActivityLocked(r, resultWho, requestCode);
             }
             Binder.restoreCallingIdentity(origId);
         }
@@ -4949,7 +4968,7 @@
                     mStackSupervisor.showLockTaskToast();
                     return false;
                 }
-                return task.stack.finishActivityAffinityLocked(r);
+                return task.getStack().finishActivityAffinityLocked(r);
             } finally {
                 Binder.restoreCallingIdentity(origId);
             }
@@ -4980,7 +4999,7 @@
                 if (r == null) {
                     return false;
                 }
-                return r.task.stack.safelyDestroyActivityLocked(r, "app-req");
+                return r.getStack().safelyDestroyActivityLocked(r, "app-req");
             } finally {
                 Binder.restoreCallingIdentity(origId);
             }
@@ -6530,7 +6549,7 @@
                                  PackageManager.NOTIFY_PACKAGE_USE_INSTRUMENTATION);
             }
             if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Binding proc "
-                    + processName + " with config " + mGlobalConfiguration);
+                    + processName + " with config " + getGlobalConfiguration());
             ApplicationInfo appInfo = app.instrumentationInfo != null
                     ? app.instrumentationInfo : app.info;
             app.compat = compatibilityInfoForPackageLocked(appInfo);
@@ -6555,7 +6574,7 @@
                     app.instrumentationUiAutomationConnection, testMode,
                     mBinderTransactionTrackingEnabled, enableTrackAllocation,
                     isRestrictedBackupMode || !normalMode, app.persistent,
-                    new Configuration(mGlobalConfiguration), app.compat,
+                    new Configuration(getGlobalConfiguration()), app.compat,
                     getCommonServicesLocked(app.isolated),
                     mCoreSettingsObserver.getCoreSettingsLocked(),
                     buildSerial);
@@ -6883,10 +6902,7 @@
     public final void activityResumed(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         synchronized(this) {
-            ActivityStack stack = ActivityRecord.getStackLocked(token);
-            if (stack != null) {
-                stack.activityResumedLocked(token);
-            }
+            ActivityRecord.activityResumedLocked(token);
         }
         Binder.restoreCallingIdentity(origId);
     }
@@ -6916,9 +6932,9 @@
         final long origId = Binder.clearCallingIdentity();
 
         synchronized (this) {
-            ActivityRecord r = ActivityRecord.isInStackLocked(token);
+            final ActivityRecord r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
-                r.task.stack.activityStoppedLocked(r, icicle, persistentState, description);
+                r.activityStoppedLocked(icicle, persistentState, description);
             }
         }
 
@@ -9062,7 +9078,7 @@
         rti.origActivity = tr.origActivity;
         rti.realActivity = tr.realActivity;
         rti.description = tr.lastDescription;
-        rti.stackId = tr.stack != null ? tr.stack.mStackId : -1;
+        rti.stackId = tr.getStackId();
         rti.userId = tr.userId;
         rti.taskDescription = new ActivityManager.TaskDescription(tr.lastTaskDescription);
         rti.firstActiveTime = tr.firstActiveTime;
@@ -9191,15 +9207,15 @@
                             continue;
                         }
                     }
+                    final ActivityStack stack = tr.getStack();
                     if ((flags & ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS) != 0) {
-                        if (tr.stack != null && tr.stack.isHomeStack()) {
+                        if (stack != null && stack.isHomeStack()) {
                             if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
                                     "Skipping, home stack task: " + tr);
                             continue;
                         }
                     }
                     if ((flags & ActivityManager.RECENT_INGORE_DOCKED_STACK_TOP_TASK) != 0) {
-                        final ActivityStack stack = tr.stack;
                         if (stack != null && stack.isDockedStack() && stack.topTask() == tr) {
                             if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
                                     "Skipping, top task in docked stack: " + tr);
@@ -9207,7 +9223,7 @@
                         }
                     }
                     if ((flags & ActivityManager.RECENT_INGORE_PINNED_STACK_TASKS) != 0) {
-                        if (tr.stack != null && tr.stack.isPinnedStack()) {
+                        if (stack != null && stack.isPinnedStack()) {
                             if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
                                     "Skipping, pinned stack task: " + tr);
                             continue;
@@ -9311,17 +9327,9 @@
                     }
                 }
 
-                // Use the full screen as the context for the task thumbnail
-                final Point displaySize = new Point();
-                final TaskThumbnailInfo thumbnailInfo = new TaskThumbnailInfo();
-                r.task.stack.getDisplaySize(displaySize);
-                thumbnailInfo.taskWidth = displaySize.x;
-                thumbnailInfo.taskHeight = displaySize.y;
-                thumbnailInfo.screenOrientation = mGlobalConfiguration.orientation;
-
                 TaskRecord task = new TaskRecord(this,
                         mStackSupervisor.getNextTaskIdForUserLocked(r.userId),
-                        ainfo, intent, description, thumbnailInfo);
+                        ainfo, intent, description, new TaskThumbnailInfo());
 
                 int trimIdx = mRecentTasks.trimForTaskLocked(task, false);
                 if (trimIdx >= 0) {
@@ -9338,7 +9346,7 @@
 
                 task.inRecents = true;
                 mRecentTasks.add(task);
-                r.task.stack.addTask(task, false, "addAppTask");
+                r.getStack().addTask(task, false, "addAppTask");
 
                 task.setLastThumbnailLocked(thumbnail);
                 task.freeLastThumbnail();
@@ -9404,7 +9412,7 @@
                 // - a non-null bounds on a non-freeform (fullscreen OR docked) task moves
                 //   that task to freeform
                 // - otherwise the task is not moved
-                int stackId = task.stack.mStackId;
+                int stackId = task.getStackId();
                 if (!StackId.isTaskResizeAllowed(stackId)) {
                     throw new IllegalArgumentException("resizeTask not allowed on task=" + task);
                 }
@@ -9414,7 +9422,7 @@
                     stackId = FREEFORM_WORKSPACE_STACK_ID;
                 }
                 boolean preserveWindow = (resizeMode & RESIZE_MODE_PRESERVE_WINDOW) != 0;
-                if (stackId != task.stack.mStackId) {
+                if (stackId != task.getStackId()) {
                     mStackSupervisor.moveTaskToStackUncheckedLocked(
                             task, stackId, ON_TOP, !FORCE_FOCUS, "resizeTask");
                     preserveWindow = false;
@@ -9441,7 +9449,7 @@
                     Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found");
                     return rect;
                 }
-                if (task.stack != null) {
+                if (task.getStack() != null) {
                     // Return the bounds from window manager since it will be adjusted for various
                     // things like the presense of a docked stack for tasks that aren't resizeable.
                     mWindowManager.getTaskBounds(task.taskId, rect);
@@ -9556,7 +9564,7 @@
         for (int i = 0; i < procsToKill.size(); i++) {
             ProcessRecord pr = procsToKill.get(i);
             if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
-                    && pr.curReceiver == null) {
+                    && pr.curReceivers.isEmpty()) {
                 pr.kill("remove task", true);
             } else {
                 // We delay killing processes that are not in the background or running a receiver.
@@ -10099,7 +10107,8 @@
             synchronized (this) {
                 final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(
                         taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
-                return tr != null && tr.stack != null && tr.stack.isHomeStack();
+                final ActivityStack stack = tr != null ? tr.getStack() : null;
+                return stack != null && stack.isHomeStack();
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -12446,7 +12455,7 @@
                 }
                 final boolean translucentChanged = r.changeWindowTranslucency(true);
                 if (translucentChanged) {
-                    r.task.stack.releaseBackgroundResources(r);
+                    r.getStack().releaseBackgroundResources(r);
                     mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                 }
                 mWindowManager.setAppFullscreen(token, true);
@@ -12473,7 +12482,7 @@
                 }
                 final boolean translucentChanged = r.changeWindowTranslucency(false);
                 if (translucentChanged) {
-                    r.task.stack.convertActivityToTranslucent(r);
+                    r.getStack().convertActivityToTranslucent(r);
                 }
                 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                 mWindowManager.setAppFullscreen(token, false);
@@ -13155,8 +13164,8 @@
             // This happens before any activities are started, so we can change global configuration
             // in-place.
             updateConfigurationLocked(configuration, null, true);
-            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                    "Initial config: " + mGlobalConfiguration);
+            final Configuration globalConfig = getGlobalConfiguration();
+            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Initial config: " + globalConfig);
 
             // Load resources only after the current configuration has been set.
             final Resources res = mContext.getResources();
@@ -13171,11 +13180,10 @@
                     com.android.internal.R.string.config_appsNotReportingCrashes));
             mUserController.mUserSwitchUiEnabled = !res.getBoolean(
                     com.android.internal.R.bool.config_customUserSwitchUi);
-            if ((mGlobalConfiguration.uiMode & UI_MODE_TYPE_TELEVISION)
-                    == UI_MODE_TYPE_TELEVISION) {
+            if ((globalConfig.uiMode & UI_MODE_TYPE_TELEVISION) == UI_MODE_TYPE_TELEVISION) {
                 mFullscreenThumbnailScale = (float) res
                     .getInteger(com.android.internal.R.integer.thumbnail_width_tv) /
-                    (float) mGlobalConfiguration.screenWidthDp;
+                    (float) globalConfig.screenWidthDp;
             } else {
                 mFullscreenThumbnailScale = res.getFraction(
                     com.android.internal.R.fraction.thumbnail_fullscreen_scale, 1, 1);
@@ -14770,7 +14778,7 @@
             pw.println("  mHeavyWeightProcess: " + mHeavyWeightProcess);
         }
         if (dumpPackage == null) {
-            pw.println("  mGlobalConfiguration: " + mGlobalConfiguration);
+            pw.println("  mGlobalConfiguration: " + getGlobalConfiguration());
         }
         if (dumpAll) {
             pw.println("  mConfigWillChange: " + getFocusedStack().mConfigWillChange);
@@ -18753,15 +18761,16 @@
     public ConfigurationInfo getDeviceConfigurationInfo() {
         ConfigurationInfo config = new ConfigurationInfo();
         synchronized (this) {
-            config.reqTouchScreen = mGlobalConfiguration.touchscreen;
-            config.reqKeyboardType = mGlobalConfiguration.keyboard;
-            config.reqNavigation = mGlobalConfiguration.navigation;
-            if (mGlobalConfiguration.navigation == Configuration.NAVIGATION_DPAD
-                    || mGlobalConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
+            final Configuration globalConfig = getGlobalConfiguration();
+            config.reqTouchScreen = globalConfig.touchscreen;
+            config.reqKeyboardType = globalConfig.keyboard;
+            config.reqNavigation = globalConfig.navigation;
+            if (globalConfig.navigation == Configuration.NAVIGATION_DPAD
+                    || globalConfig.navigation == Configuration.NAVIGATION_TRACKBALL) {
                 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
             }
-            if (mGlobalConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
-                    && mGlobalConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
+            if (globalConfig.keyboard != Configuration.KEYBOARD_UNDEFINED
+                    && globalConfig.keyboard != Configuration.KEYBOARD_NOKEYS) {
                 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
             }
             config.reqGlEsVersion = GL_ES_VERSION;
@@ -18785,7 +18794,7 @@
     public Configuration getConfiguration() {
         Configuration ci;
         synchronized(this) {
-            ci = new Configuration(mGlobalConfiguration);
+            ci = new Configuration(getGlobalConfiguration());
             ci.userSetLocale = false;
         }
         return ci;
@@ -18843,7 +18852,7 @@
     private void updateFontScaleIfNeeded(@UserIdInt int userId) {
         final float scaleFactor = Settings.System.getFloatForUser(mContext.getContentResolver(),
                 FONT_SCALE, 1.0f, userId);
-        if (mGlobalConfiguration.fontScale != scaleFactor) {
+        if (getGlobalConfiguration().fontScale != scaleFactor) {
             final Configuration configuration = mWindowManager.computeNewConfiguration();
             configuration.fontScale = scaleFactor;
             synchronized (this) {
@@ -18872,7 +18881,7 @@
     }
 
     @Override
-    public void updateConfiguration(Configuration values) {
+    public boolean updateConfiguration(Configuration values) {
         enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
                 "updateConfiguration()");
 
@@ -18887,16 +18896,23 @@
             }
 
             final long origId = Binder.clearCallingIdentity();
-            if (values != null) {
-                Settings.System.clearConfiguration(values);
+
+            try {
+                if (values != null) {
+                    Settings.System.clearConfiguration(values);
+                }
+                updateConfigurationLocked(values, null, false, false /* persistent */,
+                        UserHandle.USER_NULL, false /* deferResume */,
+                        mTmpUpdateConfigurationResult);
+                return mTmpUpdateConfigurationResult.changes != 0;
+            } finally {
+                Binder.restoreCallingIdentity(origId);
             }
-            updateConfigurationLocked(values, null, false);
-            Binder.restoreCallingIdentity(origId);
         }
     }
 
     void updateUserConfigurationLocked() {
-        final Configuration configuration = new Configuration(mGlobalConfiguration);
+        final Configuration configuration = new Configuration(getGlobalConfiguration());
         final int currentUserId = mUserController.getCurrentUserIdLocked();
         Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration,
                 currentUserId, Settings.System.canWrite(mContext));
@@ -18919,6 +18935,12 @@
     // To cache the list of supported system locales
     private String[] mSupportedSystemLocales = null;
 
+    private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+            boolean initLocale, boolean persistent, int userId, boolean deferResume) {
+        return updateConfigurationLocked(values, starting, initLocale, persistent, userId,
+                deferResume, null /* result */);
+    }
+
     /**
      * Do either or both things: (1) change the current configuration, and (2)
      * make sure the given activity is running with the (now) current
@@ -18930,7 +18952,8 @@
      *               for that particular user
      */
     private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
-            boolean initLocale, boolean persistent, int userId, boolean deferResume) {
+            boolean initLocale, boolean persistent, int userId, boolean deferResume,
+            UpdateConfigurationResult result) {
         int changes = 0;
         boolean kept = true;
 
@@ -18949,13 +18972,18 @@
                 mWindowManager.continueSurfaceLayout();
             }
         }
+
+        if (result != null) {
+            result.changes = changes;
+            result.activityRelaunched = !kept;
+        }
         return kept;
     }
 
     /** Update default (global) configuration and notify listeners about changes. */
     private int updateGlobalConfiguration(@NonNull Configuration values, boolean initLocale,
             boolean persistent, int userId, boolean deferResume) {
-        mTempGlobalConfig.setTo(mGlobalConfiguration);
+        mTempGlobalConfig.setTo(getGlobalConfiguration());
         final int changes = mTempGlobalConfig.updateFrom(values);
         if (changes == 0) {
             return 0;
@@ -18985,7 +19013,9 @@
         mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
         mTempGlobalConfig.seq = mConfigurationSeq;
 
-        mGlobalConfiguration.setTo(mTempGlobalConfig);
+        // Update stored global config and notify everyone about the change.
+        mStackSupervisor.onConfigurationChanged(mTempGlobalConfig);
+
         Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempGlobalConfig);
         // TODO(multi-display): Update UsageEvents#Event to include displayId.
         mUsageStatsService.reportConfigurationChange(mTempGlobalConfig,
@@ -19007,7 +19037,7 @@
 
         // We need another copy of global config because we're scheduling some calls instead of
         // running them in place. We need to be sure that object we send will be handled unchanged.
-        final Configuration configCopy = new Configuration(mGlobalConfiguration);
+        final Configuration configCopy = new Configuration(mTempGlobalConfig);
         if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
             Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
             msg.obj = configCopy;
@@ -19085,7 +19115,8 @@
             }
 
             if (starting != null) {
-                kept = mainStack.ensureActivityConfigurationLocked(starting, changes, false);
+                kept = starting.ensureActivityConfigurationLocked(changes,
+                        false /* preserveWindow */);
                 // And we need to make sure at this point that all other activities
                 // are made visible with the correct configuration.
                 mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes,
@@ -19128,7 +19159,7 @@
         synchronized (this) {
             ActivityRecord srec = ActivityRecord.forTokenLocked(token);
             if (srec != null) {
-                return srec.task.stack.shouldUpRecreateTaskLocked(srec, destAffinity);
+                return srec.getStack().shouldUpRecreateTaskLocked(srec, destAffinity);
             }
         }
         return false;
@@ -19140,7 +19171,7 @@
         synchronized (this) {
             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
             if (r != null) {
-                return r.task.stack.navigateUpToLocked(r, destIntent, resultCode, resultData);
+                return r.getStack().navigateUpToLocked(r, destIntent, resultCode, resultData);
             }
             return false;
         }
@@ -19172,26 +19203,28 @@
     // LIFETIME MANAGEMENT
     // =========================================================
 
-    // Returns which broadcast queue the app is the current [or imminent] receiver
-    // on, or 'null' if the app is not an active broadcast recipient.
-    private BroadcastQueue isReceivingBroadcast(ProcessRecord app) {
-        BroadcastRecord r = app.curReceiver;
-        if (r != null) {
-            return r.queue;
+    // Returns whether the app is receiving broadcast.
+    // If receiving, fetch all broadcast queues which the app is
+    // the current [or imminent] receiver on.
+    private boolean isReceivingBroadcastLocked(ProcessRecord app,
+            ArraySet<BroadcastQueue> receivingQueues) {
+        if (!app.curReceivers.isEmpty()) {
+            for (BroadcastRecord r : app.curReceivers) {
+                receivingQueues.add(r.queue);
+            }
+            return true;
         }
 
         // It's not the current receiver, but it might be starting up to become one
-        synchronized (this) {
-            for (BroadcastQueue queue : mBroadcastQueues) {
-                r = queue.mPendingBroadcast;
-                if (r != null && r.curApp == app) {
-                    // found it; report which queue it's in
-                    return queue;
-                }
+        for (BroadcastQueue queue : mBroadcastQueues) {
+            final BroadcastRecord r = queue.mPendingBroadcast;
+            if (r != null && r.curApp == app) {
+                // found it; report which queue it's in
+                receivingQueues.add(queue);
             }
         }
 
-        return null;
+        return !receivingQueues.isEmpty();
     }
 
     Association startAssociationLocked(int sourceUid, String sourceProcess, int sourceState,
@@ -19358,7 +19391,7 @@
         int schedGroup;
         int procState;
         boolean foregroundActivities = false;
-        BroadcastQueue queue;
+        final ArraySet<BroadcastQueue> queues = new ArraySet<BroadcastQueue>();
         if (app == TOP_APP) {
             // The last app on the list is the foreground app.
             adj = ProcessList.FOREGROUND_APP_ADJ;
@@ -19372,13 +19405,13 @@
             schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
             app.adjType = "instrumentation";
             procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
-        } else if ((queue = isReceivingBroadcast(app)) != null) {
+        } else if (isReceivingBroadcastLocked(app, queues)) {
             // An app that is currently receiving a broadcast also
             // counts as being in the foreground for OOM killer purposes.
             // It's placed in a sched group based on the nature of the
             // broadcast as reflected by which queue it's active in.
             adj = ProcessList.FOREGROUND_APP_ADJ;
-            schedGroup = (queue == mFgBroadcastQueue)
+            schedGroup = (queues.contains(mFgBroadcastQueue))
                     ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
             app.adjType = "broadcast";
             procState = ActivityManager.PROCESS_STATE_RECEIVER;
@@ -20389,7 +20422,7 @@
             if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
                     "Setting sched group of " + app.processName
                     + " to " + app.curSchedGroup);
-            if (app.waitingToKill != null && app.curReceiver == null
+            if (app.waitingToKill != null && app.curReceivers.isEmpty()
                     && app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
                 app.kill(app.waitingToKill, true);
                 success = false;
@@ -21329,7 +21362,7 @@
             for (i=mRemovedProcesses.size()-1; i>=0; i--) {
                 final ProcessRecord app = mRemovedProcesses.get(i);
                 if (app.activities.size() == 0
-                        && app.curReceiver == null && app.services.size() == 0) {
+                        && app.curReceivers.isEmpty() && app.services.size() == 0) {
                     Slog.i(
                         TAG, "Exiting empty application process "
                         + app.toShortString() + " ("
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 7142d3f..7d9a706 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -19,26 +19,76 @@
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
+import android.app.IActivityContainer;
+import android.app.IActivityController;
 import android.app.IActivityManager;
+import android.app.IInstrumentationWatcher;
+import android.app.IStopUserCallback;
+import android.app.Instrumentation;
 import android.app.ProfilerInfo;
+import android.app.UiAutomationConnection;
+import android.app.usage.ConfigurationStats;
+import android.app.usage.IUsageStatsManager;
+import android.app.usage.UsageStatsManager;
+import android.content.ComponentCallbacks2;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.content.pm.IPackageManager;
+import android.content.pm.InstrumentationInfo;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.ShellCommand;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.DebugUtils;
+import android.view.IWindowManager;
 
+import com.android.internal.util.HexDump;
+import com.android.internal.util.Preconditions;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
+import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
+import static android.app.ActivityManager.RESIZE_MODE_USER;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 
-class ActivityManagerShellCommand extends ShellCommand {
+final class ActivityManagerShellCommand extends ShellCommand {
     public static final String NO_CLASS_ERROR_CODE = "Error type 3";
+    private static final String SHELL_PACKAGE_NAME = "com.android.shell";
+
+    // Is the object moving in a positive direction?
+    private static final boolean MOVING_FORWARD = true;
+    // Is the object moving in the horizontal plan?
+    private static final boolean MOVING_HORIZONTALLY = true;
+    // Is the object current point great then its target point?
+    private static final boolean GREATER_THAN_TARGET = true;
+    // Amount we reduce the stack size by when testing a task re-size.
+    private static final int STACK_BOUNDS_INSET = 10;
 
     // IPC interface to activity manager -- don't need to do additional security checks.
     final IActivityManager mInterface;
@@ -84,30 +134,92 @@
                     return runStartActivity(pw);
                 case "startservice":
                 case "start-service":
-                    return 1; //runStartService(pw);
+                    return runStartService(pw);
                 case "stopservice":
                 case "stop-service":
-                    return 1; //runStopService(pw);
+                    return runStopService(pw);
+                case "broadcast":
+                    return runSendBroadcast(pw);
+                case "instrument":
+                    return runInstrument(pw);
+                case "trace-ipc":
+                    return runTraceIpc(pw);
+                case "profile":
+                    return runProfile(pw);
+                case "dumpheap":
+                    return runDumpHeap(pw);
+                case "set-debug-app":
+                    return runSetDebugApp(pw);
+                case "clear-debug-app":
+                    return runClearDebugApp(pw);
+                case "set-watch-heap":
+                    return runSetWatchHeap(pw);
+                case "clear-watch-heap":
+                    return runClearWatchHeap(pw);
+                case "bug-report":
+                    return runBugReport(pw);
                 case "force-stop":
                     return runForceStop(pw);
                 case "kill":
                     return runKill(pw);
                 case "kill-all":
                     return runKillAll(pw);
-                case "write":
-                    return runWrite(pw);
+                case "monitor":
+                    return runMonitor(pw);
+                case "hang":
+                    return runHang(pw);
+                case "restart":
+                    return runRestart(pw);
+                case "idle-maintenance":
+                    return runIdleMaintenance(pw);
+                case "screen-compat":
+                    return runScreenCompat(pw);
+                case "package-importance":
+                    return runPackageImportance(pw);
+                case "to-uri":
+                    return runToUri(pw, 0);
+                case "to-intent-uri":
+                    return runToUri(pw, Intent.URI_INTENT_SCHEME);
+                case "to-app-uri":
+                    return runToUri(pw, Intent.URI_ANDROID_APP_SCHEME);
+                case "switch-user":
+                    return runSwitchUser(pw);
+                case "get-current-user":
+                    return runGetCurrentUser(pw);
+                case "start-user":
+                    return runStartUser(pw);
+                case "unlock-user":
+                    return runUnlockUser(pw);
+                case "stop-user":
+                    return runStopUser(pw);
+                case "is-user-stopped":
+                    return runIsUserStopped(pw);
+                case "get-started-user-state":
+                    return runGetStartedUserState(pw);
                 case "track-associations":
                     return runTrackAssociations(pw);
                 case "untrack-associations":
                     return runUntrackAssociations(pw);
-                case "is-user-stopped":
-                    return runIsUserStopped(pw);
                 case "lenient-background-check":
                     return runLenientBackgroundCheck(pw);
                 case "get-uid-state":
                     return getUidState(pw);
-                case "get-started-user-state":
-                    return getStartedUserState(pw);
+                case "get-config":
+                    return runGetConfig(pw);
+                case "suppress-resize-config-changes":
+                    return runSuppressResizeConfigChanges(pw);
+                case "set-inactive":
+                    return runSetInactive(pw);
+                case "get-inactive":
+                    return runGetInactive(pw);
+                case "send-trim-memory":
+                    return runSendTrimMemory(pw);
+                case "stack":
+                    return runStack(pw);
+                case "task":
+                    return runTask(pw);
+                case "write":
+                    return runWrite(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -165,21 +277,6 @@
         });
     }
 
-    ParcelFileDescriptor openOutputFile(String path) {
-        try {
-            ParcelFileDescriptor pfd = getShellCallback().openOutputFile(path,
-                    "u:r:system_server:s0");
-            if (pfd != null) {
-                return pfd;
-            }
-        } catch (RuntimeException e) {
-            getErrPrintWriter().println("Failure opening file: " + e.getMessage());
-        }
-        getErrPrintWriter().println("Error: Unable to open file: " + path);
-        getErrPrintWriter().println("Consider using a file under /data/local/tmp/");
-        return null;
-    }
-
     int runStartActivity(PrintWriter pw) throws RemoteException {
         Intent intent;
         try {
@@ -220,6 +317,7 @@
                     packageName = activities.get(0).activityInfo.packageName;
                 }
                 pw.println("Stopping: " + packageName);
+                pw.flush();
                 mInterface.forceStopPackage(packageName, mUserId);
                 try {
                     Thread.sleep(250);
@@ -230,7 +328,7 @@
             ProfilerInfo profilerInfo = null;
 
             if (mProfileFile != null) {
-                ParcelFileDescriptor fd = openOutputFile(mProfileFile);
+                ParcelFileDescriptor fd = openOutputFileForSystem(mProfileFile);
                 if (fd == null) {
                     return 1;
                 }
@@ -238,6 +336,7 @@
             }
 
             pw.println("Starting: " + intent);
+            pw.flush();
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
             IActivityManager.WaitResult result = null;
@@ -326,6 +425,7 @@
                             "Error: Activity not started, unknown error code " + res);
                     break;
             }
+            out.flush();
             if (mWaitOption && launched) {
                 if (result == null) {
                     result = new IActivityManager.WaitResult();
@@ -343,6 +443,7 @@
                 }
                 pw.println("WaitTime: " + (endTime-startTime));
                 pw.println("Complete");
+                pw.flush();
             }
             mRepeat--;
             if (mRepeat > 0) {
@@ -352,10 +453,573 @@
         return 0;
     }
 
-    int runIsUserStopped(PrintWriter pw) {
-        int userId = UserHandle.parseUserArg(getNextArgRequired());
-        boolean stopped = mInternal.isUserStopped(userId);
-        pw.println(stopped);
+    int runStartService(PrintWriter pw) throws RemoteException {
+        final PrintWriter err = getErrPrintWriter();
+        Intent intent;
+        try {
+            intent = makeIntent(UserHandle.USER_CURRENT);
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+        if (mUserId == UserHandle.USER_ALL) {
+            err.println("Error: Can't start activity with user 'all'");
+            return -1;
+        }
+        pw.println("Starting service: " + intent);
+        pw.flush();
+        ComponentName cn = mInterface.startService(null, intent, intent.getType(),
+                SHELL_PACKAGE_NAME, mUserId);
+        if (cn == null) {
+            err.println("Error: Not found; no service started.");
+            return -1;
+        } else if (cn.getPackageName().equals("!")) {
+            err.println("Error: Requires permission " + cn.getClassName());
+            return -1;
+        } else if (cn.getPackageName().equals("!!")) {
+            err.println("Error: " + cn.getClassName());
+            return -1;
+        }
+        return 0;
+    }
+
+    int runStopService(PrintWriter pw) throws RemoteException {
+        final PrintWriter err = getErrPrintWriter();
+        Intent intent;
+        try {
+            intent = makeIntent(UserHandle.USER_CURRENT);
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+        if (mUserId == UserHandle.USER_ALL) {
+            err.println("Error: Can't stop activity with user 'all'");
+            return -1;
+        }
+        pw.println("Stopping service: " + intent);
+        pw.flush();
+        int result = mInterface.stopService(null, intent, intent.getType(), mUserId);
+        if (result == 0) {
+            err.println("Service not stopped: was not running.");
+            return -1;
+        } else if (result == 1) {
+            err.println("Service stopped");
+            return -1;
+        } else if (result == -1) {
+            err.println("Error stopping service");
+            return -1;
+        }
+        return 0;
+    }
+
+    final static class IntentReceiver extends IIntentReceiver.Stub {
+        private final PrintWriter mPw;
+        private boolean mFinished = false;
+
+        IntentReceiver(PrintWriter pw) {
+            mPw = pw;
+        }
+
+        @Override
+        public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
+                boolean ordered, boolean sticky, int sendingUser) {
+            String line = "Broadcast completed: result=" + resultCode;
+            if (data != null) line = line + ", data=\"" + data + "\"";
+            if (extras != null) line = line + ", extras: " + extras;
+            mPw.println(line);
+            mPw.flush();
+            synchronized (this) {
+                mFinished = true;
+                notifyAll();
+            }
+        }
+
+        public synchronized void waitForFinish() {
+            try {
+                while (!mFinished) wait();
+            } catch (InterruptedException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+    }
+
+    int runSendBroadcast(PrintWriter pw) throws RemoteException {
+        Intent intent;
+        try {
+            intent = makeIntent(UserHandle.USER_CURRENT);
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+        IntentReceiver receiver = new IntentReceiver(pw);
+        String[] requiredPermissions = mReceiverPermission == null ? null
+                : new String[] {mReceiverPermission};
+        pw.println("Broadcasting: " + intent);
+        pw.flush();
+        mInterface.broadcastIntent(null, intent, null, receiver, 0, null, null, requiredPermissions,
+                android.app.AppOpsManager.OP_NONE, null, true, false, mUserId);
+        receiver.waitForFinish();
+        return 0;
+    }
+
+    final static class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
+        private final IActivityManager mInterface;
+        private final PrintWriter mPw;
+        private boolean mFinished = false;
+        private boolean mRawMode = false;
+
+        InstrumentationWatcher(IActivityManager iam, PrintWriter pw) {
+            mInterface = iam;
+            mPw = pw;
+        }
+
+        /**
+         * Set or reset "raw mode".  In "raw mode", all bundles are dumped.  In "pretty mode",
+         * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
+         * @param rawMode true for raw mode, false for pretty mode.
+         */
+        public void setRawOutput(boolean rawMode) {
+            mRawMode = rawMode;
+        }
+
+        @Override
+        public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
+            synchronized (this) {
+                // pretty printer mode?
+                String pretty = null;
+                if (!mRawMode && results != null) {
+                    pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
+                }
+                if (pretty != null) {
+                    mPw.print(pretty);
+                } else {
+                    if (results != null) {
+                        for (String key : results.keySet()) {
+                            mPw.println(
+                                    "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key));
+                        }
+                    }
+                    mPw.println("INSTRUMENTATION_STATUS_CODE: " + resultCode);
+                }
+                mPw.flush();
+                notifyAll();
+            }
+        }
+
+        @Override
+        public void instrumentationFinished(ComponentName name, int resultCode,
+                Bundle results) {
+            synchronized (this) {
+                // pretty printer mode?
+                String pretty = null;
+                if (!mRawMode && results != null) {
+                    pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
+                }
+                if (pretty != null) {
+                    mPw.println(pretty);
+                } else {
+                    if (results != null) {
+                        for (String key : results.keySet()) {
+                            mPw.println(
+                                    "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key));
+                        }
+                    }
+                    mPw.println("INSTRUMENTATION_CODE: " + resultCode);
+                }
+                mPw.flush();
+                mFinished = true;
+                notifyAll();
+            }
+        }
+
+        public boolean waitForFinish() {
+            synchronized (this) {
+                while (!mFinished) {
+                    try {
+                        if (!mInterface.asBinder().pingBinder()) {
+                            return false;
+                        }
+                        wait(1000);
+                    } catch (InterruptedException e) {
+                        throw new IllegalStateException(e);
+                    }
+                }
+            }
+            return true;
+        }
+    }
+
+    int runInstrument(PrintWriter pw) throws RemoteException {
+        final PrintWriter err = getErrPrintWriter();
+        String profileFile = null;
+        boolean wait = false;
+        boolean rawMode = false;
+        boolean no_window_animation = false;
+        int userId = UserHandle.USER_CURRENT;
+        Bundle args = new Bundle();
+        String argKey = null, argValue = null;
+        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
+        String abi = null;
+
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("-p")) {
+                profileFile = getNextArgRequired();
+            } else if (opt.equals("-w")) {
+                wait = true;
+            } else if (opt.equals("-r")) {
+                rawMode = true;
+            } else if (opt.equals("-e")) {
+                argKey = getNextArgRequired();
+                argValue = getNextArgRequired();
+                args.putString(argKey, argValue);
+            } else if (opt.equals("--no_window_animation")
+                    || opt.equals("--no-window-animation")) {
+                no_window_animation = true;
+            } else if (opt.equals("--user")) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else if (opt.equals("--abi")) {
+                abi = getNextArgRequired();
+            } else {
+                err.println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+
+        if (userId == UserHandle.USER_ALL) {
+            err.println("Error: Can't start instrumentation with user 'all'");
+            return -1;
+        }
+
+        String cnArg = getNextArgRequired();
+
+        ComponentName cn;
+        if (cnArg.contains("/")) {
+            cn = ComponentName.unflattenFromString(cnArg);
+            if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
+        } else {
+            List<InstrumentationInfo> infos = mPm.queryInstrumentation(null, 0).getList();
+
+            final int numInfos = infos == null ? 0: infos.size();
+            List<ComponentName> cns = new ArrayList<>();
+            for (int i = 0; i < numInfos; i++) {
+                InstrumentationInfo info = infos.get(i);
+
+                ComponentName c = new ComponentName(info.packageName, info.name);
+                if (cnArg.equals(info.packageName)) {
+                    cns.add(c);
+                }
+            }
+
+            if (cns.size() == 0) {
+                throw new IllegalArgumentException("No instrumentation found for: " + cnArg);
+            } else if (cns.size() == 1) {
+                cn = cns.get(0);
+            } else {
+                StringBuilder cnsStr = new StringBuilder();
+                final int numCns = cns.size();
+                for (int i = 0; i < numCns; i++) {
+                    cnsStr.append(cns.get(i).flattenToString());
+                    cnsStr.append(", ");
+                }
+
+                // Remove last ", "
+                cnsStr.setLength(cnsStr.length() - 2);
+
+                throw new IllegalArgumentException("Found multiple instrumentations: "
+                        + cnsStr.toString());
+            }
+        }
+
+        InstrumentationWatcher watcher = null;
+        UiAutomationConnection connection = null;
+        if (wait) {
+            watcher = new InstrumentationWatcher(mInterface, pw);
+            watcher.setRawOutput(rawMode);
+            // Don't yet know how to support this.
+            connection = null; //new UiAutomationConnection();
+        }
+
+        float[] oldAnims = null;
+        if (no_window_animation) {
+            oldAnims = wm.getAnimationScales();
+            wm.setAnimationScale(0, 0.0f);
+            wm.setAnimationScale(1, 0.0f);
+        }
+
+        if (abi != null) {
+            final String[] supportedAbis = Build.SUPPORTED_ABIS;
+            boolean matched = false;
+            for (String supportedAbi : supportedAbis) {
+                if (supportedAbi.equals(abi)) {
+                    matched = true;
+                    break;
+                }
+            }
+
+            if (!matched) {
+                throw new RuntimeException(
+                        "INSTRUMENTATION_FAILED: Unsupported instruction set " + abi);
+            }
+        }
+
+        if (!mInterface.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId,
+                abi)) {
+            throw new RuntimeException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
+        }
+
+        if (watcher != null) {
+            if (!watcher.waitForFinish()) {
+                pw.println("INSTRUMENTATION_ABORTED: System has crashed.");
+            }
+        }
+
+        if (oldAnims != null) {
+            wm.setAnimationScales(oldAnims);
+        }
+        return 0;
+    }
+
+    int runTraceIpc(PrintWriter pw) throws RemoteException {
+        String op = getNextArgRequired();
+        if (op.equals("start")) {
+            return runTraceIpcStart(pw);
+        } else if (op.equals("stop")) {
+            return runTraceIpcStop(pw);
+        } else {
+            getErrPrintWriter().println("Error: unknown trace ipc command '" + op + "'");
+            return -1;
+        }
+    }
+
+    int runTraceIpcStart(PrintWriter pw) throws RemoteException {
+        pw.println("Starting IPC tracing.");
+        pw.flush();
+        mInterface.startBinderTracking();
+        return 0;
+    }
+
+    int runTraceIpcStop(PrintWriter pw) throws RemoteException {
+        final PrintWriter err = getErrPrintWriter();
+        String opt;
+        String filename = null;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("--dump-file")) {
+                filename = getNextArgRequired();
+            } else {
+                err.println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+        if (filename == null) {
+            err.println("Error: Specify filename to dump logs to.");
+            return -1;
+        }
+
+        File file = new File(filename);
+        file.delete();
+        ParcelFileDescriptor fd = openOutputFileForSystem(filename);
+        if (fd == null) {
+            return -1;
+        }
+
+        ;
+        if (!mInterface.stopBinderTrackingAndDump(fd)) {
+            err.println("STOP TRACE FAILED.");
+            return -1;
+        }
+
+        pw.println("Stopped IPC tracing. Dumping logs to: " + filename);
+        return 0;
+    }
+
+    static void removeWallOption() {
+        String props = SystemProperties.get("dalvik.vm.extra-opts");
+        if (props != null && props.contains("-Xprofile:wallclock")) {
+            props = props.replace("-Xprofile:wallclock", "");
+            props = props.trim();
+            SystemProperties.set("dalvik.vm.extra-opts", props);
+        }
+    }
+
+    private int runProfile(PrintWriter pw) throws RemoteException {
+        final PrintWriter err = getErrPrintWriter();
+        String profileFile = null;
+        boolean start = false;
+        boolean wall = false;
+        int userId = UserHandle.USER_CURRENT;
+        int profileType = 0;
+        mSamplingInterval = 0;
+
+        String process = null;
+
+        String cmd = getNextArgRequired();
+
+        if ("start".equals(cmd)) {
+            start = true;
+            String opt;
+            while ((opt=getNextOption()) != null) {
+                if (opt.equals("--user")) {
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                } else if (opt.equals("--wall")) {
+                    wall = true;
+                } else if (opt.equals("--sampling")) {
+                    mSamplingInterval = Integer.parseInt(getNextArgRequired());
+                } else {
+                    err.println("Error: Unknown option: " + opt);
+                    return -1;
+                }
+            }
+            process = getNextArgRequired();
+        } else if ("stop".equals(cmd)) {
+            String opt;
+            while ((opt=getNextOption()) != null) {
+                if (opt.equals("--user")) {
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                } else {
+                    err.println("Error: Unknown option: " + opt);
+                    return -1;
+                }
+            }
+            process = getNextArg();
+        } else {
+            // Compatibility with old syntax: process is specified first.
+            process = cmd;
+            cmd = getNextArgRequired();
+            if ("start".equals(cmd)) {
+                start = true;
+            } else if (!"stop".equals(cmd)) {
+                throw new IllegalArgumentException("Profile command " + process + " not valid");
+            }
+        }
+
+        if (userId == UserHandle.USER_ALL) {
+            err.println("Error: Can't profile with user 'all'");
+            return -1;
+        }
+
+        ParcelFileDescriptor fd = null;
+        ProfilerInfo profilerInfo = null;
+
+        if (start) {
+            profileFile = getNextArgRequired();
+            fd = openOutputFileForSystem(profileFile);
+            if (fd == null) {
+                return -1;
+            }
+            profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false);
+        }
+
+        try {
+            if (wall) {
+                // XXX doesn't work -- this needs to be set before booting.
+                String props = SystemProperties.get("dalvik.vm.extra-opts");
+                if (props == null || !props.contains("-Xprofile:wallclock")) {
+                    props = props + " -Xprofile:wallclock";
+                    //SystemProperties.set("dalvik.vm.extra-opts", props);
+                }
+            } else if (start) {
+                //removeWallOption();
+            }
+            if (!mInterface.profileControl(process, userId, start, profilerInfo, profileType)) {
+                wall = false;
+                err.println("PROFILE FAILED on process " + process);
+                return -1;
+            }
+        } finally {
+            if (!wall) {
+                //removeWallOption();
+            }
+        }
+        return 0;
+    }
+
+    int runDumpHeap(PrintWriter pw) throws RemoteException {
+        final PrintWriter err = getErrPrintWriter();
+        boolean managed = true;
+        int userId = UserHandle.USER_CURRENT;
+
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+                if (userId == UserHandle.USER_ALL) {
+                    err.println("Error: Can't dump heap with user 'all'");
+                    return -1;
+                }
+            } else if (opt.equals("-n")) {
+                managed = false;
+            } else {
+                err.println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+        String process = getNextArgRequired();
+        String heapFile = getNextArgRequired();
+
+        File file = new File(heapFile);
+        file.delete();
+        ParcelFileDescriptor fd = openOutputFileForSystem(heapFile);
+        if (fd == null) {
+            return -1;
+        }
+
+        if (!mInterface.dumpHeap(process, userId, managed, heapFile, fd)) {
+            err.println("HEAP DUMP FAILED on process " + process);
+            return -1;
+        }
+        return 0;
+    }
+
+    int runSetDebugApp(PrintWriter pw) throws RemoteException {
+        boolean wait = false;
+        boolean persistent = false;
+
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("-w")) {
+                wait = true;
+            } else if (opt.equals("--persistent")) {
+                persistent = true;
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+
+        String pkg = getNextArgRequired();
+        mInterface.setDebugApp(pkg, wait, persistent);
+        return 0;
+    }
+
+    int runClearDebugApp(PrintWriter pw) throws RemoteException {
+        mInterface.setDebugApp(null, false, true);
+        return 0;
+    }
+
+    int runSetWatchHeap(PrintWriter pw) throws RemoteException {
+        String proc = getNextArgRequired();
+        String limit = getNextArgRequired();
+        mInterface.setDumpHeapDebugLimit(proc, 0, Long.parseLong(limit), null);
+        return 0;
+    }
+
+    int runClearWatchHeap(PrintWriter pw) throws RemoteException {
+        String proc = getNextArgRequired();
+        mInterface.setDumpHeapDebugLimit(proc, 0, -1, null);
+        return 0;
+    }
+
+    int runBugReport(PrintWriter pw) throws RemoteException {
+        String opt;
+        int bugreportType = ActivityManager.BUGREPORT_OPTION_FULL;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("--progress")) {
+                bugreportType = ActivityManager.BUGREPORT_OPTION_INTERACTIVE;
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+        mInterface.requestBugReport(bugreportType);
+        pw.println("Your lovely bug report is being created; please be patient.");
         return 0;
     }
 
@@ -367,7 +1031,7 @@
             if (opt.equals("--user")) {
                 userId = UserHandle.parseUserArg(getNextArgRequired());
             } else {
-                pw.println("Error: Unknown option: " + opt);
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
                 return -1;
             }
         }
@@ -383,7 +1047,7 @@
             if (opt.equals("--user")) {
                 userId = UserHandle.parseUserArg(getNextArgRequired());
             } else {
-                pw.println("Error: Unknown option: " + opt);
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
                 return -1;
             }
         }
@@ -396,11 +1060,553 @@
         return 0;
     }
 
-    int runWrite(PrintWriter pw) {
-        mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
-                "registerUidObserver()");
-        mInternal.mRecentTasks.flush();
-        pw.println("All tasks persisted.");
+    static final class MyActivityController extends IActivityController.Stub {
+        final IActivityManager mInterface;
+        final PrintWriter mPw;
+        final InputStream mInput;
+        final String mGdbPort;
+        final boolean mMonkey;
+
+        static final int STATE_NORMAL = 0;
+        static final int STATE_CRASHED = 1;
+        static final int STATE_EARLY_ANR = 2;
+        static final int STATE_ANR = 3;
+
+        int mState;
+
+        static final int RESULT_DEFAULT = 0;
+
+        static final int RESULT_CRASH_DIALOG = 0;
+        static final int RESULT_CRASH_KILL = 1;
+
+        static final int RESULT_EARLY_ANR_CONTINUE = 0;
+        static final int RESULT_EARLY_ANR_KILL = 1;
+
+        static final int RESULT_ANR_DIALOG = 0;
+        static final int RESULT_ANR_KILL = 1;
+        static final int RESULT_ANR_WAIT = 1;
+
+        int mResult;
+
+        Process mGdbProcess;
+        Thread mGdbThread;
+        boolean mGotGdbPrint;
+
+        MyActivityController(IActivityManager iam, PrintWriter pw, InputStream input,
+                String gdbPort, boolean monkey) {
+            mInterface = iam;
+            mPw = pw;
+            mInput = input;
+            mGdbPort = gdbPort;
+            mMonkey = monkey;
+        }
+
+        @Override
+        public boolean activityResuming(String pkg) {
+            synchronized (this) {
+                mPw.println("** Activity resuming: " + pkg);
+                mPw.flush();
+            }
+            return true;
+        }
+
+        @Override
+        public boolean activityStarting(Intent intent, String pkg) {
+            synchronized (this) {
+                mPw.println("** Activity starting: " + pkg);
+                mPw.flush();
+            }
+            return true;
+        }
+
+        @Override
+        public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg,
+                long timeMillis, String stackTrace) {
+            synchronized (this) {
+                mPw.println("** ERROR: PROCESS CRASHED");
+                mPw.println("processName: " + processName);
+                mPw.println("processPid: " + pid);
+                mPw.println("shortMsg: " + shortMsg);
+                mPw.println("longMsg: " + longMsg);
+                mPw.println("timeMillis: " + timeMillis);
+                mPw.println("stack:");
+                mPw.print(stackTrace);
+                mPw.println("#");
+                mPw.flush();
+                int result = waitControllerLocked(pid, STATE_CRASHED);
+                return result == RESULT_CRASH_KILL ? false : true;
+            }
+        }
+
+        @Override
+        public int appEarlyNotResponding(String processName, int pid, String annotation) {
+            synchronized (this) {
+                mPw.println("** ERROR: EARLY PROCESS NOT RESPONDING");
+                mPw.println("processName: " + processName);
+                mPw.println("processPid: " + pid);
+                mPw.println("annotation: " + annotation);
+                mPw.flush();
+                int result = waitControllerLocked(pid, STATE_EARLY_ANR);
+                if (result == RESULT_EARLY_ANR_KILL) return -1;
+                return 0;
+            }
+        }
+
+        @Override
+        public int appNotResponding(String processName, int pid, String processStats) {
+            synchronized (this) {
+                mPw.println("** ERROR: PROCESS NOT RESPONDING");
+                mPw.println("processName: " + processName);
+                mPw.println("processPid: " + pid);
+                mPw.println("processStats:");
+                mPw.print(processStats);
+                mPw.println("#");
+                mPw.flush();
+                int result = waitControllerLocked(pid, STATE_ANR);
+                if (result == RESULT_ANR_KILL) return -1;
+                if (result == RESULT_ANR_WAIT) return 1;
+                return 0;
+            }
+        }
+
+        @Override
+        public int systemNotResponding(String message) {
+            synchronized (this) {
+                mPw.println("** ERROR: PROCESS NOT RESPONDING");
+                mPw.println("message: " + message);
+                mPw.println("#");
+                mPw.println("Allowing system to die.");
+                mPw.flush();
+                return -1;
+            }
+        }
+
+        void killGdbLocked() {
+            mGotGdbPrint = false;
+            if (mGdbProcess != null) {
+                mPw.println("Stopping gdbserver");
+                mPw.flush();
+                mGdbProcess.destroy();
+                mGdbProcess = null;
+            }
+            if (mGdbThread != null) {
+                mGdbThread.interrupt();
+                mGdbThread = null;
+            }
+        }
+
+        int waitControllerLocked(int pid, int state) {
+            if (mGdbPort != null) {
+                killGdbLocked();
+
+                try {
+                    mPw.println("Starting gdbserver on port " + mGdbPort);
+                    mPw.println("Do the following:");
+                    mPw.println("  adb forward tcp:" + mGdbPort + " tcp:" + mGdbPort);
+                    mPw.println("  gdbclient app_process :" + mGdbPort);
+                    mPw.flush();
+
+                    mGdbProcess = Runtime.getRuntime().exec(new String[] {
+                            "gdbserver", ":" + mGdbPort, "--attach", Integer.toString(pid)
+                    });
+                    final InputStreamReader converter = new InputStreamReader(
+                            mGdbProcess.getInputStream());
+                    mGdbThread = new Thread() {
+                        @Override
+                        public void run() {
+                            BufferedReader in = new BufferedReader(converter);
+                            String line;
+                            int count = 0;
+                            while (true) {
+                                synchronized (MyActivityController.this) {
+                                    if (mGdbThread == null) {
+                                        return;
+                                    }
+                                    if (count == 2) {
+                                        mGotGdbPrint = true;
+                                        MyActivityController.this.notifyAll();
+                                    }
+                                }
+                                try {
+                                    line = in.readLine();
+                                    if (line == null) {
+                                        return;
+                                    }
+                                    mPw.println("GDB: " + line);
+                                    mPw.flush();
+                                    count++;
+                                } catch (IOException e) {
+                                    return;
+                                }
+                            }
+                        }
+                    };
+                    mGdbThread.start();
+
+                    // Stupid waiting for .5s.  Doesn't matter if we end early.
+                    try {
+                        this.wait(500);
+                    } catch (InterruptedException e) {
+                    }
+
+                } catch (IOException e) {
+                    mPw.println("Failure starting gdbserver: " + e);
+                    mPw.flush();
+                    killGdbLocked();
+                }
+            }
+            mState = state;
+            mPw.println("");
+            printMessageForState();
+            mPw.flush();
+
+            while (mState != STATE_NORMAL) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                }
+            }
+
+            killGdbLocked();
+
+            return mResult;
+        }
+
+        void resumeController(int result) {
+            synchronized (this) {
+                mState = STATE_NORMAL;
+                mResult = result;
+                notifyAll();
+            }
+        }
+
+        void printMessageForState() {
+            switch (mState) {
+                case STATE_NORMAL:
+                    mPw.println("Monitoring activity manager...  available commands:");
+                    break;
+                case STATE_CRASHED:
+                    mPw.println("Waiting after crash...  available commands:");
+                    mPw.println("(c)ontinue: show crash dialog");
+                    mPw.println("(k)ill: immediately kill app");
+                    break;
+                case STATE_EARLY_ANR:
+                    mPw.println("Waiting after early ANR...  available commands:");
+                    mPw.println("(c)ontinue: standard ANR processing");
+                    mPw.println("(k)ill: immediately kill app");
+                    break;
+                case STATE_ANR:
+                    mPw.println("Waiting after ANR...  available commands:");
+                    mPw.println("(c)ontinue: show ANR dialog");
+                    mPw.println("(k)ill: immediately kill app");
+                    mPw.println("(w)ait: wait some more");
+                    break;
+            }
+            mPw.println("(q)uit: finish monitoring");
+        }
+
+        void run() throws RemoteException {
+            try {
+                printMessageForState();
+                mPw.flush();
+
+                mInterface.setActivityController(this, mMonkey);
+                mState = STATE_NORMAL;
+
+                InputStreamReader converter = new InputStreamReader(mInput);
+                BufferedReader in = new BufferedReader(converter);
+                String line;
+
+                while ((line = in.readLine()) != null) {
+                    boolean addNewline = true;
+                    if (line.length() <= 0) {
+                        addNewline = false;
+                    } else if ("q".equals(line) || "quit".equals(line)) {
+                        resumeController(RESULT_DEFAULT);
+                        break;
+                    } else if (mState == STATE_CRASHED) {
+                        if ("c".equals(line) || "continue".equals(line)) {
+                            resumeController(RESULT_CRASH_DIALOG);
+                        } else if ("k".equals(line) || "kill".equals(line)) {
+                            resumeController(RESULT_CRASH_KILL);
+                        } else {
+                            mPw.println("Invalid command: " + line);
+                        }
+                    } else if (mState == STATE_ANR) {
+                        if ("c".equals(line) || "continue".equals(line)) {
+                            resumeController(RESULT_ANR_DIALOG);
+                        } else if ("k".equals(line) || "kill".equals(line)) {
+                            resumeController(RESULT_ANR_KILL);
+                        } else if ("w".equals(line) || "wait".equals(line)) {
+                            resumeController(RESULT_ANR_WAIT);
+                        } else {
+                            mPw.println("Invalid command: " + line);
+                        }
+                    } else if (mState == STATE_EARLY_ANR) {
+                        if ("c".equals(line) || "continue".equals(line)) {
+                            resumeController(RESULT_EARLY_ANR_CONTINUE);
+                        } else if ("k".equals(line) || "kill".equals(line)) {
+                            resumeController(RESULT_EARLY_ANR_KILL);
+                        } else {
+                            mPw.println("Invalid command: " + line);
+                        }
+                    } else {
+                        mPw.println("Invalid command: " + line);
+                    }
+
+                    synchronized (this) {
+                        if (addNewline) {
+                            mPw.println("");
+                        }
+                        printMessageForState();
+                        mPw.flush();
+                    }
+                }
+
+            } catch (IOException e) {
+                e.printStackTrace(mPw);
+                mPw.flush();
+            } finally {
+                mInterface.setActivityController(null, mMonkey);
+            }
+        }
+    }
+
+    int runMonitor(PrintWriter pw) throws RemoteException {
+        String opt;
+        String gdbPort = null;
+        boolean monkey = false;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("--gdb")) {
+                gdbPort = getNextArgRequired();
+            } else if (opt.equals("-m")) {
+                monkey = true;
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+
+        MyActivityController controller = new MyActivityController(mInterface, pw,
+                getRawInputStream(), gdbPort, monkey);
+        controller.run();
+        return 0;
+    }
+
+    int runHang(PrintWriter pw) throws RemoteException {
+        String opt;
+        boolean allowRestart = false;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("--allow-restart")) {
+                allowRestart = true;
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+
+        pw.println("Hanging the system...");
+        pw.flush();
+        mInterface.hang(new Binder(), allowRestart);
+        return 0;
+    }
+
+    int runRestart(PrintWriter pw) throws RemoteException {
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            getErrPrintWriter().println("Error: Unknown option: " + opt);
+            return -1;
+        }
+
+        pw.println("Restart the system...");
+        pw.flush();
+        mInterface.restart();
+        return 0;
+    }
+
+    int runIdleMaintenance(PrintWriter pw) throws RemoteException {
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            getErrPrintWriter().println("Error: Unknown option: " + opt);
+            return -1;
+        }
+
+        pw.println("Performing idle maintenance...");
+        mInterface.sendIdleJobTrigger();
+        return 0;
+    }
+
+    int runScreenCompat(PrintWriter pw) throws RemoteException {
+        String mode = getNextArgRequired();
+        boolean enabled;
+        if ("on".equals(mode)) {
+            enabled = true;
+        } else if ("off".equals(mode)) {
+            enabled = false;
+        } else {
+            getErrPrintWriter().println("Error: enabled mode must be 'on' or 'off' at " + mode);
+            return -1;
+        }
+
+        String packageName = getNextArgRequired();
+        do {
+            try {
+                mInterface.setPackageScreenCompatMode(packageName, enabled
+                        ? ActivityManager.COMPAT_MODE_ENABLED
+                        : ActivityManager.COMPAT_MODE_DISABLED);
+            } catch (RemoteException e) {
+            }
+            packageName = getNextArg();
+        } while (packageName != null);
+        return 0;
+    }
+
+    int runPackageImportance(PrintWriter pw) throws RemoteException {
+        String packageName = getNextArgRequired();
+        int procState = mInterface.getPackageProcessState(packageName, "com.android.shell");
+        pw.println(ActivityManager.RunningAppProcessInfo.procStateToImportance(procState));
+        return 0;
+    }
+
+    int runToUri(PrintWriter pw, int flags) throws RemoteException {
+        Intent intent;
+        try {
+            intent = makeIntent(UserHandle.USER_CURRENT);
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+        pw.println(intent.toUri(flags));
+        return 0;
+    }
+
+    int runSwitchUser(PrintWriter pw) throws RemoteException {
+        String user = getNextArgRequired();
+        mInterface.switchUser(Integer.parseInt(user));
+        return 0;
+    }
+
+    int runGetCurrentUser(PrintWriter pw) throws RemoteException {
+        UserInfo currentUser = Preconditions.checkNotNull(mInterface.getCurrentUser(),
+                "Current user not set");
+        pw.println(currentUser.id);
+        return 0;
+    }
+
+    int runStartUser(PrintWriter pw) throws RemoteException {
+        String user = getNextArgRequired();
+        boolean success = mInterface.startUserInBackground(Integer.parseInt(user));
+        if (success) {
+            pw.println("Success: user started");
+        } else {
+            getErrPrintWriter().println("Error: could not start user");
+        }
+        return 0;
+    }
+
+    private static byte[] argToBytes(String arg) {
+        if (arg.equals("!")) {
+            return null;
+        } else {
+            return HexDump.hexStringToByteArray(arg);
+        }
+    }
+
+    int runUnlockUser(PrintWriter pw) throws RemoteException {
+        int userId = Integer.parseInt(getNextArgRequired());
+        byte[] token = argToBytes(getNextArgRequired());
+        byte[] secret = argToBytes(getNextArgRequired());
+        boolean success = mInterface.unlockUser(userId, token, secret, null);
+        if (success) {
+            pw.println("Success: user unlocked");
+        } else {
+            getErrPrintWriter().println("Error: could not unlock user");
+        }
+        return 0;
+    }
+
+    static final class StopUserCallback extends IStopUserCallback.Stub {
+        private boolean mFinished = false;
+
+        public synchronized void waitForFinish() {
+            try {
+                while (!mFinished) wait();
+            } catch (InterruptedException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        @Override
+        public synchronized void userStopped(int userId) {
+            mFinished = true;
+            notifyAll();
+        }
+
+        @Override
+        public synchronized void userStopAborted(int userId) {
+            mFinished = true;
+            notifyAll();
+        }
+    }
+
+    int runStopUser(PrintWriter pw) throws RemoteException {
+        boolean wait = false;
+        boolean force = false;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            if ("-w".equals(opt)) {
+                wait = true;
+            } else if ("-f".equals(opt)) {
+                force = true;
+            } else {
+                getErrPrintWriter().println("Error: unknown option: " + opt);
+                return -1;
+            }
+        }
+        int user = Integer.parseInt(getNextArgRequired());
+        StopUserCallback callback = wait ? new StopUserCallback() : null;
+
+        int res = mInterface.stopUser(user, force, callback);
+        if (res != ActivityManager.USER_OP_SUCCESS) {
+            String txt = "";
+            switch (res) {
+                case ActivityManager.USER_OP_IS_CURRENT:
+                    txt = " (Can't stop current user)";
+                    break;
+                case ActivityManager.USER_OP_UNKNOWN_USER:
+                    txt = " (Unknown user " + user + ")";
+                    break;
+                case ActivityManager.USER_OP_ERROR_IS_SYSTEM:
+                    txt = " (System user cannot be stopped)";
+                    break;
+                case ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP:
+                    txt = " (Can't stop user " + user
+                            + " - one of its related users can't be stopped)";
+                    break;
+            }
+            getErrPrintWriter().println("Switch failed: " + res + txt);
+            return -1;
+        } else if (callback != null) {
+            callback.waitForFinish();
+        }
+        return 0;
+    }
+
+    int runIsUserStopped(PrintWriter pw) {
+        int userId = UserHandle.parseUserArg(getNextArgRequired());
+        boolean stopped = mInternal.isUserStopped(userId);
+        pw.println(stopped);
+        return 0;
+    }
+
+    int runGetStartedUserState(PrintWriter pw) throws RemoteException {
+        mInternal.enforceCallingPermission(android.Manifest.permission.DUMP,
+                "runGetStartedUserState()");
+        final int userId = Integer.parseInt(getNextArgRequired());
+        try {
+            pw.println(mInternal.getStartedUserState(userId));
+        } catch (NullPointerException e) {
+            pw.println("User is not started: " + userId);
+        }
         return 0;
     }
 
@@ -460,15 +1666,799 @@
         return 0;
     }
 
-    int getStartedUserState(PrintWriter pw) throws RemoteException {
-        mInternal.enforceCallingPermission(android.Manifest.permission.DUMP,
-                "getStartedUserState()");
-        final int userId = Integer.parseInt(getNextArgRequired());
+    private List<Configuration> getRecentConfigurations(int days) {
+        IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
+                Context.USAGE_STATS_SERVICE));
+        final long now = System.currentTimeMillis();
+        final long nDaysAgo = now - (days * 24 * 60 * 60 * 1000);
         try {
-            pw.println(mInternal.getStartedUserState(userId));
-        } catch (NullPointerException e) {
-            pw.println("User is not started: " + userId);
+            @SuppressWarnings("unchecked")
+            ParceledListSlice<ConfigurationStats> configStatsSlice = usm.queryConfigurationStats(
+                    UsageStatsManager.INTERVAL_BEST, nDaysAgo, now, "com.android.shell");
+            if (configStatsSlice == null) {
+                return Collections.emptyList();
+            }
+
+            final ArrayMap<Configuration, Integer> recentConfigs = new ArrayMap<>();
+            final List<ConfigurationStats> configStatsList = configStatsSlice.getList();
+            final int configStatsListSize = configStatsList.size();
+            for (int i = 0; i < configStatsListSize; i++) {
+                final ConfigurationStats stats = configStatsList.get(i);
+                final int indexOfKey = recentConfigs.indexOfKey(stats.getConfiguration());
+                if (indexOfKey < 0) {
+                    recentConfigs.put(stats.getConfiguration(), stats.getActivationCount());
+                } else {
+                    recentConfigs.setValueAt(indexOfKey,
+                            recentConfigs.valueAt(indexOfKey) + stats.getActivationCount());
+                }
+            }
+
+            final Comparator<Configuration> comparator = new Comparator<Configuration>() {
+                @Override
+                public int compare(Configuration a, Configuration b) {
+                    return recentConfigs.get(b).compareTo(recentConfigs.get(a));
+                }
+            };
+
+            ArrayList<Configuration> configs = new ArrayList<>(recentConfigs.size());
+            configs.addAll(recentConfigs.keySet());
+            Collections.sort(configs, comparator);
+            return configs;
+
+        } catch (RemoteException e) {
+            return Collections.emptyList();
         }
+    }
+
+    int runGetConfig(PrintWriter pw) throws RemoteException {
+        int days = 14;
+        String option = getNextOption();
+        if (option != null) {
+            if (!option.equals("--days")) {
+                throw new IllegalArgumentException("unrecognized option " + option);
+            }
+
+            days = Integer.parseInt(getNextArgRequired());
+            if (days <= 0) {
+                throw new IllegalArgumentException("--days must be a positive integer");
+            }
+        }
+
+        Configuration config = mInterface.getConfiguration();
+        if (config == null) {
+            getErrPrintWriter().println("Activity manager has no configuration");
+            return -1;
+        }
+
+        pw.println("config: " + Configuration.resourceQualifierString(config));
+        pw.println("abi: " + TextUtils.join(",", Build.SUPPORTED_ABIS));
+
+        final List<Configuration> recentConfigs = getRecentConfigurations(days);
+        final int recentConfigSize = recentConfigs.size();
+        if (recentConfigSize > 0) {
+            pw.println("recentConfigs:");
+        }
+
+        for (int i = 0; i < recentConfigSize; i++) {
+            pw.println("  config: " + Configuration.resourceQualifierString(
+                    recentConfigs.get(i)));
+        }
+        return 0;
+    }
+
+    int runSuppressResizeConfigChanges(PrintWriter pw) throws RemoteException {
+        boolean suppress = Boolean.valueOf(getNextArgRequired());
+        mInterface.suppressResizeConfigChanges(suppress);
+        return 0;
+    }
+
+    int runSetInactive(PrintWriter pw) throws RemoteException {
+        int userId = UserHandle.USER_CURRENT;
+
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+        String packageName = getNextArgRequired();
+        String value = getNextArgRequired();
+
+        IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
+                Context.USAGE_STATS_SERVICE));
+        usm.setAppInactive(packageName, Boolean.parseBoolean(value), userId);
+        return 0;
+    }
+
+    int runGetInactive(PrintWriter pw) throws RemoteException {
+        int userId = UserHandle.USER_CURRENT;
+
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+        String packageName = getNextArgRequired();
+
+        IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
+                Context.USAGE_STATS_SERVICE));
+        boolean isIdle = usm.isAppInactive(packageName, userId);
+        pw.println("Idle=" + isIdle);
+        return 0;
+    }
+
+    int runSendTrimMemory(PrintWriter pw) throws RemoteException {
+        int userId = UserHandle.USER_CURRENT;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+                if (userId == UserHandle.USER_ALL) {
+                    getErrPrintWriter().println("Error: Can't use user 'all'");
+                    return -1;
+                }
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+
+        String proc = getNextArgRequired();
+        String levelArg = getNextArgRequired();
+        int level;
+        switch (levelArg) {
+            case "HIDDEN":
+                level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
+                break;
+            case "RUNNING_MODERATE":
+                level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
+                break;
+            case "BACKGROUND":
+                level = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
+                break;
+            case "RUNNING_LOW":
+                level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
+                break;
+            case "MODERATE":
+                level = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
+                break;
+            case "RUNNING_CRITICAL":
+                level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
+                break;
+            case "COMPLETE":
+                level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
+                break;
+            default:
+                getErrPrintWriter().println("Error: Unknown level option: " + levelArg);
+                return -1;
+        }
+        if (!mInterface.setProcessMemoryTrimLevel(proc, userId, level)) {
+            getErrPrintWriter().println("Unknown error: failed to set trim level");
+            return -1;
+        }
+        return 0;
+    }
+
+    int runStack(PrintWriter pw) throws RemoteException {
+        String op = getNextArgRequired();
+        switch (op) {
+            case "start":
+                return runStackStart(pw);
+            case "movetask":
+                return runStackMoveTask(pw);
+            case "resize":
+                return runStackResize(pw);
+            case "resize-animated":
+                return runStackResizeAnimated(pw);
+            case "resize-docked-stack":
+                return runStackResizeDocked(pw);
+            case "positiontask":
+                return runStackPositionTask(pw);
+            case "list":
+                return runStackList(pw);
+            case "info":
+                return runStackInfo(pw);
+            case "move-top-activity-to-pinned-stack":
+                return runMoveTopActivityToPinnedStack(pw);
+            case "size-docked-stack-test":
+                return runStackSizeDockedStackTest(pw);
+            case "remove":
+                return runStackRemove(pw);
+            default:
+                getErrPrintWriter().println("Error: unknown command '" + op + "'");
+                return -1;
+        }
+    }
+
+
+    private Rect getBounds() {
+        String leftStr = getNextArgRequired();
+        int left = Integer.parseInt(leftStr);
+        String topStr = getNextArgRequired();
+        int top = Integer.parseInt(topStr);
+        String rightStr = getNextArgRequired();
+        int right = Integer.parseInt(rightStr);
+        String bottomStr = getNextArgRequired();
+        int bottom = Integer.parseInt(bottomStr);
+        if (left < 0) {
+            getErrPrintWriter().println("Error: bad left arg: " + leftStr);
+            return null;
+        }
+        if (top < 0) {
+            getErrPrintWriter().println("Error: bad top arg: " + topStr);
+            return null;
+        }
+        if (right <= 0) {
+            getErrPrintWriter().println("Error: bad right arg: " + rightStr);
+            return null;
+        }
+        if (bottom <= 0) {
+            getErrPrintWriter().println("Error: bad bottom arg: " + bottomStr);
+            return null;
+        }
+        return new Rect(left, top, right, bottom);
+    }
+
+    int runStackStart(PrintWriter pw) throws RemoteException {
+        String displayIdStr = getNextArgRequired();
+        int displayId = Integer.parseInt(displayIdStr);
+        Intent intent;
+        try {
+            intent = makeIntent(UserHandle.USER_CURRENT);
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+
+        IActivityContainer container = mInterface.createStackOnDisplay(displayId);
+        if (container != null) {
+            container.startActivity(intent);
+        }
+        return 0;
+    }
+
+    int runStackMoveTask(PrintWriter pw) throws RemoteException {
+        String taskIdStr = getNextArgRequired();
+        int taskId = Integer.parseInt(taskIdStr);
+        String stackIdStr = getNextArgRequired();
+        int stackId = Integer.parseInt(stackIdStr);
+        String toTopStr = getNextArgRequired();
+        final boolean toTop;
+        if ("true".equals(toTopStr)) {
+            toTop = true;
+        } else if ("false".equals(toTopStr)) {
+            toTop = false;
+        } else {
+            getErrPrintWriter().println("Error: bad toTop arg: " + toTopStr);
+            return -1;
+        }
+
+        mInterface.moveTaskToStack(taskId, stackId, toTop);
+        return 0;
+    }
+
+    int runStackResize(PrintWriter pw) throws RemoteException {
+        String stackIdStr = getNextArgRequired();
+        int stackId = Integer.parseInt(stackIdStr);
+        final Rect bounds = getBounds();
+        if (bounds == null) {
+            getErrPrintWriter().println("Error: invalid input bounds");
+            return -1;
+        }
+        return resizeStack(stackId, bounds, 0);
+    }
+
+    int runStackResizeAnimated(PrintWriter pw) throws RemoteException {
+        String stackIdStr = getNextArgRequired();
+        int stackId = Integer.parseInt(stackIdStr);
+        final Rect bounds;
+        if ("null".equals(peekNextArg())) {
+            bounds = null;
+        } else {
+            bounds = getBounds();
+            if (bounds == null) {
+                getErrPrintWriter().println("Error: invalid input bounds");
+                return -1;
+            }
+        }
+        return resizeStackUnchecked(stackId, bounds, 0, true);
+    }
+
+    int resizeStackUnchecked(int stackId, Rect bounds, int delayMs, boolean animate)
+            throws RemoteException {
+        try {
+            mInterface.resizeStack(stackId, bounds, false, false, animate, -1);
+            Thread.sleep(delayMs);
+        } catch (InterruptedException e) {
+        }
+        return 0;
+    }
+
+    int runStackResizeDocked(PrintWriter pw) throws RemoteException {
+        final Rect bounds = getBounds();
+        final Rect taskBounds = getBounds();
+        if (bounds == null || taskBounds == null) {
+            getErrPrintWriter().println("Error: invalid input bounds");
+            return -1;
+        }
+        mInterface.resizeDockedStack(bounds, taskBounds, null, null, null);
+        return 0;
+    }
+
+    int resizeStack(int stackId, Rect bounds, int delayMs) throws RemoteException {
+        if (bounds == null) {
+            getErrPrintWriter().println("Error: invalid input bounds");
+            return -1;
+        }
+        return resizeStackUnchecked(stackId, bounds, delayMs, false);
+    }
+
+    int runStackPositionTask(PrintWriter pw) throws RemoteException {
+        String taskIdStr = getNextArgRequired();
+        int taskId = Integer.parseInt(taskIdStr);
+        String stackIdStr = getNextArgRequired();
+        int stackId = Integer.parseInt(stackIdStr);
+        String positionStr = getNextArgRequired();
+        int position = Integer.parseInt(positionStr);
+
+        mInterface.positionTaskInStack(taskId, stackId, position);
+        return 0;
+    }
+
+    int runStackList(PrintWriter pw) throws RemoteException {
+        List<ActivityManager.StackInfo> stacks = mInterface.getAllStackInfos();
+        for (ActivityManager.StackInfo info : stacks) {
+            pw.println(info);
+        }
+        return 0;
+    }
+
+    int runStackInfo(PrintWriter pw) throws RemoteException {
+        String stackIdStr = getNextArgRequired();
+        int stackId = Integer.parseInt(stackIdStr);
+        ActivityManager.StackInfo info = mInterface.getStackInfo(stackId);
+        pw.println(info);
+        return 0;
+    }
+
+    int runStackRemove(PrintWriter pw) throws RemoteException {
+        String stackIdStr = getNextArgRequired();
+        int stackId = Integer.parseInt(stackIdStr);
+        mInterface.removeStack(stackId);
+        return 0;
+    }
+
+    int runMoveTopActivityToPinnedStack(PrintWriter pw) throws RemoteException {
+        int stackId = Integer.parseInt(getNextArgRequired());
+        final Rect bounds = getBounds();
+        if (bounds == null) {
+            getErrPrintWriter().println("Error: invalid input bounds");
+            return -1;
+        }
+
+        if (!mInterface.moveTopActivityToPinnedStack(stackId, bounds)) {
+            getErrPrintWriter().println("Didn't move top activity to pinned stack.");
+            return -1;
+        }
+        return 0;
+    }
+
+    int runStackSizeDockedStackTest(PrintWriter pw) throws RemoteException {
+        final PrintWriter err = getErrPrintWriter();
+        final int stepSize = Integer.parseInt(getNextArgRequired());
+        final String side = getNextArgRequired();
+        final String delayStr = getNextArg();
+        final int delayMs = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
+
+        ActivityManager.StackInfo info = mInterface.getStackInfo(DOCKED_STACK_ID);
+        if (info == null) {
+            err.println("Docked stack doesn't exist");
+            return -1;
+        }
+        if (info.bounds == null) {
+            err.println("Docked stack doesn't have a bounds");
+            return -1;
+        }
+        Rect bounds = info.bounds;
+
+        final boolean horizontalGrowth = "l".equals(side) || "r".equals(side);
+        final int changeSize = (horizontalGrowth ? bounds.width() : bounds.height()) / 2;
+        int currentPoint;
+        switch (side) {
+            case "l":
+                currentPoint = bounds.left;
+                break;
+            case "r":
+                currentPoint = bounds.right;
+                break;
+            case "t":
+                currentPoint = bounds.top;
+                break;
+            case "b":
+                currentPoint = bounds.bottom;
+                break;
+            default:
+                err.println("Unknown growth side: " + side);
+                return -1;
+        }
+
+        final int startPoint = currentPoint;
+        final int minPoint = currentPoint - changeSize;
+        final int maxPoint = currentPoint + changeSize;
+
+        int maxChange;
+        pw.println("Shrinking docked stack side=" + side);
+        pw.flush();
+        while (currentPoint > minPoint) {
+            maxChange = Math.min(stepSize, currentPoint - minPoint);
+            currentPoint -= maxChange;
+            setBoundsSide(bounds, side, currentPoint);
+            int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+            if (res < 0) {
+                return res;
+            }
+        }
+
+        pw.println("Growing docked stack side=" + side);
+        pw.flush();
+        while (currentPoint < maxPoint) {
+            maxChange = Math.min(stepSize, maxPoint - currentPoint);
+            currentPoint += maxChange;
+            setBoundsSide(bounds, side, currentPoint);
+            int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+            if (res < 0) {
+                return res;
+            }
+        }
+
+        pw.println("Back to Original size side=" + side);
+        pw.flush();
+        while (currentPoint > startPoint) {
+            maxChange = Math.min(stepSize, currentPoint - startPoint);
+            currentPoint -= maxChange;
+            setBoundsSide(bounds, side, currentPoint);
+            int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+            if (res < 0) {
+                return res;
+            }
+        }
+        return 0;
+    }
+
+    void setBoundsSide(Rect bounds, String side, int value) {
+        switch (side) {
+            case "l":
+                bounds.left = value;
+                break;
+            case "r":
+                bounds.right = value;
+                break;
+            case "t":
+                bounds.top = value;
+                break;
+            case "b":
+                bounds.bottom = value;
+                break;
+            default:
+                getErrPrintWriter().println("Unknown set side: " + side);
+                break;
+        }
+    }
+
+    int runTask(PrintWriter pw) throws RemoteException {
+        String op = getNextArgRequired();
+        if (op.equals("lock")) {
+            return runTaskLock(pw);
+        } else if (op.equals("resizeable")) {
+            return runTaskResizeable(pw);
+        } else if (op.equals("resize")) {
+            return runTaskResize(pw);
+        } else if (op.equals("drag-task-test")) {
+            return runTaskDragTaskTest(pw);
+        } else if (op.equals("size-task-test")) {
+            return runTaskSizeTaskTest(pw);
+        } else {
+            getErrPrintWriter().println("Error: unknown command '" + op + "'");
+            return -1;
+        }
+    }
+
+    int runTaskLock(PrintWriter pw) throws RemoteException {
+        String taskIdStr = getNextArgRequired();
+        if (taskIdStr.equals("stop")) {
+            mInterface.stopLockTaskMode();
+        } else {
+            int taskId = Integer.parseInt(taskIdStr);
+            mInterface.startLockTaskMode(taskId);
+        }
+        pw.println("Activity manager is " + (mInterface.isInLockTaskMode() ? "" : "not ") +
+                "in lockTaskMode");
+        return 0;
+    }
+
+    int runTaskResizeable(PrintWriter pw) throws RemoteException {
+        final String taskIdStr = getNextArgRequired();
+        final int taskId = Integer.parseInt(taskIdStr);
+        final String resizeableStr = getNextArgRequired();
+        final int resizeableMode = Integer.parseInt(resizeableStr);
+        mInterface.setTaskResizeable(taskId, resizeableMode);
+        return 0;
+    }
+
+    int runTaskResize(PrintWriter pw) throws RemoteException {
+        final String taskIdStr = getNextArgRequired();
+        final int taskId = Integer.parseInt(taskIdStr);
+        final Rect bounds = getBounds();
+        if (bounds == null) {
+            getErrPrintWriter().println("Error: invalid input bounds");
+            return -1;
+        }
+        taskResize(taskId, bounds, 0, false);
+        return 0;
+    }
+
+    void taskResize(int taskId, Rect bounds, int delay_ms, boolean pretendUserResize)
+            throws RemoteException {
+        final int resizeMode = pretendUserResize ? RESIZE_MODE_USER : RESIZE_MODE_SYSTEM;
+        mInterface.resizeTask(taskId, bounds, resizeMode);
+        try {
+            Thread.sleep(delay_ms);
+        } catch (InterruptedException e) {
+        }
+    }
+
+    int runTaskDragTaskTest(PrintWriter pw) throws RemoteException {
+        final int taskId = Integer.parseInt(getNextArgRequired());
+        final int stepSize = Integer.parseInt(getNextArgRequired());
+        final String delayStr = getNextArg();
+        final int delay_ms = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
+        final ActivityManager.StackInfo stackInfo;
+        Rect taskBounds;
+        stackInfo = mInterface.getStackInfo(mInterface.getFocusedStackId());
+        taskBounds = mInterface.getTaskBounds(taskId);
+        final Rect stackBounds = stackInfo.bounds;
+        int travelRight = stackBounds.width() - taskBounds.width();
+        int travelLeft = -travelRight;
+        int travelDown = stackBounds.height() - taskBounds.height();
+        int travelUp = -travelDown;
+        int passes = 0;
+
+        // We do 2 passes to get back to the original location of the task.
+        while (passes < 2) {
+            // Move right
+            pw.println("Moving right...");
+            pw.flush();
+            travelRight = moveTask(taskId, taskBounds, stackBounds, stepSize,
+                    travelRight, MOVING_FORWARD, MOVING_HORIZONTALLY, delay_ms);
+            pw.println("Still need to travel right by " + travelRight);
+
+            // Move down
+            pw.println("Moving down...");
+            pw.flush();
+            travelDown = moveTask(taskId, taskBounds, stackBounds, stepSize,
+                    travelDown, MOVING_FORWARD, !MOVING_HORIZONTALLY, delay_ms);
+            pw.println("Still need to travel down by " + travelDown);
+
+            // Move left
+            pw.println("Moving left...");
+            pw.flush();
+            travelLeft = moveTask(taskId, taskBounds, stackBounds, stepSize,
+                    travelLeft, !MOVING_FORWARD, MOVING_HORIZONTALLY, delay_ms);
+            pw.println("Still need to travel left by " + travelLeft);
+
+            // Move up
+            pw.println("Moving up...");
+            pw.flush();
+            travelUp = moveTask(taskId, taskBounds, stackBounds, stepSize,
+                    travelUp, !MOVING_FORWARD, !MOVING_HORIZONTALLY, delay_ms);
+            pw.println("Still need to travel up by " + travelUp);
+
+            taskBounds = mInterface.getTaskBounds(taskId);
+            passes++;
+        }
+        return 0;
+    }
+
+    int moveTask(int taskId, Rect taskRect, Rect stackRect, int stepSize,
+            int maxToTravel, boolean movingForward, boolean horizontal, int delay_ms)
+            throws RemoteException {
+        int maxMove;
+        if (movingForward) {
+            while (maxToTravel > 0
+                    && ((horizontal && taskRect.right < stackRect.right)
+                    ||(!horizontal && taskRect.bottom < stackRect.bottom))) {
+                if (horizontal) {
+                    maxMove = Math.min(stepSize, stackRect.right - taskRect.right);
+                    maxToTravel -= maxMove;
+                    taskRect.right += maxMove;
+                    taskRect.left += maxMove;
+                } else {
+                    maxMove = Math.min(stepSize, stackRect.bottom - taskRect.bottom);
+                    maxToTravel -= maxMove;
+                    taskRect.top += maxMove;
+                    taskRect.bottom += maxMove;
+                }
+                taskResize(taskId, taskRect, delay_ms, false);
+            }
+        } else {
+            while (maxToTravel < 0
+                    && ((horizontal && taskRect.left > stackRect.left)
+                    ||(!horizontal && taskRect.top > stackRect.top))) {
+                if (horizontal) {
+                    maxMove = Math.min(stepSize, taskRect.left - stackRect.left);
+                    maxToTravel -= maxMove;
+                    taskRect.right -= maxMove;
+                    taskRect.left -= maxMove;
+                } else {
+                    maxMove = Math.min(stepSize, taskRect.top - stackRect.top);
+                    maxToTravel -= maxMove;
+                    taskRect.top -= maxMove;
+                    taskRect.bottom -= maxMove;
+                }
+                taskResize(taskId, taskRect, delay_ms, false);
+            }
+        }
+        // Return the remaining distance we didn't travel because we reached the target location.
+        return maxToTravel;
+    }
+
+    int getStepSize(int current, int target, int inStepSize, boolean greaterThanTarget) {
+        int stepSize = 0;
+        if (greaterThanTarget && target < current) {
+            current -= inStepSize;
+            stepSize = inStepSize;
+            if (target > current) {
+                stepSize -= (target - current);
+            }
+        }
+        if (!greaterThanTarget && target > current) {
+            current += inStepSize;
+            stepSize = inStepSize;
+            if (target < current) {
+                stepSize += (current - target);
+            }
+        }
+        return stepSize;
+    }
+
+    int runTaskSizeTaskTest(PrintWriter pw) throws RemoteException {
+        final int taskId = Integer.parseInt(getNextArgRequired());
+        final int stepSize = Integer.parseInt(getNextArgRequired());
+        final String delayStr = getNextArg();
+        final int delay_ms = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
+        final ActivityManager.StackInfo stackInfo;
+        final Rect initialTaskBounds;
+        stackInfo = mInterface.getStackInfo(mInterface.getFocusedStackId());
+        initialTaskBounds = mInterface.getTaskBounds(taskId);
+        final Rect stackBounds = stackInfo.bounds;
+        stackBounds.inset(STACK_BOUNDS_INSET, STACK_BOUNDS_INSET);
+        final Rect currentTaskBounds = new Rect(initialTaskBounds);
+
+        // Size by top-left
+        pw.println("Growing top-left");
+        pw.flush();
+        do {
+            currentTaskBounds.top -= getStepSize(
+                    currentTaskBounds.top, stackBounds.top, stepSize, GREATER_THAN_TARGET);
+
+            currentTaskBounds.left -= getStepSize(
+                    currentTaskBounds.left, stackBounds.left, stepSize, GREATER_THAN_TARGET);
+
+            taskResize(taskId, currentTaskBounds, delay_ms, true);
+        } while (stackBounds.top < currentTaskBounds.top
+                || stackBounds.left < currentTaskBounds.left);
+
+        // Back to original size
+        pw.println("Shrinking top-left");
+        pw.flush();
+        do {
+            currentTaskBounds.top += getStepSize(
+                    currentTaskBounds.top, initialTaskBounds.top, stepSize, !GREATER_THAN_TARGET);
+
+            currentTaskBounds.left += getStepSize(
+                    currentTaskBounds.left, initialTaskBounds.left, stepSize, !GREATER_THAN_TARGET);
+
+            taskResize(taskId, currentTaskBounds, delay_ms, true);
+        } while (initialTaskBounds.top > currentTaskBounds.top
+                || initialTaskBounds.left > currentTaskBounds.left);
+
+        // Size by top-right
+        pw.println("Growing top-right");
+        pw.flush();
+        do {
+            currentTaskBounds.top -= getStepSize(
+                    currentTaskBounds.top, stackBounds.top, stepSize, GREATER_THAN_TARGET);
+
+            currentTaskBounds.right += getStepSize(
+                    currentTaskBounds.right, stackBounds.right, stepSize, !GREATER_THAN_TARGET);
+
+            taskResize(taskId, currentTaskBounds, delay_ms, true);
+        } while (stackBounds.top < currentTaskBounds.top
+                || stackBounds.right > currentTaskBounds.right);
+
+        // Back to original size
+        pw.println("Shrinking top-right");
+        pw.flush();
+        do {
+            currentTaskBounds.top += getStepSize(
+                    currentTaskBounds.top, initialTaskBounds.top, stepSize, !GREATER_THAN_TARGET);
+
+            currentTaskBounds.right -= getStepSize(currentTaskBounds.right, initialTaskBounds.right,
+                    stepSize, GREATER_THAN_TARGET);
+
+            taskResize(taskId, currentTaskBounds, delay_ms, true);
+        } while (initialTaskBounds.top > currentTaskBounds.top
+                || initialTaskBounds.right < currentTaskBounds.right);
+
+        // Size by bottom-left
+        pw.println("Growing bottom-left");
+        pw.flush();
+        do {
+            currentTaskBounds.bottom += getStepSize(
+                    currentTaskBounds.bottom, stackBounds.bottom, stepSize, !GREATER_THAN_TARGET);
+
+            currentTaskBounds.left -= getStepSize(
+                    currentTaskBounds.left, stackBounds.left, stepSize, GREATER_THAN_TARGET);
+
+            taskResize(taskId, currentTaskBounds, delay_ms, true);
+        } while (stackBounds.bottom > currentTaskBounds.bottom
+                || stackBounds.left < currentTaskBounds.left);
+
+        // Back to original size
+        pw.println("Shrinking bottom-left");
+        pw.flush();
+        do {
+            currentTaskBounds.bottom -= getStepSize(currentTaskBounds.bottom,
+                    initialTaskBounds.bottom, stepSize, GREATER_THAN_TARGET);
+
+            currentTaskBounds.left += getStepSize(
+                    currentTaskBounds.left, initialTaskBounds.left, stepSize, !GREATER_THAN_TARGET);
+
+            taskResize(taskId, currentTaskBounds, delay_ms, true);
+        } while (initialTaskBounds.bottom < currentTaskBounds.bottom
+                || initialTaskBounds.left > currentTaskBounds.left);
+
+        // Size by bottom-right
+        pw.println("Growing bottom-right");
+        pw.flush();
+        do {
+            currentTaskBounds.bottom += getStepSize(
+                    currentTaskBounds.bottom, stackBounds.bottom, stepSize, !GREATER_THAN_TARGET);
+
+            currentTaskBounds.right += getStepSize(
+                    currentTaskBounds.right, stackBounds.right, stepSize, !GREATER_THAN_TARGET);
+
+            taskResize(taskId, currentTaskBounds, delay_ms, true);
+        } while (stackBounds.bottom > currentTaskBounds.bottom
+                || stackBounds.right > currentTaskBounds.right);
+
+        // Back to original size
+        pw.println("Shrinking bottom-right");
+        pw.flush();
+        do {
+            currentTaskBounds.bottom -= getStepSize(currentTaskBounds.bottom,
+                    initialTaskBounds.bottom, stepSize, GREATER_THAN_TARGET);
+
+            currentTaskBounds.right -= getStepSize(currentTaskBounds.right, initialTaskBounds.right,
+                    stepSize, GREATER_THAN_TARGET);
+
+            taskResize(taskId, currentTaskBounds, delay_ms, true);
+        } while (initialTaskBounds.bottom < currentTaskBounds.bottom
+                || initialTaskBounds.right < currentTaskBounds.right);
+        return 0;
+    }
+
+    int runWrite(PrintWriter pw) {
+        mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
+                "registerUidObserver()");
+        mInternal.mRecentTasks.flush();
+        pw.println("All tasks persisted.");
         return 0;
     }
 
@@ -511,45 +2501,189 @@
         } else {
             pw.println("Activity manager (activity) commands:");
             pw.println("  help");
-            pw.println("    Print this help text.");
+            pw.println("      Print this help text.");
             pw.println("  start-activity [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]");
             pw.println("          [--sampling INTERVAL] [-R COUNT] [-S]");
             pw.println("          [--track-allocation] [--user <USER_ID> | current] <INTENT>");
-            pw.println("    Start an Activity.  Options are:");
-            pw.println("    -D: enable debugging");
-            pw.println("    -N: enable native debugging");
-            pw.println("    -W: wait for launch to complete");
-            pw.println("    --start-profiler <FILE>: start profiler and send results to <FILE>");
-            pw.println("    --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
-            pw.println("        between samples (use with --start-profiler)");
-            pw.println("    -P <FILE>: like above, but profiling stops when app goes idle");
-            pw.println("    -R: repeat the activity launch <COUNT> times.  Prior to each repeat,");
-            pw.println("        the top activity will be finished.");
-            pw.println("    -S: force stop the target app before starting the activity");
-            pw.println("    --track-allocation: enable tracking of object allocations");
-            pw.println("    --user <USER_ID> | current: Specify which user to run as; if not");
-            pw.println("        specified then run as the current user.");
-            pw.println("    --stack <STACK_ID>: Specify into which stack should the activity be put.");
+            pw.println("      Start an Activity.  Options are:");
+            pw.println("      -D: enable debugging");
+            pw.println("      -N: enable native debugging");
+            pw.println("      -W: wait for launch to complete");
+            pw.println("      --start-profiler <FILE>: start profiler and send results to <FILE>");
+            pw.println("      --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
+            pw.println("          between samples (use with --start-profiler)");
+            pw.println("      -P <FILE>: like above, but profiling stops when app goes idle");
+            pw.println("      -R: repeat the activity launch <COUNT> times.  Prior to each repeat,");
+            pw.println("          the top activity will be finished.");
+            pw.println("      -S: force stop the target app before starting the activity");
+            pw.println("      --track-allocation: enable tracking of object allocations");
+            pw.println("      --user <USER_ID> | current: Specify which user to run as; if not");
+            pw.println("          specified then run as the current user.");
+            pw.println("      --stack <STACK_ID>: Specify into which stack should the activity be put.");
+            pw.println("  start-service [--user <USER_ID> | current] <INTENT>");
+            pw.println("      Start a Service.  Options are:");
+            pw.println("      --user <USER_ID> | current: Specify which user to run as; if not");
+            pw.println("          specified then run as the current user.");
+            pw.println("  stop-service [--user <USER_ID> | current] <INTENT>");
+            pw.println("      Stop a Service.  Options are:");
+            pw.println("      --user <USER_ID> | current: Specify which user to run as; if not");
+            pw.println("          specified then run as the current user.");
+            pw.println("  broadcast [--user <USER_ID> | all | current] <INTENT>");
+            pw.println("      Send a broadcast Intent.  Options are:");
+            pw.println("      --user <USER_ID> | all | current: Specify which user to send to; if not");
+            pw.println("          specified then send to all users.");
+            pw.println("      --receiver-permission <PERMISSION>: Require receiver to hold permission.");
+            pw.println("  trace-ipc [start|stop] [--dump-file <FILE>]");
+            pw.println("      Trace IPC transactions.");
+            pw.println("      start: start tracing IPC transactions.");
+            pw.println("      stop: stop tracing IPC transactions and dump the results to file.");
+            pw.println("      --dump-file <FILE>: Specify the file the trace should be dumped to.");
+            pw.println("  profile [start|stop] [--user <USER_ID> current] [--sampling INTERVAL]");
+            pw.println("          <PROCESS> <FILE>");
+            pw.println("      Start and stop profiler on a process.  The given <PROCESS> argument");
+            pw.println("        may be either a process name or pid.  Options are:");
+            pw.println("      --user <USER_ID> | current: When supplying a process name,");
+            pw.println("          specify user of process to profile; uses current user if not specified.");
+            pw.println("  dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>");
+            pw.println("      Dump the heap of a process.  The given <PROCESS> argument may");
+            pw.println("        be either a process name or pid.  Options are:");
+            pw.println("      -n: dump native heap instead of managed heap");
+            pw.println("      --user <USER_ID> | current: When supplying a process name,");
+            pw.println("          specify user of process to dump; uses current user if not specified.");
+            pw.println("  set-debug-app [-w] [--persistent] <PACKAGE>");
+            pw.println("      Set application <PACKAGE> to debug.  Options are:");
+            pw.println("      -w: wait for debugger when application starts");
+            pw.println("      --persistent: retain this value");
+            pw.println("  clear-debug-app");
+            pw.println("      Clear the previously set-debug-app.");
+            pw.println("  set-watch-heap <PROCESS> <MEM-LIMIT>");
+            pw.println("      Start monitoring pss size of <PROCESS>, if it is at or");
+            pw.println("      above <HEAP-LIMIT> then a heap dump is collected for the user to report.");
+            pw.println("  clear-watch-heap");
+            pw.println("      Clear the previously set-watch-heap.");
+            pw.println("  bug-report [--progress]");
+            pw.println("      Request bug report generation; will launch a notification");
+            pw.println("        when done to select where it should be delivered. Options are:");
+            pw.println("     --progress: will launch a notification right away to show its progress.");
             pw.println("  force-stop [--user <USER_ID> | all | current] <PACKAGE>");
-            pw.println("    Completely stop the given application package.");
+            pw.println("      Completely stop the given application package.");
             pw.println("  kill [--user <USER_ID> | all | current] <PACKAGE>");
-            pw.println("    Kill all processes associated with the given application.");
+            pw.println("      Kill all processes associated with the given application.");
             pw.println("  kill-all");
-            pw.println("    Kill all processes that are safe to kill (cached, etc).");
-            pw.println("  write");
-            pw.println("    Write all pending state to storage.");
-            pw.println("  track-associations");
-            pw.println("    Enable association tracking.");
-            pw.println("  untrack-associations");
-            pw.println("    Disable and clear association tracking.");
+            pw.println("      Kill all processes that are safe to kill (cached, etc).");
+            pw.println("  monitor [--gdb <port>]");
+            pw.println("      Start monitoring for crashes or ANRs.");
+            pw.println("      --gdb: start gdbserv on the given port at crash/ANR");
+            pw.println("  hang [--allow-restart]");
+            pw.println("      Hang the system.");
+            pw.println("      --allow-restart: allow watchdog to perform normal system restart");
+            pw.println("  restart");
+            pw.println("      Restart the user-space system.");
+            pw.println("  idle-maintenance");
+            pw.println("      Perform idle maintenance now.");
+            pw.println("  screen-compat [on|off] <PACKAGE>");
+            pw.println("      Control screen compatibility mode of <PACKAGE>.");
+            pw.println("  package-importance <PACKAGE>");
+            pw.println("      Print current importance of <PACKAGE>.");
+            pw.println("  to-uri [INTENT]");
+            pw.println("      Print the given Intent specification as a URI.");
+            pw.println("  to-intent-uri [INTENT]");
+            pw.println("      Print the given Intent specification as an intent: URI.");
+            pw.println("  to-app-uri [INTENT]");
+            pw.println("      Print the given Intent specification as an android-app: URI.");
+            pw.println("  switch-user <USER_ID>");
+            pw.println("      Switch to put USER_ID in the foreground, starting");
+            pw.println("      execution of that user if it is currently stopped.");
+            pw.println("  get-current-user");
+            pw.println("      Returns id of the current foreground user.");
+            pw.println("  start-user <USER_ID>");
+            pw.println("      Start USER_ID in background if it is currently stopped;");
+            pw.println("      use switch-user if you want to start the user in foreground");
+            pw.println("  unlock-user <USER_ID> [TOKEN_HEX]");
+            pw.println("      Attempt to unlock the given user using the given authorization token.");
+            pw.println("  stop-user [-w] [-f] <USER_ID>");
+            pw.println("      Stop execution of USER_ID, not allowing it to run any");
+            pw.println("      code until a later explicit start or switch to it.");
+            pw.println("      -w: wait for stop-user to complete.");
+            pw.println("      -f: force stop even if there are related users that cannot be stopped.");
             pw.println("  is-user-stopped <USER_ID>");
-            pw.println("    Returns whether <USER_ID> has been stopped or not.");
-            pw.println("  lenient-background-check [<true|false>]");
-            pw.println("    Optionally controls lenient background check mode, returns current mode.");
-            pw.println("  get-uid-state <UID>");
-            pw.println("    Gets the process state of an app given its <UID>.");
+            pw.println("      Returns whether <USER_ID> has been stopped or not.");
             pw.println("  get-started-user-state <USER_ID>");
-            pw.println("    Gets the current state of the given started user.");
+            pw.println("      Gets the current state of the given started user.");
+            pw.println("  track-associations");
+            pw.println("      Enable association tracking.");
+            pw.println("  untrack-associations");
+            pw.println("      Disable and clear association tracking.");
+            pw.println("  lenient-background-check [<true|false>]");
+            pw.println("      Optionally controls lenient background check mode, returns current mode.");
+            pw.println("  get-uid-state <UID>");
+            pw.println("      Gets the process state of an app given its <UID>.");
+            pw.println("  get-config");
+            pw.println("      Rtrieve the configuration and any recent configurations of the device.");
+            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");
+            pw.println("      Sets the inactive state of an app.");
+            pw.println("  get-inactive [--user <USER_ID>] <PACKAGE>");
+            pw.println("      Returns the inactive state of an app.");
+            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("  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_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>");
+            pw.println("           Change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.");
+            pw.println("       resize-animated <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>");
+            pw.println("           Same as resize, but allow animation.");
+            pw.println("       resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]");
+            pw.println("           Change docked stack to <LEFT,TOP,RIGHT,BOTTOM>");
+            pw.println("           and supplying temporary different task bounds indicated by");
+            pw.println("           <TASK_LEFT,TOP,RIGHT,BOTTOM>");
+            pw.println("       size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]");
+            pw.println("           Test command for sizing docked stack by");
+            pw.println("           <STEP_SIZE> increments from the side <l>eft, <t>op, <r>ight, or <b>ottom");
+            pw.println("           applying the optional [DELAY_MS] between each step.");
+            pw.println("       move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>");
+            pw.println("           Moves the top activity from");
+            pw.println("           <STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for the");
+            pw.println("           bounds of the pinned stack.");
+            pw.println("       positiontask <TASK_ID> <STACK_ID> <POSITION>");
+            pw.println("           Place <TASK_ID> in <STACK_ID> at <POSITION>");
+            pw.println("       list");
+            pw.println("           List all of the activity stacks and their sizes.");
+            pw.println("       info <STACK_ID>");
+            pw.println("           Display the information about activity stack <STACK_ID>.");
+            pw.println("       remove <STACK_ID>");
+            pw.println("           Remove stack <STACK_ID>.");
+            pw.println("  task [COMMAND] [...]: sub-commands for operating on activity tasks.");
+            pw.println("       lock <TASK_ID>");
+            pw.println("           Bring <TASK_ID> to the front and don't allow other tasks to run.");
+            pw.println("       lock stop");
+            pw.println("           End the current task lock.");
+            pw.println("       resizeable <TASK_ID> [0|1|2|3]");
+            pw.println("           Change resizeable mode of <TASK_ID> to one of the following:");
+            pw.println("           0: unresizeable");
+            pw.println("           1: crop_windows");
+            pw.println("           2: resizeable");
+            pw.println("           3: resizeable_and_pipable");
+            pw.println("       resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>");
+            pw.println("           Makes sure <TASK_ID> is in a stack with the specified bounds.");
+            pw.println("           Forces the task to be resizeable and creates a stack if no existing stack");
+            pw.println("           has the specified bounds.");
+            pw.println("       drag-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS]");
+            pw.println("           Test command for dragging/moving <TASK_ID> by");
+            pw.println("           <STEP_SIZE> increments around the screen applying the optional [DELAY_MS]");
+            pw.println("           between each step.");
+            pw.println("       size-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS]");
+            pw.println("           Test command for sizing <TASK_ID> by <STEP_SIZE>");
+            pw.println("           increments within the screen applying the optional [DELAY_MS] between");
+            pw.println("           each step.");
+            pw.println("  write");
+            pw.println("      Write all pending state to storage.");
             pw.println();
             Intent.printIntentArgsHelp(pw, "");
         }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index e52671f..d89f02d 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -20,22 +20,38 @@
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
+import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
+import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
+import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
+import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.view.Display.DEFAULT_DISPLAY;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SCREENSHOTS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_THUMBNAILS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SCREENSHOTS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_THUMBNAILS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityManagerService.TAKE_FULLSCREEN_SCREENSHOTS;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityOptions;
 import android.app.PendingIntent;
@@ -50,6 +66,7 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.PersistableBundle;
@@ -81,6 +98,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Objects;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -92,12 +110,16 @@
  */
 final class ActivityRecord {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM;
+    private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
+    private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
+    private static final String TAG_SCREENSHOTS = TAG + POSTFIX_SCREENSHOTS;
     private static final String TAG_STATES = TAG + POSTFIX_STATES;
     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
     private static final String TAG_THUMBNAILS = TAG + POSTFIX_THUMBNAILS;
+    private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
 
     private static final boolean SHOW_ACTIVITY_START_TIME = true;
-    final public static String RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
+    private static final String RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
 
     private static final String ATTR_ID = "id";
     private static final String TAG_INTENT = "intent";
@@ -150,11 +172,11 @@
     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
     long pauseTime;         // last time we started pausing the activity
     long launchTickTime;    // base time for launch tick messages
-    Configuration configuration; // configuration activity was last running in
+    private Configuration mLastReportedConfiguration; // configuration activity was last running in
     // Overridden configuration by the activity task
-    // WARNING: Reference points to {@link TaskRecord#mOverrideConfig}, so its internal state
-    // should never be altered directly.
-    Configuration taskConfigOverride;
+    // WARNING: Reference points to {@link TaskRecord#getMergedOverrideConfig}, so its internal
+    // state should never be altered directly.
+    private Configuration mLastReportedOverrideConfiguration;
     CompatibilityInfo compat;// last used compatibility mode
     ActivityRecord resultTo; // who started this entry, so will get our reply
     final String resultWho; // additional identifier for use by resultTo.
@@ -231,6 +253,12 @@
     // on the window.
     int mRotationAnimationHint = -1;
 
+    /**
+     * Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
+     */
+    private final Configuration mTmpGlobalConfig = new Configuration();
+    private final Configuration mTmpTaskConfig = new Configuration();
+
     private static String startingWindowStateToString(int state) {
         switch (state) {
             case STARTING_WINDOW_NOT_SHOWN:
@@ -279,8 +307,10 @@
                 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
-        pw.print(prefix); pw.print("config="); pw.println(configuration);
-        pw.print(prefix); pw.print("taskConfigOverride="); pw.println(taskConfigOverride);
+        pw.print(prefix); pw.print("mLastReportedConfiguration=");
+                pw.println(mLastReportedConfiguration);
+        pw.print(prefix); pw.print("mLastReportedOverrideConfiguration=");
+                pw.println(mLastReportedOverrideConfiguration);
         if (resultTo != null || resultWho != null) {
             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
                     pw.print(" resultWho="); pw.print(resultWho);
@@ -401,15 +431,15 @@
         }
     }
 
-    public boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
+    private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
         return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
     }
 
-    public boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
+    private boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
         return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp);
     }
 
-    public boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
+    private boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
         return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp);
     }
 
@@ -442,14 +472,14 @@
         return false;
     }
 
-    public void setSizeConfigurations(int[] horizontalSizeConfiguration,
+    void setSizeConfigurations(int[] horizontalSizeConfiguration,
             int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
         mHorizontalSizeConfigurations = horizontalSizeConfiguration;
         mVerticalSizeConfigurations = verticalSizeConfigurations;
         mSmallestSizeConfigurations = smallestSizeConfigurations;
     }
 
-    void scheduleConfigurationChanged(Configuration config, boolean reportToActivity) {
+    private void scheduleConfigurationChanged(Configuration config, boolean reportToActivity) {
         if (app == null || app.thread == null) {
             return;
         }
@@ -457,14 +487,15 @@
             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + " " +
                     "reportToActivity=" + reportToActivity + " and config: " + config);
 
-            app.thread.scheduleActivityConfigurationChanged(appToken, config, reportToActivity);
+            app.thread.scheduleActivityConfigurationChanged(appToken, new Configuration(config),
+                    reportToActivity);
         } catch (RemoteException e) {
             // If process died, whatever.
         }
     }
 
     void scheduleMultiWindowModeChanged() {
-        if (task == null || task.stack == null || app == null || app.thread == null) {
+        if (task == null || task.getStack() == null || app == null || app.thread == null) {
             return;
         }
         try {
@@ -476,20 +507,19 @@
     }
 
     void schedulePictureInPictureModeChanged() {
-        if (task == null || task.stack == null || app == null || app.thread == null) {
+        if (task == null || task.getStack() == null || app == null || app.thread == null) {
             return;
         }
         try {
             app.thread.schedulePictureInPictureModeChanged(
-                    appToken, task.stack.mStackId == PINNED_STACK_ID);
+                    appToken, task.getStackId() == PINNED_STACK_ID);
         } catch (Exception e) {
             // If process died, no one cares.
         }
     }
 
     boolean isFreeform() {
-        return task != null && task.stack != null
-                && task.stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
+        return task != null && task.getStackId() == FREEFORM_WORKSPACE_STACK_ID;
     }
 
     static class Token extends IApplicationToken.Stub {
@@ -528,7 +558,6 @@
                 if (r != null) {
                     if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + r);
                     r.nowVisible = false;
-                    return;
                 }
             }
         }
@@ -544,7 +573,7 @@
                     return false;
                 }
                 anrActivity = r.getWaitingHistoryRecordLocked();
-                anrApp = r != null ? r.app : null;
+                anrApp = r.app;
             }
             return mService.inputDispatchingTimedOut(anrApp, anrActivity, r, false, reason);
         }
@@ -561,12 +590,12 @@
             }
         }
 
-        private static final ActivityRecord tokenToActivityRecordLocked(Token token) {
+        private static ActivityRecord tokenToActivityRecordLocked(Token token) {
             if (token == null) {
                 return null;
             }
             ActivityRecord r = token.weakActivity.get();
-            if (r == null || r.task == null || r.task.stack == null) {
+            if (r == null || r.getStack() == null) {
                 return null;
             }
             return r;
@@ -615,8 +644,8 @@
         resolvedType = _resolvedType;
         componentSpecified = _componentSpecified;
         rootVoiceInteraction = _rootVoiceInteraction;
-        configuration = _configuration;
-        taskConfigOverride = Configuration.EMPTY;
+        mLastReportedConfiguration = new Configuration(_configuration);
+        mLastReportedOverrideConfiguration = new Configuration();
         resultTo = _resultTo;
         resultWho = _resultWho;
         requestCode = _reqCode;
@@ -769,6 +798,12 @@
                 && isHomeIntent(intent) && !isResolverActivity()) {
             // This sure looks like a home activity!
             mActivityType = HOME_ACTIVITY_TYPE;
+
+            if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE
+                    || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
+                // We only allow home activities to be resizeable if they explicitly requested it.
+                info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+            }
         } else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
             mActivityType = RECENTS_ACTIVITY_TYPE;
         } else {
@@ -777,8 +812,9 @@
     }
 
     void setTask(TaskRecord newTask, TaskRecord taskToAffiliateWith) {
-        if (task != null && task.removeActivity(this) && task != newTask && task.stack != null) {
-            task.stack.removeTask(task, "setTask");
+        if (task != null && task.removeActivity(this) && task != newTask
+                && task.getStack() != null) {
+            task.getStack().removeTask(task, "setTask");
         }
         task = newTask;
         setTaskToAffiliateWith(taskToAffiliateWith);
@@ -792,6 +828,13 @@
         }
     }
 
+    /**
+     * @return Stack value from current task, null if there is no task.
+     */
+    ActivityStack getStack() {
+        return task != null ? task.getStack() : null;
+    }
+
     boolean changeWindowTranslucency(boolean toOpaque) {
         if (fullscreen == toOpaque) {
             return false;
@@ -825,7 +868,8 @@
     }
 
     boolean isInStackLocked() {
-        return task != null && task.stack != null && task.stack.isInStackLocked(this) != null;
+        final ActivityStack stack = getStack();
+        return stack != null && stack.isInStackLocked(this) != null;
     }
 
     boolean isHomeActivity() {
@@ -848,11 +892,11 @@
     }
 
     boolean isFocusable() {
-        return StackId.canReceiveKeys(task.stack.mStackId) || isAlwaysFocusable();
+        return StackId.canReceiveKeys(task.getStackId()) || isAlwaysFocusable();
     }
 
     boolean isResizeable() {
-        return !isHomeActivity() && ActivityInfo.isResizeableMode(info.resizeMode);
+        return ActivityInfo.isResizeableMode(info.resizeMode);
     }
 
     boolean isResizeableOrForced() {
@@ -860,8 +904,9 @@
     }
 
     boolean isNonResizableOrForced() {
-        return !isHomeActivity() && info.resizeMode != RESIZE_MODE_RESIZEABLE
-                && info.resizeMode != RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
+        return info.resizeMode != RESIZE_MODE_RESIZEABLE
+                && info.resizeMode != RESIZE_MODE_RESIZEABLE_AND_PIPABLE
+                && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
     }
 
     boolean supportsPictureInPicture() {
@@ -869,22 +914,17 @@
     }
 
     boolean canGoInDockedStack() {
-        return !isHomeActivity()
-                && (isResizeableOrForced() || info.resizeMode == RESIZE_MODE_CROP_WINDOWS);
+        return !isHomeActivity() && isResizeableOrForced();
     }
 
     boolean isAlwaysFocusable() {
         return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
     }
 
-    boolean isOnTopLauncher() {
-        return isHomeActivity() && (info.flags & FLAG_ON_TOP_LAUNCHER) != 0;
-    }
-
     void makeFinishingLocked() {
         if (!finishing) {
-            if (task != null && task.stack != null
-                    && this == task.stack.getVisibleBehindActivity()) {
+            final ActivityStack stack = getStack();
+            if (stack != null && this == stack.getVisibleBehindActivity()) {
                 // A finishing activity should not remain as visible in the background
                 mStackSupervisor.requestVisibleBehindLocked(this, false);
             }
@@ -931,7 +971,7 @@
         }
     }
 
-    void addNewIntentLocked(ReferrerIntent intent) {
+    private void addNewIntentLocked(ReferrerIntent intent) {
         if (newIntents == null) {
             newIntents = new ArrayList<>();
         }
@@ -948,7 +988,7 @@
                 intent, getUriPermissionsLocked(), userId);
         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
         boolean unsent = true;
-        final ActivityStack stack = task.stack;
+        final ActivityStack stack = getStack();
         final boolean isTopActivityInStack =
                 stack != null && stack.topRunningActivityLocked() == this;
         final boolean isTopActivityWhileSleeping =
@@ -1112,12 +1152,251 @@
                     "Setting thumbnail of " + this + " to " + newThumbnail);
             boolean thumbnailUpdated = task.setLastThumbnailLocked(newThumbnail);
             if (thumbnailUpdated && isPersistable()) {
-                mStackSupervisor.mService.notifyTaskPersisterLocked(task, false);
+                service.notifyTaskPersisterLocked(task, false);
             }
         }
         task.lastDescription = description;
     }
 
+    final Bitmap screenshotActivityLocked() {
+        if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "screenshotActivityLocked: " + this);
+        if (noDisplay) {
+            if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tNo display");
+            return null;
+        }
+
+        final ActivityStack stack = getStack();
+        if (stack.isHomeStack()) {
+            // This is an optimization -- since we never show Home or Recents within Recents itself,
+            // we can just go ahead and skip taking the screenshot if this is the home stack.
+            if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tHome stack");
+            return null;
+        }
+
+        int w = service.mThumbnailWidth;
+        int h = service.mThumbnailHeight;
+
+        if (w <= 0) {
+            Slog.e(TAG, "\tInvalid thumbnail dimensions: " + w + "x" + h);
+            return null;
+        }
+
+        if (stack.mStackId == DOCKED_STACK_ID && mStackSupervisor.mIsDockMinimized) {
+            // When the docked stack is minimized its app windows are cropped significantly so any
+            // screenshot taken will not display the apps contain. So, we avoid taking a screenshot
+            // in that case.
+            if (DEBUG_SCREENSHOTS) Slog.e(TAG, "\tIn minimized docked stack");
+            return null;
+        }
+
+        final float scale;
+        if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tTaking screenshot");
+
+        // When this flag is set, we currently take the fullscreen screenshot of the activity but
+        // scaled to half the size. This gives us a "good-enough" fullscreen thumbnail to use within
+        // SystemUI while keeping memory usage low.
+        if (TAKE_FULLSCREEN_SCREENSHOTS) {
+            w = h = -1;
+            scale = service.mFullscreenThumbnailScale;
+        }
+
+        return service.mWindowManager.screenshotApplications(appToken, DEFAULT_DISPLAY, w, h,
+                scale);
+    }
+
+    void setVisible(boolean newVisible) {
+        visible = newVisible;
+        if (!visible && mUpdateTaskThumbnailWhenHidden) {
+            updateThumbnailLocked(screenshotActivityLocked(), null /* description */);
+            mUpdateTaskThumbnailWhenHidden = false;
+        }
+        service.mWindowManager.setAppVisibility(appToken, visible);
+        final ArrayList<ActivityContainer> containers = mChildContainers;
+        for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) {
+            final ActivityContainer container = containers.get(containerNdx);
+            container.setVisible(visible);
+        }
+        mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
+    }
+
+    /** Return true if the input activity should be made visible */
+    boolean shouldBeVisible(boolean behindTranslucentActivity, boolean stackVisibleBehind,
+            ActivityRecord visibleBehind, boolean behindFullscreenActivity) {
+        if (!okToShowLocked()) {
+            return false;
+        }
+
+        // mLaunchingBehind: Activities launching behind are at the back of the task stack
+        // but must be drawn initially for the animation as though they were visible.
+        final boolean activityVisibleBehind =
+                (behindTranslucentActivity || stackVisibleBehind) && visibleBehind == this;
+
+        boolean isVisible =
+                !behindFullscreenActivity || mLaunchTaskBehind || activityVisibleBehind;
+
+        if (service.mSupportsLeanbackOnly && isVisible && isRecentsActivity()) {
+            // On devices that support leanback only (Android TV), Recents activity can only be
+            // visible if the home stack is the focused stack or we are in split-screen mode.
+            isVisible = mStackSupervisor.getStack(DOCKED_STACK_ID) != null
+                    || mStackSupervisor.isFocusedStack(getStack());
+        }
+
+        return isVisible;
+    }
+
+    void makeVisibleIfNeeded(ActivityRecord starting) {
+        // This activity is not currently visible, but is running. Tell it to become visible.
+        if (state == ActivityState.RESUMED || this == starting) {
+            if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
+                    "Not making visible, r=" + this + " state=" + state + " starting=" + starting);
+            return;
+        }
+
+        // If this activity is paused, tell it to now show its window.
+        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                "Making visible and scheduling visibility: " + this);
+        final ActivityStack stack = getStack();
+        try {
+            if (stack.mTranslucentActivityWaiting != null) {
+                updateOptionsLocked(returningOptions);
+                stack.mUndrawnActivitiesBelowTopTranslucent.add(this);
+            }
+            setVisible(true);
+            sleeping = false;
+            app.pendingUiClean = true;
+            app.thread.scheduleWindowVisibility(appToken, true /* showWindow */);
+            // The activity may be waiting for stop, but that is no longer appropriate for it.
+            mStackSupervisor.mStoppingActivities.remove(this);
+            mStackSupervisor.mGoingToSleepActivities.remove(this);
+        } catch (Exception e) {
+            // Just skip on any failure; we'll make it visible when it next restarts.
+            Slog.w(TAG, "Exception thrown making visibile: " + intent.getComponent(), e);
+        }
+        handleAlreadyVisible();
+    }
+
+    boolean handleAlreadyVisible() {
+        stopFreezingScreenLocked(false);
+        try {
+            if (returningOptions != null) {
+                app.thread.scheduleOnNewActivityOptions(appToken, returningOptions);
+            }
+        } catch(RemoteException e) {
+        }
+        return state == ActivityState.RESUMED;
+    }
+
+    static void activityResumedLocked(IBinder token) {
+        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+        if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
+        if (r != null) {
+            r.icicle = null;
+            r.haveState = false;
+        }
+    }
+
+    /**
+     * Once we know that we have asked an application to put an activity in the resumed state
+     * (either by launching it or explicitly telling it), this function updates the rest of our
+     * state to match that fact.
+     */
+    void completeResumeLocked() {
+        final boolean wasVisible = visible;
+        visible = true;
+        if (!wasVisible) {
+            // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
+            mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
+        }
+        idle = false;
+        results = null;
+        newIntents = null;
+        stopped = false;
+
+        if (isHomeActivity()) {
+            ProcessRecord app = task.mActivities.get(0).app;
+            if (app != null && app != service.mHomeProcess) {
+                service.mHomeProcess = app;
+            }
+        }
+
+        if (nowVisible) {
+            // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now.
+            mStackSupervisor.reportActivityVisibleLocked(this);
+            mStackSupervisor.notifyActivityDrawnForKeyguard();
+        }
+
+        // Schedule an idle timeout in case the app doesn't do it for us.
+        mStackSupervisor.scheduleIdleTimeoutLocked(this);
+
+        mStackSupervisor.reportResumedActivityLocked(this);
+
+        resumeKeyDispatchingLocked();
+        final ActivityStack stack = getStack();
+        stack.mNoAnimActivities.clear();
+
+        // Mark the point when the activity is resuming
+        // TODO: To be more accurate, the mark should be before the onCreate,
+        //       not after the onResume. But for subsequent starts, onResume is fine.
+        if (app != null) {
+            cpuTimeAtResume = service.mProcessCpuTracker.getCpuTimeForPid(app.pid);
+        } else {
+            cpuTimeAtResume = 0; // Couldn't get the cpu time of process
+        }
+
+        returningOptions = null;
+
+        if (stack.getVisibleBehindActivity() == this) {
+            // When resuming an activity, require it to call requestVisibleBehind() again.
+            stack.setVisibleBehindActivity(null /* ActivityRecord */);
+        }
+        mStackSupervisor.checkReadyForSleepLocked();
+    }
+
+    final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
+            CharSequence description) {
+        final ActivityStack stack = getStack();
+        if (state != ActivityState.STOPPING) {
+            Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
+            stack.mHandler.removeMessages(ActivityStack.STOP_TIMEOUT_MSG, this);
+            return;
+        }
+        if (newPersistentState != null) {
+            persistentState = newPersistentState;
+            service.notifyTaskPersisterLocked(task, false);
+        }
+        if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + icicle);
+        if (newIcicle != null) {
+            // If icicle is null, this is happening due to a timeout, so we haven't really saved
+            // the state.
+            icicle = newIcicle;
+            haveState = true;
+            launchCount = 0;
+            updateThumbnailLocked(null /* newThumbnail */, description);
+        }
+        if (!stopped) {
+            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
+            stack.mHandler.removeMessages(ActivityStack.STOP_TIMEOUT_MSG, this);
+            stopped = true;
+            state = ActivityState.STOPPED;
+
+            service.mWindowManager.notifyAppStopped(appToken);
+
+            if (stack.getVisibleBehindActivity() == this) {
+                mStackSupervisor.requestVisibleBehindLocked(this, false /* visible */);
+            }
+            if (finishing) {
+                clearOptionsLocked();
+            } else {
+                if (deferRelaunchUntilPaused) {
+                    stack.destroyActivityLocked(this, true /* removeFromApp */, "stop-config");
+                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                } else {
+                    mStackSupervisor.updatePreviousProcessLocked(this);
+                }
+            }
+        }
+    }
+
     void startLaunchTickingLocked() {
         if (ActivityManagerService.IS_USER_BUILD) {
             return;
@@ -1133,7 +1412,7 @@
             return false;
         }
 
-        final ActivityStack stack = task.stack;
+        final ActivityStack stack = getStack();
         if (stack == null) {
             return false;
         }
@@ -1146,7 +1425,7 @@
 
     void finishLaunchTickingLocked() {
         launchTickTime = 0;
-        final ActivityStack stack = task.stack;
+        final ActivityStack stack = getStack();
         if (stack != null) {
             stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
         }
@@ -1180,7 +1459,7 @@
         if (displayStartTime != 0) {
             reportLaunchTimeLocked(curTime);
         }
-        final ActivityStack stack = task.stack;
+        final ActivityStack stack = getStack();
         if (fullyDrawnStartTime != 0 && stack != null) {
             final long thisTime = curTime - fullyDrawnStartTime;
             final long totalTime = stack.mFullyDrawnStartTime != 0
@@ -1212,7 +1491,7 @@
     }
 
     private void reportLaunchTimeLocked(final long curTime) {
-        final ActivityStack stack = task.stack;
+        final ActivityStack stack = getStack();
         if (stack == null) {
             return;
         }
@@ -1356,13 +1635,13 @@
 
     static ActivityRecord isInStackLocked(IBinder token) {
         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
-        return (r != null) ? r.task.stack.isInStackLocked(r) : null;
+        return (r != null) ? r.getStack().isInStackLocked(r) : null;
     }
 
     static ActivityStack getStackLocked(IBinder token) {
         final ActivityRecord r = ActivityRecord.isInStackLocked(token);
         if (r != null) {
-            return r.task.stack;
+            return r.getStack();
         }
         return null;
     }
@@ -1373,8 +1652,9 @@
             // This would be redundant.
             return false;
         }
-        if (task == null || task.stack == null || this == task.stack.mResumedActivity
-                || this == task.stack.mPausingActivity || !haveState || !stopped) {
+        final ActivityStack stack = getStack();
+        if (stack == null || this == stack.mResumedActivity || this == stack.mPausingActivity
+                || !haveState || !stopped) {
             // We're not ready for this kind of thing.
             return false;
         }
@@ -1424,6 +1704,255 @@
         }
     }
 
+    // TODO: now used only in one place to address race-condition. Remove when that will be fixed.
+    void setLastReportedConfiguration(@NonNull Configuration config) {
+        mLastReportedConfiguration.setTo(config);
+    }
+
+    /** Call when override config was sent to the Window Manager to update internal records. */
+    void onOverrideConfigurationSent() {
+        mLastReportedOverrideConfiguration.setTo(task.getMergedOverrideConfiguration());
+    }
+
+    /**
+     * Make sure the given activity matches the current configuration. Returns false if the activity
+     * had to be destroyed.  Returns true if the configuration is the same, or the activity will
+     * remain running as-is for whatever reason. Ensures the HistoryRecord is updated with the
+     * correct configuration and all other bookkeeping is handled.
+     */
+    boolean ensureActivityConfigurationLocked(int globalChanges, boolean preserveWindow) {
+        final ActivityStack stack = getStack();
+        if (stack.mConfigWillChange) {
+            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                    "Skipping config check (will change): " + this);
+            return true;
+        }
+
+        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                "Ensuring correct configuration: " + this);
+
+        // Short circuit: if the two configurations are equal (the common case), then there is
+        // nothing to do.
+        final Configuration newGlobalConfig = service.getGlobalConfiguration();
+        final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
+        if (mLastReportedConfiguration.equals(newGlobalConfig)
+                && mLastReportedOverrideConfiguration.equals(newTaskMergedOverrideConfig)
+                && !forceNewConfig) {
+            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                    "Configuration unchanged in " + this);
+            return true;
+        }
+
+        // We don't worry about activities that are finishing.
+        if (finishing) {
+            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                    "Configuration doesn't matter in finishing " + this);
+            stopFreezingScreenLocked(false);
+            return true;
+        }
+
+        // Okay we now are going to make this activity have the new config.
+        // But then we need to figure out how it needs to deal with that.
+        mTmpGlobalConfig.setTo(mLastReportedConfiguration);
+        mTmpTaskConfig.setTo(mLastReportedOverrideConfiguration);
+        mLastReportedConfiguration.setTo(newGlobalConfig);
+        mLastReportedOverrideConfiguration.setTo(newTaskMergedOverrideConfig);
+
+        int taskChanges = getTaskConfigurationChanges(this, newTaskMergedOverrideConfig,
+                mTmpTaskConfig);
+        final int changes = mTmpGlobalConfig.diff(newGlobalConfig) | taskChanges;
+        if (changes == 0 && !forceNewConfig) {
+            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                    "Configuration no differences in " + this);
+            // There are no significant differences, so we won't relaunch but should still deliver
+            // the new configuration to the client process.
+            scheduleConfigurationChanged(newTaskMergedOverrideConfig, true);
+            return true;
+        }
+
+        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                "Configuration changes for " + this + " ; taskChanges="
+                        + Configuration.configurationDiffToString(taskChanges) + ", allChanges="
+                        + Configuration.configurationDiffToString(changes));
+
+        // If the activity isn't currently running, just leave the new configuration and it will
+        // pick that up next time it starts.
+        if (app == null || app.thread == null) {
+            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                    "Configuration doesn't matter not running " + this);
+            stopFreezingScreenLocked(false);
+            forceNewConfig = false;
+            return true;
+        }
+
+        // Figure out how to handle the changes between the configurations.
+        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                "Checking to restart " + info.name + ": changed=0x"
+                        + Integer.toHexString(changes) + ", handles=0x"
+                        + Integer.toHexString(info.getRealConfigChanged())
+                        + ", newGlobalConfig=" + newGlobalConfig
+                        + ", newTaskMergedOverrideConfig=" + newTaskMergedOverrideConfig);
+
+        if ((changes&(~info.getRealConfigChanged())) != 0 || forceNewConfig) {
+            // Aha, the activity isn't handling the change, so DIE DIE DIE.
+            configChangeFlags |= changes;
+            startFreezingScreenLocked(app, globalChanges);
+            forceNewConfig = false;
+            preserveWindow &= isResizeOnlyChange(changes);
+            if (app == null || app.thread == null) {
+                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                        "Config is destroying non-running " + this);
+                stack.destroyActivityLocked(this, true, "config");
+            } else if (state == ActivityState.PAUSING) {
+                // A little annoying: we are waiting for this activity to finish pausing. Let's not
+                // do anything now, but just flag that it needs to be restarted when done pausing.
+                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                        "Config is skipping already pausing " + this);
+                deferRelaunchUntilPaused = true;
+                preserveWindowOnDeferredRelaunch = preserveWindow;
+                return true;
+            } else if (state == ActivityState.RESUMED) {
+                // Try to optimize this case: the configuration is changing and we need to restart
+                // the top, resumed activity. Instead of doing the normal handshaking, just say
+                // "restart!".
+                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                        "Config is relaunching resumed " + this);
+
+                if (DEBUG_STATES && !visible) {
+                    Slog.v(TAG_STATES, "Config is relaunching resumed invisible activity " + this
+                            + " called by " + Debug.getCallers(4));
+                }
+
+                relaunchActivityLocked(true /* andResume */, preserveWindow);
+            } else {
+                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                        "Config is relaunching non-resumed " + this);
+                relaunchActivityLocked(false /* andResume */, preserveWindow);
+            }
+
+            // All done...  tell the caller we weren't able to keep this activity around.
+            return false;
+        }
+
+        // Default case: the activity can handle this new configuration, so hand it over.
+        // NOTE: We only forward the task override configuration as the system level configuration
+        // changes is always sent to all processes when they happen so it can just use whatever
+        // system level configuration it last got.
+        scheduleConfigurationChanged(newTaskMergedOverrideConfig, true);
+        stopFreezingScreenLocked(false);
+
+        return true;
+    }
+
+    private static int getTaskConfigurationChanges(ActivityRecord record, Configuration taskConfig,
+            Configuration oldTaskOverride) {
+        // If we went from full-screen to non-full-screen, make sure to use the correct
+        // configuration task diff, so the diff stays as small as possible.
+        if (Configuration.EMPTY.equals(oldTaskOverride)
+                && !Configuration.EMPTY.equals(taskConfig)) {
+            oldTaskOverride = record.task.extractOverrideConfig(record.mLastReportedConfiguration);
+        }
+
+        // Conversely, do the same when going the other direction.
+        if (Configuration.EMPTY.equals(taskConfig)
+                && !Configuration.EMPTY.equals(oldTaskOverride)) {
+            taskConfig = record.task.extractOverrideConfig(record.mLastReportedConfiguration);
+        }
+
+        // Determine what has changed.  May be nothing, if this is a config that has come back from
+        // the app after going idle.  In that case we just want to leave the official config object
+        // now in the activity and do nothing else.
+        int taskChanges = oldTaskOverride.diff(taskConfig, true /* skipUndefined */);
+        // We don't want to use size changes if they don't cross boundaries that are important to
+        // the app.
+        if ((taskChanges & CONFIG_SCREEN_SIZE) != 0) {
+            final boolean crosses = record.crossesHorizontalSizeThreshold(
+                    oldTaskOverride.screenWidthDp, taskConfig.screenWidthDp)
+                    || record.crossesVerticalSizeThreshold(
+                    oldTaskOverride.screenHeightDp, taskConfig.screenHeightDp);
+            if (!crosses) {
+                taskChanges &= ~CONFIG_SCREEN_SIZE;
+            }
+        }
+        if ((taskChanges & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
+            final int oldSmallest = oldTaskOverride.smallestScreenWidthDp;
+            final int newSmallest = taskConfig.smallestScreenWidthDp;
+            if (!record.crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
+                taskChanges &= ~CONFIG_SMALLEST_SCREEN_SIZE;
+            }
+        }
+        return taskChanges;
+    }
+
+    private static boolean isResizeOnlyChange(int change) {
+        return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
+                | CONFIG_SCREEN_LAYOUT)) == 0;
+    }
+
+    void relaunchActivityLocked(boolean andResume, boolean preserveWindow) {
+        if (service.mSuppressResizeConfigChanges && preserveWindow) {
+            configChangeFlags = 0;
+            return;
+        }
+
+        List<ResultInfo> pendingResults = null;
+        List<ReferrerIntent> pendingNewIntents = null;
+        if (andResume) {
+            pendingResults = results;
+            pendingNewIntents = newIntents;
+        }
+        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
+                "Relaunching: " + this + " with results=" + pendingResults
+                        + " newIntents=" + pendingNewIntents + " andResume=" + andResume
+                        + " preserveWindow=" + preserveWindow);
+        EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
+                        : EventLogTags.AM_RELAUNCH_ACTIVITY, userId, System.identityHashCode(this),
+                task.taskId, shortComponentName);
+
+        startFreezingScreenLocked(app, 0);
+
+        mStackSupervisor.removeChildActivityContainers(this);
+
+        try {
+            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
+                    "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
+                            + " callers=" + Debug.getCallers(6));
+            forceNewConfig = false;
+            mStackSupervisor.activityRelaunchingLocked(this);
+            app.thread.scheduleRelaunchActivity(appToken, pendingResults, pendingNewIntents,
+                    configChangeFlags, !andResume,
+                    new Configuration(service.getGlobalConfiguration()),
+                    new Configuration(task.getMergedOverrideConfiguration()), preserveWindow);
+            // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
+            // pass in 'andResume' if this activity is currently resumed, which implies we aren't
+            // sleeping.
+        } catch (RemoteException e) {
+            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
+        }
+
+        if (andResume) {
+            if (DEBUG_STATES) {
+                Slog.d(TAG_STATES, "Resumed after relaunch " + this);
+            }
+            results = null;
+            newIntents = null;
+            service.showUnsupportedZoomDialogIfNeededLocked(this);
+            service.showAskCompatModeDialogLocked(this);
+        } else {
+            service.mHandler.removeMessages(ActivityStack.PAUSE_TIMEOUT_MSG, this);
+            state = ActivityState.PAUSED;
+            // if the app is relaunched when it's stopped, and we're not resuming,
+            // put it back into stopped state.
+            if (stopped) {
+                getStack().addToStopping(this, true /* immediate */);
+            }
+        }
+
+        configChangeFlags = 0;
+        deferRelaunchUntilPaused = false;
+        preserveWindowOnDeferredRelaunch = false;
+    }
+
     void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
         out.attribute(null, ATTR_ID, String.valueOf(createTime));
         out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d820627..55066fd 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -22,26 +22,20 @@
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
-import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
-import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-import static android.content.res.Configuration.SCREENLAYOUT_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CLEANUP;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKSCREEN;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SCREENSHOTS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
@@ -52,13 +46,11 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_APP;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONTAINERS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SCREENSHOTS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
@@ -69,7 +61,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityManagerService.LOCK_SCREEN_SHOWN;
-import static com.android.server.am.ActivityManagerService.TAKE_FULLSCREEN_SCREENSHOTS;
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.STARTING_WINDOW_REMOVED;
@@ -99,7 +90,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
-import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.net.Uri;
@@ -110,7 +100,6 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -124,7 +113,6 @@
 import android.view.Display;
 
 import com.android.internal.app.IVoiceInteractor;
-import com.android.internal.content.ReferrerIntent;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityManagerService.ItemMatcher;
@@ -143,19 +131,17 @@
 /**
  * State and management of a single stack of activities.
  */
-final class ActivityStack {
+final class ActivityStack extends ConfigurationContainer {
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_AM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_APP = TAG + POSTFIX_APP;
     private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
-    private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
     private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
     private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
     private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
     private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
     private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
-    private static final String TAG_SCREENSHOTS = TAG + POSTFIX_SCREENSHOTS;
     private static final String TAG_STACK = TAG + POSTFIX_STACK;
     private static final String TAG_STATES = TAG + POSTFIX_STATES;
     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
@@ -170,36 +156,47 @@
     // How long we wait until giving up on the last activity to pause.  This
     // is short because it directly impacts the responsiveness of starting the
     // next activity.
-    static final int PAUSE_TIMEOUT = 500;
+    private static final int PAUSE_TIMEOUT = 500;
 
     // How long we wait for the activity to tell us it has stopped before
     // giving up.  This is a good amount of time because we really need this
     // from the application in order to get its saved state.
-    static final int STOP_TIMEOUT = 10 * 1000;
+    private static final int STOP_TIMEOUT = 10 * 1000;
 
     // How long we wait until giving up on an activity telling us it has
     // finished destroying itself.
-    static final int DESTROY_TIMEOUT = 10 * 1000;
+    private static final int DESTROY_TIMEOUT = 10 * 1000;
 
     // How long until we reset a task when the user returns to it.  Currently
     // disabled.
-    static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
-
-    // How long between activity launches that we consider safe to not warn
-    // the user about an unexpected activity being launched on top.
-    static final long START_WARN_TIME = 5 * 1000;
+    private static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
 
     // Set to false to disable the preview that is shown while a new activity
     // is being started.
-    static final boolean SHOW_APP_STARTING_PREVIEW = true;
+    private static final boolean SHOW_APP_STARTING_PREVIEW = true;
 
     // How long to wait for all background Activities to redraw following a call to
     // convertToTranslucent().
-    static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000;
+    private static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000;
 
     // How many activities have to be scheduled to stop to force a stop pass.
     private static final int MAX_STOPPING_TO_FORCE = 3;
 
+    @Override
+    protected int getChildCount() {
+        return mTaskHistory.size();
+    }
+
+    @Override
+    protected ConfigurationContainer getChildAt(int index) {
+        return mTaskHistory.get(index);
+    }
+
+    @Override
+    protected ConfigurationContainer getParent() {
+        return mActivityContainer.mActivityDisplay;
+    }
+
     enum ActivityState {
         INITIALIZING,
         RESUMED,
@@ -218,18 +215,18 @@
     static final int STACK_VISIBLE = 1;
     // Stack is considered visible, but only becuase it has activity that is visible behind other
     // activities and there is a specific combination of stacks.
-    static final int STACK_VISIBLE_ACTIVITY_BEHIND = 2;
+    private static final int STACK_VISIBLE_ACTIVITY_BEHIND = 2;
 
     /* The various modes for the method {@link #removeTask}. */
     // Task is being completely removed from all stacks in the system.
-    static final int REMOVE_TASK_MODE_DESTROYING = 0;
+    private static final int REMOVE_TASK_MODE_DESTROYING = 0;
     // Task is being removed from this stack so we can add it to another stack. In the case we are
     // moving we don't want to perform some operations on the task like removing it from window
     // manager or recents.
     static final int REMOVE_TASK_MODE_MOVING = 1;
     // Similar to {@link #REMOVE_TASK_MODE_MOVING} and the task will be added to the top of its new
     // stack and the new stack will be on top of all stacks.
-    static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
+    private static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
 
     // The height/width divide used when fitting a task within a bounds with method
     // {@link #fitWithinBounds}.
@@ -239,7 +236,7 @@
     private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3;
 
     final ActivityManagerService mService;
-    final WindowManagerService mWindowManager;
+    private final WindowManagerService mWindowManager;
     private final RecentTasks mRecentTasks;
 
     /**
@@ -286,13 +283,6 @@
      */
     ActivityRecord mResumedActivity = null;
 
-    /**
-     * This is the last activity that has been started.  It is only used to
-     * identify when multiple activities are started at once so that the user
-     * can be warned they may not be in the activity they think they are.
-     */
-    ActivityRecord mLastStartedActivity = null;
-
     // The topmost Activity passed to convertToTranslucent(). When non-null it means we are
     // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they
     // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the
@@ -300,7 +290,7 @@
     // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last
     // background activity being drawn then the same call will be made with a true value.
     ActivityRecord mTranslucentActivityWaiting = null;
-    private ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = new ArrayList<>();
+    ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = new ArrayList<>();
 
     /**
      * Set when we know we are going to be calling updateConfiguration()
@@ -313,11 +303,11 @@
     // Current bounds of the stack or null if fullscreen.
     Rect mBounds = null;
 
-    boolean mUpdateBoundsDeferred;
-    boolean mUpdateBoundsDeferredCalled;
-    final Rect mDeferredBounds = new Rect();
-    final Rect mDeferredTaskBounds = new Rect();
-    final Rect mDeferredTaskInsetBounds = new Rect();
+    private boolean mUpdateBoundsDeferred;
+    private boolean mUpdateBoundsDeferredCalled;
+    private final Rect mDeferredBounds = new Rect();
+    private final Rect mDeferredTaskBounds = new Rect();
+    private final Rect mDeferredTaskInsetBounds = new Rect();
 
     long mLaunchStartTime = 0;
     long mFullyDrawnStartTime = 0;
@@ -338,7 +328,7 @@
     private final Rect tempRect2 = new Rect();
 
     /** Run all ActivityStacks through this */
-    final ActivityStackSupervisor mStackSupervisor;
+    private final ActivityStackSupervisor mStackSupervisor;
 
     private final LaunchingTaskPositioner mTaskPositioner;
 
@@ -351,7 +341,7 @@
     static final int RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG =
             ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
 
-    static class ScheduleDestroyArgs {
+    private static class ScheduleDestroyArgs {
         final ProcessRecord mOwner;
         final String mReason;
         ScheduleDestroyArgs(ProcessRecord owner, String reason) {
@@ -362,7 +352,7 @@
 
     final Handler mHandler;
 
-    final class ActivityStackHandler extends Handler {
+    private class ActivityStackHandler extends Handler {
 
         ActivityStackHandler(Looper looper) {
             super(looper);
@@ -407,7 +397,8 @@
                     Slog.w(TAG, "Activity stop timeout for " + r);
                     synchronized (mService) {
                         if (r.isInHistory()) {
-                            activityStoppedLocked(r, null, null, null);
+                            r.activityStoppedLocked(null /* icicle */,
+                                    null /* persistentState */, null /* description */);
                         }
                     }
                 } break;
@@ -466,6 +457,7 @@
             mTaskPositioner.setDisplay(activityDisplay.mDisplay);
             mTaskPositioner.configure(mBounds);
         }
+        onParentChanged();
 
         if (mStackId == DOCKED_STACK_ID) {
             // If we created a docked stack we want to resize it so it resizes all other stacks
@@ -482,6 +474,7 @@
             mTaskPositioner.reset();
         }
         mWindowManager.detachStack(mStackId);
+        onParentChanged();
         if (mStackId == DOCKED_STACK_ID) {
             // If we removed a docked stack we want to resize it so it resizes all other stacks
             // in the system to fullscreen.
@@ -490,7 +483,7 @@
         }
     }
 
-    public void getDisplaySize(Point out) {
+    void getDisplaySize(Point out) {
         mActivityContainer.mActivityDisplay.mDisplay.getSize(out);
     }
 
@@ -644,9 +637,9 @@
             return null;
         }
         final TaskRecord task = r.task;
-        if (task != null && task.stack != null
-                && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
-            if (task.stack != this) Slog.w(TAG,
+        final ActivityStack stack = r.getStack();
+        if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
+            if (stack != this) Slog.w(TAG,
                     "Illegal state! task does not point to stack it is in.");
             return r;
         }
@@ -720,7 +713,7 @@
     /**
      * @param task If non-null, the task will be moved to the back of the stack.
      * */
-    void moveToBack(TaskRecord task) {
+    private void moveToBack(TaskRecord task) {
         if (!isAttached()) {
             return;
         }
@@ -914,7 +907,7 @@
         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + r + " (starting new instance)"
                 + " callers=" + Debug.getCallers(5));
         setResumedActivityLocked(r, "minimalResumeActivityLocked");
-        completeResumeLocked(r);
+        r.completeResumeLocked();
         setLaunchTime(r);
         if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
                 "Launch completed; removing icicle of " + r.icicle);
@@ -955,7 +948,7 @@
         }
     }
 
-    void clearLaunchTime(ActivityRecord r) {
+    private void clearLaunchTime(ActivityRecord r) {
         // Make sure that there is no activity waiting for this to launch.
         if (mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
             r.displayStartTime = r.fullyDrawnStartTime = 0;
@@ -1037,50 +1030,6 @@
         }
     }
 
-    public final Bitmap screenshotActivitiesLocked(ActivityRecord who) {
-        if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "screenshotActivitiesLocked: " + who);
-        if (who.noDisplay) {
-            if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tNo display");
-            return null;
-        }
-
-        if (isHomeStack()) {
-            // This is an optimization -- since we never show Home or Recents within Recents itself,
-            // we can just go ahead and skip taking the screenshot if this is the home stack.
-            if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tHome stack");
-            return null;
-        }
-
-        int w = mService.mThumbnailWidth;
-        int h = mService.mThumbnailHeight;
-
-        if (w <= 0) {
-            Slog.e(TAG, "\tInvalid thumbnail dimensions: " + w + "x" + h);
-            return null;
-        }
-
-        if (mStackId == DOCKED_STACK_ID && mStackSupervisor.mIsDockMinimized) {
-            // When the docked stack is minimized its app windows are cropped significantly so any
-            // screenshot taken will not display the apps contain. So, we avoid taking a screenshot
-            // in that case.
-            if (DEBUG_SCREENSHOTS) Slog.e(TAG, "\tIn minimized docked stack");
-            return null;
-        }
-
-        float scale = 1f;
-        if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tTaking screenshot");
-
-        // When this flag is set, we currently take the fullscreen screenshot of the activity but
-        // scaled to half the size. This gives us a "good-enough" fullscreen thumbnail to use within
-        // SystemUI while keeping memory usage low.
-        if (TAKE_FULLSCREEN_SCREENSHOTS) {
-            w = h = -1;
-            scale = mService.mFullscreenThumbnailScale;
-        }
-
-        return mWindowManager.screenshotApplications(who.appToken, DEFAULT_DISPLAY, w, h, scale);
-    }
-
     /**
      * Start pausing the currently resumed activity.  It is an error to call this if there
      * is already an activity being paused or there is no resumed activity.
@@ -1239,57 +1188,6 @@
         mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
     }
 
-    final void activityResumedLocked(IBinder token) {
-        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
-        if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
-        r.icicle = null;
-        r.haveState = false;
-    }
-
-    final void activityStoppedLocked(ActivityRecord r, Bundle icicle,
-            PersistableBundle persistentState, CharSequence description) {
-        if (r.state != ActivityState.STOPPING) {
-            Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r);
-            mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
-            return;
-        }
-        if (persistentState != null) {
-            r.persistentState = persistentState;
-            mService.notifyTaskPersisterLocked(r.task, false);
-        }
-        if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + r + ": " + icicle);
-        if (icicle != null) {
-            // If icicle is null, this is happening due to a timeout, so we
-            // haven't really saved the state.
-            r.icicle = icicle;
-            r.haveState = true;
-            r.launchCount = 0;
-            r.updateThumbnailLocked(null, description);
-        }
-        if (!r.stopped) {
-            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + r + " (stop complete)");
-            mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
-            r.stopped = true;
-            r.state = ActivityState.STOPPED;
-
-            mWindowManager.notifyAppStopped(r.appToken);
-
-            if (getVisibleBehindActivity() == r) {
-                mStackSupervisor.requestVisibleBehindLocked(r, false);
-            }
-            if (r.finishing) {
-                r.clearOptionsLocked();
-            } else {
-                if (r.deferRelaunchUntilPaused) {
-                    destroyActivityLocked(r, true, "stop-config");
-                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
-                } else {
-                    mStackSupervisor.updatePreviousProcessLocked(r);
-                }
-            }
-        }
-    }
-
     private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
         ActivityRecord prev = mPausingActivity;
         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
@@ -1310,7 +1208,7 @@
                 if (prev.deferRelaunchUntilPaused) {
                     // Complete the deferred relaunch that was waiting for pause to complete.
                     if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
-                    relaunchActivityLocked(prev, prev.configChangeFlags, false,
+                    prev.relaunchActivityLocked(false /* andResume */,
                             prev.preserveWindowOnDeferredRelaunch);
                 } else if (wasStopping) {
                     // We are also stopping, the stop request must have gone soon after the pause.
@@ -1387,7 +1285,7 @@
         mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS);
     }
 
-    private void addToStopping(ActivityRecord r, boolean immediate) {
+    void addToStopping(ActivityRecord r, boolean immediate) {
         if (!mStackSupervisor.mStoppingActivities.contains(r)) {
             mStackSupervisor.mStoppingActivities.add(r);
         }
@@ -1408,77 +1306,6 @@
         }
     }
 
-    /**
-     * Once we know that we have asked an application to put an activity in
-     * the resumed state (either by launching it or explicitly telling it),
-     * this function updates the rest of our state to match that fact.
-     */
-    private void completeResumeLocked(ActivityRecord next) {
-        boolean wasVisible = next.visible;
-        next.visible = true;
-        if (!wasVisible) {
-            // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
-            mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
-        }
-        next.idle = false;
-        next.results = null;
-        next.newIntents = null;
-        next.stopped = false;
-
-        if (next.isHomeActivity()) {
-            ProcessRecord app = next.task.mActivities.get(0).app;
-            if (app != null && app != mService.mHomeProcess) {
-                mService.mHomeProcess = app;
-            }
-        }
-
-        if (next.nowVisible) {
-            // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now.
-            mStackSupervisor.reportActivityVisibleLocked(next);
-            mStackSupervisor.notifyActivityDrawnForKeyguard();
-        }
-
-        // schedule an idle timeout in case the app doesn't do it for us.
-        mStackSupervisor.scheduleIdleTimeoutLocked(next);
-
-        mStackSupervisor.reportResumedActivityLocked(next);
-
-        next.resumeKeyDispatchingLocked();
-        mNoAnimActivities.clear();
-
-        // Mark the point when the activity is resuming
-        // TODO: To be more accurate, the mark should be before the onCreate,
-        //       not after the onResume. But for subsequent starts, onResume is fine.
-        if (next.app != null) {
-            next.cpuTimeAtResume = mService.mProcessCpuTracker.getCpuTimeForPid(next.app.pid);
-        } else {
-            next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
-        }
-
-        next.returningOptions = null;
-
-        if (getVisibleBehindActivity() == next) {
-            // When resuming an activity, require it to call requestVisibleBehind() again.
-            setVisibleBehindActivity(null);
-        }
-        mStackSupervisor.checkReadyForSleepLocked();
-    }
-
-    private void setVisible(ActivityRecord r, boolean visible) {
-        r.visible = visible;
-        if (!visible && r.mUpdateTaskThumbnailWhenHidden) {
-            r.updateThumbnailLocked(r.task.stack.screenshotActivitiesLocked(r), null);
-            r.mUpdateTaskThumbnailWhenHidden = false;
-        }
-        mWindowManager.setAppVisibility(r.appToken, visible);
-        final ArrayList<ActivityContainer> containers = r.mChildContainers;
-        for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) {
-            ActivityContainer container = containers.get(containerNdx);
-            container.setVisible(visible);
-        }
-        mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
-    }
-
     // Find the first visible activity above the passed activity and if it is translucent return it
     // otherwise return null;
     ActivityRecord findNextTranslucentActivity(ActivityRecord r) {
@@ -1487,7 +1314,7 @@
             return null;
         }
 
-        ActivityStack stack = task.stack;
+        final ActivityStack stack = task.getStack();
         if (stack == null) {
             return null;
         }
@@ -1531,7 +1358,7 @@
         ArrayList<ActivityStack> stacks = mStacks;
         final ActivityRecord parent = mActivityContainer.mParentActivity;
         if (parent != null) {
-            stacks = parent.task.stack.mStacks;
+            stacks = parent.getStack().mStacks;
         }
         if (stacks != null) {
             for (int i = stacks.size() - 1; i >= 0; --i) {
@@ -1781,7 +1608,8 @@
                     // is finishing, we no longer change its visibility, but we still need to take
                     // the screenshots if startPausingLocked decided it should be taken.
                     if (r.mUpdateTaskThumbnailWhenHidden) {
-                        r.updateThumbnailLocked(screenshotActivitiesLocked(r), null);
+                        r.updateThumbnailLocked(r.screenshotActivityLocked(),
+                                null /* description */);
                         r.mUpdateTaskThumbnailWhenHidden = false;
                     }
                     continue;
@@ -1792,14 +1620,14 @@
                 }
                 aboveTop = false;
 
-                if (shouldBeVisible(r, behindTranslucentActivity, stackVisibleBehind,
+                if (r.shouldBeVisible(behindTranslucentActivity, stackVisibleBehind,
                         visibleBehind, behindFullscreenActivity)) {
                     if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
                             + " finishing=" + r.finishing + " state=" + r.state);
                     // First: if this is not the current activity being started, make
                     // sure it matches the current configuration.
                     if (r != starting) {
-                        ensureActivityConfigurationLocked(r, 0, preserveWindows);
+                        r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindows);
                     }
 
                     if (r.app == null || r.app.thread == null) {
@@ -1817,11 +1645,11 @@
                         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
                                 "Skipping: already visible at " + r);
 
-                        if (handleAlreadyVisible(r)) {
+                        if (r.handleAlreadyVisible()) {
                             resumeNextActivity = false;
                         }
                     } else {
-                        makeVisibleIfNeeded(starting, r);
+                        r.makeVisibleIfNeeded(starting);
                     }
                     // Aggregate current change flags.
                     configChanges |= r.configChangeFlags;
@@ -1902,33 +1730,6 @@
         }
     }
 
-    /** Return true if the input activity should be made visible */
-    private boolean shouldBeVisible(ActivityRecord r, boolean behindTranslucentActivity,
-            boolean stackVisibleBehind, ActivityRecord visibleBehind,
-            boolean behindFullscreenActivity) {
-
-        if (r == null || !r.okToShowLocked()) {
-            return false;
-        }
-
-        // mLaunchingBehind: Activities launching behind are at the back of the task stack
-        // but must be drawn initially for the animation as though they were visible.
-        final boolean activityVisibleBehind =
-                (behindTranslucentActivity || stackVisibleBehind) && visibleBehind == r;
-
-        boolean isVisible =
-                !behindFullscreenActivity || r.mLaunchTaskBehind || activityVisibleBehind;
-
-        if (mService.mSupportsLeanbackOnly && isVisible && r.isRecentsActivity()) {
-            // On devices that support leanback only (Android TV), Recents activity can only be
-            // visible if the home stack is the focused stack or we are in split-screen mode.
-            isVisible = mStackSupervisor.getStack(DOCKED_STACK_ID) != null
-                    || mStackSupervisor.isFocusedStack(this);
-        }
-
-        return isVisible;
-    }
-
     private void checkTranslucentActivityWaiting(ActivityRecord top) {
         if (mTranslucentActivityWaiting != top) {
             mUndrawnActivitiesBelowTopTranslucent.clear();
@@ -1956,7 +1757,7 @@
             }
             if (!r.visible || r.mLaunchTaskBehind) {
                 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
-                setVisible(r, true);
+                r.setVisible(true);
             }
             if (r != starting) {
                 mStackSupervisor.startSpecificActivityLocked(r, andResume, false);
@@ -1975,7 +1776,7 @@
         // keeping the screen frozen.
         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.state);
         try {
-            setVisible(r, false);
+            r.setVisible(false);
             switch (r.state) {
                 case STOPPING:
                 case STOPPED:
@@ -2025,50 +1826,6 @@
         return behindFullscreenActivity;
     }
 
-    private void makeVisibleIfNeeded(ActivityRecord starting, ActivityRecord r) {
-
-        // This activity is not currently visible, but is running. Tell it to become visible.
-        if (r.state == ActivityState.RESUMED || r == starting) {
-            if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
-                    "Not making visible, r=" + r + " state=" + r.state + " starting=" + starting);
-            return;
-        }
-
-        // If this activity is paused, tell it to now show its window.
-        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
-                "Making visible and scheduling visibility: " + r);
-        try {
-            if (mTranslucentActivityWaiting != null) {
-                r.updateOptionsLocked(r.returningOptions);
-                mUndrawnActivitiesBelowTopTranslucent.add(r);
-            }
-            setVisible(r, true);
-            r.sleeping = false;
-            r.app.pendingUiClean = true;
-            r.app.thread.scheduleWindowVisibility(r.appToken, true);
-            // The activity may be waiting for stop, but that is no longer
-            // appropriate for it.
-            mStackSupervisor.mStoppingActivities.remove(r);
-            mStackSupervisor.mGoingToSleepActivities.remove(r);
-        } catch (Exception e) {
-            // Just skip on any failure; we'll make it
-            // visible when it next restarts.
-            Slog.w(TAG, "Exception thrown making visibile: " + r.intent.getComponent(), e);
-        }
-        handleAlreadyVisible(r);
-    }
-
-    private boolean handleAlreadyVisible(ActivityRecord r) {
-        r.stopFreezingScreenLocked(false);
-        try {
-            if (r.returningOptions != null) {
-                r.app.thread.scheduleOnNewActivityOptions(r.appToken, r.returningOptions);
-            }
-        } catch(RemoteException e) {
-        }
-        return r.state == ActivityState.RESUMED;
-    }
-
     void convertActivityToTranslucent(ActivityRecord r) {
         mTranslucentActivityWaiting = r;
         mUndrawnActivitiesBelowTopTranslucent.clear();
@@ -2276,7 +2033,7 @@
         }
 
         final TaskRecord nextTask = next.task;
-        if (prevTask != null && prevTask.stack == this &&
+        if (prevTask != null && prevTask.getStack() == this &&
                 prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
             if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
             if (prevTask == nextTask) {
@@ -2529,7 +2286,7 @@
             boolean notUpdated = true;
             if (mStackSupervisor.isFocusedStack(this)) {
                 Configuration config = mWindowManager.updateOrientationFromAppTokens(
-                        mService.mGlobalConfiguration,
+                        mService.getGlobalConfiguration(),
                         next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
                 if (config != null) {
                     next.frozenBeforeDestroy = true;
@@ -2554,7 +2311,7 @@
                 if (!next.visible || next.stopped) {
                     mWindowManager.setAppVisibility(next.appToken, true);
                 }
-                completeResumeLocked(next);
+                next.completeResumeLocked();
                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                 return true;
             }
@@ -2628,7 +2385,7 @@
             // From this point on, if something goes wrong there is no way
             // to recover the activity.
             try {
-                completeResumeLocked(next);
+                next.completeResumeLocked();
             } catch (Exception e) {
                 // If any exception gets thrown, toss away this
                 // activity and try the next one.
@@ -2903,7 +2660,7 @@
      * @param forceReset
      * @return An ActivityOptions that needs to be processed.
      */
-    final ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) {
+    private ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) {
         ActivityOptions topOptions = null;
 
         int replyChainEnd = -1;
@@ -3485,7 +3242,7 @@
         return true;
     }
 
-    final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
+    private void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
         // send the result
         ActivityRecord resultTo = r.resultTo;
         if (resultTo != null) {
@@ -3630,7 +3387,7 @@
         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
         r.state = ActivityState.FINISHING;
         final boolean finishingActivityInNonFocusedStack
-                = r.task.stack != mStackSupervisor.getFocusedStack()
+                = r.getStack() != mStackSupervisor.getFocusedStack()
                 && prevState == ActivityState.PAUSED && mode == FINISH_AFTER_VISIBLE;
 
         if (mode == FINISH_IMMEDIATELY
@@ -3811,8 +3568,7 @@
      *
      * Note: Call before #removeActivityFromHistoryLocked.
      */
-    final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
-            boolean setState) {
+    private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
         if (mResumedActivity == r) {
             mResumedActivity = null;
         }
@@ -3902,7 +3658,7 @@
     /**
      * Perform clean-up of service connections in an activity record.
      */
-    final void cleanUpActivityServicesLocked(ActivityRecord r) {
+    private void cleanUpActivityServicesLocked(ActivityRecord r) {
         // Throw away any services that have been bound by this activity.
         if (r.connections != null) {
             Iterator<ConnectionRecord> it = r.connections.iterator();
@@ -3920,7 +3676,7 @@
         mHandler.sendMessage(msg);
     }
 
-    final void destroyActivitiesLocked(ProcessRecord owner, String reason) {
+    private void destroyActivitiesLocked(ProcessRecord owner, String reason) {
         boolean lastIsOpaque = false;
         boolean activityRemoved = false;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -4197,7 +3953,7 @@
         }
     }
 
-    boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
+    private boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
         removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
         removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
                 "mStoppingActivities");
@@ -4288,7 +4044,7 @@
         return hasVisibleActivities;
     }
 
-    final void updateTransitLocked(int transit, ActivityOptions options) {
+    private void updateTransitLocked(int transit, ActivityOptions options) {
         if (options != null) {
             ActivityRecord r = topRunningActivityLocked();
             if (r != null && r.state != ActivityState.RESUMED) {
@@ -4300,7 +4056,7 @@
         mWindowManager.prepareAppTransition(transit, false);
     }
 
-    void updateTaskMovement(TaskRecord task, boolean toFront) {
+    private void updateTaskMovement(TaskRecord task, boolean toFront) {
         if (task.isPersistable) {
             task.mLastTimeMoved = System.currentTimeMillis();
             // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
@@ -4509,8 +4265,7 @@
         return true;
     }
 
-    static final void logStartActivity(int tag, ActivityRecord r,
-            TaskRecord task) {
+    static void logStartActivity(int tag, ActivityRecord r, TaskRecord task) {
         final Uri data = r.intent.getData();
         final String strData = data != null ? data.toSafeString() : null;
 
@@ -4539,7 +4294,8 @@
                     (start.task == task) ? activities.indexOf(start) : activities.size() - 1;
             for (; activityIndex >= 0; --activityIndex) {
                 final ActivityRecord r = activities.get(activityIndex);
-                updatedConfig |= ensureActivityConfigurationLocked(r, 0, preserveWindow);
+                updatedConfig |= r.ensureActivityConfigurationLocked(0 /* globalChanges */,
+                        preserveWindow);
                 if (r.fullscreen) {
                     behindFullscreen = true;
                     break;
@@ -4582,7 +4338,7 @@
                 }
             }
 
-            mTmpConfigs.put(task.taskId, task.mOverrideConfig);
+            mTmpConfigs.put(task.taskId, task.getOverrideConfiguration());
             mTmpBounds.put(task.taskId, task.mBounds);
             if (tempTaskInsetBounds != null) {
                 mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds);
@@ -4636,245 +4392,6 @@
         }
     }
 
-    /**
-     * Make sure the given activity matches the current configuration. Returns false if the activity
-     * had to be destroyed.  Returns true if the configuration is the same, or the activity will
-     * remain running as-is for whatever reason. Ensures the HistoryRecord is updated with the
-     * correct configuration and all other bookkeeping is handled.
-     */
-    boolean ensureActivityConfigurationLocked(
-            ActivityRecord r, int globalChanges, boolean preserveWindow) {
-        if (mConfigWillChange) {
-            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                    "Skipping config check (will change): " + r);
-            return true;
-        }
-
-        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                "Ensuring correct configuration: " + r);
-
-        // Short circuit: if the two configurations are equal (the common case), then there is
-        // nothing to do.
-        final Configuration newConfig = mService.mGlobalConfiguration;
-        r.task.sanitizeOverrideConfiguration(newConfig);
-        final Configuration taskConfig = r.task.mOverrideConfig;
-        if (r.configuration.equals(newConfig)
-                && r.taskConfigOverride.equals(taskConfig)
-                && !r.forceNewConfig) {
-            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                    "Configuration unchanged in " + r);
-            return true;
-        }
-
-        // We don't worry about activities that are finishing.
-        if (r.finishing) {
-            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                    "Configuration doesn't matter in finishing " + r);
-            r.stopFreezingScreenLocked(false);
-            return true;
-        }
-
-        // Okay we now are going to make this activity have the new config.
-        // But then we need to figure out how it needs to deal with that.
-        final Configuration oldConfig = r.configuration;
-        final Configuration oldTaskOverride = r.taskConfigOverride;
-        r.configuration = newConfig;
-        r.taskConfigOverride = taskConfig;
-
-        int taskChanges = getTaskConfigurationChanges(r, taskConfig, oldTaskOverride);
-        final int changes = oldConfig.diff(newConfig) | taskChanges;
-        if (changes == 0 && !r.forceNewConfig) {
-            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                    "Configuration no differences in " + r);
-            // There are no significant differences, so we won't relaunch but should still deliver
-            // the new configuration to the client process.
-            r.scheduleConfigurationChanged(taskConfig, true);
-            return true;
-        }
-
-        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                "Configuration changes for " + r + " ; taskChanges="
-                        + Configuration.configurationDiffToString(taskChanges) + ", allChanges="
-                        + Configuration.configurationDiffToString(changes));
-
-        // If the activity isn't currently running, just leave the new
-        // configuration and it will pick that up next time it starts.
-        if (r.app == null || r.app.thread == null) {
-            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                    "Configuration doesn't matter not running " + r);
-            r.stopFreezingScreenLocked(false);
-            r.forceNewConfig = false;
-            return true;
-        }
-
-        // Figure out how to handle the changes between the configurations.
-        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                "Checking to restart " + r.info.name + ": changed=0x"
-                + Integer.toHexString(changes) + ", handles=0x"
-                + Integer.toHexString(r.info.getRealConfigChanged()) + ", newConfig=" + newConfig
-                + ", taskConfig=" + taskConfig);
-
-        if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
-            // Aha, the activity isn't handling the change, so DIE DIE DIE.
-            r.configChangeFlags |= changes;
-            r.startFreezingScreenLocked(r.app, globalChanges);
-            r.forceNewConfig = false;
-            preserveWindow &= isResizeOnlyChange(changes);
-            if (r.app == null || r.app.thread == null) {
-                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                        "Config is destroying non-running " + r);
-                destroyActivityLocked(r, true, "config");
-            } else if (r.state == ActivityState.PAUSING) {
-                // A little annoying: we are waiting for this activity to finish pausing. Let's not
-                // do anything now, but just flag that it needs to be restarted when done pausing.
-                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                        "Config is skipping already pausing " + r);
-                r.deferRelaunchUntilPaused = true;
-                r.preserveWindowOnDeferredRelaunch = preserveWindow;
-                return true;
-            } else if (r.state == ActivityState.RESUMED) {
-                // Try to optimize this case: the configuration is changing and we need to restart
-                // the top, resumed activity. Instead of doing the normal handshaking, just say
-                // "restart!".
-                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                        "Config is relaunching resumed " + r);
-
-                if (DEBUG_STATES && !r.visible) {
-                    Slog.v(TAG_STATES, "Config is relaunching resumed invisible activity " + r
-                            + " called by " + Debug.getCallers(4));
-                }
-
-                relaunchActivityLocked(r, r.configChangeFlags, true, preserveWindow);
-            } else {
-                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                        "Config is relaunching non-resumed " + r);
-                relaunchActivityLocked(r, r.configChangeFlags, false, preserveWindow);
-            }
-
-            // All done...  tell the caller we weren't able to keep this activity around.
-            return false;
-        }
-
-        // Default case: the activity can handle this new configuration, so hand it over.
-        // NOTE: We only forward the task override configuration as the system level configuration
-        // changes is always sent to all processes when they happen so it can just use whatever
-        // system level configuration it last got.
-        r.scheduleConfigurationChanged(taskConfig, true);
-        r.stopFreezingScreenLocked(false);
-
-        return true;
-    }
-
-    private int getTaskConfigurationChanges(ActivityRecord record, Configuration taskConfig,
-            Configuration oldTaskOverride) {
-
-        // If we went from full-screen to non-full-screen, make sure to use the correct
-        // configuration task diff, so the diff stays as small as possible.
-        if (Configuration.EMPTY.equals(oldTaskOverride)
-                && !Configuration.EMPTY.equals(taskConfig)) {
-            oldTaskOverride = record.task.extractOverrideConfig(record.configuration);
-        }
-
-        // Conversely, do the same when going the other direction.
-        if (Configuration.EMPTY.equals(taskConfig)
-                && !Configuration.EMPTY.equals(oldTaskOverride)) {
-            taskConfig = record.task.extractOverrideConfig(record.configuration);
-        }
-
-        // Determine what has changed.  May be nothing, if this is a config
-        // that has come back from the app after going idle.  In that case
-        // we just want to leave the official config object now in the
-        // activity and do nothing else.
-        int taskChanges = oldTaskOverride.diff(taskConfig, true /* skipUndefined */);
-        // We don't want to use size changes if they don't cross boundaries that are important to
-        // the app.
-        if ((taskChanges & CONFIG_SCREEN_SIZE) != 0) {
-            final boolean crosses = record.crossesHorizontalSizeThreshold(
-                    oldTaskOverride.screenWidthDp, taskConfig.screenWidthDp)
-                    || record.crossesVerticalSizeThreshold(
-                    oldTaskOverride.screenHeightDp, taskConfig.screenHeightDp);
-            if (!crosses) {
-                taskChanges &= ~CONFIG_SCREEN_SIZE;
-            }
-        }
-        if ((taskChanges & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
-            final int oldSmallest = oldTaskOverride.smallestScreenWidthDp;
-            final int newSmallest = taskConfig.smallestScreenWidthDp;
-            if (!record.crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
-                taskChanges &= ~CONFIG_SMALLEST_SCREEN_SIZE;
-            }
-        }
-        return taskChanges;
-    }
-
-    private static boolean isResizeOnlyChange(int change) {
-        return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
-                | CONFIG_SCREEN_LAYOUT)) == 0;
-    }
-
-    private void relaunchActivityLocked(
-            ActivityRecord r, int changes, boolean andResume, boolean preserveWindow) {
-        if (mService.mSuppressResizeConfigChanges && preserveWindow) {
-            r.configChangeFlags = 0;
-            return;
-        }
-
-        List<ResultInfo> results = null;
-        List<ReferrerIntent> newIntents = null;
-        if (andResume) {
-            results = r.results;
-            newIntents = r.newIntents;
-        }
-        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
-                "Relaunching: " + r + " with results=" + results + " newIntents=" + newIntents
-                + " andResume=" + andResume + " preserveWindow=" + preserveWindow);
-        EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
-                : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r),
-                r.task.taskId, r.shortComponentName);
-
-        r.startFreezingScreenLocked(r.app, 0);
-
-        mStackSupervisor.removeChildActivityContainers(r);
-
-        try {
-            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
-                    "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + r
-                    + " callers=" + Debug.getCallers(6));
-            r.forceNewConfig = false;
-            mStackSupervisor.activityRelaunchingLocked(r);
-            r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes,
-                    !andResume, new Configuration(mService.mGlobalConfiguration),
-                    new Configuration(r.task.mOverrideConfig), preserveWindow);
-            // Note: don't need to call pauseIfSleepingLocked() here, because
-            // the caller will only pass in 'andResume' if this activity is
-            // currently resumed, which implies we aren't sleeping.
-        } catch (RemoteException e) {
-            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
-        }
-
-        if (andResume) {
-            if (DEBUG_STATES) {
-                Slog.d(TAG_STATES, "Resumed after relaunch " + r);
-            }
-            r.results = null;
-            r.newIntents = null;
-            mService.showUnsupportedZoomDialogIfNeededLocked(r);
-            mService.showAskCompatModeDialogLocked(r);
-        } else {
-            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
-            r.state = ActivityState.PAUSED;
-            // if the app is relaunched when it's stopped, and we're not resuming,
-            // put it back into stopped state.
-            if (r.stopped) {
-                addToStopping(r, true /* immediate */);
-            }
-        }
-
-        r.configChangeFlags = 0;
-        r.deferRelaunchUntilPaused = false;
-        r.preserveWindowOnDeferredRelaunch = false;
-    }
-
     boolean willActivityBeVisibleLocked(IBinder token) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
@@ -5028,7 +4545,7 @@
         }
     }
 
-    public void unhandledBackLocked() {
+    void unhandledBackLocked() {
         final int top = mTaskHistory.size() - 1;
         if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top);
         if (top >= 0) {
@@ -5228,7 +4745,7 @@
             }
         }
 
-        task.stack = null;
+        task.setStack(null);
     }
 
     TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
@@ -5261,7 +4778,7 @@
     void addTask(final TaskRecord task, final boolean toTop, String reason) {
         final ActivityStack prevStack = preAddTask(task, reason, toTop);
 
-        task.stack = this;
+        task.setStack(this);
         if (toTop) {
             insertTaskAtTop(task, null);
         } else {
@@ -5273,9 +4790,9 @@
 
     void positionTask(final TaskRecord task, int position) {
         final ActivityRecord topRunningActivity = task.topRunningActivityLocked();
-        final boolean wasResumed = topRunningActivity == task.stack.mResumedActivity;
+        final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity;
         final ActivityStack prevStack = preAddTask(task, "positionTask", !ON_TOP);
-        task.stack = this;
+        task.setStack(this);
         insertTaskAtPosition(task, position);
         postAddTask(task, prevStack);
         if (wasResumed) {
@@ -5289,7 +4806,7 @@
     }
 
     private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) {
-        final ActivityStack prevStack = task.stack;
+        final ActivityStack prevStack = task.getStack();
         if (prevStack != null && prevStack != this) {
             prevStack.removeTask(task, reason,
                     toTop ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
@@ -5314,10 +4831,11 @@
         mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
                 r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                 (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, r.info.configChanges,
-                task.voiceSession != null, r.mLaunchTaskBehind, bounds, task.mOverrideConfig,
-                task.mResizeMode, r.isAlwaysFocusable(), task.isHomeTask(),
-                r.appInfo.targetSdkVersion, r.mRotationAnimationHint, task.isOnTopLauncher());
-        r.taskConfigOverride = task.mOverrideConfig;
+                task.voiceSession != null, r.mLaunchTaskBehind, bounds,
+                task.getOverrideConfiguration(), task.mResizeMode, r.isAlwaysFocusable(),
+                task.isHomeTask(), r.appInfo.targetSdkVersion, r.mRotationAnimationHint,
+                task.isOnTopLauncher());
+        r.onOverrideConfigurationSent();
     }
 
     void moveToFrontAndResumeStateIfNeeded(
@@ -5343,7 +4861,7 @@
      * created on this stack which the activity is added to.
      * */
     void moveActivityToStack(ActivityRecord r) {
-        final ActivityStack prevStack = r.task.stack;
+        final ActivityStack prevStack = r.getStack();
         if (prevStack.mStackId == mStackId) {
             // You are already in the right stack silly...
             return;
@@ -5368,9 +4886,10 @@
 
     private void setAppTask(ActivityRecord r, TaskRecord task) {
         final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
-        mWindowManager.setAppTask(r.appToken, task.taskId, mStackId, bounds, task.mOverrideConfig,
-                task.mResizeMode, task.isHomeTask(), task.isOnTopLauncher());
-        r.taskConfigOverride = task.mOverrideConfig;
+        mWindowManager.setAppTask(r.appToken, task.taskId, mStackId, bounds,
+                task.getOverrideConfiguration(), task.mResizeMode, task.isHomeTask(),
+                task.isOnTopLauncher());
+        r.onOverrideConfigurationSent();
     }
 
     public int getStackId() {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 67604d3..cd7481c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -178,7 +178,8 @@
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
 import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
 
-public final class ActivityStackSupervisor implements DisplayListener {
+public final class ActivityStackSupervisor extends ConfigurationContainer
+        implements DisplayListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
     private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
     private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
@@ -412,6 +413,21 @@
 
     private final ResizeDockedStackTimeout mResizeDockedStackTimeout;
 
+    @Override
+    protected int getChildCount() {
+        return mActivityDisplays.size();
+    }
+
+    @Override
+    protected ConfigurationContainer getChildAt(int index) {
+        return mActivityDisplays.valueAt(index);
+    }
+
+    @Override
+    protected ConfigurationContainer getParent() {
+        return null;
+    }
+
     static class FindTaskResult {
         ActivityRecord r;
         boolean matchedByRootAffinity;
@@ -571,7 +587,7 @@
 
         final ActivityRecord parent = stack.mActivityContainer.mParentActivity;
         if (parent != null) {
-            stack = parent.task.stack;
+            stack = parent.getStack();
         }
         return stack == mFocusedStack;
     }
@@ -584,7 +600,7 @@
 
         final ActivityRecord parent = stack.mActivityContainer.mParentActivity;
         if (parent != null) {
-            stack = parent.task.stack;
+            stack = parent.getStack();
         }
         return stack == mHomeStack.mStacks.get((mHomeStack.mStacks.size() - 1));
     }
@@ -1182,7 +1198,7 @@
         // just restarting it anyway.
         if (checkConfig) {
             Configuration config = mWindowManager.updateOrientationFromAppTokens(
-                    mService.mGlobalConfiguration,
+                    mService.getGlobalConfiguration(),
                     r.mayFreezeScreenLocked(app) ? r.appToken : null);
             // Deferring resume here because we're going to launch new activity shortly.
             // We don't want to perform a redundant launch of the same record while ensuring
@@ -1210,7 +1226,7 @@
             setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
         }
 
-        final ActivityStack stack = task.stack;
+        final ActivityStack stack = task.getStack();
         try {
             if (app.thread == null) {
                 throw new RemoteException();
@@ -1272,12 +1288,16 @@
                 app.pendingUiClean = true;
             }
             app.forceProcessStateUpTo(mService.mTopProcessState);
+            // Because we could be starting an Activity in the system process this may not go across
+            // a Binder interface which would create a new Configuration. Consequently we have to
+            // always create a new Configuration here.
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                     System.identityHashCode(r), r.info,
-                    new Configuration(mService.mGlobalConfiguration),
-                    new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
-                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
-                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
+                    new Configuration(mService.getGlobalConfiguration()),
+                    new Configuration(task.getMergedOverrideConfiguration()), r.compat,
+                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
+                    r.persistentState, results, newIntents, !andResume,
+                    mService.isNextTransitionForward(), profilerInfo);
 
             if ((app.info.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                 // This may be a heavy-weight process!  Note that the package
@@ -1359,7 +1379,7 @@
         ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                 r.info.applicationInfo.uid, true);
 
-        r.task.stack.setLaunchTime(r);
+        r.getStack().setLaunchTime(r);
 
         if (app != null && app.thread != null) {
             try {
@@ -1599,7 +1619,7 @@
             // We'll update with whatever configuration it now says
             // it used to launch.
             if (config != null) {
-                r.configuration = config;
+                r.setLastReportedConfiguration(config);
             }
 
             // We are now idle.  If someone is waiting for a thumbnail from
@@ -1607,7 +1627,7 @@
             r.idle = true;
 
             //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
-            if (isFocusedStack(r.task.stack) || fromTimeout) {
+            if (isFocusedStack(r.getStack()) || fromTimeout) {
                 booting = checkFinishBootingLocked();
             }
         }
@@ -1645,7 +1665,7 @@
         // waiting for the next one to start.
         for (int i = 0; i < NS; i++) {
             r = stops.get(i);
-            final ActivityStack stack = r.task.stack;
+            final ActivityStack stack = r.getStack();
             if (stack != null) {
                 if (r.finishing) {
                     stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
@@ -1659,7 +1679,7 @@
         // waiting for the next one to start.
         for (int i = 0; i < NF; i++) {
             r = finishes.get(i);
-            final ActivityStack stack = r.task.stack;
+            final ActivityStack stack = r.getStack();
             if (stack != null) {
                 activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");
             }
@@ -1835,7 +1855,8 @@
             // we'll just indicate that this task returns to the home task.
             task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
         }
-        if (task.stack == null) {
+        ActivityStack currentStack = task.getStack();
+        if (currentStack == null) {
             Slog.e(TAG, "findTaskToMoveToFrontLocked: can't move task="
                     + task + " to front. Stack is null");
             return;
@@ -1849,10 +1870,10 @@
                 if (stackId == INVALID_STACK_ID) {
                     stackId = task.getLaunchStackId();
                 }
-                if (stackId != task.stack.mStackId) {
-                    final ActivityStack stack = moveTaskToStackUncheckedLocked(
-                            task, stackId, ON_TOP, !FORCE_FOCUS, reason);
-                    stackId = stack.mStackId;
+                if (stackId != currentStack.mStackId) {
+                    currentStack = moveTaskToStackUncheckedLocked(task, stackId, ON_TOP,
+                            !FORCE_FOCUS, reason);
+                    stackId = currentStack.mStackId;
                     // moveTaskToStackUncheckedLocked() should already placed the task on top,
                     // still need moveTaskToFrontLocked() below for any transition settings.
                 }
@@ -1864,20 +1885,21 @@
                     // WM resizeTask must be done after the task is moved to the correct stack,
                     // because Task's setBounds() also updates dim layer's bounds, but that has
                     // dependency on the stack.
-                    mWindowManager.resizeTask(task.taskId, task.mBounds, task.mOverrideConfig,
-                            false /* relayout */, false /* forced */);
+                    mWindowManager.resizeTask(task.taskId, task.mBounds,
+                            task.getOverrideConfiguration(), false /* relayout */,
+                            false /* forced */);
                 }
             }
         }
 
         final ActivityRecord r = task.getTopActivity();
-        task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
+        currentStack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
                 r == null ? null : r.appTimeTracker, reason);
 
         if (DEBUG_STACK) Slog.d(TAG_STACK,
-                "findTaskToMoveToFront: moved to front of stack=" + task.stack);
+                "findTaskToMoveToFront: moved to front of stack=" + currentStack);
 
-        handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, task.stack.mStackId,
+        handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, currentStack.mStackId,
                 forceNonResizeable);
     }
 
@@ -2212,7 +2234,7 @@
             // All we can do for now is update the bounds so it can be used when the task is
             // added to window manager.
             task.updateOverrideConfiguration(bounds);
-            if (task.stack != null && task.stack.mStackId != FREEFORM_WORKSPACE_STACK_ID) {
+            if (task.getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
                 // re-restore the task so it can have the proper stack association.
                 restoreRecentTaskLocked(task, FREEFORM_WORKSPACE_STACK_ID);
             }
@@ -2233,11 +2255,9 @@
         if (updatedConfig) {
             final ActivityRecord r = task.topRunningActivityLocked();
             if (r != null) {
-                final ActivityStack stack = task.stack;
-                kept = stack.ensureActivityConfigurationLocked(r, 0, preserveWindow);
+                kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindow);
 
                 if (!deferResume) {
-
                     // All other activities must be made visible with their correct configuration.
                     ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
                     if (!kept) {
@@ -2246,7 +2266,8 @@
                 }
             }
         }
-        mWindowManager.resizeTask(task.taskId, task.mBounds, task.mOverrideConfig, kept, forced);
+        mWindowManager.resizeTask(task.taskId, task.mBounds, task.getOverrideConfiguration(), kept,
+                forced);
 
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
         return kept;
@@ -2291,15 +2312,16 @@
             stackId = FULLSCREEN_WORKSPACE_STACK_ID;
         }
 
-        if (task.stack != null) {
+        final ActivityStack currentStack = task.getStack();
+        if (currentStack != null) {
             // Task has already been restored once. See if we need to do anything more
-            if (task.stack.mStackId == stackId) {
+            if (currentStack.mStackId == stackId) {
                 // Nothing else to do since it is already restored in the right stack.
                 return true;
             }
             // Remove current stack association, so we can re-associate the task with the
             // right stack below.
-            task.stack.removeTask(task, "restoreRecentTaskLocked", REMOVE_TASK_MODE_MOVING);
+            currentStack.removeTask(task, "restoreRecentTaskLocked", REMOVE_TASK_MODE_MOVING);
         }
 
         final ActivityStack stack =
@@ -2343,7 +2365,7 @@
         }
 
         final ActivityRecord r = task.topRunningActivityLocked();
-        final ActivityStack prevStack = task.stack;
+        final ActivityStack prevStack = task.getStack();
         final boolean wasFocused = isFocusedStack(prevStack) && (topRunningActivityLocked() == r);
         final boolean wasResumed = prevStack.mResumedActivity == r;
         // In some cases the focused stack isn't the front stack. E.g. pinned stack.
@@ -2393,7 +2415,8 @@
             return false;
         }
 
-        if (task.stack != null && task.stack.mStackId == stackId) {
+        final ActivityStack currentStack = task.getStack();
+        if (currentStack != null && currentStack.mStackId == stackId) {
             // You are already in the right stack silly...
             Slog.i(TAG, "moveTaskToStack: taskId=" + taskId + " already in stackId=" + stackId);
             return true;
@@ -2405,7 +2428,7 @@
         }
 
         final ActivityRecord topActivity = task.getTopActivity();
-        final int sourceStackId = task.stack != null ? task.stack.mStackId : INVALID_STACK_ID;
+        final int sourceStackId = task.getStackId();
         final boolean mightReplaceWindow =
                 StackId.replaceWindowsOnTaskMove(sourceStackId, stackId) && topActivity != null;
         if (mightReplaceWindow) {
@@ -2505,7 +2528,7 @@
         try {
             final TaskRecord task = r.task;
 
-            if (r == task.stack.getVisibleBehindActivity()) {
+            if (r == task.getStack().getVisibleBehindActivity()) {
                 // An activity can't be pinned and visible behind at the same time. Go ahead and
                 // release it from been visible behind before pinning.
                 requestVisibleBehindLocked(r, false);
@@ -2555,13 +2578,13 @@
         }
 
         final TaskRecord task = r.task;
-        if (task == null || task.stack == null) {
+        final ActivityStack stack = r.getStack();
+        if (stack == null) {
             Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: r="
                     + r + " task=" + task);
             return false;
         }
 
-        final ActivityStack stack = task.stack;
         if (stack == mFocusedStack && stack.topRunningActivityLocked() == r) {
             if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
                     "moveActivityStackToFront: already on top, r=" + r);
@@ -2586,7 +2609,7 @@
         task.updateOverrideConfigurationForStack(stack);
 
         mWindowManager.positionTaskInStack(
-                taskId, stackId, position, task.mBounds, task.mOverrideConfig);
+                taskId, stackId, position, task.mBounds, task.getOverrideConfiguration());
         stack.positionTask(task, position);
         // The task might have already been running and its visibility needs to be synchronized with
         // the visibility of the stack / windows.
@@ -2771,7 +2794,7 @@
     }
 
     boolean reportResumedActivityLocked(ActivityRecord r) {
-        final ActivityStack stack = r.task.stack;
+        final ActivityStack stack = r.getStack();
         if (isFocusedStack(stack)) {
             mService.updateUsageStats(r, true);
         }
@@ -2795,7 +2818,7 @@
     }
 
     boolean requestVisibleBehindLocked(ActivityRecord r, boolean visible) {
-        final ActivityStack stack = r.task.stack;
+        final ActivityStack stack = r.getStack();
         if (stack == null) {
             if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG_VISIBLE_BEHIND,
                     "requestVisibleBehind: r=" + r + " visible=" + visible + " stack is null");
@@ -2859,12 +2882,12 @@
     }
 
     // Called when WindowManager has finished animating the launchingBehind activity to the back.
-    void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
+    private void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
         final TaskRecord task = r.task;
-        final ActivityStack stack = task.stack;
+        final ActivityStack stack = task.getStack();
 
         r.mLaunchTaskBehind = false;
-        task.setLastThumbnailLocked(stack.screenshotActivitiesLocked(r));
+        task.setLastThumbnailLocked(r.screenshotActivityLocked());
         mRecentTasks.addLocked(task);
         mService.notifyTaskStackChangedLocked();
         mWindowManager.setAppVisibility(r.appToken, false);
@@ -3606,7 +3629,7 @@
                     lockTaskModeState != LOCK_TASK_MODE_NONE);
             resumeFocusedStackTopActivityLocked();
         } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
-            handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, task.stack.mStackId,
+            handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, task.getStackId(),
                     true /* forceNonResizable */);
         }
     }
@@ -3715,7 +3738,7 @@
     }
 
     void scheduleReportPictureInPictureModeChangedIfNeeded(TaskRecord task, ActivityStack prevStack) {
-        final ActivityStack stack = task.stack;
+        final ActivityStack stack = task.getStack();
         if (prevStack == null || prevStack == stack
                 || (prevStack.mStackId != PINNED_STACK_ID && stack.mStackId != PINNED_STACK_ID)) {
             return;
@@ -4227,7 +4250,7 @@
 
     /** Exactly one of these classes per Display in the system. Capable of holding zero or more
      * attached {@link ActivityStack}s */
-    class ActivityDisplay {
+    class ActivityDisplay extends ConfigurationContainer {
         /** Actual Display this object tracks. */
         int mDisplayId;
         Display mDisplay;
@@ -4287,6 +4310,21 @@
         public String toString() {
             return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
         }
+
+        @Override
+        protected int getChildCount() {
+            return mStacks.size();
+        }
+
+        @Override
+        protected ConfigurationContainer getChildAt(int index) {
+            return mStacks.get(index);
+        }
+
+        @Override
+        protected ConfigurationContainer getParent() {
+            return ActivityStackSupervisor.this;
+        }
     }
 
     class VirtualActivityDisplay extends ActivityDisplay {
@@ -4392,7 +4430,7 @@
                 focusedStack != null ? focusedStack.topActivity() : null;
 
         if (launchStackId != INVALID_STACK_ID) {
-            if (task.stack.mStackId != launchStackId) {
+            if (task.getStackId() != launchStackId) {
                 moveTaskToStackLocked(
                         taskId, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents",
                         ANIMATE);
@@ -4418,8 +4456,8 @@
 
             mService.mActivityStarter.postStartActivityUncheckedProcessing(task.getTopActivity(),
                     ActivityManager.START_TASK_TO_FRONT,
-                    sourceRecord != null ? sourceRecord.task.stack.mStackId : INVALID_STACK_ID,
-                    sourceRecord, task.stack);
+                    sourceRecord != null ? sourceRecord.task.getStackId() : INVALID_STACK_ID,
+                    sourceRecord, task.getStack());
             return ActivityManager.START_TASK_TO_FRONT;
         }
         callingUid = task.mCallingUid;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 028c6ac..a834af7 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -98,6 +98,7 @@
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.hardware.power.V1_0.PowerHint;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -360,7 +361,7 @@
             }
         }
 
-        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
+        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
 
         if (err != START_SUCCESS) {
             if (resultRecord != null) {
@@ -469,9 +470,9 @@
         }
 
         ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
-                intent, resolvedType, aInfo, mService.mGlobalConfiguration, resultRecord, resultWho,
-                requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
-                options, sourceRecord);
+                intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord,
+                resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor,
+                container, options, sourceRecord);
         if (outActivity != null) {
             outActivity[0] = r;
         }
@@ -591,8 +592,9 @@
         }
 
         int startedActivityStackId = INVALID_STACK_ID;
-        if (r.task != null && r.task.stack != null) {
-            startedActivityStackId = r.task.stack.mStackId;
+        final ActivityStack currentStack = r.getStack();
+        if (currentStack != null) {
+            startedActivityStackId = currentStack.mStackId;
         } else if (mTargetStack != null) {
             startedActivityStackId = targetStack.mStackId;
         }
@@ -780,7 +782,7 @@
                 stack = container.mStack;
             }
             stack.mConfigWillChange = globalConfig != null
-                    && mService.mGlobalConfiguration.diff(globalConfig) != 0;
+                    && mService.getGlobalConfiguration().diff(globalConfig) != 0;
             if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                     "Starting activity when config will change = " + stack.mConfigWillChange);
 
@@ -1002,7 +1004,7 @@
                 curTop.task != null && mStartActivity != null &&
                 curTop.task != mStartActivity.task )) &&
                 mService.mLocalPowerManager != null) {
-            mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 1);
+            mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
             mPowerHintSent = true;
         }
     }
@@ -1010,7 +1012,7 @@
     void sendPowerHintForLaunchEndIfNeeded() {
         // Trigger launch power hint if activity is launched
         if (mPowerHintSent && mService.mLocalPowerManager != null) {
-            mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 0);
+            mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
             mPowerHintSent = false;
         }
     }
@@ -1099,10 +1101,12 @@
         }
 
         if (mStartActivity.packageName == null) {
-            if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
-                mStartActivity.resultTo.task.stack.sendActivityResultLocked(
-                        -1, mStartActivity.resultTo, mStartActivity.resultWho,
-                        mStartActivity.requestCode, RESULT_CANCELED, null);
+            final ActivityStack sourceStack = mStartActivity.resultTo != null
+                    ? mStartActivity.resultTo.getStack() : null;
+            if (sourceStack != null) {
+                sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
+                        mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
+                        null /* data */);
             }
             ActivityOptions.abort(mOptions);
             return START_CLASS_NOT_FOUND;
@@ -1312,15 +1316,17 @@
     }
 
     private void sendNewTaskResultRequestIfNeeded() {
-        if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
-                && mStartActivity.resultTo.task.stack != null) {
+        final ActivityStack sourceStack = mStartActivity.resultTo != null
+                ? mStartActivity.resultTo.getStack() : null;
+        if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
             // For whatever reason this activity is being launched into a new task...
             // yet the caller has requested a result back.  Well, that is pretty messed up,
             // so instead immediately send back a cancel and let the new task continue launched
             // as normal without a dependency on its originator.
             Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
-            mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
-                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
+            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
+                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
+                    null /* data */);
             mStartActivity.resultTo = null;
         }
     }
@@ -1328,7 +1334,7 @@
     private void computeLaunchingTaskFlags() {
         // If the caller is not coming from another activity, but has given us an explicit task into
         // which they would like us to launch the new activity, then let's see about doing that.
-        if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
+        if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
             final Intent baseIntent = mInTask.getBaseIntent();
             final ActivityRecord root = mInTask.getRootActivity();
             if (baseIntent == null) {
@@ -1415,7 +1421,7 @@
             return;
         }
         if (!mSourceRecord.finishing) {
-            mSourceStack = mSourceRecord.task.stack;
+            mSourceStack = mSourceRecord.getStack();
             return;
         }
 
@@ -1474,7 +1480,7 @@
     }
 
     private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
-        mTargetStack = intentActivity.task.stack;
+        mTargetStack = intentActivity.getStack();
         mTargetStack.mLastPausedActivity = null;
         // If the target task is not in the front, then we need to bring it to the front...
         // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
@@ -1606,7 +1612,7 @@
                 // is put in the right place.
                 mSourceRecord = intentActivity;
                 final TaskRecord task = mSourceRecord.task;
-                if (task != null && task.stack == null) {
+                if (task != null && task.getStack() == null) {
                     // Target stack got cleared when we all activities were removed above.
                     // Go ahead and reset it.
                     mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
@@ -1722,18 +1728,19 @@
         }
 
         final TaskRecord sourceTask = mSourceRecord.task;
+        final ActivityStack sourceStack = mSourceRecord.getStack();
         // We only want to allow changing stack if the target task is not the top one,
         // otherwise we would move the launching task to the other side, rather than show
         // two side by side.
-        final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
+        final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
         if (moveStackAllowed) {
             mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
                     mOptions);
         }
 
         if (mTargetStack == null) {
-            mTargetStack = sourceTask.stack;
-        } else if (mTargetStack != sourceTask.stack) {
+            mTargetStack = sourceStack;
+        } else if (mTargetStack != sourceStack) {
             mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
                     ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
         }
@@ -1800,7 +1807,7 @@
         if (mLaunchBounds != null) {
             mInTask.updateOverrideConfiguration(mLaunchBounds);
             int stackId = mInTask.getLaunchStackId();
-            if (stackId != mInTask.stack.mStackId) {
+            if (stackId != mInTask.getStackId()) {
                 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
                         mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
                 stackId = stack.mStackId;
@@ -1809,7 +1816,7 @@
                 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
             }
         }
-        mTargetStack = mInTask.stack;
+        mTargetStack = mInTask.getStack();
         mTargetStack.moveTaskToFrontLocked(
                 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
 
@@ -1916,10 +1923,10 @@
             return stack;
         }
 
-        if (task != null && task.stack != null) {
-            stack = task.stack;
-            if (stack.isOnHomeDisplay()) {
-                if (mSupervisor.mFocusedStack != stack) {
+        final ActivityStack currentStack = task != null ? task.getStack() : null;
+        if (currentStack != null) {
+            if (currentStack.isOnHomeDisplay()) {
+                if (mSupervisor.mFocusedStack != currentStack) {
                     if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                             "computeStackFocus: Setting " + "focused stack to r=" + r
                                     + " task=" + task);
@@ -1929,7 +1936,7 @@
                                     + mSupervisor.mFocusedStack);
                 }
             }
-            return stack;
+            return currentStack;
         }
 
         final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
@@ -1980,7 +1987,7 @@
 
         // We are reusing a task, keep the stack!
         if (mReuseTask != null) {
-            return mReuseTask.stack;
+            return mReuseTask.getStack();
         }
 
         final int launchStackId =
@@ -2001,7 +2008,7 @@
 
         // The parent activity doesn't want to launch the activity on top of itself, but
         // instead tries to put it onto other side in side-by-side mode.
-        final ActivityStack parentStack = task != null ? task.stack
+        final ActivityStack parentStack = task != null ? task.getStack()
                 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
                 : mSupervisor.mFocusedStack;
 
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 3b4b8d6..4e69162 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -228,7 +228,8 @@
     public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
         final Intent intent = r.intent;
         for (int i = mParallelBroadcasts.size() - 1; i >= 0; i--) {
-            if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
+            final Intent curIntent = mParallelBroadcasts.get(i).intent;
+            if (intent.filterEquals(curIntent)) {
                 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                         "***** DROPPING PARALLEL ["
                 + mQueueName + "]: " + intent);
@@ -267,7 +268,7 @@
 
         r.receiver = app.thread.asBinder();
         r.curApp = app;
-        app.curReceiver = r;
+        app.curReceivers.add(r);
         app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
         mService.updateLruProcessLocked(app, false, null);
         mService.updateOomAdjLocked();
@@ -295,7 +296,7 @@
                         "Process cur broadcast " + r + ": NOT STARTED!");
                 r.receiver = null;
                 r.curApp = null;
-                app.curReceiver = null;
+                app.curReceivers.remove(r);
             }
         }
     }
@@ -396,8 +397,8 @@
         }
         r.receiver = null;
         r.intent.setComponent(null);
-        if (r.curApp != null && r.curApp.curReceiver == r) {
-            r.curApp.curReceiver = null;
+        if (r.curApp != null && r.curApp.curReceivers.contains(r)) {
+            r.curApp.curReceivers.remove(r);
         }
         if (r.curFilter != null) {
             r.curFilter.receiverList.curBroadcast = null;
@@ -650,7 +651,7 @@
                 // things that directly call the IActivityManager API, which
                 // are already core system stuff so don't matter for this.
                 r.curApp = filter.receiverList.app;
-                filter.receiverList.app.curReceiver = r;
+                filter.receiverList.app.curReceivers.add(r);
                 mService.updateOomAdjLocked(r.curApp);
             }
         }
@@ -678,7 +679,7 @@
                 r.curFilter = null;
                 filter.receiverList.curBroadcast = null;
                 if (filter.receiverList.app != null) {
-                    filter.receiverList.app.curReceiver = null;
+                    filter.receiverList.app.curReceivers.remove(r);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index 3437ae6..1e7911a 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -219,6 +219,9 @@
             int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized,
             boolean _sticky, boolean _initialSticky,
             int _userId) {
+        if (_intent == null) {
+            throw new NullPointerException("Can't construct with a null intent");
+        }
         queue = _queue;
         intent = _intent;
         targetComp = _intent.getComponent();
diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
index 0b282ed..bfc0456 100644
--- a/services/core/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -38,6 +38,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -197,18 +198,19 @@
     }
 
     public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
-        CompatibilityInfo ci = new CompatibilityInfo(ai, mService.mGlobalConfiguration.screenLayout,
-                mService.mGlobalConfiguration.smallestScreenWidthDp,
+        final Configuration globalConfig = mService.getGlobalConfiguration();
+        CompatibilityInfo ci = new CompatibilityInfo(ai, globalConfig.screenLayout,
+                globalConfig.smallestScreenWidthDp,
                 (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0);
         //Slog.i(TAG, "*********** COMPAT FOR PKG " + ai.packageName + ": " + ci);
         return ci;
     }
 
     public int computeCompatModeLocked(ApplicationInfo ai) {
-        boolean enabled = (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0;
-        CompatibilityInfo info = new CompatibilityInfo(ai,
-                mService.mGlobalConfiguration.screenLayout,
-                mService.mGlobalConfiguration.smallestScreenWidthDp, enabled);
+        final boolean enabled = (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0;
+        final Configuration globalConfig = mService.getGlobalConfiguration();
+        final CompatibilityInfo info = new CompatibilityInfo(ai, globalConfig.screenLayout,
+                globalConfig.smallestScreenWidthDp, enabled);
         if (info.alwaysSupportsScreen()) {
             return ActivityManager.COMPAT_MODE_NEVER;
         }
@@ -383,7 +385,8 @@
             }
 
             if (starting != null) {
-                stack.ensureActivityConfigurationLocked(starting, 0, false);
+                starting.ensureActivityConfigurationLocked(0 /* globalChanges */,
+                        false /* preserveWindow */);
                 // And we need to make sure at this point that all other activities
                 // are made visible with the correct configuration.
                 stack.ensureActivitiesVisibleLocked(starting, 0, !PRESERVE_WINDOWS);
@@ -408,8 +411,9 @@
             out.startTag(null, "compat-packages");
 
             final IPackageManager pm = AppGlobals.getPackageManager();
-            final int screenLayout = mService.mGlobalConfiguration.screenLayout;
-            final int smallestScreenWidthDp = mService.mGlobalConfiguration.smallestScreenWidthDp;
+            final Configuration globalConfig = mService.getGlobalConfiguration();
+            final int screenLayout = globalConfig.screenLayout;
+            final int smallestScreenWidthDp = globalConfig.smallestScreenWidthDp;
             final Iterator<Map.Entry<String, Integer>> it = pkgs.entrySet().iterator();
             while (it.hasNext()) {
                 Map.Entry<String, Integer> entry = it.next();
diff --git a/services/core/java/com/android/server/am/ConfigurationContainer.java b/services/core/java/com/android/server/am/ConfigurationContainer.java
new file mode 100644
index 0000000..30f5309
--- /dev/null
+++ b/services/core/java/com/android/server/am/ConfigurationContainer.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import android.content.res.Configuration;
+
+/**
+ * Contains common logic for classes that have override configurations and are organized in a
+ * hierarchy.
+ */
+abstract class ConfigurationContainer<E extends ConfigurationContainer> {
+
+    /** Contains override configuration settings applied to this configuration container. */
+    private Configuration mOverrideConfiguration = new Configuration();
+
+    /**
+     * Contains full configuration applied to this configuration container. Corresponds to full
+     * parent's config with applied {@link #mOverrideConfiguration}.
+     */
+    private Configuration mFullConfiguration = new Configuration();
+
+    /**
+     * Contains merged override configuration settings from the top of the hierarchy down to this
+     * particular instance. It is different from {@link #mFullConfiguration} because it starts from
+     * topmost container's override config instead of global config.
+     */
+    private Configuration mMergedOverrideConfiguration = new Configuration();
+
+    /**
+     * Returns full configuration applied to this configuration container.
+     * This method should be used for getting settings applied in each particular level of the
+     * hierarchy.
+     */
+    Configuration getConfiguration() {
+        return mFullConfiguration;
+    }
+
+    /**
+     * Notify that parent config changed and we need to update full configuration.
+     * @see #mFullConfiguration
+     */
+    void onConfigurationChanged(Configuration newParentConfig) {
+        mFullConfiguration.setTo(newParentConfig);
+        mFullConfiguration.updateFrom(mOverrideConfiguration);
+        for (int i = getChildCount() - 1; i >= 0; --i) {
+            final ConfigurationContainer child = getChildAt(i);
+            child.onConfigurationChanged(mFullConfiguration);
+        }
+    }
+
+    /** Returns override configuration applied to this configuration container. */
+    Configuration getOverrideConfiguration() {
+        return mOverrideConfiguration;
+    }
+
+    /**
+     * Update override configuration and recalculate full config.
+     * @see #mOverrideConfiguration
+     * @see #mFullConfiguration
+     */
+    void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+        mOverrideConfiguration.setTo(overrideConfiguration);
+        // Update full configuration of this container and all its children.
+        final ConfigurationContainer parent = getParent();
+        onConfigurationChanged(parent != null ? parent.getConfiguration() : Configuration.EMPTY);
+        // Update merged override config of this container and all its children.
+        onMergedOverrideConfigurationChanged();
+    }
+
+    /**
+     * Get merged override configuration from the top of the hierarchy down to this particular
+     * instance. This should be reported to client as override config.
+     */
+    Configuration getMergedOverrideConfiguration() {
+        return mMergedOverrideConfiguration;
+    }
+
+    /**
+     * Update merged override configuration based on corresponding parent's config and notify all
+     * its children. If there is no parent, merged override configuration will set equal to current
+     * override config.
+     * @see #mMergedOverrideConfiguration
+     */
+    private void onMergedOverrideConfigurationChanged() {
+        final ConfigurationContainer parent = getParent();
+        if (parent != null) {
+            mMergedOverrideConfiguration.setTo(parent.getMergedOverrideConfiguration());
+            mMergedOverrideConfiguration.updateFrom(mOverrideConfiguration);
+        } else {
+            mMergedOverrideConfiguration.setTo(mOverrideConfiguration);
+        }
+        for (int i = getChildCount() - 1; i >= 0; --i) {
+            final ConfigurationContainer child = getChildAt(i);
+            child.onMergedOverrideConfigurationChanged();
+        }
+    }
+
+    /**
+     * Must be called when new parent for the container was set.
+     */
+    void onParentChanged() {
+        final ConfigurationContainer parent = getParent();
+        // Update full configuration of this container and all its children.
+        onConfigurationChanged(parent != null ? parent.mFullConfiguration : Configuration.EMPTY);
+        // Update merged override configuration of this container and all its children.
+        onMergedOverrideConfigurationChanged();
+    }
+
+    abstract protected int getChildCount();
+
+    abstract protected E getChildAt(int index);
+
+    abstract protected ConfigurationContainer getParent();
+}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 9c08453..c494171 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -296,9 +296,10 @@
                         }
                         break;
                     case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
-                        if (key.activity.task.stack != null) {
-                            key.activity.task.stack.sendActivityResultLocked(-1, key.activity,
-                                    key.who, key.requestCode, code, finalIntent);
+                        final ActivityStack stack = key.activity.getStack();
+                        if (stack != null) {
+                            stack.sendActivityResultLocked(-1, key.activity, key.who,
+                                    key.requestCode, code, finalIntent);
                         }
                         break;
                     case ActivityManager.INTENT_SENDER_BROADCAST:
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 3fffefb..49fe79c 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -143,7 +143,7 @@
     Bundle instrumentationArguments;// as given to us
     ComponentName instrumentationResultClass;// copy of instrumentationClass
     boolean usingWrapper;       // Set to true when process was launched with a wrapper attached
-    BroadcastRecord curReceiver;// receiver currently running in the app
+    final ArraySet<BroadcastRecord> curReceivers = new ArraySet<BroadcastRecord>();// receivers currently running in the app
     long lastWakeTime;          // How long proc held wake lock at last check
     long lastCpuTime;           // How long proc has run CPU at last check
     long curCpuTime;            // How long proc has run CPU most recently
@@ -427,8 +427,11 @@
                 pw.print(prefix); pw.print("  - "); pw.println(conProviders.get(i).toShortString());
             }
         }
-        if (curReceiver != null) {
-            pw.print(prefix); pw.print("curReceiver="); pw.println(curReceiver);
+        if (!curReceivers.isEmpty()) {
+            pw.print(prefix); pw.println("Current Receivers:");
+            for (int i=0; i < curReceivers.size(); i++) {
+                pw.print(prefix); pw.print("  - "); pw.println(curReceivers.valueAt(i));
+            }
         }
         if (receivers.size() > 0) {
             pw.print(prefix); pw.println("Receivers:");
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index beb863b..bc9bda2f 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -129,7 +129,8 @@
     }
 
     void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
-        if (task != null && task.stack != null && task.stack.isHomeStack()) {
+        final ActivityStack stack = task != null ? task.getStack() : null;
+        if (stack != null && stack.isHomeStack()) {
             // Never persist the home stack.
             return;
         }
@@ -147,8 +148,9 @@
             }
         }
         for (int i = size() - 1; i >= 0; i--) {
-            TaskRecord task = get(i);
-            if (task.isPersistable && (task.stack == null || !task.stack.isHomeStack())) {
+            final TaskRecord task = get(i);
+            final ActivityStack stack = task.getStack();
+            if (task.isPersistable && (stack == null || !stack.isHomeStack())) {
                 // Set of persisted taskIds for task.userId should not be null here
                 // TODO Investigate why it can happen. For now initialize with an empty set
                 if (mPersistedTaskIds.get(task.userId) == null) {
@@ -618,10 +620,12 @@
         final Intent intent = task.intent;
         final boolean document = intent != null && intent.isDocument();
         int maxRecents = task.maxRecents - 1;
+        final ActivityStack stack = task.getStack();
         for (int i = 0; i < recentsCount; i++) {
             final TaskRecord tr = get(i);
+            final ActivityStack trStack = tr.getStack();
             if (task != tr) {
-                if (task.stack != null && tr.stack != null && task.stack != tr.stack) {
+                if (stack != null && trStack != null && stack != trStack) {
                     continue;
                 }
                 if (task.userId != tr.userId) {
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 43eb251..1ecb2e9 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -54,6 +54,8 @@
 import java.util.Comparator;
 import java.util.List;
 
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+
 public class TaskPersister {
     static final String TAG = "TaskPersister";
     static final boolean DEBUG = false;
@@ -450,7 +452,7 @@
 
                                 final int taskId = task.taskId;
                                 if (mStackSupervisor.anyTaskForIdLocked(taskId,
-                                        /* restoreFromRecents= */ false, 0) != null) {
+                                        /* restoreFromRecents= */ false, HOME_STACK_ID) != null) {
                                     // Should not happen.
                                     Slog.wtf(TAG, "Existing task with taskId " + taskId + "found");
                                 } else if (userId != task.userId) {
@@ -639,8 +641,9 @@
                             final TaskRecord task = mRecentTasks.get(taskNdx);
                             if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task +
                                     " persistable=" + task.isPersistable);
+                            final ActivityStack stack = task.getStack();
                             if ((task.isPersistable || task.inRecents)
-                                    && (task.stack == null || !task.stack.isHomeStack())) {
+                                    && (stack == null || !stack.isHomeStack())) {
                                 if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
                                 persistentTaskIds.add(task.taskId);
                             } else {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 6cc4d73..9d97dd3 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -56,6 +56,8 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
@@ -67,15 +69,15 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
 import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
+import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
-import static android.content.res.Configuration.SCREENLAYOUT_LONG_MASK;
-import static android.content.res.Configuration.SCREENLAYOUT_SIZE_MASK;
 import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
@@ -93,18 +95,18 @@
 import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
 
-final class TaskRecord {
+final class TaskRecord extends ConfigurationContainer {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
     private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
     private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
 
-    static final String ATTR_TASKID = "task_id";
+    private static final String ATTR_TASKID = "task_id";
     private static final String TAG_INTENT = "intent";
     private static final String TAG_AFFINITYINTENT = "affinity_intent";
-    static final String ATTR_REALACTIVITY = "real_activity";
-    static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
+    private static final String ATTR_REALACTIVITY = "real_activity";
+    private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
     private static final String ATTR_ORIGACTIVITY = "orig_activity";
     private static final String TAG_ACTIVITY = "activity";
     private static final String ATTR_AFFINITY = "affinity";
@@ -121,7 +123,7 @@
     private static final String ATTR_LASTDESCRIPTION = "last_description";
     private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
     private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
-    static final String ATTR_TASK_AFFILIATION = "task_affiliation";
+    private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
     private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
     private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
     private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
@@ -132,12 +134,15 @@
     private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
     private static final String ATTR_MIN_WIDTH = "min_width";
     private static final String ATTR_MIN_HEIGHT = "min_height";
+    private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
 
-
+    // Current version of the task record we persist. Used to check if we need to run any upgrade
+    // code.
+    private static final int PERSIST_TASK_VERSION = 1;
     private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
 
     static final int INVALID_TASK_ID = -1;
-    static final int INVALID_MIN_SIZE = -1;
+    private static final int INVALID_MIN_SIZE = -1;
 
     final int taskId;       // Unique identifier for this task.
     String affinity;        // The affinity name for this task, or null; may change identity.
@@ -173,8 +178,8 @@
                             // Based on the {@link ActivityInfo#resizeMode} of the root activity.
     boolean mTemporarilyUnresizable; // Separate flag from mResizeMode used to suppress resize
                                      // changes on a temporary basis.
-    int mLockTaskMode;      // Which tasklock mode to launch this task in. One of
-                            // ActivityManager.LOCK_TASK_LAUNCH_MODE_*
+    private int mLockTaskMode;  // Which tasklock mode to launch this task in. One of
+                                // ActivityManager.LOCK_TASK_LAUNCH_MODE_*
     private boolean mPrivileged;    // The root activity application of this task holds
                                     // privileged permissions.
     private boolean mIsOnTopLauncher; // Whether this task is an on-top launcher. See
@@ -202,8 +207,8 @@
     /** List of all activities in the task arranged in history order */
     final ArrayList<ActivityRecord> mActivities;
 
-    /** Current stack */
-    ActivityStack stack;
+    /** Current stack. Setter must always be used to update the value. */
+    private ActivityStack mStack;
 
     /** Takes on same set of values as ActivityRecord.mActivityType */
     int taskType;
@@ -223,7 +228,7 @@
     private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE;
 
     /** If original intent did not allow relinquishing task identity, save that information */
-    boolean mNeverRelinquishIdentity = true;
+    private boolean mNeverRelinquishIdentity = true;
 
     // Used in the unique case where we are clearing the task in order to reuse it. In that case we
     // do not want to delete the stack when the task goes empty.
@@ -271,8 +276,8 @@
     // This number will be assigned when we evaluate OOM scores for all visible tasks.
     int mLayerRank = -1;
 
-    /** Contains configurations settings that are different from the parent's configuration. */
-    Configuration mOverrideConfig = Configuration.EMPTY;
+    /** Helper object used for updating override configuration. */
+    private Configuration mTmpConfig = new Configuration();
 
     TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
             IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
@@ -402,7 +407,7 @@
     private void setIntent(Intent _intent, ActivityInfo info) {
         if (intent == null) {
             mNeverRelinquishIdentity =
-                    (info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+                    (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
         } else if (mNeverRelinquishIdentity) {
             return;
         }
@@ -527,6 +532,38 @@
         mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
     }
 
+    ActivityStack getStack() {
+        return mStack;
+    }
+
+    /** Must be used for setting parent stack because it performs configuration updates. */
+    void setStack(ActivityStack stack) {
+        mStack = stack;
+        onParentChanged();
+    }
+
+    /**
+     * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
+     */
+    int getStackId() {
+        return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
+    }
+
+    @Override
+    protected int getChildCount() {
+        return 0;
+    }
+
+    @Override
+    protected ConfigurationContainer getChildAt(int index) {
+        return null;
+    }
+
+    @Override
+    protected ConfigurationContainer getParent() {
+        return mStack;
+    }
+
     // Close up recents linked list.
     void closeRecentsChain() {
         if (mPrevAffiliate != null) {
@@ -576,23 +613,26 @@
      * @return whether the thumbnail was set
      */
     boolean setLastThumbnailLocked(Bitmap thumbnail) {
-        final Configuration serviceConfig = mService.mGlobalConfiguration;
         int taskWidth = 0;
         int taskHeight = 0;
         if (mBounds != null) {
             // Non-fullscreen tasks
             taskWidth = mBounds.width();
             taskHeight = mBounds.height();
-        } else if (stack != null) {
+        } else if (mStack != null) {
             // Fullscreen tasks
             final Point displaySize = new Point();
-            stack.getDisplaySize(displaySize);
+            mStack.getDisplaySize(displaySize);
             taskWidth = displaySize.x;
             taskHeight = displaySize.y;
         } else {
             Slog.e(TAG, "setLastThumbnailLocked() called on Task without stack");
         }
-        return setLastThumbnailLocked(thumbnail, taskWidth, taskHeight, serviceConfig.orientation);
+        // We need to provide the current orientation of the display on which this task resides,
+        // not the orientation of the task.
+        final int orientation =
+                getStack().mActivityContainer.mActivityDisplay.getConfiguration().orientation;
+        return setLastThumbnailLocked(thumbnail, taskWidth, taskHeight, orientation);
     }
 
     /**
@@ -681,7 +721,7 @@
     }
 
     ActivityRecord topRunningActivityLocked() {
-        if (stack != null) {
+        if (mStack != null) {
             for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
                 ActivityRecord r = mActivities.get(activityNdx);
                 if (!r.finishing && r.okToShowLocked()) {
@@ -693,7 +733,7 @@
     }
 
     ActivityRecord topRunningActivityWithStartingWindowLocked() {
-        if (stack != null) {
+        if (mStack != null) {
             for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
                 ActivityRecord r = mActivities.get(activityNdx);
                 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
@@ -817,7 +857,7 @@
             mService.notifyTaskPersisterLocked(this, false);
         }
 
-        if (stack != null && stack.mStackId == PINNED_STACK_ID) {
+        if (getStackId() == PINNED_STACK_ID) {
             // We normally notify listeners of task stack changes on pause, however pinned stack
             // activities are normally in the paused state so no notification will be sent there
             // before the activity is removed. We send it here so instead.
@@ -849,13 +889,13 @@
             if (r.finishing) {
                 continue;
             }
-            if (stack == null) {
+            if (mStack == null) {
                 // Task was restored from persistent storage.
                 r.takeFromHistory();
                 mActivities.remove(activityNdx);
                 --activityNdx;
                 --numActivities;
-            } else if (stack.finishActivityLocked(
+            } else if (mStack.finishActivityLocked(
                     r, Activity.RESULT_CANCELED, null, "clear-task-index", false)) {
                 --activityNdx;
                 --numActivities;
@@ -910,7 +950,7 @@
                     if (opts != null) {
                         ret.updateOptionsLocked(opts);
                     }
-                    if (stack != null && stack.finishActivityLocked(
+                    if (mStack != null && mStack.finishActivityLocked(
                             r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
                         --activityNdx;
                         --numActivities;
@@ -924,8 +964,8 @@
                         && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
                         && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
                     if (!ret.finishing) {
-                        if (stack != null) {
-                            stack.finishActivityLocked(
+                        if (mStack != null) {
+                            mStack.finishActivityLocked(
                                     ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
                         }
                         return null;
@@ -939,11 +979,11 @@
         return null;
     }
 
-    public TaskThumbnail getTaskThumbnailLocked() {
-        if (stack != null) {
-            final ActivityRecord resumedActivity = stack.mResumedActivity;
+    TaskThumbnail getTaskThumbnailLocked() {
+        if (mStack != null) {
+            final ActivityRecord resumedActivity = mStack.mResumedActivity;
             if (resumedActivity != null && resumedActivity.task == this) {
-                final Bitmap thumbnail = stack.screenshotActivitiesLocked(resumedActivity);
+                final Bitmap thumbnail = resumedActivity.screenshotActivityLocked();
                 setLastThumbnailLocked(thumbnail);
             }
         }
@@ -952,7 +992,7 @@
         return taskThumbnail;
     }
 
-    public void removeTaskActivitiesLocked() {
+    void removeTaskActivitiesLocked() {
         // Just remove the entire task.
         performClearTaskAtIndexLocked(0);
     }
@@ -1032,20 +1072,16 @@
     }
 
     boolean isResizeable() {
-        return !isHomeTask() && (mService.mForceResizableActivities
-                || ActivityInfo.isResizeableMode(mResizeMode)) && !mTemporarilyUnresizable;
+        return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode))
+                && !mTemporarilyUnresizable;
     }
 
     boolean isOnTopLauncher() {
         return isHomeTask() && mIsOnTopLauncher;
     }
 
-    boolean inCropWindowsResizeMode() {
-        return !isResizeable() && mResizeMode == RESIZE_MODE_CROP_WINDOWS;
-    }
-
     boolean canGoInDockedStack() {
-        return isResizeable() || inCropWindowsResizeMode();
+        return isResizeable();
     }
 
     /**
@@ -1072,12 +1108,12 @@
         // utility activities.
         int activityNdx;
         final int numActivities = mActivities.size();
-        final boolean relinquish = numActivities == 0 ? false :
-                (mActivities.get(0).info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) != 0;
+        final boolean relinquish = numActivities != 0 &&
+                (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
         for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
                 ++activityNdx) {
             final ActivityRecord r = mActivities.get(activityNdx);
-            if (relinquish && (r.info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
+            if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
                 // This will be the top activity for determining taskDescription. Pre-inc to
                 // overcome initial decrement below.
                 ++activityNdx;
@@ -1132,7 +1168,7 @@
                 continue;
             }
             effectiveNdx = activityNdx;
-            if ((r.info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
+            if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
                 break;
             }
         }
@@ -1200,6 +1236,7 @@
         }
         out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
         out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
+        out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
 
         if (affinityIntent != null) {
             out.startTag(null, TAG_AFFINITYINTENT);
@@ -1266,6 +1303,7 @@
         Rect bounds = null;
         int minWidth = INVALID_MIN_SIZE;
         int minHeight = INVALID_MIN_SIZE;
+        int persistTaskVersion = 0;
 
         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
             final String attrName = in.getAttributeName(attrNdx);
@@ -1327,8 +1365,6 @@
                 callingPackage = attrValue;
             } else if (ATTR_RESIZE_MODE.equals(attrName)) {
                 resizeMode = Integer.parseInt(attrValue);
-                resizeMode = (resizeMode == RESIZE_MODE_CROP_WINDOWS)
-                        ? RESIZE_MODE_FORCE_RESIZEABLE : resizeMode;
             } else if (ATTR_PRIVILEGED.equals(attrName)) {
                 privileged = Boolean.parseBoolean(attrValue);
             } else if (ATTR_NON_FULLSCREEN_BOUNDS.equals(attrName)) {
@@ -1337,6 +1373,8 @@
                 minWidth = Integer.parseInt(attrValue);
             } else if (ATTR_MIN_HEIGHT.equals(attrName)) {
                 minHeight = Integer.parseInt(attrValue);
+            } else if (ATTR_PERSIST_TASK_VERSION.equals(attrName)) {
+                persistTaskVersion = Integer.parseInt(attrValue);
             } else {
                 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
             }
@@ -1391,6 +1429,16 @@
                     + ": effectiveUid=" + effectiveUid);
         }
 
+        if (persistTaskVersion < 1) {
+            // We need to convert the resize mode of home activities saved before version one if
+            // they are marked as RESIZE_MODE_RESIZEABLE to RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION
+            // since we didn't have that differentiation before version 1 and the system didn't
+            // resize home activities before then.
+            if (taskType == HOME_ACTIVITY_TYPE && resizeMode == RESIZE_MODE_RESIZEABLE) {
+                resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
+            }
+        }
+
         final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
                 affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
                 autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
@@ -1417,7 +1465,7 @@
         // If the task has no requested minimal size, we'd like to enforce a minimal size
         // so that the user can not render the task too small to manipulate. We don't need
         // to do this for the pinned stack as the bounds are controlled by the system.
-        if (stack.mStackId != PINNED_STACK_ID) {
+        if (getStackId() != PINNED_STACK_ID) {
             if (minWidth == INVALID_MIN_SIZE) {
                 minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
             }
@@ -1472,16 +1520,17 @@
         if (Objects.equals(mBounds, bounds)) {
             return false;
         }
-        final Configuration oldConfig = mOverrideConfig;
+        mTmpConfig.setTo(getOverrideConfiguration());
         final boolean oldFullscreen = mFullscreen;
+        final Configuration newConfig = getOverrideConfiguration();
 
         mFullscreen = bounds == null;
         if (mFullscreen) {
-            if (mBounds != null && StackId.persistTaskBounds(stack.mStackId)) {
+            if (mBounds != null && StackId.persistTaskBounds(mStack.mStackId)) {
                 mLastNonFullscreenBounds = mBounds;
             }
             mBounds = null;
-            mOverrideConfig = Configuration.EMPTY;
+            newConfig.unset();
         } else {
             mTmpRect.set(bounds);
             adjustForMinimalTaskDimensions(mTmpRect);
@@ -1490,18 +1539,19 @@
             } else {
                 mBounds.set(mTmpRect);
             }
-            if (stack == null || StackId.persistTaskBounds(stack.mStackId)) {
+            if (mStack == null || StackId.persistTaskBounds(mStack.mStackId)) {
                 mLastNonFullscreenBounds = mBounds;
             }
-            mOverrideConfig = calculateOverrideConfig(mTmpRect, insetBounds,
+            calculateOverrideConfig(newConfig, mTmpRect, insetBounds,
                     mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
         }
+        onOverrideConfigurationChanged(newConfig);
 
         if (mFullscreen != oldFullscreen) {
             mService.mStackSupervisor.scheduleReportMultiWindowModeChanged(this);
         }
 
-        return !mOverrideConfig.equals(oldConfig);
+        return !mTmpConfig.equals(newConfig);
     }
 
     private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds,
@@ -1526,8 +1576,9 @@
         inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
     }
 
-    private Configuration calculateOverrideConfig(Rect bounds, Rect insetBounds,
-                                                  boolean overrideWidth, boolean overrideHeight) {
+    /** Clears passed config and fills it with new override values. */
+    private void calculateOverrideConfig(Configuration config, Rect bounds, Rect insetBounds,
+            boolean overrideWidth, boolean overrideHeight) {
         mTmpNonDecorBounds.set(bounds);
         mTmpStableBounds.set(bounds);
         subtractNonDecorInsets(
@@ -1537,16 +1588,16 @@
                 mTmpStableBounds, insetBounds != null ? insetBounds : bounds,
                 overrideWidth, overrideHeight);
 
-        // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen area,
+        // For calculating screenWidthDp, screenHeightDp, we use the stable inset screen area,
         // i.e. the screen area without the system bars.
-        final Configuration serviceConfig = mService.mGlobalConfiguration;
-        final Configuration config = new Configuration(Configuration.EMPTY);
-        // TODO(multidisplay): Update Dp to that of display stack is on.
-        final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+        // Additionally task dimensions should not be bigger than its parents dimensions.
+        final Configuration parentConfig = getParent().getConfiguration();
+        config.unset();
+        final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
         config.screenWidthDp =
-                Math.min((int)(mTmpStableBounds.width() / density), serviceConfig.screenWidthDp);
+                Math.min((int)(mTmpStableBounds.width() / density), parentConfig.screenWidthDp);
         config.screenHeightDp =
-                Math.min((int)(mTmpStableBounds.height() / density), serviceConfig.screenHeightDp);
+                Math.min((int)(mTmpStableBounds.height() / density), parentConfig.screenHeightDp);
 
         // TODO: Orientation?
         config.orientation = (config.screenWidthDp <= config.screenHeightDp)
@@ -1558,14 +1609,15 @@
         // never go away in Honeycomb.
         final int compatScreenWidthDp = (int)(mTmpNonDecorBounds.width() / density);
         final int compatScreenHeightDp = (int)(mTmpNonDecorBounds.height() / density);
-        final int sl = Configuration.resetScreenLayout(serviceConfig.screenLayout);
+        // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
+        // calculation with partial default.
+        final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
         final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
-        final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);;
+        final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
         config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
 
         config.smallestScreenWidthDp = mService.mWindowManager.getSmallestWidthForTaskBounds(
                 insetBounds != null ? insetBounds : bounds);
-        return config;
     }
 
     /**
@@ -1574,12 +1626,14 @@
      * {@param config}.
      */
     Configuration extractOverrideConfig(Configuration config) {
-        final Configuration extracted = new Configuration(Configuration.EMPTY);
+        final Configuration extracted = new Configuration();
         extracted.screenWidthDp = config.screenWidthDp;
         extracted.screenHeightDp = config.screenHeightDp;
         extracted.smallestScreenWidthDp = config.smallestScreenWidthDp;
         extracted.orientation = config.orientation;
-        extracted.screenLayout = config.screenLayout;
+        // We're only overriding LONG, SIZE and COMPAT parts of screenLayout.
+        extracted.screenLayout = config.screenLayout & (Configuration.SCREENLAYOUT_LONG_MASK
+                | Configuration.SCREENLAYOUT_SIZE_MASK | Configuration.SCREENLAYOUT_COMPAT_NEEDED);
         return extracted;
     }
 
@@ -1592,29 +1646,6 @@
         return bounds;
     }
 
-    /**
-     * Update fields that are not overridden for task from global configuration.
-     *
-     * @param globalConfig global configuration to update from.
-     */
-    void sanitizeOverrideConfiguration(Configuration globalConfig) {
-        // If it's fullscreen, the override config should be empty and we should leave it alone.
-        if (mFullscreen) {
-            return;
-        }
-
-        // screenLayout field is set in #calculateOverrideConfig but only part of it is really
-        // overridden - aspect ratio and size. Other flags (like layout direction) can be updated
-        // separately in global config and they also must be updated in override config.
-        int overrideScreenLayout = mOverrideConfig.screenLayout;
-        int newScreenLayout = globalConfig.screenLayout;
-        newScreenLayout = (newScreenLayout & ~SCREENLAYOUT_LONG_MASK)
-                | (overrideScreenLayout & SCREENLAYOUT_LONG_MASK);
-        newScreenLayout = (newScreenLayout & ~SCREENLAYOUT_SIZE_MASK)
-                | (overrideScreenLayout & SCREENLAYOUT_SIZE_MASK);
-        mOverrideConfig.screenLayout = newScreenLayout;
-    }
-
     static Rect validateBounds(Rect bounds) {
         if (bounds != null && bounds.isEmpty()) {
             Slog.wtf(TAG, "Received strange task bounds: " + bounds, new Throwable());
@@ -1626,7 +1657,7 @@
     /** Updates the task's bounds and override configuration to match what is expected for the
      * input stack. */
     void updateOverrideConfigurationForStack(ActivityStack inStack) {
-        if (stack != null && stack == inStack) {
+        if (mStack != null && mStack == inStack) {
             return;
         }
 
@@ -1670,17 +1701,17 @@
             return null;
         }
 
-        if (stack == null) {
+        if (mStack == null) {
             return null;
         }
 
-        final int stackId = stack.mStackId;
+        final int stackId = mStack.mStackId;
         if (stackId == HOME_STACK_ID
                 || stackId == FULLSCREEN_WORKSPACE_STACK_ID
                 || (stackId == DOCKED_STACK_ID && !isResizeable())) {
-            return isResizeable() ? stack.mBounds : null;
+            return isResizeable() ? mStack.mBounds : null;
         } else if (!StackId.persistTaskBounds(stackId)) {
-            return stack.mBounds;
+            return mStack.mBounds;
         }
         return mLastNonFullscreenBounds;
     }
@@ -1688,7 +1719,7 @@
     boolean canMatchRootAffinity() {
         // We don't allow root affinity matching on the pinned stack as no other task should
         // be launching in it based on affinity.
-        return rootAffinity != null && (stack == null || stack.mStackId != PINNED_STACK_ID);
+        return rootAffinity != null && getStackId() != PINNED_STACK_ID;
     }
 
     void dump(PrintWriter pw, String prefix) {
@@ -1779,9 +1810,7 @@
         if (lastDescription != null) {
             pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
         }
-        if (stack != null) {
-            pw.print(prefix); pw.print("stackId="); pw.println(stack.mStackId);
-        }
+        pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
         pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
                 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
                 pw.print(" isResizeable=" + isResizeable());
@@ -1798,7 +1827,7 @@
             sb.append(" U=");
             sb.append(userId);
             sb.append(" StackId=");
-            sb.append(stack != null ? stack.mStackId : INVALID_STACK_ID);
+            sb.append(getStackId());
             sb.append(" sz=");
             sb.append(mActivities.size());
             sb.append('}');
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index e7198d3..363d7cb 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -134,7 +134,9 @@
 
     @Override
     // Called concurrently by multiple binder threads.
-    public synchronized void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs) {
+    // This method must not block or perform long-running operations.
+    public synchronized void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs,
+            String hostname, String[] ipAddresses, int ipAddressesCount, int uid) {
         maybeVerboseLog(String.format("onDnsEvent(%d, %d, %d, %d)",
                 netId, eventType, returnCode, latencyMs));
 
@@ -146,6 +148,14 @@
         batch.addResult((byte) eventType, (byte) returnCode, latencyMs);
     }
 
+    @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,
+            int uid) {
+        maybeVerboseLog(String.format("onConnectEvent(%d, %d)", netId, latencyMs));
+    }
+
     public synchronized void dump(PrintWriter writer) {
         IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
         pw.println(TAG + ":");
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 50faf3b..921fd23 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -405,11 +405,13 @@
         // Check carrier config for entitlement checks
         final CarrierConfigManager configManager = (CarrierConfigManager) mContext
              .getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        boolean isEntitlementCheckRequired = configManager.getConfig().getBoolean(
-             CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
-
-        if (!isEntitlementCheckRequired) {
-            return false;
+        if (configManager != null && configManager.getConfig() != null) {
+            // we do have a CarrierConfigManager and it has a config.
+            boolean isEntitlementCheckRequired = configManager.getConfig().getBoolean(
+                    CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
+            if (!isEntitlementCheckRequired) {
+                return false;
+            }
         }
         return (provisionApp.length == 2);
     }
@@ -895,7 +897,7 @@
                     }
                 } else {
                     mUsbTetherRequested = true;
-                    usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS);
+                    usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
                 }
             } else {
                 final long ident = Binder.clearCallingIdentity();
@@ -905,7 +907,7 @@
                     Binder.restoreCallingIdentity(ident);
                 }
                 if (mRndisEnabled) {
-                    usbManager.setCurrentFunction(null);
+                    usbManager.setCurrentFunction(null, false);
                 }
                 mUsbTetherRequested = false;
             }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index ede3bda..afc6247 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -27,6 +27,8 @@
 import android.annotation.UserIdInt;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -76,6 +78,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.net.LegacyVpnInfo;
@@ -241,12 +244,14 @@
     /**
      * Update current state, dispaching event to listeners.
      */
-    private void updateState(DetailedState detailedState, String reason) {
+    @VisibleForTesting
+    protected void updateState(DetailedState detailedState, String reason) {
         if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason);
         mNetworkInfo.setDetailedState(detailedState, reason, null);
         if (mNetworkAgent != null) {
             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
         }
+        updateAlwaysOnNotification(detailedState);
     }
 
     /**
@@ -280,7 +285,10 @@
         }
 
         mLockdown = (mAlwaysOn && lockdown);
-        if (!isCurrentPreparedPackage(packageName)) {
+        if (isCurrentPreparedPackage(packageName)) {
+            updateAlwaysOnNotification(mNetworkInfo.getDetailedState());
+        } else {
+            // Prepare this app. The notification will update as a side-effect of updateState().
             prepareInternal(packageName);
         }
         maybeRegisterPackageChangeReceiverLocked(packageName);
@@ -682,22 +690,19 @@
         }
     }
 
-    private void agentDisconnect(NetworkInfo networkInfo, NetworkAgent networkAgent) {
-        networkInfo.setIsAvailable(false);
-        networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
+    private void agentDisconnect(NetworkAgent networkAgent) {
         if (networkAgent != null) {
+            NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo);
+            networkInfo.setIsAvailable(false);
+            networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
             networkAgent.sendNetworkInfo(networkInfo);
         }
     }
 
-    private void agentDisconnect(NetworkAgent networkAgent) {
-        NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo);
-        agentDisconnect(networkInfo, networkAgent);
-    }
-
     private void agentDisconnect() {
         if (mNetworkInfo.isConnected()) {
-            agentDisconnect(mNetworkInfo, mNetworkAgent);
+            mNetworkInfo.setIsAvailable(false);
+            updateState(DetailedState.DISCONNECTED, "agentDisconnect");
             mNetworkAgent = null;
         }
     }
@@ -1250,6 +1255,43 @@
         }
     }
 
+    private void updateAlwaysOnNotification(DetailedState networkState) {
+        final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
+        updateAlwaysOnNotificationInternal(visible);
+    }
+
+    @VisibleForTesting
+    protected void updateAlwaysOnNotificationInternal(boolean visible) {
+        final UserHandle user = UserHandle.of(mUserHandle);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            final NotificationManager notificationManager = NotificationManager.from(mContext);
+            if (!visible) {
+                notificationManager.cancelAsUser(TAG, 0, user);
+                return;
+            }
+            final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
+            final PendingIntent configIntent = PendingIntent.getActivityAsUser(
+                    mContext, /* request */ 0, intent,
+                    PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT,
+                    null, user);
+            final Notification.Builder builder = new Notification.Builder(mContext)
+                    .setDefaults(0)
+                    .setSmallIcon(R.drawable.vpn_connected)
+                    .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected))
+                    .setContentText(mContext.getString(R.string.vpn_lockdown_config))
+                    .setContentIntent(configIntent)
+                    .setCategory(Notification.CATEGORY_SYSTEM)
+                    .setPriority(Notification.PRIORITY_LOW)
+                    .setVisibility(Notification.VISIBILITY_PUBLIC)
+                    .setOngoing(true)
+                    .setColor(mContext.getColor(R.color.system_notification_accent_color));
+            notificationManager.notifyAsUser(TAG, 0, builder.build(), user);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     private native int jniCreate(int mtu);
     private native String jniGetName(int tun);
     private native int jniSetAddresses(String interfaze, String addresses);
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 2d6bef4..72feab7 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -795,7 +795,17 @@
      *           Use {@link AuthorityInfo#UNDEFINED} to sync all authorities.
      */
     public void scheduleSync(Account requestedAccount, int userId, int reason,
-            String requestedAuthority, Bundle extras, int targetSyncState) {
+                             String requestedAuthority, Bundle extras, int targetSyncState) {
+        scheduleSync(requestedAccount, userId, reason, requestedAuthority, extras, targetSyncState,
+                0 /* min delay */);
+    }
+
+    /**
+     * @param minDelayMillis The sync can't land before this delay expires.
+     */
+    private void scheduleSync(Account requestedAccount, int userId, int reason,
+                             String requestedAuthority, Bundle extras, int targetSyncState,
+                             final long minDelayMillis) {
         final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
         if (extras == null) {
             extras = new Bundle();
@@ -906,7 +916,7 @@
                                 if (result != null
                                         && result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) {
                                     scheduleSync(account.account, userId, reason, authority,
-                                            finalExtras, targetSyncState);
+                                            finalExtras, targetSyncState, minDelayMillis);
                                 }
                             }
                         ));
@@ -967,7 +977,8 @@
                     postScheduleSyncMessage(
                             new SyncOperation(account.account, account.userId,
                                     owningUid, owningPackage, reason, source,
-                                    authority, newExtras, allowParallelSyncs)
+                                    authority, newExtras, allowParallelSyncs),
+                            minDelayMillis
                     );
                 } else if (targetSyncState == AuthorityInfo.UNDEFINED
                         || targetSyncState == isSyncable) {
@@ -982,7 +993,8 @@
                     postScheduleSyncMessage(
                             new SyncOperation(account.account, account.userId,
                                     owningUid, owningPackage, reason, source,
-                                    authority, extras, allowParallelSyncs)
+                                    authority, extras, allowParallelSyncs),
+                            minDelayMillis
                     );
                 }
             }
@@ -1088,14 +1100,14 @@
     }
 
     /**
-     * Schedule sync based on local changes to a provider. Occurs within interval
-     * [LOCAL_SYNC_DELAY, 2*LOCAL_SYNC_DELAY].
+     * Schedule sync based on local changes to a provider. We wait for at least LOCAL_SYNC_DELAY
+     * ms to batch syncs.
      */
     public void scheduleLocalSync(Account account, int userId, int reason, String authority) {
         final Bundle extras = new Bundle();
         extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
         scheduleSync(account, userId, reason, authority, extras,
-                AuthorityInfo.UNDEFINED);
+                AuthorityInfo.UNDEFINED, LOCAL_SYNC_DELAY);
     }
 
     public SyncAdapterType[] getSyncAdapterTypes(int userId) {
@@ -1152,9 +1164,10 @@
         mSyncHandler.sendMessageDelayed(monitorMessage, SYNC_MONITOR_WINDOW_LENGTH_MILLIS);
     }
 
-    private void postScheduleSyncMessage(SyncOperation syncOperation) {
-        mSyncHandler.obtainMessage(mSyncHandler.MESSAGE_SCHEDULE_SYNC, syncOperation)
-                .sendToTarget();
+    private void postScheduleSyncMessage(SyncOperation syncOperation, long minDelayMillis) {
+        ScheduleSyncMessagePayload payload =
+                new ScheduleSyncMessagePayload(syncOperation, minDelayMillis);
+        mSyncHandler.obtainMessage(mSyncHandler.MESSAGE_SCHEDULE_SYNC, payload).sendToTarget();
     }
 
     /**
@@ -1194,6 +1207,16 @@
         }
     }
 
+    private static class ScheduleSyncMessagePayload {
+        final SyncOperation syncOperation;
+        final long minDelayMillis;
+
+        ScheduleSyncMessagePayload(SyncOperation syncOperation, long minDelayMillis) {
+            this.syncOperation = syncOperation;
+            this.minDelayMillis = minDelayMillis;
+        }
+    }
+
     private void clearBackoffSetting(EndPoint target) {
         Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(target);
         if (backoff != null && backoff.first == SyncStorageEngine.NOT_IN_BACKOFF_MODE &&
@@ -1262,7 +1285,7 @@
             if (!op.isPeriodic && op.target.matchesSpec(target)) {
                 count++;
                 getJobScheduler().cancel(op.jobId);
-                postScheduleSyncMessage(op);
+                postScheduleSyncMessage(op, 0 /* min delay */);
             }
         }
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -2417,8 +2440,10 @@
                 mDataConnectionIsConnected = readDataConnectionState();
                 switch (msg.what) {
                     case MESSAGE_SCHEDULE_SYNC:
-                        SyncOperation op = (SyncOperation) msg.obj;
-                        scheduleSyncOperationH(op);
+                        ScheduleSyncMessagePayload syncPayload =
+                                (ScheduleSyncMessagePayload) msg.obj;
+                        SyncOperation op = syncPayload.syncOperation;
+                        scheduleSyncOperationH(op, syncPayload.minDelayMillis);
                         break;
 
                     case MESSAGE_START_SYNC:
@@ -3101,7 +3126,8 @@
                         maybeRescheduleSync(syncResult, syncOperation);
                     } else {
                         // create a normal sync instance that will respect adapter backoffs
-                        postScheduleSyncMessage(syncOperation.createOneTimeSyncOperation());
+                        postScheduleSyncMessage(syncOperation.createOneTimeSyncOperation(),
+                                0 /* min delay */);
                     }
                     historyMessage = ContentResolver.syncErrorToString(
                             syncResultToErrorNumber(syncResult));
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 20bccf1..1991c00 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.BIND_DREAM_SERVICE;
 
+import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.util.DumpUtils;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
@@ -88,6 +89,8 @@
     private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
     private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
 
+    private AmbientDisplayConfiguration mDozeConfig;
+
     public DreamManagerService(Context context) {
         super(context);
         mContext = context;
@@ -97,6 +100,7 @@
         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mPowerManagerInternal = getLocalService(PowerManagerInternal.class);
         mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG);
+        mDozeConfig = new AmbientDisplayConfiguration(mContext);
     }
 
     @Override
@@ -121,7 +125,7 @@
                 }
             }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
             mContext.getContentResolver().registerContentObserver(
-                    Settings.Secure.getUriFor(Settings.Secure.DOZE_ENABLED), false,
+                    Settings.Secure.getUriFor(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP), false,
                     mDozeEnabledObserver, UserHandle.USER_ALL);
             writePulseGestureEnabled();
         }
@@ -326,19 +330,12 @@
     }
 
     private ComponentName getDozeComponent(int userId) {
-        // Read the component from a system property to facilitate debugging.
-        // Note that for production devices, the dream should actually be declared in
-        // a config.xml resource.
-        String name = Build.IS_DEBUGGABLE ? SystemProperties.get("debug.doze.component") : null;
-        if (TextUtils.isEmpty(name)) {
-            // Read the component from a config.xml resource.
-            // The value should be specified in a resource overlay for the product.
-            name = mContext.getResources().getString(
-                    com.android.internal.R.string.config_dozeComponent);
+        if (mDozeConfig.enabled(userId)) {
+            return ComponentName.unflattenFromString(mDozeConfig.ambientDisplayComponent());
+        } else {
+            return null;
         }
-        boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.DOZE_ENABLED, 1, userId) != 0;
-        return TextUtils.isEmpty(name) || !enabled ? null : ComponentName.unflattenFromString(name);
+
     }
 
     private ServiceInfo getServiceInfo(ComponentName name) {
diff --git a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
index cca9f10..353f450 100644
--- a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
+++ b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
@@ -99,6 +99,7 @@
     };
     private boolean mSimNeedsEmergencyAffordance;
     private boolean mNetworkNeedsEmergencyAffordance;
+    private boolean mVoiceCapable;
 
     private void requestCellScan() {
         mHandler.obtainMessage(CELL_INFO_STATE_CHANGED).sendToTarget();
@@ -125,8 +126,8 @@
 
     private void updateEmergencyAffordanceNeeded() {
         synchronized (mLock) {
-            mEmergencyAffordanceNeeded = mSimNeedsEmergencyAffordance ||
-                    mNetworkNeedsEmergencyAffordance;
+            mEmergencyAffordanceNeeded = mVoiceCapable && (mSimNeedsEmergencyAffordance ||
+                    mNetworkNeedsEmergencyAffordance);
             Settings.Global.putInt(mContext.getContentResolver(),
                     Settings.Global.EMERGENCY_AFFORDANCE_NEEDED,
                     mEmergencyAffordanceNeeded ? 1 : 0);
@@ -157,6 +158,11 @@
     public void onBootPhase(int phase) {
         if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
             mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+            mVoiceCapable = mTelephonyManager.isVoiceCapable();
+            if (!mVoiceCapable) {
+                updateEmergencyAffordanceNeeded();
+                return;
+            }
             mSubscriptionManager = SubscriptionManager.from(mContext);
             HandlerThread thread = new HandlerThread(TAG);
             thread.start();
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index 87da866..5297589 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -115,6 +115,7 @@
             final int result = daemon.authenticate(mOpId, getGroupId());
             if (result != 0) {
                 Slog.w(TAG, "startAuthentication failed, result=" + result);
+                MetricsLogger.histogram(getContext(), "fingeprintd_auth_start_error", result);
                 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
                 return result;
             }
diff --git a/services/core/java/com/android/server/fingerprint/EnrollClient.java b/services/core/java/com/android/server/fingerprint/EnrollClient.java
index 6a533c9..640a46f 100644
--- a/services/core/java/com/android/server/fingerprint/EnrollClient.java
+++ b/services/core/java/com/android/server/fingerprint/EnrollClient.java
@@ -88,6 +88,7 @@
             final int result = daemon.enroll(mCryptoToken, getGroupId(), timeout);
             if (result != 0) {
                 Slog.w(TAG, "startEnroll failed, result=" + result);
+                MetricsLogger.histogram(getContext(), "fingerprintd_enroll_start_error", result);
                 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
                 return result;
             }
diff --git a/services/core/java/com/android/server/fingerprint/EnumerateClient.java b/services/core/java/com/android/server/fingerprint/EnumerateClient.java
index 52dbd5d..26b1916 100644
--- a/services/core/java/com/android/server/fingerprint/EnumerateClient.java
+++ b/services/core/java/com/android/server/fingerprint/EnumerateClient.java
@@ -23,6 +23,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
+import com.android.internal.logging.MetricsLogger;
 
 /**
  * A class to keep track of the enumeration state for a given client.
@@ -43,6 +44,7 @@
             if (result != 0) {
                 Slog.w(TAG, "start enumerate for user " + getTargetUserId()
                     + " failed, result=" + result);
+                MetricsLogger.histogram(getContext(), "fingerprintd_enum_start_error", result);
                 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
                 return result;
             }
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 9523a1c..cda063d 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -194,6 +194,7 @@
     @Override
     public void binderDied() {
         Slog.v(TAG, "fingerprintd died");
+        MetricsLogger.count(mContext, "fingerprintd_died", 1);
         mDaemon = null;
         mCurrentUserId = UserHandle.USER_CURRENT;
         handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
@@ -211,6 +212,7 @@
                         updateActiveGroup(ActivityManager.getCurrentUser(), null);
                     } else {
                         Slog.w(TAG, "Failed to open Fingerprint HAL!");
+                        MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
                         mDaemon = null;
                     }
                 } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/fingerprint/RemovalClient.java b/services/core/java/com/android/server/fingerprint/RemovalClient.java
index bcf2264..f939f41 100644
--- a/services/core/java/com/android/server/fingerprint/RemovalClient.java
+++ b/services/core/java/com/android/server/fingerprint/RemovalClient.java
@@ -24,6 +24,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Slog;
+import com.android.internal.logging.MetricsLogger;
 
 /**
  * A class to keep track of the remove state for a given client.
@@ -46,6 +47,7 @@
             final int result = daemon.remove(mFingerId, getGroupId());
             if (result != 0) {
                 Slog.w(TAG, "startRemove with id = " + mFingerId + " failed, result=" + result);
+                MetricsLogger.histogram(getContext(), "fingerprintd_remove_start_error", result);
                 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
                 return result;
             }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 5dc9d02..72ee218 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -2011,6 +2011,9 @@
     @ServiceThreadOnly
     void standby() {
         assertRunOnServiceThread();
+        if (!canGoToStandby()) {
+            return;
+        }
         mStandbyMessageReceived = true;
         mPowerManager.goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_HDMI, 0);
         // PowerManger will send the broadcast Intent.ACTION_SCREEN_OFF and after this gets
@@ -2038,10 +2041,13 @@
     @ServiceThreadOnly
     private void onStandby(final int standbyAction) {
         assertRunOnServiceThread();
-        if (!canGoToStandby()) return;
         mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
         invokeVendorCommandListenersOnControlStateChanged(false,
                 HdmiControlManager.CONTROL_STATE_CHANGED_REASON_STANDBY);
+        if (!canGoToStandby()) {
+            mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
+            return;
+        }
 
         final List<HdmiCecLocalDevice> devices = getAllLocalDevices();
         disableDevices(new PendingActionClearedCallback() {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index fe3a02d..970da99 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -216,7 +216,7 @@
         private static final int DEFAULT_FG_JOB_COUNT = 4;
         private static final int DEFAULT_BG_NORMAL_JOB_COUNT = 6;
         private static final int DEFAULT_BG_MODERATE_JOB_COUNT = 4;
-        private static final int DEFAULT_BG_LOW_JOB_COUNT = 2;
+        private static final int DEFAULT_BG_LOW_JOB_COUNT = 1;
         private static final int DEFAULT_BG_CRITICAL_JOB_COUNT = 1;
 
         /**
@@ -428,7 +428,18 @@
                                         }
                                         cancelJobsForUid(pkgUid, true);
                                     }
-                                } catch (RemoteException e) { /* cannot happen */ }
+                                } catch (RemoteException|IllegalArgumentException e) {
+                                    /*
+                                     * IllegalArgumentException means that the package doesn't exist.
+                                     * This arises when PACKAGE_CHANGED broadcast delivery has lagged
+                                     * behind outright uninstall, so by the time we try to act it's gone.
+                                     * We don't need to act on this PACKAGE_CHANGED when this happens;
+                                     * we'll get a PACKAGE_REMOVED later and clean up then.
+                                     *
+                                     * RemoteException can't actually happen; the package manager is
+                                     * running in this same process.
+                                     */
+                                }
                                 break;
                             }
                         }
@@ -906,7 +917,11 @@
     private boolean isCurrentlyActiveLocked(JobStatus job) {
         for (int i=0; i<mActiveServices.size(); i++) {
             JobServiceContext serviceContext = mActiveServices.get(i);
-            final JobStatus running = serviceContext.getRunningJob();
+            // The 'unsafe' direct-internal-reference running-job inspector is okay to
+            // use here because we are already holding the necessary lock *and* we
+            // immediately discard the returned object reference, if any; we return
+            // only a boolean state indicator to the caller.
+            final JobStatus running = serviceContext.getRunningJobUnsafeLocked();
             if (running != null && running.matches(job.getUid(), job.getJobId())) {
                 return true;
             }
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 27f397d..b089ba7 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -231,6 +231,15 @@
         return job == null ? null : new JobStatus(job);
     }
 
+    /**
+     * Internal non-cloning inspection of the currently running job, if any.  The lock
+     * must be held when calling this *and* for the entire lifetime of using its returned
+     * JobStatus object!
+     */
+    JobStatus getRunningJobUnsafeLocked() {
+        return mRunningJob;
+    }
+
     /** Called externally when a job that was scheduled for execution should be cancelled. */
     void cancelExecutingJob(int reason) {
         mCallbackHandler.obtainMessage(MSG_CANCEL, reason, 0 /* unused */).sendToTarget();
diff --git a/services/core/java/com/android/server/lights/Light.java b/services/core/java/com/android/server/lights/Light.java
index b18a181..0bab86b 100644
--- a/services/core/java/com/android/server/lights/Light.java
+++ b/services/core/java/com/android/server/lights/Light.java
@@ -16,25 +16,28 @@
 
 package com.android.server.lights;
 
+import android.hardware.light.V2_0.Flash;
+import android.hardware.light.V2_0.Brightness;
+
 public abstract class Light {
-    public static final int LIGHT_FLASH_NONE = 0;
-    public static final int LIGHT_FLASH_TIMED = 1;
-    public static final int LIGHT_FLASH_HARDWARE = 2;
+    public static final int LIGHT_FLASH_NONE = Flash.NONE;
+    public static final int LIGHT_FLASH_TIMED = Flash.TIMED;
+    public static final int LIGHT_FLASH_HARDWARE = Flash.HARDWARE;
 
     /**
      * Light brightness is managed by a user setting.
      */
-    public static final int BRIGHTNESS_MODE_USER = 0;
+    public static final int BRIGHTNESS_MODE_USER = Brightness.USER;
 
     /**
      * Light brightness is managed by a light sensor.
      */
-    public static final int BRIGHTNESS_MODE_SENSOR = 1;
+    public static final int BRIGHTNESS_MODE_SENSOR = Brightness.SENSOR;
 
     /**
      * Low-persistence light mode.
      */
-    public static final int BRIGHTNESS_MODE_LOW_PERSISTENCE = 2;
+    public static final int BRIGHTNESS_MODE_LOW_PERSISTENCE = Brightness.LOW_PERSISTENCE;
 
     public abstract void setBrightness(int brightness);
     public abstract void setBrightness(int brightness, int brightnessMode);
diff --git a/services/core/java/com/android/server/lights/LightsManager.java b/services/core/java/com/android/server/lights/LightsManager.java
index 2f20509..be20a44 100644
--- a/services/core/java/com/android/server/lights/LightsManager.java
+++ b/services/core/java/com/android/server/lights/LightsManager.java
@@ -16,16 +16,18 @@
 
 package com.android.server.lights;
 
+import android.hardware.light.V2_0.Type;
+
 public abstract class LightsManager {
-    public static final int LIGHT_ID_BACKLIGHT = 0;
-    public static final int LIGHT_ID_KEYBOARD = 1;
-    public static final int LIGHT_ID_BUTTONS = 2;
-    public static final int LIGHT_ID_BATTERY = 3;
-    public static final int LIGHT_ID_NOTIFICATIONS = 4;
-    public static final int LIGHT_ID_ATTENTION = 5;
-    public static final int LIGHT_ID_BLUETOOTH = 6;
-    public static final int LIGHT_ID_WIFI = 7;
-    public static final int LIGHT_ID_COUNT = 8;
+    public static final int LIGHT_ID_BACKLIGHT = Type.BACKLIGHT;
+    public static final int LIGHT_ID_KEYBOARD = Type.KEYBOARD;
+    public static final int LIGHT_ID_BUTTONS = Type.BUTTONS;
+    public static final int LIGHT_ID_BATTERY = Type.BATTERY;
+    public static final int LIGHT_ID_NOTIFICATIONS = Type.NOTIFICATIONS;
+    public static final int LIGHT_ID_ATTENTION = Type.ATTENTION;
+    public static final int LIGHT_ID_BLUETOOTH = Type.BLUETOOTH;
+    public static final int LIGHT_ID_WIFI = Type.WIFI;
+    public static final int LIGHT_ID_COUNT = Type.COUNT;
 
     public abstract Light getLight(int id);
 }
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index ca64817..bba0a50 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -133,7 +133,7 @@
                 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
                         + Integer.toHexString(color) + ")");
                 try {
-                    setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
+                    setLight_native(mId, color, mode, onMS, offMS, brightnessMode);
                 } finally {
                     Trace.traceEnd(Trace.TRACE_TAG_POWER);
                 }
@@ -155,8 +155,6 @@
     public LightsService(Context context) {
         super(context);
 
-        mNativePointer = init_native();
-
         for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) {
             mLights[i] = new LightImpl(i);
         }
@@ -217,7 +215,7 @@
     private final LightsManager mService = new LightsManager() {
         @Override
         public Light getLight(int id) {
-            if (id < LIGHT_ID_COUNT) {
+            if (0 <= id && id < LIGHT_ID_COUNT) {
                 return mLights[id];
             } else {
                 return null;
@@ -225,12 +223,6 @@
         }
     };
 
-    @Override
-    protected void finalize() throws Throwable {
-        finalize_native(mNativePointer);
-        super.finalize();
-    }
-
     private Handler mH = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -239,11 +231,6 @@
         }
     };
 
-    private static native long init_native();
-    private static native void finalize_native(long ptr);
-
-    static native void setLight_native(long ptr, int light, int color, int mode,
+    static native void setLight_native(int light, int color, int mode,
             int onMS, int offMS, int brightnessMode);
-
-    private long mNativePointer;
 }
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 7580cf4..ae98077 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -452,8 +452,12 @@
             new ConnectivityManager.NetworkCallback() {
         @Override
         public void onAvailable(Network network) {
-            requestUtcTime();
-            xtraDownloadRequest();
+            if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
+                requestUtcTime();
+            }
+            if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
+                xtraDownloadRequest();
+            }
         }
     };
 
@@ -1002,6 +1006,11 @@
     }
 
     private void handleDownloadXtraData() {
+        if (!mSupportsXtra) {
+            // native code reports xtra not supported, don't try
+            Log.d(TAG, "handleDownloadXtraData() called when Xtra not supported");
+            return;
+        }
         if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
             // already downloading data
             return;
@@ -2125,9 +2134,7 @@
                     handleInjectNtpTime();
                     break;
                 case DOWNLOAD_XTRA_DATA:
-                    if (mSupportsXtra) {
-                        handleDownloadXtraData();
-                    }
+                    handleDownloadXtraData();
                     break;
                 case INJECT_NTP_TIME_FINISHED:
                     mInjectNtpTimePending = STATE_IDLE;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 547cc51..2bccfee 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2046,25 +2046,30 @@
 
     @Override
     public void setRestrictBackground(boolean restrictBackground) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
-        final long token = Binder.clearCallingIdentity();
+        Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setRestrictBackground");
         try {
-            maybeRefreshTrustedTime();
-            synchronized (mUidRulesFirstLock) {
-                if (restrictBackground == mRestrictBackground) {
-                    // Ideally, UI should never allow this scenario...
-                    Slog.w(TAG, "setRestrictBackground: already " + restrictBackground);
-                    return;
+            mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                maybeRefreshTrustedTime();
+                synchronized (mUidRulesFirstLock) {
+                    if (restrictBackground == mRestrictBackground) {
+                        // Ideally, UI should never allow this scenario...
+                        Slog.w(TAG, "setRestrictBackground: already " + restrictBackground);
+                        return;
+                    }
+                    setRestrictBackgroundUL(restrictBackground);
                 }
-                setRestrictBackgroundUL(restrictBackground);
+
+            } finally {
+                Binder.restoreCallingIdentity(token);
             }
 
+            mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, restrictBackground ? 1 : 0, 0)
+                    .sendToTarget();
         } finally {
-            Binder.restoreCallingIdentity(token);
+            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
         }
-
-        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, restrictBackground ? 1 : 0, 0)
-                .sendToTarget();
     }
 
     private void setRestrictBackgroundUL(boolean restrictBackground) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0c7c8aa..61bf3bd 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -30,6 +30,7 @@
 import static android.service.notification.NotificationRankerService.REASON_PACKAGE_CHANGED;
 import static android.service.notification.NotificationRankerService.REASON_PACKAGE_SUSPENDED;
 import static android.service.notification.NotificationRankerService.REASON_PROFILE_TURNED_OFF;
+import static android.service.notification.NotificationRankerService.REASON_SNOOZED;
 import static android.service.notification.NotificationRankerService.REASON_UNAUTOBUNDLED;
 import static android.service.notification.NotificationRankerService.REASON_USER_STOPPED;
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
@@ -309,6 +310,8 @@
     private float mMaxPackageEnqueueRate = DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE;
     private String mSystemNotificationSound;
 
+    private SnoozeHelper mSnoozeHelper;
+
     private static class Archive {
         final int mBufferSize;
         final ArrayDeque<StatusBarNotification> mBuffer;
@@ -999,6 +1002,22 @@
                 sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
             }
         });
+        mSnoozeHelper = new SnoozeHelper(getContext(), new SnoozeHelper.Callback() {
+            @Override
+            public void repost(int userId, NotificationRecord r) {
+                try {
+                    if (DBG) {
+                        Slog.d(TAG, "Reposting " + r.getKey());
+                    }
+                    enqueueNotificationInternal(r.sbn.getPackageName(), r.sbn.getOpPkg(),
+                            r.sbn.getUid(), r.sbn.getInitialPid(), r.sbn.getTag(), r.sbn.getId(),
+                            r.sbn.getNotification(), new int[1], userId);
+                } catch (Exception e) {
+                    Slog.e(TAG, "Cannot un-snooze notification", e);
+                }
+            }
+        }, mUserProfiles);
+
         final File systemDir = new File(Environment.getDataDirectory(), "system");
         mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml"));
 
@@ -1810,6 +1829,13 @@
             }
         }
 
+        /**
+         * Allow an INotificationListener to simulate clearing (dismissing) a single notification.
+         *
+         * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onNotificationClear}
+         *
+         * @param token The binder for the listener, to check that the caller is allowed
+         */
         private void cancelNotificationFromListenerLocked(ManagedServiceInfo info,
                 int callingUid, int callingPid, String pkg, String tag, int id, int userId) {
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
@@ -1819,6 +1845,23 @@
         }
 
         /**
+         * Allow an INotificationListener to snooze a single notification.
+         *
+         * @param token The binder for the listener, to check that the caller is allowed
+         */
+        @Override
+        public void snoozeNotificationFromListener(INotificationListener token, String key,
+                long snoozeUntil) {
+            long identity = Binder.clearCallingIdentity();
+            try {
+                final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+                snoozeNotificationInt(key, snoozeUntil, info);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        /**
          * Allow an INotificationListener to simulate clearing (dismissing) a single notification.
          *
          * {@see com.android.server.StatusBarManagerService.NotificationCallbacks#onNotificationClear}
@@ -2592,6 +2635,11 @@
                 pw.println("\n  Notification ranker services:");
                 mRankerServices.dump(pw, filter);
             }
+
+            if (!zenOnly) {
+                mSnoozeHelper.dump(pw, filter);
+            }
+
             pw.println("\n  Policy access:");
             pw.print("    mPolicyAccess: "); pw.println(mPolicyAccess);
 
@@ -2765,6 +2813,16 @@
         public void run() {
 
             synchronized (mNotificationList) {
+                if (mSnoozeHelper.isSnoozed(userId, r.sbn.getPackageName(), r.getKey())) {
+                    // TODO: log to event log
+                    if (DBG) {
+                        Slog.d(TAG, "Ignored enqueue for snoozed notification " + r.getKey());
+                    }
+                    mSnoozeHelper.update(userId, r);
+                    savePolicyFile();
+                    return;
+                }
+
                 final StatusBarNotification n = r.sbn;
                 if (DBG) Slog.d(TAG, "EnqueueNotificationRunnable.run for: " + n.getKey());
                 NotificationRecord old = mNotificationsByKey.get(n.getKey());
@@ -3578,6 +3636,11 @@
                         cancelGroupChildrenLocked(r, callingUid, callingPid, listenerName,
                                 REASON_GROUP_SUMMARY_CANCELED, sendDelete);
                         updateLightsLocked();
+                    } else {
+                        final boolean wasSnoozed = mSnoozeHelper.cancel(userId, pkg, tag, id);
+                        if (wasSnoozed) {
+                            savePolicyFile();
+                        }
                     }
                 }
             }
@@ -3641,7 +3704,7 @@
                 if (pkg != null && !r.sbn.getPackageName().equals(pkg)) {
                     continue;
                 }
-                if (channelId == null || !channelId.equals(r.getChannel().getId())) {
+                if (channelId != null && !channelId.equals(r.getChannel().getId())) {
                     continue;
                 }
                 if (canceledNotifications == null) {
@@ -3654,6 +3717,7 @@
                 mNotificationList.remove(i);
                 cancelNotificationLocked(r, false, reason);
             }
+            mSnoozeHelper.cancel(userId, pkg);
             if (doit && canceledNotifications != null) {
                 final int M = canceledNotifications.size();
                 for (int i = 0; i < M; i++) {
@@ -3668,6 +3732,28 @@
         }
     }
 
+    void snoozeNotificationInt(String key, long until, ManagedServiceInfo listener) {
+        String listenerName = listener == null ? null : listener.component.toShortString();
+        // TODO: write to event log
+        if (DBG) {
+            Slog.d(TAG, String.format("snooze event(%s, %d, %s)", key, until,
+                    listenerName));
+        }
+        if (until < System.currentTimeMillis()) {
+            return;
+        }
+        synchronized (mNotificationList) {
+            final NotificationRecord r = mNotificationsByKey.get(key);
+            if (r != null) {
+                mNotificationList.remove(r);
+                cancelNotificationLocked(r, false, REASON_SNOOZED);
+                updateLightsLocked();
+                mSnoozeHelper.snooze(r, r.getUser().getIdentifier(), until);
+                savePolicyFile();
+            }
+        }
+    }
+
     void cancelAllLocked(int callingUid, int callingPid, int userId, int reason,
             ManagedServiceInfo listener, boolean includeCurrentProfiles) {
         String listenerName = listener == null ? null : listener.component.toShortString();
@@ -3699,6 +3785,7 @@
                 canceledNotifications.add(r);
             }
         }
+        mSnoozeHelper.cancel(userId, includeCurrentProfiles);
         int M = canceledNotifications != null ? canceledNotifications.size() : 0;
         for (int i = 0; i < M; i++) {
             cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid,
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 7182da1..d59115e 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -162,6 +162,7 @@
                             r = mRestoredWithoutUids.get(name);
                             if (r == null) {
                                 r = new Record();
+                                r.pkg = name;
                                 mRestoredWithoutUids.put(name, r);
                             }
                         } else {
@@ -606,7 +607,7 @@
     }
 
     public void onPackagesChanged(boolean removingPackage, String[] pkgList) {
-        if (!removingPackage || pkgList == null || pkgList.length == 0
+        if (removingPackage || pkgList == null || pkgList.length == 0
                 || mRestoredWithoutUids.isEmpty()) {
             return; // nothing to do
         }
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
new file mode 100644
index 0000000..738403e
--- /dev/null
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -0,0 +1,281 @@
+/*
+ * 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.notification;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Slog;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Date;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * NotificationManagerService helper for handling snoozed notifications.
+ */
+public class SnoozeHelper {
+    private static final String TAG = "SnoozeHelper";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final String INDENT = "    ";
+
+    private static final String REPOST_ACTION = SnoozeHelper.class.getSimpleName() + ".EVALUATE";
+    private static final int REQUEST_CODE_REPOST = 1;
+    private static final String REPOST_SCHEME = "repost";
+    private static final String EXTRA_PKG = "pkg";
+    private static final String EXTRA_KEY = "key";
+    private static final String EXTRA_USER_ID = "userId";
+
+    private final Context mContext;
+    private AlarmManager mAm;
+    private final ManagedServices.UserProfiles mUserProfiles;
+
+    // User id : package name : notification key : record.
+    private ArrayMap<Integer, ArrayMap<String, ArrayMap<String, NotificationRecord>>>
+            mSnoozedNotifications = new ArrayMap<>();
+    private Callback mCallback;
+
+    public SnoozeHelper(Context context, Callback callback,
+            ManagedServices.UserProfiles userProfiles) {
+        mContext = context;
+        IntentFilter filter = new IntentFilter(REPOST_ACTION);
+        filter.addDataScheme(REPOST_SCHEME);
+        mContext.registerReceiver(mBroadcastReceiver, filter);
+        mAm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+        mCallback = callback;
+        mUserProfiles = userProfiles;
+    }
+
+    protected boolean isSnoozed(int userId, String pkg, String key) {
+        return mSnoozedNotifications.containsKey(userId)
+                && mSnoozedNotifications.get(userId).containsKey(pkg)
+                && mSnoozedNotifications.get(userId).get(pkg).containsKey(key);
+    }
+
+    /**
+     * Records a notification that should be snoozed until the given time and schedules an alarm
+     * to repost at that time.
+     */
+    protected void snooze(NotificationRecord record, int userId, long until) {
+        ArrayMap<String, ArrayMap<String, NotificationRecord>> records =
+                mSnoozedNotifications.get(userId);
+        if (records == null) {
+            records = new ArrayMap<>();
+        }
+        ArrayMap<String, NotificationRecord> pkgRecords = records.get(record.sbn.getPackageName());
+        if (pkgRecords == null) {
+            pkgRecords = new ArrayMap<>();
+        }
+        pkgRecords.put(record.getKey(), record);
+        records.put(record.sbn.getPackageName(), pkgRecords);
+        mSnoozedNotifications.put(userId, records);
+        if (DEBUG) {
+            Slog.d(TAG, "Snoozing " + record.getKey() + " until " + new Date(until));
+        }
+        scheduleRepost(record.sbn.getPackageName(), record.getKey(), userId, until);
+    }
+
+
+    protected boolean cancel(int userId, String pkg, String tag, int id) {
+        if (mSnoozedNotifications.containsKey(userId)) {
+            ArrayMap<String, NotificationRecord> recordsForPkg =
+                    mSnoozedNotifications.get(userId).get(pkg);
+            if (recordsForPkg != null) {
+                final Set<Map.Entry<String, NotificationRecord>> records = recordsForPkg.entrySet();
+                String key = null;
+                for (Map.Entry<String, NotificationRecord> record : records) {
+                    final StatusBarNotification sbn = record.getValue().sbn;
+                    if (Objects.equals(sbn.getTag(), tag) && sbn.getId() == id) {
+                        key = record.getKey();
+                    }
+                }
+                if (key != null) {
+                    recordsForPkg.remove(key);
+                    cancelAlarm(userId, pkg, key);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    protected boolean cancel(int userId, boolean includeCurrentProfiles) {
+        int[] userIds = {userId};
+        if (includeCurrentProfiles) {
+            userIds = mUserProfiles.getCurrentProfileIds();
+        }
+        final int N = userIds.length;
+        for (int i = 0; i < N; i++) {
+            final ArrayMap<String, ArrayMap<String, NotificationRecord>> snoozedPkgs =
+                    mSnoozedNotifications.remove(userIds[i]);
+            if (snoozedPkgs != null) {
+                final int M = snoozedPkgs.size();
+                for (int j = 0; j < M; j++) {
+                    final ArrayMap<String, NotificationRecord> records = snoozedPkgs.valueAt(j);
+                    if (records != null) {
+                        int P = records.size();
+                        for (int k = 0; k < P; k++) {
+                            cancelAlarm(userId, snoozedPkgs.keyAt(j), records.keyAt(k));
+                        }
+                    }
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected boolean cancel(int userId, String pkg) {
+        if (mSnoozedNotifications.containsKey(userId)) {
+            if (mSnoozedNotifications.get(userId).containsKey(pkg)) {
+                ArrayMap<String, NotificationRecord> records =
+                        mSnoozedNotifications.get(userId).remove(pkg);
+                int N = records.size();
+                for (int i = 0; i < N; i++) {
+                    cancelAlarm(userId, pkg, records.keyAt(i));
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void cancelAlarm(int userId, String pkg, String key) {
+        final PendingIntent pi = createPendingIntent(pkg, key, userId);
+        mAm.cancel(pi);
+    }
+
+    /**
+     * Updates the notification record so the most up to date information is shown on re-post.
+     */
+    protected void update(int userId, NotificationRecord record) {
+        ArrayMap<String, ArrayMap<String, NotificationRecord>> records =
+                mSnoozedNotifications.get(userId);
+        if (records == null) {
+            return;
+        }
+        ArrayMap<String, NotificationRecord> pkgRecords = records.get(record.sbn.getPackageName());
+        if (pkgRecords == null) {
+            return;
+        }
+        pkgRecords.put(record.getKey(), record);
+    }
+
+    @VisibleForTesting
+    void repost(String pkg, String key, int userId) {
+        ArrayMap<String, ArrayMap<String, NotificationRecord>> records =
+                mSnoozedNotifications.get(userId);
+        if (records == null) {
+            return;
+        }
+        ArrayMap<String, NotificationRecord> pkgRecords = records.get(pkg);
+        if (pkgRecords == null) {
+            return;
+        }
+        final NotificationRecord record = pkgRecords.remove(key);
+        if (record != null) {
+            mCallback.repost(userId, record);
+        }
+    }
+
+    private PendingIntent createPendingIntent(String pkg, String key, int userId) {
+        return PendingIntent.getBroadcast(mContext,
+                REQUEST_CODE_REPOST,
+                new Intent(REPOST_ACTION)
+                        .setData(new Uri.Builder().scheme(REPOST_SCHEME).appendPath(key).build())
+                        .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+                        .putExtra(EXTRA_PKG, pkg)
+                        .putExtra(EXTRA_KEY, key)
+                        .putExtra(EXTRA_USER_ID, userId),
+                PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+
+    private void scheduleRepost(String pkg, String key, int userId, long time) {
+        final PendingIntent pi = createPendingIntent(pkg, key, userId);
+        mAm.cancel(pi);
+        if (DEBUG) Slog.d(TAG, "Scheduling evaluate for " + new Date(time));
+        mAm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pi);
+    }
+
+    public void dump(PrintWriter pw, NotificationManagerService.DumpFilter filter) {
+        pw.println("\n  Snoozed notifications:");
+        for (int userId : mSnoozedNotifications.keySet()) {
+            pw.print(INDENT);
+            pw.println("user: " + userId);
+            ArrayMap<String, ArrayMap<String, NotificationRecord>> snoozedPkgs =
+                    mSnoozedNotifications.get(userId);
+            for (String pkg : snoozedPkgs.keySet()) {
+                pw.print(INDENT);
+                pw.print(INDENT);
+                pw.println("package: " + pkg);
+                Set<String> snoozedKeys = snoozedPkgs.get(pkg).keySet();
+                for (String key : snoozedKeys) {
+                    pw.print(INDENT);
+                    pw.print(INDENT);
+                    pw.print(INDENT);
+                    pw.println(key);
+                }
+            }
+        }
+    }
+
+    protected void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
+
+    }
+
+    public void readXml(XmlPullParser parser, boolean forRestore)
+            throws XmlPullParserException, IOException {
+
+    }
+
+    @VisibleForTesting
+    void setAlarmManager(AlarmManager am) {
+        mAm = am;
+    }
+
+    protected interface Callback {
+        void repost(int userId, NotificationRecord r);
+    }
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DEBUG) {
+                Slog.d(TAG, "Reposting notification");
+            }
+            if (REPOST_ACTION.equals(intent.getAction())) {
+                repost(intent.getStringExtra(EXTRA_PKG), intent.getStringExtra(EXTRA_KEY),
+                        intent.getIntExtra(EXTRA_USER_ID, 0));
+            }
+        }
+    };
+}
diff --git a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
index 759030b..5f08257 100644
--- a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
+++ b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Build;
 import android.os.IDeviceIdentifiersPolicyService;
@@ -53,9 +54,15 @@
 
         @Override
         public @Nullable String getSerial() throws RemoteException {
-            if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
-                mContext.enforceCallingOrSelfPermission(
-                        Manifest.permission.READ_PHONE_STATE, "getSerial");
+            if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID
+                    && mContext.checkCallingOrSelfPermission(
+                            Manifest.permission.READ_PHONE_STATE)
+                                    != PackageManager.PERMISSION_GRANTED
+                    && mContext.checkCallingOrSelfPermission(
+                            Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+                                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("getSerial requires READ_PHONE_STATE"
+                        + " or READ_PRIVILEGED_PHONE_STATE permission");
             }
             return SystemProperties.get("ro.serialno", Build.UNKNOWN);
         }
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index ded85f3..00e45fd 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -150,6 +150,8 @@
 
     private static final int MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS = 1;
 
+    private static final String ACTION_TRACK = "com.android.fitness.TRACK";
+
     private final PackageManagerService mService;
     private final Handler mHandler;
 
@@ -603,8 +605,9 @@
                 grantRuntimePermissionsLPw(musicPackage, STORAGE_PERMISSIONS, userId);
             }
 
-            // Android Wear Home
+            // Watches
             if (mService.hasSystemFeature(PackageManager.FEATURE_WATCH, 0)) {
+                // Home application on watches
                 Intent homeIntent = new Intent(Intent.ACTION_MAIN);
                 homeIntent.addCategory(Intent.CATEGORY_HOME_MAIN);
 
@@ -621,6 +624,16 @@
                     grantRuntimePermissionsLPw(wearHomePackage, LOCATION_PERMISSIONS, false,
                             userId);
                 }
+
+                // Fitness tracking on watches
+                Intent trackIntent = new Intent(ACTION_TRACK);
+                PackageParser.Package trackPackage = getDefaultSystemHandlerActivityPackageLPr(
+                        trackIntent, userId);
+                if (trackPackage != null
+                        && doesPackageSupportRuntimePermissions(trackPackage)) {
+                    grantRuntimePermissionsLPw(trackPackage, SENSORS_PERMISSIONS, false, userId);
+                    grantRuntimePermissionsLPw(trackPackage, LOCATION_PERMISSIONS, false, userId);
+                }
             }
 
             // Print Spooler
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0b8a347..2ece99f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -439,7 +439,13 @@
             if (!FileUtils.isValidExtFilename(name)) {
                 throw new IllegalArgumentException("Invalid name: " + name);
             }
-            final File target = new File(resolveStageDir(), name);
+            final File target;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                target = new File(resolveStageDir(), name);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
 
             // TODO: this should delegate to DCS so the system process avoids
             // holding open FDs into containers.
@@ -1084,7 +1090,12 @@
                 if (stageDir != null) {
                     prepareStageDir(stageDir);
                 } else if (stageCid != null) {
-                    prepareExternalStageCid(stageCid, params.sizeBytes);
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        prepareExternalStageCid(stageCid, params.sizeBytes);
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
 
                     // TODO: deliver more granular progress for ASEC allocation
                     mInternalProgress = 0.25f;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index df02b86..e48d6fb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -466,8 +466,8 @@
 
     private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
     /**
-     * If VENDOR_OVERLAY_SKU_PROPERTY is set, search for runtime resource overlay APKs in
-     * VENDOR_OVERLAY_DIR/<value of VENDOR_OVERLAY_SKU_PROPERTY> rather than in
+     * If VENDOR_OVERLAY_SKU_PROPERTY is set, search for runtime resource overlay APKs also in
+     * VENDOR_OVERLAY_DIR/<value of VENDOR_OVERLAY_SKU_PROPERTY> in addition to
      * VENDOR_OVERLAY_DIR.
      */
     private static final String VENDOR_OVERLAY_SKU_PROPERTY = "ro.boot.vendor.overlay.sku";
@@ -2285,18 +2285,17 @@
                 }
             }
 
-            // Collect vendor overlay packages.
-            // (Do this before scanning any apps.)
+            // Collect vendor overlay packages. (Do this before scanning any apps.)
             // For security and version matching reason, only consider
             // overlay packages if they reside in the right directory.
-            File vendorOverlayDir;
             String overlaySkuDir = SystemProperties.get(VENDOR_OVERLAY_SKU_PROPERTY);
             if (!overlaySkuDir.isEmpty()) {
-                vendorOverlayDir = new File(VENDOR_OVERLAY_DIR, overlaySkuDir);
-            } else {
-                vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
+                scanDirTracedLI(new File(VENDOR_OVERLAY_DIR, overlaySkuDir), mDefParseFlags
+                        | PackageParser.PARSE_IS_SYSTEM
+                        | PackageParser.PARSE_IS_SYSTEM_DIR
+                        | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
             }
-            scanDirTracedLI(vendorOverlayDir, mDefParseFlags
+            scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags
                     | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR
                     | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
@@ -2539,8 +2538,7 @@
                 // NOTE: We ignore potential failures here during a system scan (like
                 // the rest of the commands above) because there's precious little we
                 // can do about it. A settings error is reported, though.
-                adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */,
-                        false /* boot complete */);
+                adjustCpuAbisForSharedUserLPw(setting.packages, null /*scannedPackage*/);
             }
 
             // Now that we know all the packages we are keeping,
@@ -4013,6 +4011,11 @@
 
     @Override
     public void grantRuntimePermission(String packageName, String name, final int userId) {
+        grantRuntimePermission(packageName, name, userId, false /* Only if not fixed by policy */);
+    }
+
+    private void grantRuntimePermission(String packageName, String name, final int userId,
+            boolean overridePolicy) {
         if (!sUserManager.exists(userId)) {
             Log.e(TAG, "No such user:" + userId);
             return;
@@ -4065,6 +4068,10 @@
                 throw new SecurityException("Cannot grant system fixed permission "
                         + name + " for package " + packageName);
             }
+            if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+                throw new SecurityException("Cannot grant policy fixed permission "
+                        + name + " for package " + packageName);
+            }
 
             if (bp.isDevelopment()) {
                 // Development permissions must be handled specially, since they are not
@@ -4125,6 +4132,11 @@
 
     @Override
     public void revokeRuntimePermission(String packageName, String name, int userId) {
+        revokeRuntimePermission(packageName, name, userId, false /* Only if not fixed by policy */);
+    }
+
+    private void revokeRuntimePermission(String packageName, String name, int userId,
+            boolean overridePolicy) {
         if (!sUserManager.exists(userId)) {
             Log.e(TAG, "No such user:" + userId);
             return;
@@ -4175,6 +4187,10 @@
                 throw new SecurityException("Cannot revoke system fixed permission "
                         + name + " for package " + packageName);
             }
+            if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+                throw new SecurityException("Cannot revoke policy fixed permission "
+                        + name + " for package " + packageName);
+            }
 
             if (bp.isDevelopment()) {
                 // Development permissions must be handled specially, since they are not
@@ -4710,11 +4726,16 @@
         }
         // reader
         synchronized (mPackages) {
-            final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, 0, false);
-            if (suid == null) {
-                return -1;
+            SharedUserSetting suid;
+            try {
+                suid = mSettings.getSharedUserLPw(sharedUserName, 0, 0, false);
+                if (suid != null) {
+                    return suid.userId;
+                }
+            } catch (PackageManagerException ignore) {
+                // can't happen, but, still need to catch it
             }
-            return suid.userId;
+            return -1;
         }
     }
 
@@ -6877,11 +6898,11 @@
             if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
                 // This package has been renamed to its original name.  Let's
                 // use that.
-                ps = mSettings.peekPackageLPr(oldName);
+                ps = mSettings.getPackageLPr(oldName);
             }
             // If there was no original package, see one for the real package name.
             if (ps == null) {
-                ps = mSettings.peekPackageLPr(pkg.packageName);
+                ps = mSettings.getPackageLPr(pkg.packageName);
             }
             // Check to see if this package could be hiding/updating a system
             // package.  Must look for it either under the original or real
@@ -7121,7 +7142,7 @@
     }
 
     private static String fixProcessName(String defProcessName,
-            String processName, int uid) {
+            String processName) {
         if (processName == null) {
             return defProcessName;
         }
@@ -7793,7 +7814,7 @@
         }
     }
 
-    private void addSharedLibraryLPw(ArraySet<String> usesLibraryFiles, SharedLibraryEntry file,
+    private void addSharedLibraryLPr(ArraySet<String> usesLibraryFiles, SharedLibraryEntry file,
             PackageParser.Package changingLib) {
         if (file.path != null) {
             usesLibraryFiles.add(file.path);
@@ -7814,7 +7835,7 @@
         }
     }
 
-    private void updateSharedLibrariesLPw(PackageParser.Package pkg,
+    private void updateSharedLibrariesLPr(PackageParser.Package pkg,
             PackageParser.Package changingLib) throws PackageManagerException {
         if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
             final ArraySet<String> usesLibraryFiles = new ArraySet<>();
@@ -7826,7 +7847,7 @@
                             "Package " + pkg.packageName + " requires unavailable shared library "
                             + pkg.usesLibraries.get(i) + "; failing!");
                 }
-                addSharedLibraryLPw(usesLibraryFiles, file, changingLib);
+                addSharedLibraryLPr(usesLibraryFiles, file, changingLib);
             }
             N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
             for (int i=0; i<N; i++) {
@@ -7836,7 +7857,7 @@
                             + " desires unavailable shared library "
                             + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
                 } else {
-                    addSharedLibraryLPw(usesLibraryFiles, file, changingLib);
+                    addSharedLibraryLPr(usesLibraryFiles, file, changingLib);
                 }
             }
             N = usesLibraryFiles.size();
@@ -7865,7 +7886,7 @@
     private void updateAllSharedLibrariesLPw() {
         for (PackageParser.Package pkg : mPackages.values()) {
             try {
-                updateSharedLibrariesLPw(pkg, null);
+                updateSharedLibrariesLPr(pkg, null);
             } catch (PackageManagerException e) {
                 Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
             }
@@ -7883,7 +7904,7 @@
                 }
                 res.add(pkg);
                 try {
-                    updateSharedLibrariesLPw(pkg, changingPkg);
+                    updateSharedLibrariesLPr(pkg, changingPkg);
                 } catch (PackageManagerException e) {
                     Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
                 }
@@ -7994,7 +8015,7 @@
      *
      * @throws PackageManagerException If bytecode could not be found when it should exist
      */
-    private static void enforceCodePolicy(PackageParser.Package pkg)
+    private static void assertCodePolicy(PackageParser.Package pkg)
             throws PackageManagerException {
         final boolean shouldHaveCode =
                 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0;
@@ -8017,164 +8038,24 @@
 
     private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
             final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
-            throws PackageManagerException {
-        final File scanFile = new File(pkg.codePath);
-        if (pkg.applicationInfo.getCodePath() == null ||
-                pkg.applicationInfo.getResourcePath() == null) {
-            // Bail out. The resource and code paths haven't been set.
-            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
-                    "Code and resource paths haven't been set correctly");
-        }
-
-        // Apply policy
-        if ((policyFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
-            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
-            if (pkg.applicationInfo.isDirectBootAware()) {
-                // we're direct boot aware; set for all components
-                for (PackageParser.Service s : pkg.services) {
-                    s.info.encryptionAware = s.info.directBootAware = true;
-                }
-                for (PackageParser.Provider p : pkg.providers) {
-                    p.info.encryptionAware = p.info.directBootAware = true;
-                }
-                for (PackageParser.Activity a : pkg.activities) {
-                    a.info.encryptionAware = a.info.directBootAware = true;
-                }
-                for (PackageParser.Activity r : pkg.receivers) {
-                    r.info.encryptionAware = r.info.directBootAware = true;
-                }
-            }
-        } else {
-            // Only allow system apps to be flagged as core apps.
-            pkg.coreApp = false;
-            // clear flags not applicable to regular apps
-            pkg.applicationInfo.privateFlags &=
-                    ~ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
-            pkg.applicationInfo.privateFlags &=
-                    ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
-        }
-        pkg.mTrustedOverlay = (policyFlags&PackageParser.PARSE_TRUSTED_OVERLAY) != 0;
-
-        if ((policyFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
-            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
-        }
-
-        if ((policyFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) {
-            enforceCodePolicy(pkg);
-        }
-
-        if (mCustomResolverComponentName != null &&
-                mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
-            setUpCustomResolverActivity(pkg);
-        }
-
-        if (pkg.packageName.equals("android")) {
-            synchronized (mPackages) {
-                if (mAndroidApplication != null) {
-                    Slog.w(TAG, "*************************************************");
-                    Slog.w(TAG, "Core android package being redefined.  Skipping.");
-                    Slog.w(TAG, " file=" + scanFile);
-                    Slog.w(TAG, "*************************************************");
-                    throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
-                            "Core android package being redefined.  Skipping.");
-                }
-
-                if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
-                    // Set up information for our fall-back user intent resolution activity.
-                    mPlatformPackage = pkg;
-                    pkg.mVersionCode = mSdkVersion;
-                    mAndroidApplication = pkg.applicationInfo;
-
-                    if (!mResolverReplaced) {
-                        mResolveActivity.applicationInfo = mAndroidApplication;
-                        mResolveActivity.name = ResolverActivity.class.getName();
-                        mResolveActivity.packageName = mAndroidApplication.packageName;
-                        mResolveActivity.processName = "system:ui";
-                        mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
-                        mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER;
-                        mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
-                        mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert;
-                        mResolveActivity.exported = true;
-                        mResolveActivity.enabled = true;
-                        mResolveActivity.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
-                        mResolveActivity.configChanges = ActivityInfo.CONFIG_SCREEN_SIZE
-                                | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE
-                                | ActivityInfo.CONFIG_SCREEN_LAYOUT
-                                | ActivityInfo.CONFIG_ORIENTATION
-                                | ActivityInfo.CONFIG_KEYBOARD
-                                | ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
-                        mResolveInfo.activityInfo = mResolveActivity;
-                        mResolveInfo.priority = 0;
-                        mResolveInfo.preferredOrder = 0;
-                        mResolveInfo.match = 0;
-                        mResolveComponentName = new ComponentName(
-                                mAndroidApplication.packageName, mResolveActivity.name);
-                    }
-                }
-            }
-        }
-
+                    throws PackageManagerException {
         if (DEBUG_PACKAGE_SCANNING) {
             if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
                 Log.d(TAG, "Scanning package " + pkg.packageName);
         }
 
-        synchronized (mPackages) {
-            if (mPackages.containsKey(pkg.packageName)
-                    || mSharedLibraries.containsKey(pkg.packageName)) {
-                throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
-                        "Application package " + pkg.packageName
-                                + " already installed.  Skipping duplicate.");
-            }
+        applyPolicy(pkg, policyFlags);
 
-            // If we're only installing presumed-existing packages, require that the
-            // scanned APK is both already known and at the path previously established
-            // for it.  Previously unknown packages we pick up normally, but if we have an
-            // a priori expectation about this package's install presence, enforce it.
-            // With a singular exception for new system packages. When an OTA contains
-            // a new system package, we allow the codepath to change from a system location
-            // to the user-installed location. If we don't allow this change, any newer,
-            // user-installed version of the application will be ignored.
-            if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) {
-                if (mExpectingBetter.containsKey(pkg.packageName)) {
-                    logCriticalInfo(Log.WARN,
-                            "Relax SCAN_REQUIRE_KNOWN requirement for package " + pkg.packageName);
-                } else {
-                    PackageSetting known = mSettings.peekPackageLPr(pkg.packageName);
-                    if (known != null) {
-                        if (DEBUG_PACKAGE_SCANNING) {
-                            Log.d(TAG, "Examining " + pkg.codePath
-                                    + " and requiring known paths " + known.codePathString
-                                    + " & " + known.resourcePathString);
-                        }
-                        if (!pkg.applicationInfo.getCodePath().equals(known.codePathString)
-                                || !pkg.applicationInfo.getResourcePath().equals(
-                                known.resourcePathString)) {
-                            throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
-                                    "Application package " + pkg.packageName
-                                            + " found at " + pkg.applicationInfo.getCodePath()
-                                            + " but expected at " + known.codePathString
-                                            + "; ignoring.");
-                        }
-                    }
-                }
-            }
-        }
+        assertPackageIsValid(pkg, policyFlags);
 
         // Initialize package source and resource directories
-        File destCodeFile = new File(pkg.applicationInfo.getCodePath());
-        File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
+        final File scanFile = new File(pkg.codePath);
+        final File destCodeFile = new File(pkg.applicationInfo.getCodePath());
+        final File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
 
         SharedUserSetting suid = null;
         PackageSetting pkgSetting = null;
 
-        if (!isSystemApp(pkg)) {
-            // Only system apps can use these features.
-            pkg.mOriginalPackages = null;
-            pkg.mRealPackage = null;
-            pkg.mAdoptPermissions = null;
-        }
-
         // Getting the package setting may have a side-effect, so if we
         // are only checking if scan would succeed, stash a copy of the
         // old setting to restore at the end.
@@ -8183,12 +8064,9 @@
         // writer
         synchronized (mPackages) {
             if (pkg.mSharedUserId != null) {
-                suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, 0, true);
-                if (suid == null) {
-                    throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
-                            "Creating application package " + pkg.packageName
-                            + " for shared user failed");
-                }
+                // SIDE EFFECTS; may potentially allocate a new shared user
+                suid = mSettings.getSharedUserLPw(
+                        pkg.mSharedUserId, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/);
                 if (DEBUG_PACKAGE_SCANNING) {
                     if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
                         Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
@@ -8215,10 +8093,9 @@
                         // it is not already done.
                         pkg.setPackageName(renamed);
                     }
-
                 } else {
                     for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
-                        if ((origPackage = mSettings.peekPackageLPr(
+                        if ((origPackage = mSettings.getPackageLPr(
                                 pkg.mOriginalPackages.get(i))) != null) {
                             // We do have the package already installed under its
                             // original name...  should we use it?
@@ -8254,7 +8131,7 @@
 
             // See comments in nonMutatedPs declaration
             if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
-                PackageSetting foundPs = mSettings.peekPackageLPr(pkg.packageName);
+                PackageSetting foundPs = mSettings.getPackageLPr(pkg.packageName);
                 if (foundPs != null) {
                     nonMutatedPs = new PackageSetting(foundPs);
                 }
@@ -8264,10 +8141,11 @@
             if (pkgSetting != null && pkgSetting.sharedUser != suid) {
                 PackageManagerService.reportSettingsProblem(Log.WARN,
                         "Package " + pkg.packageName + " shared user changed from "
-                        + (pkgSetting.sharedUser != null ? pkgSetting.sharedUser.name : "<nothing>")
-                        + " to "
-                        + (suid != null ? suid.name : "<nothing>")
-                        + "; replacing with new");
+                                + (pkgSetting.sharedUser != null
+                                        ? pkgSetting.sharedUser.name : "<nothing>")
+                                + " to "
+                                + (suid != null ? suid.name : "<nothing>")
+                                + "; replacing with new");
                 pkgSetting = null;
             }
             final PackageSetting oldPkgSetting =
@@ -8277,6 +8155,7 @@
             if (pkgSetting == null) {
                 final String parentPackageName = (pkg.parentPackage != null)
                         ? pkg.parentPackage.packageName : null;
+                // REMOVE SharedUserSetting from method; update in a separate call
                 pkgSetting = Settings.createNewSetting(pkg.packageName, origPackage,
                         disabledPkgSetting, realName, suid, destCodeFile, destResourceFile,
                         pkg.applicationInfo.nativeLibraryRootDir, pkg.applicationInfo.primaryCpuAbi,
@@ -8284,19 +8163,23 @@
                         pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, user,
                         true /*allowInstall*/, parentPackageName, pkg.getChildPackageNames(),
                         UserManagerService.getInstance());
+                // SIDE EFFECTS; updates system state; move elsewhere
                 if (origPackage != null) {
                     mSettings.addRenamedPackageLPw(pkg.packageName, origPackage.name);
                 }
                 mSettings.addUserToSettingLPw(pkgSetting);
             } else {
+                // REMOVE SharedUserSetting from method; update in a separate call
                 Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, suid, destCodeFile,
                         pkg.applicationInfo.nativeLibraryDir, pkg.applicationInfo.primaryCpuAbi,
                         pkg.applicationInfo.secondaryCpuAbi, pkg.applicationInfo.flags,
                         pkg.applicationInfo.privateFlags, pkg.getChildPackageNames(),
                         UserManagerService.getInstance());
             }
-            mSettings.writeUserRestrictions(pkgSetting, oldPkgSetting);
+            // SIDE EFFECTS; persists system state to files on disk; move elsewhere
+            mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting);
 
+            // SIDE EFFECTS; modifies system state; move elsewhere
             if (pkgSetting.origPackage != null) {
                 // If we are first transitioning from an original package,
                 // fix up the new package's name now.  We need to do this after
@@ -8318,6 +8201,7 @@
                 pkgSetting.origPackage = null;
             }
 
+            // SIDE EFFECTS; modifies system state; move elsewhere
             if ((scanFlags & SCAN_CHECK_ONLY) == 0 && realName != null) {
                 // Make a note of it.
                 mTransferedPackages.add(pkg.packageName);
@@ -8327,13 +8211,13 @@
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
 
-            if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+            if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                 // Check all shared libraries and map to their actual file path.
                 // We only do this here for apps not on a system dir, because those
                 // are the only ones that can fail an install due to this.  We
                 // will take care of the system apps by updating all of their
                 // library paths after the scan is done.
-                updateSharedLibrariesLPw(pkg, null);
+                updateSharedLibrariesLPr(pkg, null);
             }
 
             if (mFoundPolicyFile) {
@@ -8355,12 +8239,13 @@
                     } else {
                         pkgSetting.signatures.mSignatures = pkg.mSignatures;
                         String msg = "System package " + pkg.packageName
-                            + " signature changed; retaining data.";
+                                + " signature changed; retaining data.";
                         reportSettingsProblem(Log.WARN, msg);
                     }
                 }
             } else {
                 try {
+                    // SIDE EFFECTS; compareSignaturesCompat() changes KeysetManagerService
                     verifySignaturesLP(pkgSetting, pkg);
                     // We just determined the app is signed correctly, so bring
                     // over the latest parsed certs.
@@ -8379,57 +8264,31 @@
                     // that unreasonable.
                     if (pkgSetting.sharedUser != null) {
                         if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
-                                              pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
+                                pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
                             throw new PackageManagerException(
                                     INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
-                                            "Signature mismatch for shared user: "
+                                    "Signature mismatch for shared user: "
                                             + pkgSetting.sharedUser);
                         }
                     }
                     // File a report about this.
                     String msg = "System package " + pkg.packageName
-                        + " signature changed; retaining data.";
+                            + " signature changed; retaining data.";
                     reportSettingsProblem(Log.WARN, msg);
                 }
             }
-            // Verify that this new package doesn't have any content providers
-            // that conflict with existing packages.  Only do this if the
-            // package isn't already installed, since we don't want to break
-            // things that are installed.
-            if ((scanFlags & SCAN_NEW_INSTALL) != 0) {
-                final int N = pkg.providers.size();
-                int i;
-                for (i=0; i<N; i++) {
-                    PackageParser.Provider p = pkg.providers.get(i);
-                    if (p.info.authority != null) {
-                        String names[] = p.info.authority.split(";");
-                        for (int j = 0; j < names.length; j++) {
-                            if (mProvidersByAuthority.containsKey(names[j])) {
-                                PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
-                                final String otherPackageName =
-                                        ((other != null && other.getComponentName() != null) ?
-                                                other.getComponentName().getPackageName() : "?");
-                                throw new PackageManagerException(
-                                        INSTALL_FAILED_CONFLICTING_PROVIDER,
-                                                "Can't install because provider name " + names[j]
-                                                + " (in package " + pkg.applicationInfo.packageName
-                                                + ") is already used by " + otherPackageName);
-                            }
-                        }
-                    }
-                }
-            }
 
             if ((scanFlags & SCAN_CHECK_ONLY) == 0 && pkg.mAdoptPermissions != null) {
                 // This package wants to adopt ownership of permissions from
                 // another package.
                 for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
                     final String origName = pkg.mAdoptPermissions.get(i);
-                    final PackageSetting orig = mSettings.peekPackageLPr(origName);
+                    final PackageSetting orig = mSettings.getPackageLPr(origName);
                     if (orig != null) {
                         if (verifyPackageUpdateLPr(orig, pkg)) {
                             Slog.i(TAG, "Adopting permissions from " + origName + " to "
                                     + pkg.packageName);
+                            // SIDE EFFECTS; updates permissions system state; move elsewhere
                             mSettings.transferPermissionsLPw(origName, pkg.packageName);
                         }
                     }
@@ -8437,26 +8296,21 @@
             }
         }
 
-        final String pkgName = pkg.packageName;
-
-        final long scanFileTime = getLastModifiedTime(pkg, scanFile);
-        final boolean forceDex = (scanFlags & SCAN_FORCE_DEX) != 0;
         pkg.applicationInfo.processName = fixProcessName(
                 pkg.applicationInfo.packageName,
-                pkg.applicationInfo.processName,
-                pkg.applicationInfo.uid);
+                pkg.applicationInfo.processName);
 
         if (pkg != mPlatformPackage) {
             // Get all of our default paths setup
             pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM);
         }
 
-        final String path = scanFile.getPath();
         final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
 
         if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
-            derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /*extractLibs*/);
+            derivePackageAbi(
+                    pkg, scanFile, cpuAbiOverride, true /*extractLibs*/, mAppLib32InstallDir);
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             // Some system apps still use directory structure for native libraries
@@ -8465,9 +8319,8 @@
             if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() &&
                     pkg.applicationInfo.primaryCpuAbi == null) {
                 setBundledAppAbisAndRoots(pkg, pkgSetting);
-                setNativeLibraryPaths(pkg);
+                setNativeLibraryPaths(pkg, mAppLib32InstallDir);
             }
-
         } else {
             if ((scanFlags & SCAN_MOVE) != 0) {
                 // We haven't run dex-opt for this move (since we've moved the compiled output too)
@@ -8481,7 +8334,7 @@
             // ABIs we've determined above. For non-moves, the path will be updated based on the
             // ABIs we determined during compilation, but the path will depend on the final
             // package path (after the rename away from the stage path).
-            setNativeLibraryPaths(pkg);
+            setNativeLibraryPaths(pkg, mAppLib32InstallDir);
         }
 
         // This is a special case for the "system" package, where the ABI is
@@ -8528,6 +8381,7 @@
                     " secondary=" + pkg.applicationInfo.secondaryCpuAbi);
         }
 
+        // SIDE EFFECTS; removes DEX files from disk; move elsewhere
         if ((scanFlags & SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
             // We don't do this here during boot because we can do it all
             // at once after scanning all existing packages.
@@ -8535,8 +8389,7 @@
             // We also do this *before* we perform dexopt on this package, so that
             // we can avoid redundant dexopts, and also to make sure we've got the
             // code and package path correct.
-            adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
-                    pkg, true /* boot complete */);
+            adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages, pkg);
         }
 
         if (mFactoryTest && pkg.requestedPermissions.contains(
@@ -8548,7 +8401,25 @@
             pkgSetting.isOrphaned = true;
         }
 
-        ArrayList<PackageParser.Package> clientLibPkgs = null;
+        // Take care of first install / last update times.
+        final long scanFileTime = getLastModifiedTime(pkg, scanFile);
+        if (currentTime != 0) {
+            if (pkgSetting.firstInstallTime == 0) {
+                pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
+            } else if ((scanFlags & SCAN_UPDATE_TIME) != 0) {
+                pkgSetting.lastUpdateTime = currentTime;
+            }
+        } else if (pkgSetting.firstInstallTime == 0) {
+            // We need *something*.  Take time time stamp of the file.
+            pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
+        } else if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
+            if (scanFileTime != pkgSetting.timeStamp) {
+                // A package on the system image has changed; consider this
+                // to be an update.
+                pkgSetting.lastUpdateTime = scanFileTime;
+            }
+        }
+        pkgSetting.setTimeStamp(scanFileTime);
 
         if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
             if (nonMutatedPs != null) {
@@ -8556,27 +8427,239 @@
                     mSettings.mPackages.put(nonMutatedPs.name, nonMutatedPs);
                 }
             }
-            return pkg;
+        } else {
+            // Modify state for the given package setting
+            commitPackageSettings(pkg, pkgSetting, user, scanFlags,
+                    (policyFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/);
+        }
+        return pkg;
+    }
+
+    /**
+     * Applies policy to the parsed package based upon the given policy flags.
+     * Ensures the package is in a good state.
+     * <p>
+     * Implementation detail: This method must NOT have any side effect. It would
+     * ideally be static, but, it requires locks to read system state.
+     */
+    private void applyPolicy(PackageParser.Package pkg, int policyFlags) {
+        if ((policyFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
+            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+            if (pkg.applicationInfo.isDirectBootAware()) {
+                // we're direct boot aware; set for all components
+                for (PackageParser.Service s : pkg.services) {
+                    s.info.encryptionAware = s.info.directBootAware = true;
+                }
+                for (PackageParser.Provider p : pkg.providers) {
+                    p.info.encryptionAware = p.info.directBootAware = true;
+                }
+                for (PackageParser.Activity a : pkg.activities) {
+                    a.info.encryptionAware = a.info.directBootAware = true;
+                }
+                for (PackageParser.Activity r : pkg.receivers) {
+                    r.info.encryptionAware = r.info.directBootAware = true;
+                }
+            }
+        } else {
+            // Only allow system apps to be flagged as core apps.
+            pkg.coreApp = false;
+            // clear flags not applicable to regular apps
+            pkg.applicationInfo.privateFlags &=
+                    ~ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
+            pkg.applicationInfo.privateFlags &=
+                    ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
+        }
+        pkg.mTrustedOverlay = (policyFlags&PackageParser.PARSE_TRUSTED_OVERLAY) != 0;
+
+        if ((policyFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
+            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
         }
 
-        // Only privileged apps and updated privileged apps can add child packages.
-        if (pkg.childPackages != null && !pkg.childPackages.isEmpty()) {
-            if ((policyFlags & PARSE_IS_PRIVILEGED) == 0) {
-                throw new PackageManagerException("Only privileged apps and updated "
-                        + "privileged apps can add child packages. Ignoring package "
-                        + pkg.packageName);
+        if (!isSystemApp(pkg)) {
+            // Only system apps can use these features.
+            pkg.mOriginalPackages = null;
+            pkg.mRealPackage = null;
+            pkg.mAdoptPermissions = null;
+        }
+    }
+
+    /**
+     * Asserts the parsed package is valid according to teh given policy. If the
+     * package is invalid, for whatever reason, throws {@link PackgeManagerException}.
+     * <p>
+     * Implementation detail: This method must NOT have any side effects. It would
+     * ideally be static, but, it requires locks to read system state.
+     *
+     * @throws PackageManagerException If the package fails any of the validation checks
+     */
+    private void assertPackageIsValid(PackageParser.Package pkg, int policyFlags)
+            throws PackageManagerException {
+        if ((policyFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) {
+            assertCodePolicy(pkg);
+        }
+
+        if (pkg.applicationInfo.getCodePath() == null ||
+                pkg.applicationInfo.getResourcePath() == null) {
+            // Bail out. The resource and code paths haven't been set.
+            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                    "Code and resource paths haven't been set correctly");
+        }
+
+        // Make sure we're not adding any bogus keyset info
+        KeySetManagerService ksms = mSettings.mKeySetManagerService;
+        ksms.assertScannedPackageValid(pkg);
+
+        synchronized (mPackages) {
+            // The special "android" package can only be defined once
+            if (pkg.packageName.equals("android")) {
+                if (mAndroidApplication != null) {
+                    Slog.w(TAG, "*************************************************");
+                    Slog.w(TAG, "Core android package being redefined.  Skipping.");
+                    Slog.w(TAG, " codePath=" + pkg.codePath);
+                    Slog.w(TAG, "*************************************************");
+                    throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
+                            "Core android package being redefined.  Skipping.");
+                }
             }
-            final int childCount = pkg.childPackages.size();
-            for (int i = 0; i < childCount; i++) {
-                PackageParser.Package childPkg = pkg.childPackages.get(i);
-                if (mSettings.hasOtherDisabledSystemPkgWithChildLPr(pkg.packageName,
-                        childPkg.packageName)) {
-                    throw new PackageManagerException("Cannot override a child package of "
-                            + "another disabled system app. Ignoring package " + pkg.packageName);
+
+            // A package name must be unique; don't allow duplicates
+            if (mPackages.containsKey(pkg.packageName)
+                    || mSharedLibraries.containsKey(pkg.packageName)) {
+                throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
+                        "Application package " + pkg.packageName
+                        + " already installed.  Skipping duplicate.");
+            }
+
+            // Only privileged apps and updated privileged apps can add child packages.
+            if (pkg.childPackages != null && !pkg.childPackages.isEmpty()) {
+                if ((policyFlags & PARSE_IS_PRIVILEGED) == 0) {
+                    throw new PackageManagerException("Only privileged apps can add child "
+                            + "packages. Ignoring package " + pkg.packageName);
+                }
+                final int childCount = pkg.childPackages.size();
+                for (int i = 0; i < childCount; i++) {
+                    PackageParser.Package childPkg = pkg.childPackages.get(i);
+                    if (mSettings.hasOtherDisabledSystemPkgWithChildLPr(pkg.packageName,
+                            childPkg.packageName)) {
+                        throw new PackageManagerException("Can't override child of "
+                                + "another disabled app. Ignoring package " + pkg.packageName);
+                    }
+                }
+            }
+
+            // If we're only installing presumed-existing packages, require that the
+            // scanned APK is both already known and at the path previously established
+            // for it.  Previously unknown packages we pick up normally, but if we have an
+            // a priori expectation about this package's install presence, enforce it.
+            // With a singular exception for new system packages. When an OTA contains
+            // a new system package, we allow the codepath to change from a system location
+            // to the user-installed location. If we don't allow this change, any newer,
+            // user-installed version of the application will be ignored.
+            if ((policyFlags & SCAN_REQUIRE_KNOWN) != 0) {
+                if (mExpectingBetter.containsKey(pkg.packageName)) {
+                    logCriticalInfo(Log.WARN,
+                            "Relax SCAN_REQUIRE_KNOWN requirement for package " + pkg.packageName);
+                } else {
+                    PackageSetting known = mSettings.getPackageLPr(pkg.packageName);
+                    if (known != null) {
+                        if (DEBUG_PACKAGE_SCANNING) {
+                            Log.d(TAG, "Examining " + pkg.codePath
+                                    + " and requiring known paths " + known.codePathString
+                                    + " & " + known.resourcePathString);
+                        }
+                        if (!pkg.applicationInfo.getCodePath().equals(known.codePathString)
+                                || !pkg.applicationInfo.getResourcePath().equals(
+                                        known.resourcePathString)) {
+                            throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
+                                    "Application package " + pkg.packageName
+                                    + " found at " + pkg.applicationInfo.getCodePath()
+                                    + " but expected at " + known.codePathString
+                                    + "; ignoring.");
+                        }
+                    }
+                }
+            }
+
+            // Verify that this new package doesn't have any content providers
+            // that conflict with existing packages.  Only do this if the
+            // package isn't already installed, since we don't want to break
+            // things that are installed.
+            if ((policyFlags & SCAN_NEW_INSTALL) != 0) {
+                final int N = pkg.providers.size();
+                int i;
+                for (i=0; i<N; i++) {
+                    PackageParser.Provider p = pkg.providers.get(i);
+                    if (p.info.authority != null) {
+                        String names[] = p.info.authority.split(";");
+                        for (int j = 0; j < names.length; j++) {
+                            if (mProvidersByAuthority.containsKey(names[j])) {
+                                PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
+                                final String otherPackageName =
+                                        ((other != null && other.getComponentName() != null) ?
+                                                other.getComponentName().getPackageName() : "?");
+                                throw new PackageManagerException(
+                                        INSTALL_FAILED_CONFLICTING_PROVIDER,
+                                        "Can't install because provider name " + names[j]
+                                                + " (in package " + pkg.applicationInfo.packageName
+                                                + ") is already used by " + otherPackageName);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Adds a scanned package to the system. When this method is finished, the package will
+     * be available for query, resolution, etc...
+     */
+    private void commitPackageSettings(PackageParser.Package pkg, PackageSetting pkgSetting,
+            UserHandle user, int scanFlags, boolean chatty) throws PackageManagerException {
+        final String pkgName = pkg.packageName;
+        if (mCustomResolverComponentName != null &&
+                mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
+            setUpCustomResolverActivity(pkg);
+        }
+
+        if (pkg.packageName.equals("android")) {
+            synchronized (mPackages) {
+                if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
+                    // Set up information for our fall-back user intent resolution activity.
+                    mPlatformPackage = pkg;
+                    pkg.mVersionCode = mSdkVersion;
+                    mAndroidApplication = pkg.applicationInfo;
+
+                    if (!mResolverReplaced) {
+                        mResolveActivity.applicationInfo = mAndroidApplication;
+                        mResolveActivity.name = ResolverActivity.class.getName();
+                        mResolveActivity.packageName = mAndroidApplication.packageName;
+                        mResolveActivity.processName = "system:ui";
+                        mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
+                        mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER;
+                        mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
+                        mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert;
+                        mResolveActivity.exported = true;
+                        mResolveActivity.enabled = true;
+                        mResolveActivity.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
+                        mResolveActivity.configChanges = ActivityInfo.CONFIG_SCREEN_SIZE
+                                | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE
+                                | ActivityInfo.CONFIG_SCREEN_LAYOUT
+                                | ActivityInfo.CONFIG_ORIENTATION
+                                | ActivityInfo.CONFIG_KEYBOARD
+                                | ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
+                        mResolveInfo.activityInfo = mResolveActivity;
+                        mResolveInfo.priority = 0;
+                        mResolveInfo.preferredOrder = 0;
+                        mResolveInfo.match = 0;
+                        mResolveComponentName = new ComponentName(
+                                mAndroidApplication.packageName, mResolveActivity.name);
+                    }
                 }
             }
         }
 
+        ArrayList<PackageParser.Package> clientLibPkgs = null;
         // writer
         synchronized (mPackages) {
             if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
@@ -8653,10 +8736,6 @@
             }
         }
 
-        // Make sure we're not adding any bogus keyset info
-        KeySetManagerService ksms = mSettings.mKeySetManagerService;
-        ksms.assertScannedPackageValid(pkg);
-
         // writer
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
 
@@ -8668,8 +8747,9 @@
                 // Note that |user| might be null during the initial boot scan. If a codePath
                 // for an app has changed during a boot scan, it's due to an app update that's
                 // part of the system partition and marker changes must be applied to all users.
-                maybeRenameForeignDexMarkers(pkgSetting.pkg, pkg,
-                    (user != null) ? user : UserHandle.ALL);
+                final int userId = ((user != null) ? user : UserHandle.ALL).getIdentifier();
+                final int[] userIds = resolveUserIds(userId);
+                maybeRenameForeignDexMarkers(pkgSetting.pkg, pkg, userIds);
             }
 
             // Add the new setting to mSettings
@@ -8685,25 +8765,8 @@
                 }
             }
 
-            // Take care of first install / last update times.
-            if (currentTime != 0) {
-                if (pkgSetting.firstInstallTime == 0) {
-                    pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
-                } else if ((scanFlags&SCAN_UPDATE_TIME) != 0) {
-                    pkgSetting.lastUpdateTime = currentTime;
-                }
-            } else if (pkgSetting.firstInstallTime == 0) {
-                // We need *something*.  Take time time stamp of the file.
-                pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
-            } else if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
-                if (scanFileTime != pkgSetting.timeStamp) {
-                    // A package on the system image has changed; consider this
-                    // to be an update.
-                    pkgSetting.lastUpdateTime = scanFileTime;
-                }
-            }
-
             // Add the package's KeySets to the global KeySetManagerService
+            KeySetManagerService ksms = mSettings.mKeySetManagerService;
             ksms.addScannedPackageLPw(pkg);
 
             int N = pkg.providers.size();
@@ -8712,7 +8775,7 @@
             for (i=0; i<N; i++) {
                 PackageParser.Provider p = pkg.providers.get(i);
                 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        p.info.processName, pkg.applicationInfo.uid);
+                        p.info.processName);
                 mProviders.addProvider(p);
                 p.syncable = p.info.isSyncable;
                 if (p.info.authority != null) {
@@ -8738,7 +8801,7 @@
                                 p.info.authority = p.info.authority + ";" + names[j];
                             }
                             if (DEBUG_PACKAGE_SCANNING) {
-                                if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
+                                if (chatty)
                                     Log.d(TAG, "Registered content provider: " + names[j]
                                             + ", className = " + p.info.name + ", isSyncable = "
                                             + p.info.isSyncable);
@@ -8753,7 +8816,7 @@
                         }
                     }
                 }
-                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if (chatty) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8771,9 +8834,9 @@
             for (i=0; i<N; i++) {
                 PackageParser.Service s = pkg.services.get(i);
                 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        s.info.processName, pkg.applicationInfo.uid);
+                        s.info.processName);
                 mServices.addService(s);
-                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if (chatty) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8791,9 +8854,9 @@
             for (i=0; i<N; i++) {
                 PackageParser.Activity a = pkg.receivers.get(i);
                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        a.info.processName, pkg.applicationInfo.uid);
+                        a.info.processName);
                 mReceivers.addActivity(a, "receiver");
-                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if (chatty) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8811,9 +8874,9 @@
             for (i=0; i<N; i++) {
                 PackageParser.Activity a = pkg.activities.get(i);
                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        a.info.processName, pkg.applicationInfo.uid);
+                        a.info.processName);
                 mActivities.addActivity(a, "activity");
-                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if (chatty) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8835,7 +8898,7 @@
                 final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName);
                 if (cur == null || isPackageUpdate) {
                     mPermissionGroups.put(pg.info.name, pg);
-                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
+                    if (chatty) {
                         if (r == null) {
                             r = new StringBuilder(256);
                         } else {
@@ -8850,7 +8913,7 @@
                     Slog.w(TAG, "Permission group " + pg.info.name + " from package "
                             + pg.info.packageName + " ignored: original from "
                             + cur.info.packageName);
-                    if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
+                    if (chatty) {
                         if (r == null) {
                             r = new StringBuilder(256);
                         } else {
@@ -8929,7 +8992,7 @@
                             bp.uid = pkg.applicationInfo.uid;
                             bp.sourcePackage = p.info.packageName;
                             p.info.flags |= PermissionInfo.FLAG_INSTALLED;
-                            if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
+                            if (chatty) {
                                 if (r == null) {
                                     r = new StringBuilder(256);
                                 } else {
@@ -8948,7 +9011,7 @@
                                 + p.info.packageName + " ignored: original from "
                                 + bp.sourcePackage);
                     }
-                } else if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
+                } else if (chatty) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -8978,11 +9041,10 @@
                 a.info.dataDir = pkg.applicationInfo.dataDir;
                 a.info.deviceProtectedDataDir = pkg.applicationInfo.deviceProtectedDataDir;
                 a.info.credentialProtectedDataDir = pkg.applicationInfo.credentialProtectedDataDir;
-
                 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
                 a.info.secondaryNativeLibraryDir = pkg.applicationInfo.secondaryNativeLibraryDir;
                 mInstrumentation.put(a.getComponentName(), a);
-                if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
+                if (chatty) {
                     if (r == null) {
                         r = new StringBuilder(256);
                     } else {
@@ -9002,8 +9064,6 @@
                 }
             }
 
-            pkgSetting.setTimeStamp(scanFileTime);
-
             // Create idmap files for pairs of (packages, overlay packages).
             // Note: "android", ie framework-res.apk, is handled by native layers.
             if (pkg.mOverlayTarget != null) {
@@ -9033,11 +9093,10 @@
             throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                     "scanPackageLI failed to createIdmap");
         }
-        return pkg;
     }
 
-    private void maybeRenameForeignDexMarkers(PackageParser.Package existing,
-            PackageParser.Package update, UserHandle user) {
+    private static void maybeRenameForeignDexMarkers(PackageParser.Package existing,
+            PackageParser.Package update, int[] userIds) {
         if (existing.applicationInfo == null || update.applicationInfo == null) {
             // This isn't due to an app installation.
             return;
@@ -9085,7 +9144,7 @@
             markerSuffixes.add(updatedPathName.replace('/', '@'));
         }
 
-        for (int userId : resolveUserIds(user.getIdentifier())) {
+        for (int userId : userIds) {
             File profileDir = Environment.getDataProfilesDeForeignDexDirectory(userId);
 
             for (String markerSuffix : markerSuffixes) {
@@ -9111,8 +9170,9 @@
      *
      * If {@code extractLibs} is true, native libraries are extracted from the app if required.
      */
-    private void derivePackageAbi(PackageParser.Package pkg, File scanFile,
-                                 String cpuAbiOverride, boolean extractLibs)
+    private static void derivePackageAbi(PackageParser.Package pkg, File scanFile,
+                                 String cpuAbiOverride, boolean extractLibs,
+                                 File appLib32InstallDir)
             throws PackageManagerException {
         // TODO: We can probably be smarter about this stuff. For installed apps,
         // we can calculate this information at install time once and for all. For
@@ -9121,7 +9181,7 @@
 
         // Give ourselves some initial paths; we'll come back for another
         // pass once we've determined ABI below.
-        setNativeLibraryPaths(pkg);
+        setNativeLibraryPaths(pkg, appLib32InstallDir);
 
         // We would never need to extract libs for forward-locked and external packages,
         // since the container service will do it for us. We shouldn't attempt to
@@ -9256,7 +9316,7 @@
 
         // Now that we've calculated the ABIs and determined if it's an internal app,
         // we will go ahead and populate the nativeLibraryPath.
-        setNativeLibraryPaths(pkg);
+        setNativeLibraryPaths(pkg, appLib32InstallDir);
     }
 
     /**
@@ -9273,7 +9333,7 @@
      * adds unnecessary complexity.
      */
     private void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
-            PackageParser.Package scannedPackage, boolean bootComplete) {
+            PackageParser.Package scannedPackage) {
         String requiredInstructionSet = null;
         if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) {
             requiredInstructionSet = VMRuntime.getInstructionSet(
@@ -9438,7 +9498,7 @@
      * Derive and set the location of native libraries for the given package,
      * which varies depending on where and how the package was installed.
      */
-    private void setNativeLibraryPaths(PackageParser.Package pkg) {
+    private static void setNativeLibraryPaths(PackageParser.Package pkg, File appLib32InstallDir) {
         final ApplicationInfo info = pkg.applicationInfo;
         final String codePath = pkg.codePath;
         final File codeFile = new File(codePath);
@@ -9477,7 +9537,7 @@
                         .getAbsolutePath();
             } else {
                 final String apkName = deriveCodePathName(codePath);
-                info.nativeLibraryRootDir = new File(mAppLib32InstallDir, apkName)
+                info.nativeLibraryRootDir = new File(appLib32InstallDir, apkName)
                         .getAbsolutePath();
             }
 
@@ -9505,7 +9565,7 @@
      * of this information, and instead assume that the system was built
      * sensibly.
      */
-    private void setBundledAppAbisAndRoots(PackageParser.Package pkg,
+    private static void setBundledAppAbisAndRoots(PackageParser.Package pkg,
                                            PackageSetting pkgSetting) {
         final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());
 
@@ -14441,7 +14501,7 @@
                 childRemovedRes.isUpdate = false;
                 childRemovedRes.dataRemoved = true;
                 synchronized (mPackages) {
-                    PackageSetting childPs = mSettings.peekPackageLPr(childPkg.packageName);
+                    PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
                     if (childPs != null) {
                         childRemovedRes.origUsers = childPs.queryInstalledUsers(allUsers, true);
                     }
@@ -14596,7 +14656,7 @@
             }
         } else {
             synchronized (mPackages) {
-                PackageSetting ps = mSettings.peekPackageLPr(pkg.packageName);
+                PackageSetting ps = mSettings.getPackageLPr(pkg.packageName);
                 if (ps != null) {
                     res.removedInfo.removedForAllUsers = mPackages.get(ps.name) == null;
                     if (res.removedInfo.removedChildPackages != null) {
@@ -14774,7 +14834,7 @@
             for (int i = 0; i < childCount; i++) {
                 PackageSetting childPs = null;
                 synchronized (mPackages) {
-                    childPs = mSettings.peekPackageLPr(ps.childPackageNames.get(i));
+                    childPs = mSettings.getPackageLPr(ps.childPackageNames.get(i));
                 }
                 if (childPs != null) {
                     NativeLibraryHelper.removeNativeBinariesLI(childPs
@@ -15047,7 +15107,7 @@
                     childRes.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
                     childRes.pkg = childPkg;
                     childRes.name = childPkg.packageName;
-                    PackageSetting childPs = mSettings.peekPackageLPr(childPkg.packageName);
+                    PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
                     if (childPs != null) {
                         childRes.origUsers = childPs.queryInstalledUsers(
                                 sUserManager.getUserIds(), true);
@@ -15269,7 +15329,7 @@
                 String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ?
                     args.abiOverride : pkg.cpuAbiOverride);
                 derivePackageAbi(pkg, new File(pkg.codePath), abiOverride,
-                        true /* extract libs */);
+                        true /*extractLibs*/, mAppLib32InstallDir);
             } catch (PackageManagerException pme) {
                 Slog.e(TAG, "Error deriving application ABI", pme);
                 res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");
@@ -15279,7 +15339,7 @@
             // Shared libraries for the package need to be updated.
             synchronized (mPackages) {
                 try {
-                    updateSharedLibrariesLPw(pkg, null);
+                    updateSharedLibrariesLPr(pkg, null);
                 } catch (PackageManagerException e) {
                     Slog.e(TAG, "updateSharedLibrariesLPw failed: " + e.getMessage());
                 }
@@ -15328,7 +15388,7 @@
             for (int i = 0; i < childCount; i++) {
                 PackageParser.Package childPkg = pkg.childPackages.get(i);
                 PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName);
-                PackageSetting childPs = mSettings.peekPackageLPr(childPkg.packageName);
+                PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
                 if (childPs != null) {
                     childRes.newUsers = childPs.queryInstalledUsers(
                             sUserManager.getUserIds(), true);
@@ -16127,7 +16187,7 @@
         }
         try {
             // update shared libraries for the newly re-installed system package
-            updateSharedLibrariesLPw(newPkg, null);
+            updateSharedLibrariesLPr(newPkg, null);
         } catch (PackageManagerException e) {
             Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
         }
@@ -16205,7 +16265,7 @@
         for (int i = 0; i < childCount; i++) {
             PackageSetting childPs;
             synchronized (mPackages) {
-                childPs = mSettings.peekPackageLPr(ps.childPackageNames.get(i));
+                childPs = mSettings.getPackageLPr(ps.childPackageNames.get(i));
             }
             if (childPs != null) {
                 PackageRemovedInfo childOutInfo = (outInfo != null
@@ -16382,7 +16442,7 @@
                     PackageRemovedInfo childInfo = new PackageRemovedInfo();
                     childInfo.removedPackage = childPackageName;
                     outInfo.removedChildPackages.put(childPackageName, childInfo);
-                    PackageSetting childPs = mSettings.peekPackageLPr(childPackageName);
+                    PackageSetting childPs = mSettings.getPackageLPr(childPackageName);
                     if (childPs != null) {
                         childInfo.origUsers = childPs.queryInstalledUsers(allUserHandles, true);
                     }
@@ -16422,14 +16482,14 @@
             // app but were not declared in the update.
             if (isSystemApp(ps)) {
                 synchronized (mPackages) {
-                    PackageSetting updatedPs = mSettings.peekPackageLPr(ps.name);
+                    PackageSetting updatedPs = mSettings.getPackageLPr(ps.name);
                     final int childCount = (updatedPs.childPackageNames != null)
                             ? updatedPs.childPackageNames.size() : 0;
                     for (int i = 0; i < childCount; i++) {
                         String childPackageName = updatedPs.childPackageNames.get(i);
                         if (outInfo.removedChildPackages == null
                                 || outInfo.removedChildPackages.indexOfKey(childPackageName) < 0) {
-                            PackageSetting childPs = mSettings.peekPackageLPr(childPackageName);
+                            PackageSetting childPs = mSettings.getPackageLPr(childPackageName);
                             if (childPs == null) {
                                 continue;
                             }
@@ -20618,9 +20678,9 @@
     }
 
     /** Called by UserManagerService */
-    void createNewUser(int userId) {
+    void createNewUser(int userId, String[] disallowedPackages) {
         synchronized (mInstallLock) {
-            mSettings.createNewUserLI(this, mInstaller, userId);
+            mSettings.createNewUserLI(this, mInstaller, userId, disallowedPackages);
         }
         synchronized (mPackages) {
             scheduleWritePackageRestrictionsLocked(userId);
@@ -21141,6 +21201,20 @@
                 return mSettings.wasPackageEverLaunchedLPr(packageName, userId);
             }
         }
+
+        @Override
+        public void grantRuntimePermission(String packageName, String name, int userId,
+                boolean overridePolicy) {
+            PackageManagerService.this.grantRuntimePermission(packageName, name, userId,
+                    overridePolicy);
+        }
+
+        @Override
+        public void revokeRuntimePermission(String packageName, String name, int userId,
+                boolean overridePolicy) {
+            PackageManagerService.this.revokeRuntimePermission(packageName, name, userId,
+                    overridePolicy);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 1d3471a..834d343 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -30,6 +30,10 @@
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageItemInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.ApkLite;
+import android.content.pm.PackageParser.PackageLite;
+import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
@@ -48,6 +52,7 @@
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.PrintWriterPrinter;
+import com.android.internal.content.PackageHelper;
 import com.android.internal.util.SizedInputStream;
 
 import dalvik.system.DexFile;
@@ -70,6 +75,11 @@
 import java.util.concurrent.TimeUnit;
 
 class PackageManagerShellCommand extends ShellCommand {
+    /** Path for streaming APK content */
+    private static final String STDIN_PATH = "-";
+    /** Whether or not APK content must be streamed from stdin */
+    private static final boolean FORCE_STREAM_INSTALL = true;
+
     final IPackageManager mInterface;
     final private WeakHashMap<String, Resources> mResourceCache =
             new WeakHashMap<String, Resources>();
@@ -134,15 +144,45 @@
         return -1;
     }
 
+    private void setParamsSize(InstallParams params, String inPath) {
+        // If we're forced to stream the package, the params size
+        // must be set via command-line argument. There's nothing
+        // to do here.
+        if (FORCE_STREAM_INSTALL) {
+            return;
+        }
+        final PrintWriter pw = getOutPrintWriter();
+        if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
+            File file = new File(inPath);
+            if (file.isFile()) {
+                try {
+                    ApkLite baseApk = PackageParser.parseApkLite(file, 0);
+                    PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null);
+                    params.sessionParams.setSize(PackageHelper.calculateInstalledSize(
+                            pkgLite, false, params.sessionParams.abiOverride));
+                } catch (PackageParserException | IOException e) {
+                    pw.println("Error: Failed to parse APK file: " + file);
+                    throw new IllegalArgumentException(
+                            "Error: Failed to parse APK file: " + file, e);
+                }
+            } else {
+                pw.println("Error: Can't open non-file: " + inPath);
+                throw new IllegalArgumentException("Error: Can't open non-file: " + inPath);
+            }
+        }
+    }
+
     private int runInstall() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         final InstallParams params = makeInstallParams();
+        final String inPath = getNextArg();
+
+        setParamsSize(params, inPath);
         final int sessionId = doCreateSession(params.sessionParams,
                 params.installerPackageName, params.userId);
         boolean abandonSession = true;
         try {
-            final String inPath = getNextArg();
-            if (inPath == null && params.sessionParams.sizeBytes == 0) {
+            if (inPath == null && params.sessionParams.sizeBytes == -1) {
                 pw.println("Error: must either specify a package size or an APK file");
                 return 1;
             }
@@ -1055,7 +1095,11 @@
                     }
                     break;
                 case "-S":
-                    sessionParams.setSize(Long.parseLong(getNextArg()));
+                    final long sizeBytes = Long.parseLong(getNextArg());
+                    if (sizeBytes <= 0) {
+                        throw new IllegalArgumentException("Size must be positive");
+                    }
+                    sessionParams.setSize(sizeBytes);
                     break;
                 case "--abi":
                     sessionParams.abiOverride = checkAbiArgument(getNextArg());
@@ -1160,15 +1204,22 @@
     private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
             boolean logSuccess) throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
+        if (FORCE_STREAM_INSTALL && inPath != null && !STDIN_PATH.equals(inPath)) {
+            pw.println("Error: APK content must be streamed");
+            return 1;
+        }
+        if (STDIN_PATH.equals(inPath)) {
+            inPath = null;
+        } else if (inPath != null) {
+            final File file = new File(inPath);
+            if (file.isFile()) {
+                sizeBytes = file.length();
+            }
+        }
         if (sizeBytes <= 0) {
             pw.println("Error: must specify a APK size");
             return 1;
         }
-        if (inPath != null && !"-".equals(inPath)) {
-            pw.println("Error: APK content must be streamed");
-            return 1;
-        }
-        inPath = null;
 
         final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId);
 
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 8cab355..6d514e4 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -430,10 +430,6 @@
     }
 
     PackageSetting getPackageLPr(String pkgName) {
-        return peekPackageLPr(pkgName);
-    }
-
-    PackageSetting peekPackageLPr(String pkgName) {
         return mPackages.get(pkgName);
     }
 
@@ -502,23 +498,20 @@
     }
 
     /** Gets and optionally creates a new shared user id. */
-    SharedUserSetting getSharedUserLPw(String name,
-            int pkgFlags, int pkgPrivateFlags, boolean create) {
+    SharedUserSetting getSharedUserLPw(String name, int pkgFlags, int pkgPrivateFlags,
+            boolean create) throws PackageManagerException {
         SharedUserSetting s = mSharedUsers.get(name);
-        if (s == null) {
-            if (!create) {
-                return null;
-            }
+        if (s == null && create) {
             s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
             s.userId = newUserIdLPw(s);
-            Log.i(PackageManagerService.TAG, "New shared user " + name + ": id=" + s.userId);
-            // < 0 means we couldn't assign a userid; fall out and return
-            // s, which is currently null
-            if (s.userId >= 0) {
-                mSharedUsers.put(name, s);
+            if (s.userId < 0) {
+                // < 0 means we couldn't assign a userid; throw exception
+                throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
+                        "Creating shared user " + name + " failed");
             }
+            Log.i(PackageManagerService.TAG, "New shared user " + name + ": id=" + s.userId);
+            mSharedUsers.put(name, s);
         }
-
         return s;
     }
 
@@ -875,9 +868,9 @@
      * Writes per-user package restrictions if the user state has changed. If the user
      * state has not changed, this does nothing.
      */
-    void writeUserRestrictions(PackageSetting newPackage, PackageSetting oldPackage) {
+    void writeUserRestrictionsLPw(PackageSetting newPackage, PackageSetting oldPackage) {
         // package doesn't exist; do nothing
-        if (peekPackageLPr(newPackage.name) == null) {
+        if (getPackageLPr(newPackage.name) == null) {
             return;
         }
         // no users defined; do nothing
@@ -3956,7 +3949,7 @@
     }
 
     void createNewUserLI(@NonNull PackageManagerService service, @NonNull Installer installer,
-            int userHandle) {
+            int userHandle, String[] disallowedPackages) {
         String[] volumeUuids;
         String[] names;
         int[] appIds;
@@ -3977,8 +3970,10 @@
                 if (ps.pkg == null || ps.pkg.applicationInfo == null) {
                     continue;
                 }
+                final boolean shouldInstall = ps.isSystem() &&
+                        !ArrayUtils.contains(disallowedPackages, ps.name);
                 // Only system apps are initially installed.
-                ps.setInstalled(ps.isSystem(), userHandle);
+                ps.setInstalled(shouldInstall, userHandle);
                 // Need to create a data directory for all apps under this user. Accumulate all
                 // required args and call the installer after mPackages lock has been released
                 volumeUuids[i] = ps.volumeUuid;
@@ -4088,7 +4083,7 @@
         return mVerifierDeviceIdentity;
     }
 
-    public boolean hasOtherDisabledSystemPkgWithChildLPr(String parentPackageName,
+    boolean hasOtherDisabledSystemPkgWithChildLPr(String parentPackageName,
             String childPackageName) {
         final int packageCount = mDisabledSysPackages.size();
         for (int i = 0; i < packageCount; i++) {
@@ -4260,7 +4255,7 @@
         ApplicationInfo.FLAG_LARGE_HEAP, "LARGE_HEAP",
     };
 
-    static final Object[] PRIVATE_FLAG_DUMP_SPEC = new Object[] {
+    private static final Object[] PRIVATE_FLAG_DUMP_SPEC = new Object[] {
         ApplicationInfo.PRIVATE_FLAG_HIDDEN, "HIDDEN",
         ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
         ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
@@ -4272,7 +4267,8 @@
         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",
-        ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES, "RESIZEABLE_ACTIVITIES",
+        ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET, "RESIZEABLE_ACTIVITIES_EXPLICITLY_SET",
+        ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION, "RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION",
         ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND, "BACKUP_IN_FOREGROUND",
     };
 
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 533d9b5..efd6f46 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -97,6 +97,7 @@
 import com.android.server.SystemService;
 import com.android.server.am.UserState;
 import com.android.server.storage.DeviceStorageMonitorInternal;
+
 import libcore.io.IoUtils;
 import libcore.util.Objects;
 
@@ -591,7 +592,7 @@
     @Override
     public int[] getProfileIds(int userId, boolean enabledOnly) {
         if (userId != UserHandle.getCallingUserId()) {
-            checkManageUsersPermission("getting profiles related to user " + userId);
+            checkManageOrCreateUsersPermission("getting profiles related to user " + userId);
         }
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -672,12 +673,10 @@
     public boolean isSameProfileGroup(int userId, int otherUserId) {
         if (userId == otherUserId) return true;
         checkManageUsersPermission("check if in the same profile group");
-        synchronized (mPackagesLock) {
-            return isSameProfileGroupLP(userId, otherUserId);
-        }
+        return isSameProfileGroupNoChecks(userId, otherUserId);
     }
 
-    private boolean isSameProfileGroupLP(int userId, int otherUserId) {
+    private boolean isSameProfileGroupNoChecks(int userId, int otherUserId) {
         synchronized (mUsersLock) {
             UserInfo userInfo = getUserInfoLU(userId);
             if (userInfo == null || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
@@ -879,12 +878,10 @@
     public boolean isManagedProfile(int userId) {
         int callingUserId = UserHandle.getCallingUserId();
         if (callingUserId != userId && !hasManageUsersPermission()) {
-            synchronized (mPackagesLock) {
-                if (!isSameProfileGroupLP(callingUserId, userId)) {
-                    throw new SecurityException(
-                            "You need MANAGE_USERS permission to: check if specified user a " +
-                            "managed profile outside your profile group");
-                }
+            if (!isSameProfileGroupNoChecks(callingUserId, userId)) {
+                throw new SecurityException(
+                        "You need MANAGE_USERS permission to: check if specified user a " +
+                        "managed profile outside your profile group");
             }
         }
         synchronized (mUsersLock) {
@@ -894,6 +891,18 @@
     }
 
     @Override
+    public boolean isUserUnlockingOrUnlocked(int userId) {
+        int callingUserId = UserHandle.getCallingUserId();
+        if (callingUserId != userId && !hasManageUsersPermission()) {
+            if (!isSameProfileGroupNoChecks(callingUserId, userId)) {
+                throw new SecurityException(
+                        "You need MANAGE_USERS permission to: check isUserUnlockingOrUnlocked");
+            }
+        }
+        return mLocalService.isUserUnlockingOrUnlocked(userId);
+    }
+
+    @Override
     public boolean isDemoUser(int userId) {
         int callingUserId = UserHandle.getCallingUserId();
         if (callingUserId != userId && !hasManageUsersPermission()) {
@@ -2182,9 +2191,17 @@
     }
 
     @Override
-    public UserInfo createProfileForUser(String name, int flags, int userId) {
+    public UserInfo createProfileForUser(String name, int flags, int userId,
+            String[] disallowedPackages) {
         checkManageOrCreateUsersPermission(flags);
-        return createUserInternal(name, flags, userId);
+        return createUserInternal(name, flags, userId, disallowedPackages);
+    }
+
+    @Override
+    public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags, int userId,
+            String[] disallowedPackages) {
+        checkManageOrCreateUsersPermission(flags);
+        return createUserInternalUnchecked(name, flags, userId, disallowedPackages);
     }
 
     @Override
@@ -2194,20 +2211,26 @@
     }
 
     private UserInfo createUserInternal(String name, int flags, int parentId) {
+        return createUserInternal(name, flags, parentId, null);
+    }
+
+    private UserInfo createUserInternal(String name, int flags, int parentId,
+            String[] disallowedPackages) {
         if (hasUserRestriction(UserManager.DISALLOW_ADD_USER, UserHandle.getCallingUserId())) {
             Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
             return null;
         }
+        return createUserInternalUnchecked(name, flags, parentId, disallowedPackages);
+    }
+
+    private UserInfo createUserInternalUnchecked(String name, int flags, int parentId,
+            String[] disallowedPackages) {
         DeviceStorageMonitorInternal dsm = LocalServices
                 .getService(DeviceStorageMonitorInternal.class);
         if (dsm.isMemoryLow()) {
             Log.w(LOG_TAG, "Cannot add user. Not enough space on disk.");
             return null;
         }
-        return createUserInternalUnchecked(name, flags, parentId);
-    }
-
-    private UserInfo createUserInternalUnchecked(String name, int flags, int parentId) {
         if (ActivityManager.isLowRamDeviceStatic()) {
             return null;
         }
@@ -2321,7 +2344,7 @@
             storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral());
             mPm.prepareUserData(userId, userInfo.serialNumber,
                     StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
-            mPm.createNewUser(userId);
+            mPm.createNewUser(userId, disallowedPackages);
             userInfo.partial = false;
             synchronized (mPackagesLock) {
                 writeUserLP(userData);
@@ -2371,7 +2394,8 @@
     @Override
     public UserInfo createRestrictedProfile(String name, int parentUserId) {
         checkManageOrCreateUsersPermission("setupRestrictedProfile");
-        final UserInfo user = createProfileForUser(name, UserInfo.FLAG_RESTRICTED, parentUserId);
+        final UserInfo user = createProfileForUser(
+                name, UserInfo.FLAG_RESTRICTED, parentUserId, null);
         if (user == null) {
             return null;
         }
@@ -3533,7 +3557,7 @@
 
         @Override
         public UserInfo createUserEvenWhenDisallowed(String name, int flags) {
-            UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL);
+            UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL, null);
             // Keep this in sync with UserManager.createUser
             if (user != null && !user.isAdmin()) {
                 setUserRestriction(UserManager.DISALLOW_SMS, true, user.id);
diff --git a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
index e6ec6a6..92729dc 100644
--- a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
+++ b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
@@ -43,7 +43,10 @@
     // Default value when max burnin radius is not set.
     public static final int BURN_IN_MAX_RADIUS_DEFAULT = -1;
 
-    private static final long BURNIN_PROTECTION_WAKEUP_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
+    private static final long BURNIN_PROTECTION_FIRST_WAKEUP_INTERVAL_MS =
+            TimeUnit.MINUTES.toMillis(1);
+    private static final long BURNIN_PROTECTION_SUBSEQUENT_WAKEUP_INTERVAL_MS =
+            TimeUnit.MINUTES.toMillis(2);
     private static final long BURNIN_PROTECTION_MINIMAL_INTERVAL_MS = TimeUnit.SECONDS.toMillis(10);
 
     private static final boolean DEBUG = false;
@@ -138,6 +141,9 @@
             // We don't want to adjust offsets immediately after the device goes into ambient mode.
             // Instead, we want to wait until it's more likely that the user is not observing the
             // screen anymore.
+            final long interval = mFirstUpdate
+                ? BURNIN_PROTECTION_FIRST_WAKEUP_INTERVAL_MS
+                : BURNIN_PROTECTION_SUBSEQUENT_WAKEUP_INTERVAL_MS;
             if (mFirstUpdate) {
                 mFirstUpdate = false;
             } else {
@@ -156,8 +162,7 @@
             // Next adjustment at least ten seconds in the future.
             long nextWall = nowWall + BURNIN_PROTECTION_MINIMAL_INTERVAL_MS;
             // And aligned to the minute.
-            nextWall = nextWall - nextWall % BURNIN_PROTECTION_WAKEUP_INTERVAL_MS
-                    + BURNIN_PROTECTION_WAKEUP_INTERVAL_MS;
+            nextWall = (nextWall - (nextWall % interval)) + interval;
             // Use elapsed real time that is adjusted to full minute on wall clock.
             final long nextElapsed = nowElapsed + (nextWall - nowWall);
             if (DEBUG) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b3430c6..b8b16d5 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -28,6 +28,7 @@
 import static android.view.WindowManager.DOCKED_TOP;
 import static android.view.WindowManager.DOCKED_LEFT;
 import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
 import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
 import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
 import static android.view.WindowManager.LayoutParams.*;
@@ -72,6 +73,7 @@
 import android.hardware.hdmi.HdmiPlaybackClient;
 import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
 import android.hardware.input.InputManagerInternal;
+import android.hardware.power.V1_0.PowerHint;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioSystem;
@@ -140,6 +142,7 @@
 import android.view.animation.AnimationSet;
 import android.view.animation.AnimationUtils;
 import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.policy.PhoneWindow;
 import com.android.internal.policy.IShortcutService;
@@ -176,7 +179,6 @@
     static final boolean DEBUG_STARTING_WINDOW = false;
     static final boolean DEBUG_WAKEUP = false;
     static final boolean SHOW_STARTING_ANIMATIONS = true;
-    static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
 
     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
     // No longer recommended for desk docks;
@@ -597,6 +599,13 @@
     private static final int DISMISS_KEYGUARD_CONTINUE = 2; // Keyguard has been dismissed.
     int mDismissKeyguard = DISMISS_KEYGUARD_NONE;
 
+    /**
+     * Indicates that we asked the Keyguard to be dismissed and we just wait for the Keyguard to
+     * dismiss itself.
+     */
+    @GuardedBy("Lw")
+    private boolean mCurrentlyDismissingKeyguard;
+
     /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only
      * be done once per window. */
     private WindowState mWinDismissingKeyguard;
@@ -900,7 +909,7 @@
             @Override
             public void run() {
                 // send interaction hint to improve redraw performance
-                mPowerManagerInternal.powerHint(PowerManagerInternal.POWER_HINT_INTERACTION, 0);
+                mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
                 updateRotation(false);
             }
         };
@@ -1831,7 +1840,7 @@
                     public void onFling(int duration) {
                         if (mPowerManagerInternal != null) {
                             mPowerManagerInternal.powerHint(
-                                    PowerManagerInternal.POWER_HINT_INTERACTION, duration);
+                                    PowerHint.INTERACTION, duration);
                         }
                     }
                     @Override
@@ -2726,7 +2735,7 @@
                 }
             }
 
-            if (overrideConfig != null && overrideConfig != EMPTY) {
+            if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
                 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based"
                         + " on overrideConfig" + overrideConfig + " for starting window");
                 final Context overrideContext = context.createConfigurationContext(overrideConfig);
@@ -3269,21 +3278,6 @@
                     mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
                             null, null, null, 0, null, null);
                     return -1;
-                } else if (SHOW_PROCESSES_ON_ALT_MENU &&
-                        (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
-                    Intent service = new Intent();
-                    service.setClassName(mContext, "com.android.server.LoadAverageService");
-                    ContentResolver res = mContext.getContentResolver();
-                    boolean shown = Settings.Global.getInt(
-                            res, Settings.Global.SHOW_PROCESSES, 0) != 0;
-                    if (!shown) {
-                        mContext.startService(service);
-                    } else {
-                        mContext.stopService(service);
-                    }
-                    Settings.Global.putInt(
-                            res, Settings.Global.SHOW_PROCESSES, shown ? 0 : 1);
-                    return -1;
                 }
             }
         } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
@@ -3710,10 +3704,11 @@
 
     @Override
     public boolean canShowDismissingWindowWhileLockedLw() {
-        // If the keyguard is trusted, it will unlock without a challange. Therefore, windows with
-        // FLAG_DISMISS_KEYGUARD don't need to be force hidden, as they will unlock the phone right
-        // away anyways.
-        return mKeyguardDelegate != null && mKeyguardDelegate.isTrusted();
+        // If the keyguard is trusted, it will unlock without a challenge. Therefore, if we are in
+        // the process of dismissing Keyguard, we don't need to hide them as the phone will be
+        // unlocked right away in any case.
+        return mKeyguardDelegate != null && mKeyguardDelegate.isTrusted()
+                && mCurrentlyDismissingKeyguard;
     }
 
     private void launchAssistLongPressAction() {
@@ -3966,14 +3961,6 @@
             }
         }
     }
-    final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
-            new InputEventReceiver.Factory() {
-        @Override
-        public InputEventReceiver createInputEventReceiver(
-                InputChannel inputChannel, Looper looper) {
-            return new HideNavInputEventReceiver(inputChannel, looper);
-        }
-    };
 
     @Override
     public void setRecentsVisibilityLw(boolean visible) {
@@ -4198,8 +4185,9 @@
                     mInputConsumer = null;
                 }
             } else if (mInputConsumer == null) {
-                mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(),
-                        mHideNavInputEventReceiverFactory);
+                mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
+                        INPUT_CONSUMER_NAVIGATION,
+                        (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
             }
 
             // For purposes of positioning and showing the nav bar, if we have
@@ -5420,22 +5408,27 @@
                 }
             } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
                 mKeyguardHidden = false;
-                final boolean trusted = mKeyguardDelegate.isTrusted();
-                if (trusted) {
-                    // No need to un-occlude keyguard - we'll dimiss it right away anyways.
-                } else if (setKeyguardOccludedLw(false)) {
-                    changes |= FINISH_LAYOUT_REDO_LAYOUT
-                            | FINISH_LAYOUT_REDO_CONFIG
-                            | FINISH_LAYOUT_REDO_WALLPAPER;
-                }
+                boolean willDismiss = false;
                 if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
+                    final boolean trusted = mKeyguardDelegate.isTrusted();
+                    willDismiss = trusted && mKeyguardOccluded && mKeyguardDelegate != null
+                            && mKeyguardDelegate.isShowing();
+                    if (willDismiss) {
+                        mCurrentlyDismissingKeyguard = true;
+                    }
+
                     // Only launch the next keyguard unlock window once per window.
-                    mHandler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            mKeyguardDelegate.dismiss(trusted /* allowWhileOccluded */);
-                        }
-                    });
+                    mHandler.post(() -> mKeyguardDelegate.dismiss(
+                            trusted /* allowWhileOccluded */));
+                }
+
+                // If we are currently dismissing Keyguard, there is no need to unocclude it.
+                if (!mCurrentlyDismissingKeyguard) {
+                    if (setKeyguardOccludedLw(false)) {
+                        changes |= FINISH_LAYOUT_REDO_LAYOUT
+                                | FINISH_LAYOUT_REDO_CONFIG
+                                | FINISH_LAYOUT_REDO_WALLPAPER;
+                    }
                 }
             } else {
                 mWinDismissingKeyguard = null;
@@ -5485,11 +5478,23 @@
             mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
             mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
             return true;
+        } else if (wasOccluded != isOccluded) {
+            mKeyguardOccluded = isOccluded;
+            mKeyguardDelegate.setOccluded(isOccluded, false /* animate */);
+            return false;
         } else {
             return false;
         }
     }
 
+    private void onKeyguardShowingStateChanged(boolean showing) {
+        if (!showing) {
+            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
+                mCurrentlyDismissingKeyguard = false;
+            }
+        }
+    }
+
     private boolean isStatusBarKeyguard() {
         return mStatusBar != null
                 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
@@ -7020,7 +7025,8 @@
     /** {@inheritDoc} */
     @Override
     public void systemReady() {
-        mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
+        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
+                this::onKeyguardShowingStateChanged);
         mKeyguardDelegate.onSystemReady();
 
         readCameraLensCoverState();
@@ -8106,6 +8112,7 @@
                 pw.print(" mForceStatusBarFromKeyguard=");
                 pw.println(mForceStatusBarFromKeyguard);
         pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
+                pw.print(" mCurrentlyDismissingKeyguard="); pw.println(mCurrentlyDismissingKeyguard);
                 pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
                 pw.print(" mHomePressed="); pw.println(mHomePressed);
         pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 2069f24..10c237f 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -23,6 +23,7 @@
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
 import com.android.server.UiThread;
+import com.android.server.policy.keyguard.KeyguardStateMonitor.OnShowingStateChangedCallback;
 
 import java.io.PrintWriter;
 
@@ -49,6 +50,7 @@
     private final Handler mScrimHandler;
     private final KeyguardState mKeyguardState = new KeyguardState();
     private DrawnListener mDrawnListenerWhenConnect;
+    private final OnShowingStateChangedCallback mShowingStateChangedCallback;
 
     private static final class KeyguardState {
         KeyguardState() {
@@ -117,9 +119,11 @@
         }
     };
 
-    public KeyguardServiceDelegate(Context context) {
+    public KeyguardServiceDelegate(Context context,
+            OnShowingStateChangedCallback showingStateChangedCallback) {
         mContext = context;
         mScrimHandler = UiThread.getHandler();
+        mShowingStateChangedCallback = showingStateChangedCallback;
         mScrim = createScrim(context, mScrimHandler);
     }
 
@@ -155,7 +159,7 @@
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
             mKeyguardService = new KeyguardServiceWrapper(mContext,
-                    IKeyguardService.Stub.asInterface(service));
+                    IKeyguardService.Stub.asInterface(service), mShowingStateChangedCallback);
             if (mKeyguardState.systemIsReady) {
                 // If the system is ready, it means keyguard crashed and restarted.
                 mKeyguardService.onSystemReady();
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index 1d85f34..acc67db 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -26,6 +26,7 @@
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
 import com.android.internal.policy.IKeyguardStateCallback;
+import com.android.server.policy.keyguard.KeyguardStateMonitor.OnShowingStateChangedCallback;
 
 import java.io.PrintWriter;
 
@@ -39,9 +40,11 @@
     private IKeyguardService mService;
     private String TAG = "KeyguardServiceWrapper";
 
-    public KeyguardServiceWrapper(Context context, IKeyguardService service) {
+    public KeyguardServiceWrapper(Context context, IKeyguardService service,
+            OnShowingStateChangedCallback showingStateChangedCallback) {
         mService = service;
-        mKeyguardStateMonitor = new KeyguardStateMonitor(context, service);
+        mKeyguardStateMonitor = new KeyguardStateMonitor(context, service,
+                showingStateChangedCallback);
     }
 
     @Override // Binder interface
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index 08eaaa9..712b625 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -49,10 +49,13 @@
     private int mCurrentUserId;
 
     private final LockPatternUtils mLockPatternUtils;
+    private final OnShowingStateChangedCallback mOnShowingStateChangedCallback;
 
-    public KeyguardStateMonitor(Context context, IKeyguardService service) {
+    public KeyguardStateMonitor(Context context, IKeyguardService service,
+            OnShowingStateChangedCallback showingStateChangedCallback) {
         mLockPatternUtils = new LockPatternUtils(context);
         mCurrentUserId = ActivityManager.getCurrentUser();
+        mOnShowingStateChangedCallback = showingStateChangedCallback;
         try {
             service.addStateMonitorCallback(this);
         } catch (RemoteException e) {
@@ -83,6 +86,7 @@
     @Override // Binder interface
     public void onShowingStateChanged(boolean showing) {
         mIsShowing = showing;
+        mOnShowingStateChangedCallback.onShowingStateChanged(showing);
     }
 
     @Override // Binder interface
@@ -122,4 +126,8 @@
         pw.println(prefix + "mTrusted=" + mTrusted);
         pw.println(prefix + "mCurrentUserId=" + mCurrentUserId);
     }
+
+    public interface OnShowingStateChangedCallback {
+        void onShowingStateChanged(boolean showing);
+    }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 7576cddad..706828b 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -31,6 +31,7 @@
 import android.hardware.SystemSensorManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.hardware.power.V1_0.PowerHint;
 import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.BatteryManagerInternal;
@@ -84,7 +85,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 
-import static android.os.PowerManagerInternal.POWER_HINT_INTERACTION;
 import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
 import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
@@ -163,10 +163,6 @@
     // How long a partial wake lock must be held until we consider it a long wake lock.
     static final long MIN_LONG_WAKE_CHECK_INTERVAL = 60*1000;
 
-    // Power hints defined in hardware/libhardware/include/hardware/power.h.
-    private static final int POWER_HINT_LOW_POWER = 5;
-    private static final int POWER_HINT_VR_MODE = 7;
-
     // Power features defined in hardware/libhardware/include/hardware/power.h.
     private static final int POWER_FEATURE_DOUBLE_TAP_TO_WAKE = 1;
 
@@ -826,7 +822,7 @@
 
         if (mLowPowerModeEnabled != lowPowerModeEnabled) {
             mLowPowerModeEnabled = lowPowerModeEnabled;
-            powerHintInternal(POWER_HINT_LOW_POWER, lowPowerModeEnabled ? 1 : 0);
+            powerHintInternal(PowerHint.LOW_POWER, lowPowerModeEnabled ? 1 : 0);
             postAfterBootCompleted(new Runnable() {
                 @Override
                 public void run() {
@@ -1152,7 +1148,7 @@
         Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity");
         try {
             if (eventTime > mLastInteractivePowerHintTime) {
-                powerHintInternal(POWER_HINT_INTERACTION, 0);
+                powerHintInternal(PowerHint.INTERACTION, 0);
                 mLastInteractivePowerHintTime = eventTime;
             }
 
@@ -3083,7 +3079,7 @@
     private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
         @Override
         public void onVrStateChanged(boolean enabled) {
-            powerHintInternal(POWER_HINT_VR_MODE, enabled ? 1 : 0);
+            powerHintInternal(PowerHint.VR_MODE, enabled ? 1 : 0);
         }
     };
 
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index d219aed..353d663 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -872,6 +872,11 @@
                         } catch (RemoteException e) {
                         }
                     }
+                    final Intent lockIntent = new Intent(Intent.ACTION_DEVICE_LOCKED_CHANGED);
+                    lockIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                    lockIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                    mContext.sendBroadcastAsUser(lockIntent, UserHandle.SYSTEM,
+                            Manifest.permission.TRUST_LISTENER, /* options */ null);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index b488297..47414a0 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -915,7 +915,11 @@
         public void updateTvInputInfo(TvInputInfo inputInfo, int userId) {
             String inputInfoPackageName = inputInfo.getServiceInfo().packageName;
             String callingPackageName = getCallingPackageName();
-            if (!TextUtils.equals(inputInfoPackageName, callingPackageName)) {
+            if (!TextUtils.equals(inputInfoPackageName, callingPackageName)
+                    && mContext.checkCallingPermission(
+                            android.Manifest.permission.WRITE_SECURE_SETTINGS)
+                                    != PackageManager.PERMISSION_GRANTED) {
+                // Only the app owning the input and system settings are allowed to update info.
                 throw new IllegalArgumentException("calling package " + callingPackageName
                         + " is not allowed to change TvInputInfo for " + inputInfoPackageName);
             }
diff --git a/services/core/java/com/android/server/utils/PriorityDump.java b/services/core/java/com/android/server/utils/PriorityDump.java
new file mode 100644
index 0000000..c05cc3f
--- /dev/null
+++ b/services/core/java/com/android/server/utils/PriorityDump.java
@@ -0,0 +1,179 @@
+/**
+ * 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.utils;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Helper for {@link android.os.Binder#dump(java.io.FileDescriptor, String[])} that supports the
+ * {@link #PRIORITY_ARG} argument.
+ * <p>
+ * Typical usage:
+ *
+ * <pre><code>
+public class SpringfieldNuclearPowerPlant extends Binder {
+
+ private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {
+
+     @Override
+     public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
+       pw.println("Donuts in the box: 1");
+     }
+
+     @Override
+     public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
+       pw.println("Nuclear reactor status: DANGER - MELTDOWN IMMINENT");
+     }
+  };
+
+  @Override
+  protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+      PriorityDump.dump(mPriorityDumper, fd, pw, args);
+  }
+}
+
+ * </code></pre>
+ *
+ * <strong>Disclaimer</strong>: a real-life service should prioritize core status over donuts :-)
+ *
+ * <p>Then to invoke it:
+ *
+ * <pre><code>
+ *
+    $ adb shell dumpsys snpp
+    Donuts in the box: 1
+    Nuclear reactor status: DANGER - MELTDOWN IMMINENT
+
+    $ adb shell dumpsys snpp --dump_priority CRITICAL
+    Donuts in the box: 1
+
+    $ adb shell dumpsys snpp --dump_priority NORMAL
+    Nuclear reactor status: DANGER - MELTDOWN IMMINENT
+
+ * </code></pre>
+ *
+ *
+ *
+ * <p>To run the unit tests:
+ * <pre><code>
+ *
+ mmm -j32 frameworks/base/services/tests/servicestests/ && \
+ adb install -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && \
+ adb shell am instrument -e class "com.android.server.utils.PriorityDumpTest" \
+ -w "com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner"
+
+ * </code></pre>
+ *
+ *
+ * @hide
+ */
+public final class PriorityDump {
+
+    public static final String PRIORITY_ARG = "--dump_priority";
+
+    private PriorityDump() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Parses {@code} and call the proper {@link PriorityDumper} method when the first argument is
+     * {@code --dump_priority}, stripping the priority and its type.
+     * <p>
+     * For example, if called as {@code --dump_priority HIGH arg1 arg2 arg3}, it will call
+     * <code>dumper.dumpHigh(fd, pw, {"arg1", "arg2", "arg3"}) </code>
+     * <p>
+     * If the {@code --dump_priority} is not set, it calls
+     * {@link PriorityDumper#dump(FileDescriptor, PrintWriter, String[])} passing the whole
+     * {@code args} instead.
+     */
+    public static void dump(PriorityDumper dumper, FileDescriptor fd, PrintWriter pw,
+            String[] args) {
+        if (args != null && args.length >= 2 && args[0].equals(PRIORITY_ARG)) {
+            final String priority = args[1];
+            switch (priority) {
+                case "CRITICAL": {
+                    dumper.dumpCritical(fd, pw, getStrippedArgs(args));
+                    return;
+                }
+                case "HIGH": {
+                    dumper.dumpHigh(fd, pw, getStrippedArgs(args));
+                    return;
+                }
+                case "NORMAL": {
+                    dumper.dumpNormal(fd, pw, getStrippedArgs(args));
+                    return;
+                }
+            }
+        }
+        dumper.dump(fd, pw, args);
+    }
+
+    /**
+     * Gets an array without the {@code --dump_priority PRIORITY} prefix.
+     */
+    private static String[] getStrippedArgs(String[] args) {
+        final String[] stripped = new String[args.length - 2];
+        System.arraycopy(args, 2, stripped, 0, stripped.length);
+        return stripped;
+    }
+
+    /**
+     * Helper for {@link android.os.Binder#dump(java.io.FileDescriptor, String[])} that supports the
+     * {@link #PRIORITY_ARG} argument.
+     *
+     * @hide
+     */
+    public static interface PriorityDumper {
+
+        /**
+         * Dumps only the critical section.
+         */
+        @SuppressWarnings("unused")
+        default void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
+        }
+
+        /**
+         * Dumps only the high-priority section.
+         */
+        @SuppressWarnings("unused")
+        default void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args) {
+        }
+
+        /**
+         * Dumps only the normal section.
+         */
+        @SuppressWarnings("unused")
+        default void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
+        }
+
+        /**
+         * Dumps all sections.
+         * <p>
+         * This method is called when
+         * {@link PriorityDump#dump(PriorityDumper, FileDescriptor, PrintWriter, String[])} is
+         * called without priority arguments. By default, it calls the 3 {@code dumpTYPE} methods,
+         * so sub-classes just need to implement the priority types they support.
+         */
+        @SuppressWarnings("unused")
+        default void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            dumpCritical(fd, pw, args);
+            dumpHigh(fd, pw, args);
+            dumpNormal(fd, pw, args);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 5514551..7439f535 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -480,6 +480,7 @@
     WallpaperData mLastWallpaper;
     IWallpaperManagerCallback mKeyguardListener;
     boolean mWaitingForUnlock;
+    boolean mShuttingDown;
 
     /**
      * ID of the current wallpaper, changed every time anything sets a wallpaper.
@@ -607,6 +608,14 @@
 
         private Runnable mResetRunnable = () -> {
             synchronized (mLock) {
+                if (mShuttingDown) {
+                    // Don't expect wallpaper services to relaunch during shutdown
+                    if (DEBUG) {
+                        Slog.i(TAG, "Ignoring relaunch timeout during shutdown");
+                    }
+                    return;
+                }
+
                 if (!mWallpaper.wallpaperUpdating
                         && mWallpaper.userId == mCurrentUserId) {
                     Slog.w(TAG, "Wallpaper reconnect timed out, "
@@ -867,6 +876,7 @@
     public WallpaperManagerService(Context context) {
         if (DEBUG) Slog.v(TAG, "WallpaperService startup");
         mContext = context;
+        mShuttingDown = false;
         mImageWallpaper = ComponentName.unflattenFromString(
                 context.getResources().getString(R.string.image_wallpaper_component));
         mIWindowManager = IWindowManager.Stub.asInterface(
@@ -931,6 +941,21 @@
             }
         }, userFilter);
 
+        final IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
+                    if (DEBUG) {
+                        Slog.i(TAG, "Shutting down");
+                    }
+                    synchronized (mLock) {
+                        mShuttingDown = true;
+                    }
+                }
+            }
+        }, shutdownFilter);
+
         try {
             ActivityManagerNative.getDefault().registerUserSwitchObserver(
                     new UserSwitchObserver() {
@@ -1012,6 +1037,7 @@
             for (String filename : sPerUserFiles) {
                 new File(wallpaperDir, filename).delete();
             }
+            mUserRestorecon.remove(userId);
         }
     }
 
@@ -1453,7 +1479,7 @@
         lockWP.cropHint.set(sysWP.cropHint);
         lockWP.width = sysWP.width;
         lockWP.height = sysWP.height;
-        lockWP.allowBackup = false;
+        lockWP.allowBackup = sysWP.allowBackup;
 
         // Migrate the bitmap files outright; no need to copy
         try {
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 43cdf59..6d97796 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.PatternMatcher;
@@ -224,7 +225,13 @@
 
         @Override // Binder call
         public String getCurrentWebViewPackageName() {
-            return WebViewUpdateService.this.mImpl.getCurrentWebViewPackageName();
+            PackageInfo pi = WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
+            return pi == null ? null : pi.packageName;
+        }
+
+        @Override // Binder call
+        public PackageInfo getCurrentWebViewPackage() {
+            return WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
         }
 
         @Override // Binder call
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index 3a93b46..b69a8c1 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -145,8 +145,8 @@
         return mSystemInterface.getWebViewPackages();
     }
 
-    String getCurrentWebViewPackageName() {
-        return mWebViewUpdater.getCurrentWebViewPackageName();
+    PackageInfo getCurrentWebViewPackage() {
+        return mWebViewUpdater.getCurrentWebViewPackage();
     }
 
     void enableFallbackLogic(boolean enable) {
@@ -316,6 +316,7 @@
                                 onWebViewProviderChanged(newPackage);
                             }
                         } catch (WebViewPackageMissingException e) {
+                            mCurrentWebViewPackage = null;
                             Slog.e(TAG, "Could not find valid WebView package to create " +
                                     "relro with " + e);
                         }
@@ -371,6 +372,7 @@
                     providerChanged = (oldPackage == null)
                             || !newPackage.packageName.equals(oldPackage.packageName);
                 } catch (WebViewPackageMissingException e) {
+                    mCurrentWebViewPackage = null;
                     Slog.e(TAG, "Tried to change WebView provider but failed to fetch WebView " +
                             "package " + e);
                     // If we don't perform the user change but don't have an installed WebView
@@ -548,11 +550,9 @@
             return new WebViewProviderResponse(webViewPackage, webViewStatus);
         }
 
-        public String getCurrentWebViewPackageName() {
+        public PackageInfo getCurrentWebViewPackage() {
             synchronized(mLock) {
-                if (mCurrentWebViewPackage == null)
-                    return null;
-                return mCurrentWebViewPackage.packageName;
+                return mCurrentWebViewPackage;
             }
         }
 
@@ -579,6 +579,7 @@
                         PackageInfo newPackage = findPreferredWebViewPackage();
                         onWebViewProviderChanged(newPackage);
                     } catch (WebViewPackageMissingException e) {
+                        mCurrentWebViewPackage = null;
                         // If we can't find any valid WebView package we are now in a state where
                         // mAnyWebViewInstalled is false, so loading WebView will be blocked and we
                         // should simply wait until we receive an intent declaring a new package was
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 0605d80..893749e 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -654,7 +654,7 @@
                 final int windowCount = windowList.size();
                 for (int i = 0; i < windowCount; i++) {
                     WindowState windowState = windowList.get(i);
-                    if (windowState.isOnScreen() &&
+                    if (windowState.isOnScreen() && windowState.isVisibleLw() &&
                             !windowState.mWinAnimator.mEnterAnimationPending) {
                         outWindows.put(windowState.mLayer, windowState);
                     }
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 305e47f..429cb2d 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
@@ -332,7 +333,7 @@
     }
 
     // This must be called while inside a transaction.
-    boolean stepAnimationLocked(long currentTime, final int displayId) {
+    boolean stepAnimationLocked(long currentTime) {
         if (mService.okToDisplay()) {
             // We will run animations as long as the display isn't frozen.
 
@@ -383,8 +384,7 @@
             return false;
         }
 
-        mAppToken.setAppLayoutChanges(
-                WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM, "AppWindowToken", displayId);
+        mAppToken.setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "AppWindowToken");
 
         clearAnimation();
         animating = false;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 508cf24..ee7c6d2 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -158,8 +158,10 @@
     ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
     ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
 
-    AppWindowToken(WindowManagerService service, IApplicationToken token, boolean _voiceInteraction) {
-        super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true);
+    AppWindowToken(WindowManagerService service, IApplicationToken token, boolean _voiceInteraction,
+            DisplayContent displayContent) {
+        super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true,
+                displayContent);
         appToken = token;
         voiceInteraction = _voiceInteraction;
         mInputApplicationHandle = new InputApplicationHandle(this);
@@ -268,7 +270,7 @@
                 final WindowState window = findMainWindow();
                 //TODO (multidisplay): Magnification is supported only for the default display.
                 if (window != null && accessibilityController != null
-                        && window.getDisplayId() == DEFAULT_DISPLAY) {
+                        && getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) {
                     accessibilityController.onAppWindowTransitionLocked(window, transit);
                 }
                 changed = true;
@@ -416,22 +418,15 @@
      * surfaces that's eligible, if the app is already stopped.
      */
     private void destroySurfaces(boolean cleanupOnResume) {
-        final DisplayContentList displayList = new DisplayContentList();
+        boolean destroyedSomething = false;
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             final WindowState win = mChildren.get(i);
-            final boolean destroyed = win.destroySurface(cleanupOnResume, mAppStopped);
-
-            if (destroyed) {
-                final DisplayContent displayContent = win.getDisplayContent();
-                if (displayContent != null && !displayList.contains(displayContent)) {
-                    displayList.add(displayContent);
-                }
-            }
+            destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
         }
-        for (int i = 0; i < displayList.size(); i++) {
-            final DisplayContent displayContent = displayList.get(i);
-            mService.mLayersController.assignLayersLocked(displayContent.getWindowList());
-            displayContent.setLayoutNeeded();
+        if (destroyedSomething) {
+            final DisplayContent dc = getDisplayContent();
+            mService.mLayersController.assignLayersLocked(dc.getWindowList());
+            dc.setLayoutNeeded();
         }
     }
 
@@ -698,7 +693,7 @@
         }
     }
 
-    boolean waitingForReplacement() {
+    private boolean waitingForReplacement() {
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             final WindowState candidate = mChildren.get(i);
             if (candidate.waitingForReplacement()) {
@@ -814,17 +809,12 @@
         }
     }
 
-    void setAppLayoutChanges(int changes, String reason, int displayId) {
-        final WindowAnimator windowAnimator = mAppAnimator.mAnimator;
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            // Child windows will be on the same display as their parents.
-            if (displayId == (mChildren.get(i)).getDisplayId()) {
-                windowAnimator.setPendingLayoutChanges(displayId, changes);
-                if (DEBUG_LAYOUT_REPEATS) {
-                    mService.mWindowPlacerLocked.debugLayoutRepeats(
-                            reason, windowAnimator.getPendingLayoutChanges(displayId));
-                }
-                break;
+    void setAppLayoutChanges(int changes, String reason) {
+        if (!mChildren.isEmpty()) {
+            final DisplayContent dc = getDisplayContent();
+            dc.pendingLayoutChanges |= changes;
+            if (DEBUG_LAYOUT_REPEATS) {
+                mService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
             }
         }
     }
@@ -897,7 +887,7 @@
     }
 
     boolean transferStartingWindow(IBinder transferFrom) {
-        final AppWindowToken fromToken = mService.findAppWindowToken(transferFrom);
+        final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
         if (fromToken == null) {
             return false;
         }
@@ -929,7 +919,7 @@
 
             if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
                     "Removing starting window: " + tStartingWindow);
-            tStartingWindow.getWindowList().remove(tStartingWindow);
+            getDisplayContent().getWindowList().remove(tStartingWindow);
             mService.mWindowsChanged = true;
             if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
                     "Removing starting " + tStartingWindow + " from " + fromToken);
@@ -1026,7 +1016,7 @@
     }
 
     @Override
-    void checkAppWindowsReadyToShow(int displayId) {
+    void checkAppWindowsReadyToShow() {
         if (allDrawn == mAppAnimator.allDrawn) {
             return;
         }
@@ -1045,9 +1035,9 @@
                     + " numInteresting=" + mNumInterestingWindows + " numDrawn=" + mNumDrawnWindows);
             // This will set mOrientationChangeComplete and cause a pass through layout.
             setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
-                    "checkAppWindowsReadyToShow: freezingScreen", displayId);
+                    "checkAppWindowsReadyToShow: freezingScreen");
         } else {
-            setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow", displayId);
+            setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
 
             // We can now show all of the drawn windows!
             if (!mService.mOpeningApps.contains(this)) {
@@ -1168,30 +1158,29 @@
     }
 
     @Override
-    void stepAppWindowsAnimation(long currentTime, int displayId) {
+    void stepAppWindowsAnimation(long currentTime) {
         mAppAnimator.wasAnimating = mAppAnimator.animating;
-        if (mAppAnimator.stepAnimationLocked(currentTime, displayId)) {
+        if (mAppAnimator.stepAnimationLocked(currentTime)) {
             mAppAnimator.animating = true;
             mService.mAnimator.setAnimating(true);
             mService.mAnimator.mAppWindowAnimating = true;
         } else if (mAppAnimator.wasAnimating) {
             // stopped animating, do one more pass through the layout
-            setAppLayoutChanges(
-                    FINISH_LAYOUT_REDO_WALLPAPER, "appToken " + this + " done", displayId);
+            setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER, "appToken " + this + " done");
             if (DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating " + this);
         }
     }
 
-    int rebuildWindowListUnchecked(DisplayContent dc, int addIndex) {
-        return super.rebuildWindowList(dc, addIndex);
+    int rebuildWindowListUnchecked(int addIndex) {
+        return super.rebuildWindowList(addIndex);
     }
 
     @Override
-    int rebuildWindowList(DisplayContent dc, int addIndex) {
+    int rebuildWindowList(int addIndex) {
         if (mIsExiting && !waitingForReplacement()) {
             return addIndex;
         }
-        return rebuildWindowListUnchecked(dc, addIndex);
+        return rebuildWindowListUnchecked(addIndex);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 42e9e23..3681123 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -23,6 +23,12 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.FLAG_PRIVATE;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
 import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.DOCKED_TOP;
@@ -43,22 +49,29 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
+import static com.android.server.wm.WindowManagerService.dipToPixel;
+import static com.android.server.wm.WindowManagerService.localLOGV;
 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager.StackId;
 import android.content.res.Configuration;
+import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.Region;
 import android.graphics.Region.Op;
 import android.hardware.display.DisplayManagerInternal;
 import android.os.Debug;
+import android.os.Handler;
+import android.os.IBinder;
 import android.util.DisplayMetrics;
 import android.util.Slog;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.IWindow;
-import android.view.Surface;
+
 import com.android.internal.util.FastPrintWriter;
 
 import java.io.FileDescriptor;
@@ -66,11 +79,11 @@
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 
-class DisplayContentList extends ArrayList<DisplayContent> {
-}
-
 /**
  * Utility class for keeping track of the WindowStates and other pertinent contents of a
  * particular Display.
@@ -78,15 +91,24 @@
  * IMPORTANT: No method from this class should ever be used without holding
  * WindowManagerService.mWindowMap.
  */
-class DisplayContent extends WindowContainer<TaskStack> {
+class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
 
     /** 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).
+    private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
+    private final NonAppWindowContainers mNonAppWindowContainers = new NonAppWindowContainers();
+
     /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
      * from mDisplayWindows; */
     private final WindowList mWindows = new WindowList();
 
+    // Mapping from a token IBinder to a WindowToken object on this display.
+    private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
+
     int mInitialDisplayWidth = 0;
     int mInitialDisplayHeight = 0;
     int mInitialDisplayDensity = 0;
@@ -122,12 +144,14 @@
     /** Save allocating when calculating rects */
     private final Rect mTmpRect = new Rect();
     private final Rect mTmpRect2 = new Rect();
+    private final RectF mTmpRectF = new RectF();
+    private final Matrix mTmpMatrix = new Matrix();
     private final Region mTmpRegion = new Region();
 
     final WindowManagerService mService;
 
     /** Remove this display when animation on it has completed. */
-    boolean mDeferredRemoval;
+    private boolean mDeferredRemoval;
 
     final DockedStackDividerController mDividerControllerLocked;
 
@@ -143,6 +167,10 @@
     private final GetWindowOnDisplaySearchResult mTmpGetWindowOnDisplaySearchResult =
             new GetWindowOnDisplaySearchResult();
 
+    // True if this display is in the process of being removed. Used to determine if the removal of
+    // the display's direct children should be allowed.
+    private boolean mRemovingDisplay = false;
+
     /**
      * @param display May not be null.
      * @param service You know.
@@ -152,11 +180,15 @@
         mDisplayId = display.getDisplayId();
         display.getDisplayInfo(mDisplayInfo);
         display.getMetrics(mDisplayMetrics);
-        isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
+        isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
         mService = service;
         initializeDisplayBaseInfo();
         mDividerControllerLocked = new DockedStackDividerController(service, this);
         mDimLayerController = new DimLayerController(this);
+
+        // These are the only direct children we should ever have and they are permanent.
+        super.addChild(mTaskStackContainers, null);
+        super.addChild(mNonAppWindowContainers, null);
     }
 
     int getDisplayId() {
@@ -167,6 +199,45 @@
         return mWindows;
     }
 
+    WindowToken getWindowToken(IBinder binder) {
+        return mTokenMap.get(binder);
+    }
+
+    AppWindowToken getAppWindowToken(IBinder binder) {
+        final WindowToken token = getWindowToken(binder);
+        if (token == null) {
+            return null;
+        }
+        return token.asAppWindowToken();
+    }
+
+    void setWindowToken(IBinder binder, WindowToken token) {
+        final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
+        if (dc != null) {
+            // We currently don't support adding a window token to the display if the display
+            // already has the binder mapped to another token. If there is a use case for supporting
+            // this moving forward we will either need to merge the WindowTokens some how or have
+            // the binder map to a list of window tokens.
+            throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this
+                    + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
+        }
+        mTokenMap.put(binder, token);
+
+        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);
+        }
+    }
+
+    WindowToken removeWindowToken(IBinder binder) {
+        final WindowToken token = mTokenMap.remove(binder);
+        if (token != null && token.asAppWindowToken() == null) {
+            mNonAppWindowContainers.removeChild(token);
+        }
+        return token;
+    }
+
     Display getDisplay() {
         return mDisplay;
     }
@@ -191,19 +262,19 @@
     }
 
     boolean isPrivate() {
-        return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0;
+        return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
     }
 
     TaskStack getHomeStack() {
-        if (mHomeStack == null && mDisplayId == Display.DEFAULT_DISPLAY) {
+        if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
             Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
         }
         return mHomeStack;
     }
 
     TaskStack getStackById(int stackId) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mChildren.get(i);
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mTaskStackContainers.get(i);
             if (stack.mStackId == stackId) {
                 return stack;
             }
@@ -228,22 +299,14 @@
      * bounds were updated.
      */
     void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mChildren.get(i);
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mTaskStackContainers.get(i);
             if (stack.updateBoundsAfterConfigChange()) {
                 changedStackList.add(stack.mStackId);
             }
         }
     }
 
-    void checkAppWindowsReadyToShow() {
-        super.checkAppWindowsReadyToShow(mDisplayId);
-    }
-
-    void stepAppWindowsAnimation(long currentTime) {
-        super.stepAppWindowsAnimation(currentTime, mDisplayId);
-    }
-
     @Override
     boolean fillsParent() {
         return true;
@@ -294,8 +357,8 @@
     void updateDisplayInfo() {
         mDisplay.getDisplayInfo(mDisplayInfo);
         mDisplay.getMetrics(mDisplayMetrics);
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            mChildren.get(i).updateDisplayInfo(null);
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            mTaskStackContainers.get(i).updateDisplayInfo(null);
         }
     }
 
@@ -318,8 +381,7 @@
     void getLogicalDisplayRect(Rect out) {
         // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
         final int orientation = mDisplayInfo.rotation;
-        boolean rotated = (orientation == Surface.ROTATION_90
-                || orientation == Surface.ROTATION_270);
+        boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
         final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
         final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
         int width = mDisplayInfo.logicalWidth;
@@ -329,51 +391,53 @@
         out.set(left, top, left + width, top + height);
     }
 
+    private void getLogicalDisplayRect(Rect out, int orientation) {
+        getLogicalDisplayRect(out);
+
+        // Rotate the Rect if needed.
+        final int currentRotation = mDisplayInfo.rotation;
+        final int rotationDelta = deltaRotation(currentRotation, orientation);
+        if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
+            createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
+            mTmpRectF.set(out);
+            mTmpMatrix.mapRect(mTmpRectF);
+            mTmpRectF.round(out);
+        }
+    }
+
     void getContentRect(Rect out) {
         out.set(mContentRect);
     }
 
     /** Refer to {@link WindowManagerService#attachStack(int, int, boolean)} */
     void attachStack(TaskStack stack, boolean onTop) {
-        if (stack.mStackId == HOME_STACK_ID) {
-            if (mHomeStack != null) {
-                throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
-            }
-            mHomeStack = stack;
-        }
-        addChild(stack, onTop);
+        mTaskStackContainers.attachStack(stack, onTop);
     }
 
     void moveStack(TaskStack stack, boolean toTop) {
-        if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
-            // This stack is always-on-top silly...
-            Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom");
-            return;
-        }
-
-        if (!mChildren.contains(stack)) {
-            Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
-        }
-        removeChild(stack);
-        addChild(stack, toTop);
+        mTaskStackContainers.moveStack(stack, toTop);
     }
 
-    private void addChild(TaskStack stack, boolean toTop) {
-        int addIndex = toTop ? mChildren.size() : 0;
+    @Override
+    protected void addChild(DisplayChildWindowContainer child,
+            Comparator<DisplayChildWindowContainer> comparator) {
+        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
+    }
 
-        if (toTop
-                && mService.isStackVisibleLocked(PINNED_STACK_ID)
-                && stack.mStackId != PINNED_STACK_ID) {
-            // The pinned stack is always the top most stack (always-on-top) when it is visible.
-            // So, stack is moved just below the pinned stack.
-            addIndex--;
-            TaskStack topStack = mChildren.get(addIndex);
-            if (topStack.mStackId != PINNED_STACK_ID) {
-                throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
-            }
+    @Override
+    protected void addChild(DisplayChildWindowContainer child, int index) {
+        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
+    }
+
+    @Override
+    protected void removeChild(DisplayChildWindowContainer child) {
+        // Only allow removal of direct children from this display if the display is in the process
+        // of been removed.
+        if (mRemovingDisplay) {
+            super.removeChild(child);
+            return;
         }
-        addChild(stack, addIndex);
-        setLayoutNeeded();
+        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
     }
 
     /**
@@ -385,8 +449,8 @@
     }
 
     int taskIdFromPoint(int x, int y) {
-        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mChildren.get(stackNdx);
+        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mTaskStackContainers.get(stackNdx);
             final int taskId = stack.taskIdFromPoint(x, y);
             if (taskId != -1) {
                 return taskId;
@@ -400,10 +464,10 @@
      * Returns null if the touch doesn't fall into a resizing area.
      */
     Task findTaskForResizePoint(int x, int y) {
-        final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
+        final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
         mTmpTaskForResizePointSearchResult.reset();
-        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
-            TaskStack stack = mChildren.get(stackNdx);
+        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mTaskStackContainers.get(stackNdx);
             if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
                 return null;
             }
@@ -418,10 +482,10 @@
 
     void setTouchExcludeRegion(Task focusedTask) {
         mTouchExcludeRegion.set(mBaseDisplayRect);
-        final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
+        final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
         mTmpRect2.setEmpty();
-        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mChildren.get(stackNdx);
+        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mTaskStackContainers.get(stackNdx);
             stack.setTouchExcludeRegion(
                     focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
         }
@@ -465,16 +529,16 @@
             }
         }
 
-        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
-            mChildren.get(stackNdx).switchUser();
+        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+            mTaskStackContainers.get(stackNdx).switchUser();
         }
 
         rebuildAppWindowList();
     }
 
     void resetAnimationBackgroundAnimator() {
-        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
-            mChildren.get(stackNdx).resetAnimationBackgroundAnimator();
+        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+            mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator();
         }
     }
 
@@ -505,12 +569,17 @@
 
     @Override
     void removeImmediately() {
-        super.removeImmediately();
-        if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
-        mDimLayerController.close();
-        if (mDisplayId == Display.DEFAULT_DISPLAY) {
-            mService.unregisterPointerEventListener(mTapDetector);
-            mService.unregisterPointerEventListener(mService.mMousePositionTracker);
+        mRemovingDisplay = true;
+        try {
+            super.removeImmediately();
+            if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
+            mDimLayerController.close();
+            if (mDisplayId == DEFAULT_DISPLAY) {
+                mService.unregisterPointerEventListener(mTapDetector);
+                mService.unregisterPointerEventListener(mService.mMousePositionTracker);
+            }
+        } finally {
+            mRemovingDisplay = false;
         }
     }
 
@@ -531,8 +600,8 @@
             float dividerAnimationTarget) {
         boolean updated = false;
 
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mChildren.get(i);
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mTaskStackContainers.get(i);
             if (stack == null || !stack.isAdjustedForIme()) {
                 continue;
             }
@@ -560,8 +629,8 @@
 
     boolean clearImeAdjustAnimation() {
         boolean changed = false;
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mChildren.get(i);
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mTaskStackContainers.get(i);
             if (stack != null && stack.isAdjustedForIme()) {
                 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
                 changed  = true;
@@ -571,8 +640,8 @@
     }
 
     void beginImeAdjustAnimation() {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mChildren.get(i);
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mTaskStackContainers.get(i);
             if (stack.isVisible() && stack.isAdjustedForIme()) {
                 stack.beginImeAdjustAnimation();
             }
@@ -601,8 +670,8 @@
         // - If IME is not visible, divider is not moved and is normal width.
 
         if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
-            for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final TaskStack stack = mChildren.get(i);
+            for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+                final TaskStack stack = mTaskStackContainers.get(i);
                 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
                 if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
                     stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
@@ -613,8 +682,8 @@
             mDividerControllerLocked.setAdjustedForIme(
                     imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
         } else {
-            for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final TaskStack stack = mChildren.get(i);
+            for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+                final TaskStack stack = mTaskStackContainers.get(i);
                 stack.resetAdjustedForIme(!dockVisible);
             }
             mDividerControllerLocked.setAdjustedForIme(
@@ -623,39 +692,23 @@
     }
 
     void prepareFreezingTaskBounds() {
-        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mChildren.get(stackNdx);
+        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mTaskStackContainers.get(stackNdx);
             stack.prepareFreezingTaskBounds();
         }
     }
 
     void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
-        final int rotationDelta = DisplayContent.deltaRotation(oldRotation, newRotation);
-        getLogicalDisplayRect(mTmpRect);
-        switch (rotationDelta) {
-            case Surface.ROTATION_0:
-                mTmpRect2.set(bounds);
-                break;
-            case Surface.ROTATION_90:
-                mTmpRect2.top = mTmpRect.bottom - bounds.right;
-                mTmpRect2.left = bounds.top;
-                mTmpRect2.right = mTmpRect2.left + bounds.height();
-                mTmpRect2.bottom = mTmpRect2.top + bounds.width();
-                break;
-            case Surface.ROTATION_180:
-                mTmpRect2.top = mTmpRect.bottom - bounds.bottom;
-                mTmpRect2.left = mTmpRect.right - bounds.right;
-                mTmpRect2.right = mTmpRect2.left + bounds.width();
-                mTmpRect2.bottom = mTmpRect2.top + bounds.height();
-                break;
-            case Surface.ROTATION_270:
-                mTmpRect2.top = bounds.left;
-                mTmpRect2.left = mTmpRect.right - bounds.bottom;
-                mTmpRect2.right = mTmpRect2.left + bounds.height();
-                mTmpRect2.bottom = mTmpRect2.top + bounds.width();
-                break;
-        }
-        bounds.set(mTmpRect2);
+        getLogicalDisplayRect(mTmpRect, newRotation);
+
+        // Compute a transform matrix to undo the coordinate space transformation,
+        // and present the window at the same physical position it previously occupied.
+        final int deltaRotation = deltaRotation(newRotation, oldRotation);
+        createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
+
+        mTmpRectF.set(bounds);
+        mTmpMatrix.mapRect(mTmpRectF);
+        mTmpRectF.round(bounds);
     }
 
     static int deltaRotation(int oldRotation, int newRotation) {
@@ -664,6 +717,35 @@
         return delta;
     }
 
+    private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
+            Matrix outMatrix) {
+        // For rotations without Z-ordering we don't need the target rectangle's position.
+        createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
+                displayHeight, outMatrix);
+    }
+
+    static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
+            float displayWidth, float displayHeight, Matrix outMatrix) {
+        switch (rotation) {
+            case ROTATION_0:
+                outMatrix.reset();
+                break;
+            case ROTATION_270:
+                outMatrix.setRotate(270, 0, 0);
+                outMatrix.postTranslate(0, displayHeight);
+                outMatrix.postTranslate(rectTop, 0);
+                break;
+            case ROTATION_180:
+                outMatrix.reset();
+                break;
+            case ROTATION_90:
+                outMatrix.setRotate(90, 0, 0);
+                outMatrix.postTranslate(displayWidth, 0);
+                outMatrix.postTranslate(-rectTop, rectLeft);
+                break;
+        }
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
         final String subPrefix = "  " + prefix;
@@ -695,8 +777,8 @@
 
         pw.println();
         pw.println("  Application tokens in top down Z order:");
-        for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
-            final TaskStack stack = mChildren.get(stackNdx);
+        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mTaskStackContainers.get(stackNdx);
             stack.dump(prefix + "  ", pw);
         }
 
@@ -705,7 +787,7 @@
             pw.println();
             pw.println("  Exiting tokens:");
             for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
-                WindowToken token = mExitingTokens.get(i);
+                final WindowToken token = mExitingTokens.get(i);
                 pw.print("  Exiting #"); pw.print(i);
                 pw.print(' '); pw.print(token);
                 pw.println(':');
@@ -720,11 +802,11 @@
 
     @Override
     public String toString() {
-        return getName() + " stacks=" + mChildren;
+        return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren;
     }
 
     String getName() {
-        return "Display " + mDisplayId + " info=" + mDisplayInfo;
+        return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
     }
 
     /**
@@ -792,21 +874,19 @@
         return true;
     }
 
-    void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus,
-                                                   WindowState newFocus) {
+    void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
         if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
             return;
         }
         final int lostFocusUid = oldFocus.mOwnerUid;
-        WindowList windows = getWindowList();
+        final WindowList windows = getWindowList();
         final int windowCount = windows.size();
+        final Handler handler = mService.mH;
         for (int i = 0; i < windowCount; i++) {
-            WindowState window = windows.get(i);
+            final WindowState window = windows.get(i);
             if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
-                if (!mService.mH.hasMessages(WindowManagerService.H.WINDOW_HIDE_TIMEOUT, window)) {
-                    mService.mH.sendMessageDelayed(
-                            mService.mH.obtainMessage(
-                                    WindowManagerService.H.WINDOW_HIDE_TIMEOUT, window),
+                if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, window)) {
+                    handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, window),
                             window.mAttrs.hideTimeoutMilliseconds);
                 }
             }
@@ -877,15 +957,15 @@
         }
 
         // No windows from this token on this display
-        if (mService.localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
+        if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
                 + client.asBinder() + " (token=" + this + ")");
 
         final WindowToken wToken = win.mToken;
 
         // Figure out where the window should go, based on the order of applications.
         mTmpGetWindowOnDisplaySearchResult.reset();
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mChildren.get(i);
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mTaskStackContainers.get(i);
             stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
             if (mTmpGetWindowOnDisplaySearchResult.reachedToken) {
                 // We have reach the token we are interested in. End search.
@@ -899,7 +979,7 @@
         // position; else we need to look some more.
         if (pos != null) {
             // Move behind any windows attached to this one.
-            final WindowToken atoken = mService.mTokenMap.get(pos.mClient.asBinder());
+            final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
             if (atoken != null) {
                 tokenWindowList = getTokenWindowsOnDisplay(atoken);
                 final int NC = tokenWindowList.size();
@@ -916,8 +996,8 @@
 
         // Continue looking down until we find the first token that has windows on this display.
         mTmpGetWindowOnDisplaySearchResult.reset();
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mChildren.get(i);
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mTaskStackContainers.get(i);
             stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
             if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) {
                 // We have found a window after the token. End search.
@@ -929,7 +1009,7 @@
 
         if (pos != null) {
             // Move in front of any windows attached to this one.
-            final WindowToken atoken = mService.mTokenMap.get(pos.mClient.asBinder());
+            final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
             if (atoken != null) {
                 final WindowState top = atoken.getTopWindow();
                 if (top != null && top.mSubLayer >= 0) {
@@ -987,6 +1067,10 @@
         mService.mWindowsChanged = true;
     }
 
+    void addToWindowList(WindowState win, int index) {
+        mWindows.add(index, win);
+    }
+
     void addChildWindowToWindowList(WindowState win) {
         final WindowState parentWindow = win.getParentWindow();
 
@@ -1081,18 +1165,18 @@
         // First add all of the exiting app tokens...  these are no longer in the main app list,
         // but still have windows shown. We put them in the back because now that the animation is
         // over we no longer will care about them.
-        final int numStacks = mChildren.size();
+        final int numStacks = mTaskStackContainers.size();
         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-            AppTokenList exitingAppTokens = mChildren.get(stackNdx).mExitingAppTokens;
+            AppTokenList exitingAppTokens = mTaskStackContainers.get(stackNdx).mExitingAppTokens;
             int NT = exitingAppTokens.size();
             for (int j = 0; j < NT; j++) {
-                i = exitingAppTokens.get(j).rebuildWindowListUnchecked(this, i);
+                i = exitingAppTokens.get(j).rebuildWindowListUnchecked(i);
             }
         }
 
         // And add in the still active app tokens in Z order.
         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-            i = mChildren.get(stackNdx).rebuildWindowList(this, i);
+            i = mTaskStackContainers.get(stackNdx).rebuildWindowList(i);
         }
 
         i -= lastBelow;
@@ -1238,6 +1322,39 @@
         }
     }
 
+    void dumpTokens(PrintWriter pw, boolean dumpAll) {
+        if (mTokenMap.isEmpty()) {
+            return;
+        }
+        pw.println("  Display #" + mDisplayId);
+        final Iterator<WindowToken> it = mTokenMap.values().iterator();
+        while (it.hasNext()) {
+            final WindowToken token = it.next();
+            pw.print("  ");
+            pw.print(token);
+            if (dumpAll) {
+                pw.println(':');
+                token.dump(pw, "    ");
+            } else {
+                pw.println();
+            }
+        }
+    }
+
+    void enableSurfaceTrace(FileDescriptor fd) {
+        for (int i = mWindows.size() - 1; i >= 0; i--) {
+            final WindowState win = mWindows.get(i);
+            win.mWinAnimator.enableSurfaceTrace(fd);
+        }
+    }
+
+    void disableSurfaceTrace() {
+        for (int i = mWindows.size() - 1; i >= 0; i--) {
+            final WindowState win = mWindows.get(i);
+            win.mWinAnimator.disableSurfaceTrace();
+        }
+    }
+
     static final class GetWindowOnDisplaySearchResult {
         boolean reachedToken;
         WindowState foundWindow;
@@ -1258,17 +1375,89 @@
         }
     }
 
-    void enableSurfaceTrace(FileDescriptor fd) {
-        for (int i = mWindows.size()  - 1; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
-            win.mWinAnimator.enableSurfaceTrace(fd);
+    /**
+     * Base class for any direct child window container of {@link #DisplayContent} need to inherit
+     * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
+     * homogeneous children type which is currently required by sub-classes of
+     * {@link WindowContainer} class.
+     */
+    static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
+
+        int size() {
+            return mChildren.size();
+        }
+
+        E get(int index) {
+            return mChildren.get(index);
+        }
+
+        @Override
+        boolean fillsParent() {
+            return true;
+        }
+
+        @Override
+        boolean isVisible() {
+            return true;
         }
     }
 
-    void disableSurfaceTrace() {
-        for (int i = mWindows.size()  - 1; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
-            win.mWinAnimator.disableSurfaceTrace();
+    /**
+     * Window container class that contains all containers on this display relating to Apps.
+     * I.e Activities.
+     */
+    private class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
+
+        void attachStack(TaskStack stack, boolean onTop) {
+            if (stack.mStackId == HOME_STACK_ID) {
+                if (mHomeStack != null) {
+                    throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
+                }
+                mHomeStack = stack;
+            }
+            addChild(stack, onTop);
+            stack.onDisplayChanged(DisplayContent.this);
         }
+
+        void moveStack(TaskStack stack, boolean toTop) {
+            if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
+                // This stack is always-on-top silly...
+                Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom");
+                return;
+            }
+
+            if (!mChildren.contains(stack)) {
+                Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
+            }
+            removeChild(stack);
+            addChild(stack, toTop);
+        }
+
+        private void addChild(TaskStack stack, boolean toTop) {
+            int addIndex = toTop ? mChildren.size() : 0;
+
+            if (toTop
+                    && mService.isStackVisibleLocked(PINNED_STACK_ID)
+                    && stack.mStackId != PINNED_STACK_ID) {
+                // The pinned stack is always the top most stack (always-on-top) when it is visible.
+                // So, stack is moved just below the pinned stack.
+                addIndex--;
+                TaskStack topStack = mChildren.get(addIndex);
+                if (topStack.mStackId != PINNED_STACK_ID) {
+                    throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
+                }
+            }
+            addChild(stack, addIndex);
+            setLayoutNeeded();
+        }
+
+    }
+
+    /**
+     * 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> {
+
     }
 }
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index a5387bd..065a3dc 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.INPUT_CONSUMER_PIP;
+import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
@@ -25,14 +27,17 @@
 import android.app.ActivityManagerNative;
 import android.graphics.Rect;
 import android.os.Debug;
+import android.os.Looper;
 import android.os.RemoteException;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
-import android.view.Display;
 import android.view.InputChannel;
+import android.view.InputEventReceiver;
 import android.view.KeyEvent;
 import android.view.WindowManager;
 
+import android.view.WindowManagerPolicy;
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.input.InputManagerService;
 import com.android.server.input.InputWindowHandle;
@@ -69,10 +74,103 @@
     private final Object mInputDevicesReadyMonitor = new Object();
     private boolean mInputDevicesReady;
 
+    /**
+     * The set of input consumer added to the window manager by name, which consumes input events
+     * for the windows below it.
+     */
+    private final ArrayMap<String, InputConsumerImpl> mInputConsumers = new ArrayMap();
+
+    private static final class EventReceiverInputConsumer extends InputConsumerImpl
+            implements WindowManagerPolicy.InputConsumer {
+        private InputMonitor mInputMonitor;
+        private final InputEventReceiver mInputEventReceiver;
+
+        EventReceiverInputConsumer(WindowManagerService service, InputMonitor monitor,
+                                   Looper looper, String name,
+                                   InputEventReceiver.Factory inputEventReceiverFactory) {
+            super(service, name, null);
+            mInputMonitor = monitor;
+            mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(
+                    mClientChannel, looper);
+        }
+
+        @Override
+        public void dismiss() {
+            synchronized (mService.mWindowMap) {
+                if (mInputMonitor.destroyInputConsumer(mWindowHandle.name)) {
+                    mInputEventReceiver.dispose();
+                }
+            }
+        }
+    }
+
     public InputMonitor(WindowManagerService service) {
         mService = service;
     }
 
+    void addInputConsumer(String name, InputConsumerImpl consumer) {
+        mInputConsumers.put(name, consumer);
+        updateInputWindowsLw(true /* force */);
+    }
+
+    boolean destroyInputConsumer(String name) {
+        if (disposeInputConsumer(mInputConsumers.remove(name))) {
+            updateInputWindowsLw(true /* force */);
+            return true;
+        }
+        return false;
+    }
+
+    private boolean disposeInputConsumer(InputConsumerImpl consumer) {
+        if (consumer != null) {
+            consumer.disposeChannelsLw();
+            return true;
+        }
+        return false;
+    }
+
+    InputConsumerImpl getInputConsumer(String name) {
+        return mInputConsumers.get(name);
+    }
+
+    void layoutInputConsumers(int dw, int dh) {
+        for (int i = mInputConsumers.size() - 1; i >= 0; i--) {
+            mInputConsumers.valueAt(i).layout(dw, dh);
+        }
+    }
+
+    WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
+            InputEventReceiver.Factory inputEventReceiverFactory) {
+        if (mInputConsumers.containsKey(name)) {
+            throw new IllegalStateException("Existing input consumer found with name: " + name);
+        }
+
+        final EventReceiverInputConsumer consumer = new EventReceiverInputConsumer(mService,
+                this, looper, name, inputEventReceiverFactory);
+        addInputConsumer(name, consumer);
+        return consumer;
+    }
+
+    void createInputConsumer(String name, InputChannel inputChannel) {
+        if (mInputConsumers.containsKey(name)) {
+            throw new IllegalStateException("Existing input consumer found with name: " + name);
+        }
+
+        final InputConsumerImpl consumer = new InputConsumerImpl(mService, name, inputChannel);
+        switch (name) {
+            case INPUT_CONSUMER_WALLPAPER:
+                consumer.mWindowHandle.hasWallpaper = true;
+                break;
+            case INPUT_CONSUMER_PIP:
+                // The touchable region of the Pip input window is cropped to the bounds of the
+                // stack, and we need FLAG_NOT_TOUCH_MODAL to ensure other events fall through
+                consumer.mWindowHandle.layoutParamsFlags |=
+                        WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+                break;
+        }
+        addInputConsumer(name, consumer);
+    }
+
     /* Notifies the window manager about a broken input channel.
      *
      * Called by the InputManager.
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1700bca..05ffe2d 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -19,8 +19,10 @@
 import android.app.AppOpsManager;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.hardware.power.V1_0.PowerHint;
 import android.os.Binder;
 import android.os.Debug;
+import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.os.RemoteException;
@@ -41,11 +43,18 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.LinkedList;
 
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
+import static android.view.WindowManager.INPUT_CONSUMER_PIP;
+import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
@@ -57,8 +66,11 @@
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -78,6 +90,7 @@
 import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
@@ -106,7 +119,7 @@
     private long mUserActivityTimeout = -1;
     private boolean mUpdateRotation = false;
     private boolean mObscured = false;
-    boolean mSyswin = false;
+    private boolean mSyswin = false;
     // Set to true when the display contains content to show the user.
     // When false, the display manager may choose to mirror or blank the display.
     private boolean mDisplayHasContent = false;
@@ -116,7 +129,7 @@
     // Last window that requires screen wakelock
     WindowState mHoldScreenWindow = null;
     // Last window that obscures all windows below
-    WindowState mObsuringWindow = null;
+    WindowState mObscuringWindow = null;
     // Only set while traversing the default display based on its content.
     // Affects the behavior of mirroring on secondary displays.
     private boolean mObscureApplicationContentOnSecondaryDisplays = false;
@@ -136,6 +149,15 @@
 
     private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
 
+    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.
@@ -178,7 +200,7 @@
         return dc;
     }
 
-    private DisplayContent getDisplayContent(int displayId) {
+    DisplayContent getDisplayContent(int displayId) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final DisplayContent current = mChildren.get(i);
             if (current.getDisplayId() == displayId) {
@@ -252,7 +274,6 @@
         }
 
         if (!attachedToDisplay) {
-            stack.attachDisplayContent(dc);
             dc.attachStack(stack, onTop);
         }
 
@@ -337,6 +358,202 @@
         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
+     * AppWindowToken represents an activity which can only exist on one display.
+     */
+    AppWindowToken getAppWindowToken(IBinder binder) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final DisplayContent dc = mChildren.get(i);
+            final AppWindowToken atoken = dc.getAppWindowToken(binder);
+            if (atoken != null) {
+                return atoken;
+            }
+        }
+        return null;
+    }
+
+    /** Returns the display object the input window token is currently mapped on. */
+    DisplayContent getWindowTokenDisplay(WindowToken token) {
+        if (token == null) {
+            return null;
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final DisplayContent dc = mChildren.get(i);
+            final WindowToken current = dc.getWindowToken(token.token);
+            if (current == token) {
+                return dc;
+            }
+        }
+
+        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 WindowToken token = new WindowToken(mService, binder, type, true,
+                getDisplayContent(DEFAULT_DISPLAY));
+        if (type == TYPE_WALLPAPER) {
+            mService.mWallpaperControllerLocked.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);
+            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();
@@ -368,7 +585,7 @@
      * Callback used to trigger bounds update after configuration change and get ids of stacks whose
      * bounds were updated.
      */
-    int[] updateStackBoundsAfterConfigChange() {
+    private int[] updateStackBoundsAfterConfigChange() {
         mChangedStackList.clear();
 
         final int numDisplays = mChildren.size();
@@ -488,8 +705,16 @@
     }
 
     void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
-        boolean addInputConsumerHandle = mService.mInputConsumer != null;
-        boolean addWallpaperInputConsumerHandle = mService.mWallpaperInputConsumer != null;
+        final InputConsumerImpl navInputConsumer =
+                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_NAVIGATION);
+        final InputConsumerImpl pipInputConsumer =
+                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_PIP);
+        final InputConsumerImpl wallpaperInputConsumer =
+                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_WALLPAPER);
+        boolean addInputConsumerHandle = navInputConsumer != null;
+        boolean addPipInputConsumerHandle = pipInputConsumer != null;
+        boolean addWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
+        final Rect pipTouchableBounds = addPipInputConsumerHandle ? new Rect() : null;
         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
         boolean disableWallpaperTouchEvents = false;
 
@@ -506,9 +731,20 @@
                     // Skip this window because it cannot possibly receive input.
                     continue;
                 }
+
+                if (addPipInputConsumerHandle
+                        && child.getStackId() == PINNED_STACK_ID
+                        && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
+                    // Update the bounds of the Pip input consumer to match the Pinned stack
+                    child.getStack().getBounds(pipTouchableBounds);
+                    pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
+                    inputMonitor.addInputWindowHandle(pipInputConsumer.mWindowHandle);
+                    addPipInputConsumerHandle = false;
+                }
+
                 if (addInputConsumerHandle
-                        && inputWindowHandle.layer <= mService.mInputConsumer.mWindowHandle.layer) {
-                    inputMonitor.addInputWindowHandle(mService.mInputConsumer.mWindowHandle);
+                        && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
+                    inputMonitor.addInputWindowHandle(navInputConsumer.mWindowHandle);
                     addInputConsumerHandle = false;
                 }
 
@@ -516,8 +752,7 @@
                     if (child.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER &&
                             child.isVisibleLw()) {
                         // Add the wallpaper input consumer above the first visible wallpaper.
-                        inputMonitor.addInputWindowHandle(
-                                mService.mWallpaperInputConsumer.mWindowHandle);
+                        inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
                         addWallpaperInputConsumerHandle = false;
                     }
                 }
@@ -528,19 +763,16 @@
 
                 final boolean hasFocus = child == inputFocus;
                 final boolean isVisible = child.isVisibleLw();
-                if ((privateFlags
-                        & WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS)
-                        != 0) {
+                if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
                     disableWallpaperTouchEvents = true;
                 }
                 final boolean hasWallpaper = wallpaperController.isWallpaperTarget(child)
-                        && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0
+                        && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
                         && !disableWallpaperTouchEvents;
-                final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
 
                 // If there's a drag in progress and 'child' is a potential drop target,
                 // make sure it's been told about the drag
-                if (inDrag && isVisible && onDefaultDisplay) {
+                if (inDrag && isVisible && dc.isDefaultDisplay) {
                     mService.mDragState.sendDragStartedIfNeededLw(child);
                 }
 
@@ -551,7 +783,7 @@
 
         if (addWallpaperInputConsumerHandle) {
             // No visible wallpaper found, add the wallpaper input consumer at the end.
-            inputMonitor.addInputWindowHandle(mService.mWallpaperInputConsumer.mWindowHandle);
+            inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
         }
     }
 
@@ -890,7 +1122,7 @@
         if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
             mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
             mService.mPowerManagerInternal.powerHint(
-                    mService.mPowerManagerInternal.POWER_HINT_SUSTAINED_PERFORMANCE_MODE,
+                    PowerHint.SUSTAINED_PERFORMANCE,
                     (mSustainedPerformanceModeEnabled ? 1 : 0));
         }
 
@@ -929,7 +1161,7 @@
             }
             mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
             mService.mPendingRemove.clear();
-            DisplayContentList displayList = new DisplayContentList();
+            ArrayList<DisplayContent> displayList = new ArrayList();
             for (i = 0; i < N; i++) {
                 final WindowState w = mService.mPendingRemoveTmp[i];
                 w.removeImmediately();
@@ -969,7 +1201,7 @@
     // TODO: Super crazy long method that should be broken down...
     private void applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw, int defaultDh) {
         mHoldScreenWindow = null;
-        mObsuringWindow = null;
+        mObscuringWindow = null;
 
         if (mService.mWatermark != null) {
             mService.mWatermark.positionSurface(defaultDw, defaultDh);
@@ -1195,7 +1427,7 @@
             // so we want to leave all of them as undimmed (for
             // performance reasons).
             if (!mObscured) {
-                mObsuringWindow = w;
+                mObscuringWindow = w;
             }
 
             mObscured = true;
@@ -1360,6 +1592,13 @@
         }
     }
 
+    void dumpTokens(PrintWriter pw, boolean dumpAll) {
+        pw.println("  All tokens:");
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            mChildren.get(i).dumpTokens(pw, dumpAll);
+        }
+    }
+
     @Override
     String getName() {
         return "ROOT";
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index f6598c1..19c9b7d 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -20,7 +20,6 @@
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -35,7 +34,6 @@
 import android.view.DisplayInfo;
 import android.view.Surface;
 
-import android.view.SurfaceControl;
 import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
@@ -43,17 +41,17 @@
 class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerUser {
     static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM;
     // Return value from {@link setBounds} indicating no change was made to the Task bounds.
-    static final int BOUNDS_CHANGE_NONE = 0;
+    private static final int BOUNDS_CHANGE_NONE = 0;
     // Return value from {@link setBounds} indicating the position of the Task bounds changed.
-    static final int BOUNDS_CHANGE_POSITION = 1;
+    private static final int BOUNDS_CHANGE_POSITION = 1;
     // Return value from {@link setBounds} indicating the size of the Task bounds changed.
-    static final int BOUNDS_CHANGE_SIZE = 1 << 1;
+    private static final int BOUNDS_CHANGE_SIZE = 1 << 1;
 
     // TODO: Track parent marks like this in WindowContainer.
     TaskStack mStack;
     final int mTaskId;
     final int mUserId;
-    boolean mDeferRemoval = false;
+    private boolean mDeferRemoval = false;
     final WindowManagerService mService;
 
     // Content limits relative to the DisplayContent this sits in.
@@ -65,7 +63,7 @@
     private final Rect mTempInsetBounds = new Rect();
 
     // Device rotation as of the last time {@link #mBounds} was set.
-    int mRotation;
+    private int mRotation;
 
     // Whether mBounds is fullscreen
     private boolean mFillsParent = true;
@@ -164,7 +162,8 @@
         stack.addTask(this, toTop);
     }
 
-    void positionTaskInStack(TaskStack stack, int position, Rect bounds, Configuration config) {
+    void positionTaskInStack(TaskStack stack, int position, Rect bounds,
+            Configuration overrideConfig) {
         if (mStack != null && stack != mStack) {
             if (DEBUG_STACK) Slog.i(TAG, "positionTaskInStack: removing taskId=" + mTaskId
                     + " from stack=" + mStack);
@@ -172,7 +171,7 @@
             mStack.removeChild(this);
         }
         stack.positionTask(this, position, showForAllUsers());
-        resizeLocked(bounds, config, false /* force */);
+        resizeLocked(bounds, overrideConfig, false /* force */);
 
         for (int activityNdx = mChildren.size() - 1; activityNdx >= 0; --activityNdx) {
             mChildren.get(activityNdx).notifyMovedInStack();
@@ -278,8 +277,7 @@
     }
 
     boolean isResizeable() {
-        return !mHomeTask
-                && (ActivityInfo.isResizeableMode(mResizeMode) || mService.mForceResizableTasks);
+        return ActivityInfo.isResizeableMode(mResizeMode) || mService.mForceResizableTasks;
     }
 
     boolean isOnTopLauncher() {
@@ -287,7 +285,7 @@
     }
 
     boolean cropWindowsToStackBounds() {
-        return !mHomeTask && (isResizeable() || mResizeMode == RESIZE_MODE_CROP_WINDOWS);
+        return isResizeable();
     }
 
     boolean isHomeTask() {
@@ -561,7 +559,7 @@
 
     @Override
     public boolean dimFullscreen() {
-        return isHomeTask() || isFullscreen();
+        return isFullscreen();
     }
 
     boolean isFullscreen() {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index e98fc39..7c39bd2 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -29,6 +29,7 @@
 import static android.view.WindowManager.DOCKED_LEFT;
 import static android.view.WindowManager.DOCKED_RIGHT;
 import static android.view.WindowManager.DOCKED_TOP;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
@@ -94,16 +95,16 @@
     private boolean mFillsParent = true;
 
     // Device rotation as of the last time {@link #mBounds} was set.
-    int mRotation;
+    private int mRotation;
 
     /** Density as of last time {@link #mBounds} was set. */
-    int mDensity;
+    private int mDensity;
 
     /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */
-    DimLayer mAnimationBackgroundSurface;
+    private DimLayer mAnimationBackgroundSurface;
 
     /** The particular window with an Animation with non-zero background color. */
-    WindowStateAnimator mAnimationBackgroundAnimator;
+    private WindowStateAnimator mAnimationBackgroundAnimator;
 
     /** Application tokens that are exiting, but still on screen for animations. */
     final AppTokenList mExitingAppTokens = new AppTokenList();
@@ -606,12 +607,12 @@
         }
     }
 
-    void attachDisplayContent(DisplayContent displayContent) {
+    void onDisplayChanged(DisplayContent dc) {
         if (mDisplayContent != null) {
-            throw new IllegalStateException("attachDisplayContent: Already attached");
+            throw new IllegalStateException("onDisplayChanged: Already attached");
         }
 
-        mDisplayContent = displayContent;
+        mDisplayContent = dc;
         mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
                 "animation background stackId=" + mStackId);
 
@@ -625,7 +626,7 @@
             // not fullscreen. If it's fullscreen, it means that we are in the transition of
             // dismissing it, so we must not resize this stack.
             bounds = new Rect();
-            displayContent.getLogicalDisplayRect(mTmpRect);
+            dc.getLogicalDisplayRect(mTmpRect);
             mTmpRect2.setEmpty();
             if (dockedStack != null) {
                 dockedStack.getRawBounds(mTmpRect2);
@@ -638,6 +639,8 @@
         }
 
         updateDisplayInfo(bounds);
+
+        super.onDisplayChanged(dc);
     }
 
     void getStackDockedModeBoundsLocked(Rect outBounds, boolean ignoreVisibility) {
@@ -1427,8 +1430,8 @@
         return super.checkCompleteDeferredRemoval();
     }
 
-    void stepAppWindowsAnimation(long currentTime, int displayId) {
-        super.stepAppWindowsAnimation(currentTime, displayId);
+    void stepAppWindowsAnimation(long currentTime) {
+        super.stepAppWindowsAnimation(currentTime);
 
         // TODO: Why aren't we just using the loop above for this? mAppAnimator.animating isn't set
         // below but is set in the loop above. See if it really matters...
@@ -1436,14 +1439,13 @@
         for (int i = 0; i < exitingCount; i++) {
             final AppWindowAnimator appAnimator = mExitingAppTokens.get(i).mAppAnimator;
             appAnimator.wasAnimating = appAnimator.animating;
-            if (appAnimator.stepAnimationLocked(currentTime, displayId)) {
+            if (appAnimator.stepAnimationLocked(currentTime)) {
                 mService.mAnimator.setAnimating(true);
                 mService.mAnimator.mAppWindowAnimating = true;
             } else if (appAnimator.wasAnimating) {
                 // stopped animating, do one more pass through the layout
-                appAnimator.mAppToken.setAppLayoutChanges(
-                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                        "exiting appToken " + appAnimator.mAppToken + " done", displayId);
+                appAnimator.mAppToken.setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
+                        "exiting appToken " + appAnimator.mAppToken + " done");
                 if (DEBUG_ANIM) Slog.v(TAG_WM,
                         "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
             }
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 58439eb..0841231 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -18,14 +18,10 @@
 
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -39,6 +35,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.util.ArraySet;
 import android.util.Slog;
 import android.view.DisplayInfo;
 import android.view.WindowManager;
@@ -149,18 +146,11 @@
     }
 
     void updateWallpaperVisibility() {
-        final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
-        if (displayContent == null) {
-            return;
-        }
         final boolean visible = isWallpaperVisible(mWallpaperTarget);
-        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-        final int dw = displayInfo.logicalWidth;
-        final int dh = displayInfo.logicalHeight;
 
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
             final WindowToken token = mWallpaperTokens.get(curTokenNdx);
-            token.updateWallpaperVisibility(dw, dh, visible, displayContent);
+            token.updateWallpaperVisibility(visible);
         }
     }
 
@@ -312,7 +302,7 @@
         return null;
     }
 
-    void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
+    private void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
         final DisplayContent displayContent = changingTarget.getDisplayContent();
         if (displayContent == null) {
             return;
@@ -384,18 +374,6 @@
         return mWallpaperAnimLayerAdjustment;
     }
 
-    void setAnimLayerAdjustment(WindowState win, int adj) {
-        if (win != mWallpaperTarget || mLowerWallpaperTarget != null) {
-            return;
-        }
-
-        if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Setting wallpaper layer adj to " + adj);
-        mWallpaperAnimLayerAdjustment = adj;
-        for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
-            mWallpaperTokens.get(i).adjustAnimLayer(adj);
-        }
-    }
-
     private void findWallpaperTarget(WindowList windows, FindWallpaperTargetResult result) {
         final WindowAnimator winAnimator = mService.mAnimator;
         result.reset();
@@ -477,101 +455,111 @@
         }
     }
 
+    /** Updates the target wallpaper if needed and returns true if an update happened. */
     private boolean updateWallpaperWindowsTarget(
             WindowList windows, FindWallpaperTargetResult result) {
 
-        boolean targetChanged = false;
         WindowState wallpaperTarget = result.wallpaperTarget;
         int wallpaperTargetIndex = result.wallpaperTargetIndex;
 
-        if (mWallpaperTarget != wallpaperTarget
-                && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != wallpaperTarget)) {
-            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
-                    "New wallpaper target: " + wallpaperTarget + " oldTarget: " + mWallpaperTarget);
+        if (mWallpaperTarget == wallpaperTarget
+                || (mLowerWallpaperTarget != null && mLowerWallpaperTarget == wallpaperTarget)) {
 
-            mLowerWallpaperTarget = null;
-            mUpperWallpaperTarget = null;
-
-            WindowState oldW = mWallpaperTarget;
-            mWallpaperTarget = wallpaperTarget;
-            targetChanged = true;
-
-            // Now what is happening...  if the current and new targets are animating,
-            // then we are in our super special mode!
-            if (wallpaperTarget != null && oldW != null) {
-                boolean oldAnim = oldW.isAnimatingLw();
-                boolean foundAnim = wallpaperTarget.isAnimatingLw();
-                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
-                        "New animation: " + foundAnim + " old animation: " + oldAnim);
-                if (foundAnim && oldAnim) {
-                    int oldI = windows.indexOf(oldW);
+            if (mLowerWallpaperTarget != null) {
+                // Is it time to stop animating?
+                if (!mLowerWallpaperTarget.isAnimatingLw()
+                        || !mUpperWallpaperTarget.isAnimatingLw()) {
                     if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
-                            "New i: " + wallpaperTargetIndex + " old i: " + oldI);
-                    if (oldI >= 0) {
-                        final boolean newTargetHidden =
-                                wallpaperTarget.mAppToken != null && wallpaperTarget.mAppToken.hiddenRequested;
-                        final boolean oldTargetHidden =
-                                oldW.mAppToken != null && oldW.mAppToken.hiddenRequested;
-                        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:"
-                                + " old#" + oldI + "=" + oldW + " hidden=" + oldTargetHidden
-                                + " new#" + wallpaperTargetIndex + "=" + wallpaperTarget
-                                + " hidden=" + newTargetHidden);
-
-                        // Set the upper and lower wallpaper targets correctly,
-                        // and make sure that we are positioning the wallpaper below the lower.
-                        if (wallpaperTargetIndex > oldI) {
-                            // The new target is on top of the old one.
-                            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
-                                    "Found target above old target.");
-                            mUpperWallpaperTarget = wallpaperTarget;
-                            mLowerWallpaperTarget = oldW;
-
-                            wallpaperTarget = oldW;
-                            wallpaperTargetIndex = oldI;
-                        } else {
-                            // The new target is below the old one.
-                            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
-                                    "Found target below old target.");
-                            mUpperWallpaperTarget = oldW;
-                            mLowerWallpaperTarget = wallpaperTarget;
-                        }
-                        if (newTargetHidden && !oldTargetHidden) {
-                            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
-                                    "Old wallpaper still the target.");
-                            // Use the old target if new target is hidden but old target
-                            // is not. If they're both hidden, still use the new target.
-                            mWallpaperTarget = oldW;
-                        } else if (newTargetHidden == oldTargetHidden
-                                && !mService.mOpeningApps.contains(wallpaperTarget.mAppToken)
-                                    && (mService.mOpeningApps.contains(oldW.mAppToken)
-                                    || mService.mClosingApps.contains(oldW.mAppToken))) {
-                            // If they're both hidden (or both not hidden), prefer the one that's
-                            // currently in opening or closing app list, this allows transition
-                            // selection logic to better determine the wallpaper status of
-                            // opening/closing apps.
-                            mWallpaperTarget = oldW;
-                        }
-                    }
+                            "No longer animating wallpaper targets!");
+                    mLowerWallpaperTarget = null;
+                    mUpperWallpaperTarget = null;
+                    mWallpaperTarget = wallpaperTarget;
+                    return true;
                 }
             }
 
-        } else if (mLowerWallpaperTarget != null) {
-            // Is it time to stop animating?
-            if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
-                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "No longer animating wallpaper targets!");
-                mLowerWallpaperTarget = null;
-                mUpperWallpaperTarget = null;
-                mWallpaperTarget = wallpaperTarget;
-                targetChanged = true;
-            }
+            return false;
+        }
+
+        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                "New wallpaper target: " + wallpaperTarget + " oldTarget: " + mWallpaperTarget);
+
+        mLowerWallpaperTarget = null;
+        mUpperWallpaperTarget = null;
+
+        WindowState oldW = mWallpaperTarget;
+        mWallpaperTarget = wallpaperTarget;
+
+        if (wallpaperTarget == null || oldW == null) {
+            return true;
+        }
+
+        // Now what is happening...  if the current and new targets are animating,
+        // then we are in our super special mode!
+        boolean oldAnim = oldW.isAnimatingLw();
+        boolean foundAnim = wallpaperTarget.isAnimatingLw();
+        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                "New animation: " + foundAnim + " old animation: " + oldAnim);
+
+        if (!foundAnim || !oldAnim) {
+            return true;
+        }
+
+        int oldI = windows.indexOf(oldW);
+        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+                "New i: " + wallpaperTargetIndex + " old i: " + oldI);
+
+        if (oldI < 0) {
+            return true;
+        }
+
+        final boolean newTargetHidden = wallpaperTarget.mAppToken != null
+                && wallpaperTarget.mAppToken.hiddenRequested;
+        final boolean oldTargetHidden = oldW.mAppToken != null
+                && oldW.mAppToken.hiddenRequested;
+
+        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:" + " old#" + oldI + "="
+                + oldW + " hidden=" + oldTargetHidden + " new#" + wallpaperTargetIndex + "="
+                + wallpaperTarget + " hidden=" + newTargetHidden);
+
+        // Set the upper and lower wallpaper targets correctly,
+        // and make sure that we are positioning the wallpaper below the lower.
+        if (wallpaperTargetIndex > oldI) {
+            // The new target is on top of the old one.
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Found target above old target.");
+            mUpperWallpaperTarget = wallpaperTarget;
+            mLowerWallpaperTarget = oldW;
+
+            wallpaperTarget = oldW;
+            wallpaperTargetIndex = oldI;
+        } else {
+            // The new target is below the old one.
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Found target below old target.");
+            mUpperWallpaperTarget = oldW;
+            mLowerWallpaperTarget = wallpaperTarget;
+        }
+
+        if (newTargetHidden && !oldTargetHidden) {
+            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Old wallpaper still the target.");
+            // Use the old target if new target is hidden but old target
+            // is not. If they're both hidden, still use the new target.
+            mWallpaperTarget = oldW;
+        } else if (newTargetHidden == oldTargetHidden
+                && !mService.mOpeningApps.contains(wallpaperTarget.mAppToken)
+                && (mService.mOpeningApps.contains(oldW.mAppToken)
+                || mService.mClosingApps.contains(oldW.mAppToken))) {
+            // If they're both hidden (or both not hidden), prefer the one that's currently in
+            // opening or closing app list, this allows transition selection logic to better
+            // determine the wallpaper status of opening/closing apps.
+            mWallpaperTarget = oldW;
         }
 
         result.setWallpaperTarget(wallpaperTarget, wallpaperTargetIndex);
-        return targetChanged;
+        return true;
     }
 
-    boolean updateWallpaperWindowsTargetByLayer(
-            WindowList windows, FindWallpaperTargetResult result) {
+    private boolean updateWallpaperWindowsTargetByLayer(WindowList windows,
+            FindWallpaperTargetResult result) {
 
         WindowState wallpaperTarget = result.wallpaperTarget;
         int wallpaperTargetIndex = result.wallpaperTargetIndex;
@@ -621,7 +609,7 @@
         return visible;
     }
 
-    boolean updateWallpaperWindowsPlacement(WindowList windows,
+    private boolean updateWallpaperWindowsPlacement(WindowList windows,
             WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible) {
 
         // TODO(multidisplay): Wallpapers on main screen only.
@@ -734,6 +722,31 @@
         return transitionReady;
     }
 
+    /**
+     * Adjusts the wallpaper windows if the input display has a pending wallpaper layout or one of
+     * the opening apps should be a wallpaper target.
+     */
+    void adjustWallpaperWindowsForAppTransitionIfNeeded(
+            DisplayContent dc, ArraySet<AppWindowToken> openingApps, WindowList windows) {
+        boolean adjust = false;
+        if ((dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
+            adjust = true;
+        } else {
+            for (int i = openingApps.size() - 1; i >= 0; --i) {
+                final AppWindowToken token = openingApps.valueAt(i);
+                if (token.windowsCanBeWallpaperTarget()) {
+                    adjust = true;
+                    break;
+                }
+            }
+        }
+
+        if (adjust && adjustWallpaperWindows()) {
+            mService.mLayersController.assignLayersLocked(windows);
+            dc.setLayoutNeeded();
+        }
+    }
+
     void addWallpaperToken(WindowToken token) {
         mWallpaperTokens.add(token);
     }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 902f4ae..285c40b 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -254,6 +254,17 @@
         }
     }
 
+    /**
+     * Notify that the display this container is on has changed.
+     * @param dc The new display this container is on.
+     */
+    void onDisplayChanged(DisplayContent dc) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer child = mChildren.get(i);
+            child.onDisplayChanged(dc);
+        }
+    }
+
     void setWaitingForDrawnIfResizingChanged() {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final WindowContainer wc = mChildren.get(i);
@@ -372,22 +383,18 @@
     }
 
     /** Checks if all windows in an app are all drawn and shows them if needed. */
-    // TODO: The displayId shouldn't be needed as there shouldn't be a container on more than one
-    // display. Remove once we migrate DisplayContent to use WindowContainer.
-    void checkAppWindowsReadyToShow(int displayId) {
+    void checkAppWindowsReadyToShow() {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final WindowContainer wc = mChildren.get(i);
-            wc.checkAppWindowsReadyToShow(displayId);
+            wc.checkAppWindowsReadyToShow();
         }
     }
 
     /** Step currently ongoing animation for App window containers. */
-    // TODO: The displayId shouldn't be needed as there shouldn't be a container on more than one
-    // display. Remove once we migrate DisplayContent to use WindowContainer.
-    void stepAppWindowsAnimation(long currentTime, int displayId) {
+    void stepAppWindowsAnimation(long currentTime) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final WindowContainer wc = mChildren.get(i);
-            wc.stepAppWindowsAnimation(currentTime, displayId);
+            wc.stepAppWindowsAnimation(currentTime);
         }
     }
 
@@ -472,16 +479,15 @@
 
     /**
      * Rebuilds the WindowList for the input display content.
-     * @param dc The display content to rebuild the window list for.
      * @param addIndex The index in the window list to add the next entry to.
      * @return The next index in the window list to.
      */
     // TODO: Hoping we can get rid of WindowList so this method wouldn't be needed.
-    int rebuildWindowList(DisplayContent dc, int addIndex) {
+    int rebuildWindowList(int addIndex) {
         final int count = mChildren.size();
         for (int i = 0; i < count; i++) {
             final WindowContainer wc = mChildren.get(i);
-            addIndex = wc.rebuildWindowList(dc, addIndex);
+            addIndex = wc.rebuildWindowList(addIndex);
         }
         return addIndex;
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5970998..02d04cc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -163,9 +163,9 @@
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 
+import static android.Manifest.permission.MANAGE_APP_TOKENS;
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
@@ -203,6 +203,7 @@
 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.EventLogTags.WM_TASK_CREATED;
 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
@@ -213,7 +214,6 @@
 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_BOOT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
@@ -222,12 +222,10 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
 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_STARTING_WINDOW;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
@@ -404,11 +402,6 @@
     final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();
 
     /**
-     * Mapping from a token IBinder to a WindowToken object.
-     */
-    final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<>();
-
-    /**
      * List of window tokens that have finished starting their application,
      * and now need to have the policy remove their windows.
      */
@@ -428,17 +421,6 @@
     final ArrayList<AppWindowToken> mWindowReplacementTimeouts = new ArrayList<>();
 
     /**
-     * The input consumer added to the window manager which consumes input events to windows below
-     * it.
-     */
-    InputConsumerImpl mInputConsumer;
-
-    /**
-     * The input consumer added to the window manager before all wallpaper windows.
-     */
-    InputConsumerImpl mWallpaperInputConsumer;
-
-    /**
      * Windows that are being resized.  Used so we can tell the client about
      * the resize after closing the transaction in which we resized the
      * underlying surface.
@@ -635,6 +617,12 @@
     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
     SettingsObserver mSettingsObserver;
 
+    // A count of the windows which are 'seamlessly rotated', e.g. a surface
+    // at an old orientation is being transformed. We freeze orientation updates
+    // while any windows are seamlessly rotated, so we need to track when this
+    // hits zero so we can apply deferred orientation updates.
+    int mSeamlessRotationCount = 0;
+
     private final class SettingsObserver extends ContentObserver {
         private final Uri mDisplayInversionEnabledUri =
                 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
@@ -907,7 +895,7 @@
         @Override
         public void onAppTransitionFinishedLocked(IBinder token) {
             mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_FINISHED);
-            AppWindowToken atoken = findAppWindowToken(token);
+            final AppWindowToken atoken = mRoot.getAppWindowToken(token);
             if (atoken == null) {
                 return;
             }
@@ -1195,7 +1183,7 @@
                 WindowState highestTarget = null;
                 int highestPos = 0;
                 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
-                    WindowList curWindows = curTarget.getWindowList();
+                    WindowList curWindows = token.getDisplayContent().getWindowList();
                     int pos = curWindows.indexOf(curTarget);
                     while (pos >= 0) {
                         WindowState win = curWindows.get(pos);
@@ -1258,7 +1246,8 @@
             // excercise to find the appropriate input method target (used for animations
             // and dialog adjustments), but for purposes of Z ordering we simply wish to
             // place it above the docked divider. Unless it is already above the divider.
-            WindowState dockedDivider = w.mDisplayContent.mDividerControllerLocked.getWindow();
+            final WindowState dockedDivider =
+                    w.getDisplayContent().mDividerControllerLocked.getWindow();
             if (dockedDivider != null && dockedDivider.isVisibleLw()) {
                 int dividerIndex = windows.indexOf(dockedDivider);
                 if (dividerIndex > 0 && dividerIndex > i) {
@@ -1276,21 +1265,6 @@
         return -1;
     }
 
-    void addInputMethodWindowToListLocked(WindowState win) {
-        int pos = findDesiredInputMethodWindowIndexLocked(true);
-        if (pos >= 0) {
-            if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
-                    TAG_WM, "Adding input method window " + win + " at " + pos);
-            // TODO(multidisplay): IMEs are only supported on the default display.
-            getDefaultWindowListLocked().add(pos, win);
-            mWindowsChanged = true;
-            moveInputMethodDialogsLocked(pos + 1);
-            return;
-        }
-        win.mToken.addWindow(win);
-        moveInputMethodDialogsLocked(pos);
-    }
-
     private void reAddWindowToListInOrderLocked(WindowState win) {
         win.mToken.addWindow(win);
         // This is a hack to get all of the child windows added as well at the right position. Child
@@ -1305,7 +1279,7 @@
         }
     }
 
-    void logWindowList(final WindowList windows, String prefix) {
+    private void logWindowList(final WindowList windows, String prefix) {
         int N = windows.size();
         while (N > 0) {
             N--;
@@ -1530,7 +1504,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 = mTokenMap.get(hasParent ? parentWindow.mAttrs.token : attrs.token);
+            WindowToken token = mRoot.getWindowToken(
+                    hasParent ? parentWindow.mAttrs.token : attrs.token, displayContent);
             // 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;
@@ -1582,7 +1557,7 @@
                         return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                     }
                 }
-                token = new WindowToken(this, attrs.token, -1, false);
+                token = new WindowToken(this, attrs.token, -1, false, displayContent);
             } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
                 atoken = token.asAppWindowToken();
                 if (atoken == null) {
@@ -1650,11 +1625,11 @@
                 // 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);
+                token = new WindowToken(this, null, -1, false, displayContent);
             }
 
             WindowState win = new WindowState(this, session, client, token, parentWindow,
-                    appOp[0], seq, attrs, viewVisibility, displayContent, session.mUid);
+                    appOp[0], seq, attrs, viewVisibility, session.mUid);
             if (win.mDeathRecipient == null) {
                 // Client has apparently died, so there is no reason to
                 // continue.
@@ -1745,7 +1720,7 @@
             if (type == TYPE_INPUT_METHOD) {
                 win.mGivenInsetsPending = true;
                 mInputMethodWindow = win;
-                addInputMethodWindowToListLocked(win);
+                win.mToken.addImeWindow(win);
                 imMayMove = false;
             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
                 mInputMethodDialogs.add(win);
@@ -1979,7 +1954,7 @@
         }
     }
 
-    public void removeWindow(Session session, IWindow client) {
+    void removeWindow(Session session, IWindow client) {
         synchronized(mWindowMap) {
             WindowState win = windowForClientLocked(session, client, false);
             if (win == null) {
@@ -2020,7 +1995,7 @@
         // Window will already be removed from token before this post clean-up method is called.
         if (token.isEmpty()) {
             if (!token.explicit) {
-                mTokenMap.remove(token.token);
+                token.removeImmediately();
             } else if (atoken != null) {
                 // TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after
                 // re-factor.
@@ -2735,10 +2710,8 @@
                 == PackageManager.PERMISSION_GRANTED) {
             return true;
         }
-        String msg = "Permission Denial: " + func + " from pid="
-                + Binder.getCallingPid()
-                + ", uid=" + Binder.getCallingUid()
-                + " requires " + permission;
+        final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
+                + ", uid=" + Binder.getCallingUid() + " requires " + permission;
         Slog.w(TAG_WM, msg);
         return false;
     }
@@ -2747,56 +2720,46 @@
         return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn();
     }
 
-    AppWindowToken findAppWindowToken(IBinder token) {
-        WindowToken wtoken = mTokenMap.get(token);
-        if (wtoken == null) {
-            return null;
-        }
-        return wtoken.asAppWindowToken();
-    }
-
     @Override
     public void addWindowToken(IBinder token, int type) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "addWindowToken()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized(mWindowMap) {
-            WindowToken wtoken = mTokenMap.get(token);
-            if (wtoken != null) {
-                Slog.w(TAG_WM, "Attempted to add existing input method token: " + token);
-                return;
-            }
-            wtoken = new WindowToken(this, token, type, true);
-            if (type == TYPE_WALLPAPER) {
-                mWallpaperControllerLocked.addWallpaperToken(wtoken);
-            }
+            mRoot.addWindowToken(token, type);
         }
     }
 
     @Override
     public void removeWindowToken(IBinder token) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "removeWindowToken()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         final long origId = Binder.clearCallingIdentity();
-        synchronized(mWindowMap) {
-            final WindowToken wtoken = mTokenMap.remove(token);
-            if (wtoken != null) {
-                wtoken.setExiting();
-                if (wtoken.windowType == TYPE_WALLPAPER) {
-                    mWallpaperControllerLocked.removeWallpaperToken(wtoken);
+        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);
+                    return;
                 }
 
-                mInputMonitor.updateInputWindowsLw(true /*force*/);
-            } else {
-                Slog.w(TAG_WM, "Attempted to remove non-existing token: " + token);
+                for (int i = removedTokens.size() - 1; i >= 0; --i) {
+                    final WindowToken wtoken = removedTokens.get(i);
+                    wtoken.setExiting();
+                    if (wtoken.windowType == TYPE_WALLPAPER) {
+                        mWallpaperControllerLocked.removeWallpaperToken(wtoken);
+                    }
+
+                    mInputMonitor.updateInputWindowsLw(true /*force*/);
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
         }
-        Binder.restoreCallingIdentity(origId);
     }
 
     private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken,
@@ -2805,9 +2768,9 @@
                 + " atoken=" + atoken + " bounds=" + bounds);
         final TaskStack stack = mStackIdToStack.get(stackId);
         if (stack == null) {
-            throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
+            throw new IllegalArgumentException("createTaskLocked: invalid stackId=" + stackId);
         }
-        EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
+        EventLog.writeEvent(WM_TASK_CREATED, taskId, stackId);
         Task task = new Task(taskId, stack, userId, this, bounds, overrideConfig, isOnTopLauncher);
         mTaskIdToTask.put(taskId, task);
         stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */, atoken.showForAllUsers);
@@ -2821,8 +2784,7 @@
             Rect taskBounds, Configuration overrideConfig, int taskResizeMode,
             boolean alwaysFocusable, boolean homeTask, int targetSdkVersion,
             int rotationAnimationHint, boolean isOnTopLauncher) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "addAppToken()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "addAppToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
@@ -2841,12 +2803,18 @@
         }
 
         synchronized(mWindowMap) {
-            AppWindowToken atoken = findAppWindowToken(token.asBinder());
+            AppWindowToken atoken = mRoot.getAppWindowToken(token.asBinder());
             if (atoken != null) {
                 Slog.w(TAG_WM, "Attempted to add existing app token: " + token);
                 return;
             }
-            atoken = new AppWindowToken(this, token, voiceInteraction);
+
+            final TaskStack stack = mStackIdToStack.get(stackId);
+            if (stack == null) {
+                throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
+            }
+
+            atoken = new AppWindowToken(this, token, voiceInteraction, stack.getDisplayContent());
             atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
             atoken.setFillsParent(fullscreen);
             atoken.showForAllUsers = showForAllUsers;
@@ -2877,13 +2845,12 @@
     public void setAppTask(IBinder token, int taskId, int stackId, Rect taskBounds,
             Configuration overrideConfig, int taskResizeMode, boolean homeTask,
             boolean isOnTopLauncher) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "setAppTask()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppTask()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized(mWindowMap) {
-            final AppWindowToken atoken = findAppWindowToken(token);
+            final AppWindowToken atoken = mRoot.getAppWindowToken(token);
             if (atoken == null) {
                 Slog.w(TAG_WM, "Attempted to set task id of non-existing app token: " + token);
                 return;
@@ -2975,8 +2942,7 @@
     @Override
     public Configuration updateOrientationFromAppTokens(
             Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "updateOrientationFromAppTokens()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
@@ -3000,12 +2966,10 @@
         Configuration config = null;
 
         if (updateOrientationFromAppTokensLocked(false)) {
-            // If we changed the orientation but mOrientationChangeComplete is
-            // already true, we used seamless rotation, and we don't need
-            // to freeze the screen.
-            if (freezeThisOneIfNeeded != null &&
-                    !mRoot.mOrientationChangeComplete) {
-                final AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
+            // If we changed the orientation but mOrientationChangeComplete is already true,
+            // we used seamless rotation, and we don't need to freeze the screen.
+            if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
+                final AppWindowToken atoken = mRoot.getAppWindowToken(freezeThisOneIfNeeded);
                 if (atoken != null) {
                     atoken.startFreezingScreen();
                 }
@@ -3089,8 +3053,7 @@
 
     @Override
     public int[] setNewConfiguration(Configuration config) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "setNewConfiguration()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewConfiguration()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
@@ -3115,13 +3078,12 @@
 
     @Override
     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "setAppOrientation()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppOrientation()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized(mWindowMap) {
-            final AppWindowToken atoken = findAppWindowToken(token.asBinder());
+            final AppWindowToken atoken = mRoot.getAppWindowToken(token.asBinder());
             if (atoken == null) {
                 Slog.w(TAG_WM, "Attempted to set orientation of non-existing app token: " + token);
                 return;
@@ -3134,9 +3096,9 @@
     @Override
     public int getAppOrientation(IApplicationToken token) {
         synchronized(mWindowMap) {
-            AppWindowToken wtoken = findAppWindowToken(token.asBinder());
+            final AppWindowToken wtoken = mRoot.getAppWindowToken(token.asBinder());
             if (wtoken == null) {
-                return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+                return SCREEN_ORIENTATION_UNSPECIFIED;
             }
 
             return wtoken.getOrientation();
@@ -3155,8 +3117,7 @@
 
     @Override
     public void setFocusedApp(IBinder token, boolean moveFocusNow) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "setFocusedApp()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "setFocusedApp()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
@@ -3166,7 +3127,7 @@
                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, was " + mFocusedApp);
                 newFocus = null;
             } else {
-                newFocus = findAppWindowToken(token);
+                newFocus = mRoot.getAppWindowToken(token);
                 if (newFocus == null) {
                     Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token);
                 }
@@ -3197,8 +3158,7 @@
      */
     @Override
     public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "prepareAppTransition()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
         synchronized(mWindowMap) {
@@ -3326,8 +3286,7 @@
 
     @Override
     public void executeAppTransition() {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "executeAppTransition()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "executeAppTransition()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
@@ -3351,8 +3310,7 @@
             int theme, CompatibilityInfo compatInfo,
             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
             int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "setAppStartingWindow()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppStartingWindow()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
@@ -3361,7 +3319,7 @@
                     TAG_WM, "setAppStartingWindow: token=" + token + " pkg=" + pkg
                     + " transferFrom=" + transferFrom);
 
-            AppWindowToken wtoken = findAppWindowToken(token);
+            final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
             if (wtoken == null) {
                 Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + token);
                 return false;
@@ -3423,7 +3381,7 @@
                 }
             }
 
-            if (wtoken != null && wtoken.transferStartingWindow(transferFrom)) {
+            if (wtoken.transferStartingWindow(transferFrom)) {
                 return true;
             }
 
@@ -3448,14 +3406,14 @@
 
     public void removeAppStartingWindow(IBinder token) {
         synchronized (mWindowMap) {
-            final AppWindowToken wtoken = mTokenMap.get(token).asAppWindowToken();
+            final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
             scheduleRemoveStartingWindowLocked(wtoken);
         }
     }
 
     public void setAppFullscreen(IBinder token, boolean toOpaque) {
         synchronized (mWindowMap) {
-            final AppWindowToken atoken = findAppWindowToken(token);
+            final AppWindowToken atoken = mRoot.getAppWindowToken(token);
             if (atoken != null) {
                 atoken.setFillsParent(toOpaque);
                 setWindowOpaqueLocked(token, toOpaque);
@@ -3470,10 +3428,10 @@
         }
     }
 
-    public void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
-        AppWindowToken wtoken = findAppWindowToken(token);
+    private void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
+        final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
         if (wtoken != null) {
-            WindowState win = wtoken.findMainWindow();
+            final WindowState win = wtoken.findMainWindow();
             if (win != null) {
                 win.mWinAnimator.setOpaqueLocked(isOpaque);
             }
@@ -3491,14 +3449,12 @@
 
     @Override
     public void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "notifyAppResumed()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "notifyAppResumed()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized(mWindowMap) {
-            final AppWindowToken wtoken;
-            wtoken = findAppWindowToken(token);
+            final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
             if (wtoken == null) {
                 Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + token);
                 return;
@@ -3509,14 +3465,13 @@
 
     @Override
     public void notifyAppStopped(IBinder token) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "notifyAppStopped()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "notifyAppStopped()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized(mWindowMap) {
             final AppWindowToken wtoken;
-            wtoken = findAppWindowToken(token);
+            wtoken = mRoot.getAppWindowToken(token);
             if (wtoken == null) {
                 Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: " + token);
                 return;
@@ -3527,15 +3482,14 @@
 
     @Override
     public void setAppVisibility(IBinder token, boolean visible) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "setAppVisibility()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppVisibility()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         AppWindowToken wtoken;
 
         synchronized(mWindowMap) {
-            wtoken = findAppWindowToken(token);
+            wtoken = mRoot.getAppWindowToken(token);
             if (wtoken == null) {
                 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
                 return;
@@ -3645,8 +3599,7 @@
 
     @Override
     public void startAppFreezingScreen(IBinder token, int configChanges) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "setAppFreezingScreen()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppFreezingScreen()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
@@ -3656,7 +3609,7 @@
                 return;
             }
 
-            final AppWindowToken wtoken = findAppWindowToken(token);
+            final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
             if (wtoken == null || wtoken.appToken == null) {
                 Slog.w(TAG_WM, "Attempted to freeze screen with non-existing app token: " + wtoken);
                 return;
@@ -3669,19 +3622,18 @@
 
     @Override
     public void stopAppFreezingScreen(IBinder token, boolean force) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "setAppFreezingScreen()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppFreezingScreen()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized(mWindowMap) {
-            AppWindowToken wtoken = findAppWindowToken(token);
+            final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
             if (wtoken == null || wtoken.appToken == null) {
                 return;
             }
             final long origId = Binder.clearCallingIdentity();
-            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + token
-                    + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
+            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + token + ": hidden="
+                    + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
             wtoken.stopFreezingScreen(true, force);
             Binder.restoreCallingIdentity(origId);
         }
@@ -3689,76 +3641,18 @@
 
     @Override
     public void removeAppToken(IBinder token) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "removeAppToken()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeAppToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
-        AppWindowToken wtoken = null;
-        AppWindowToken startingToken = null;
-        boolean delayed = false;
-
         final long origId = Binder.clearCallingIdentity();
-        synchronized(mWindowMap) {
-            WindowToken basewtoken = mTokenMap.remove(token);
-            if (basewtoken != null && (wtoken = basewtoken.asAppWindowToken()) != null) {
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + wtoken);
-                delayed = wtoken.setVisibility(null, false,
-                        TRANSIT_UNSET, true, wtoken.voiceInteraction);
-                mOpeningApps.remove(wtoken);
-                wtoken.waitingToShow = false;
-                if (mClosingApps.contains(wtoken)) {
-                    delayed = true;
-                } else if (mAppTransition.isTransitionSet()) {
-                    mClosingApps.add(wtoken);
-                    delayed = true;
-                }
-                if (DEBUG_APP_TRANSITIONS) Slog.v(
-                        TAG_WM, "Removing app " + wtoken + " delayed=" + delayed
-                        + " animation=" + wtoken.mAppAnimator.animation
-                        + " animating=" + wtoken.mAppAnimator.animating);
-                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
-                        + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
-                final TaskStack stack = wtoken.mTask.mStack;
-                if (delayed && !wtoken.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: " + wtoken);
-                    stack.mExitingAppTokens.add(wtoken);
-                    wtoken.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
-                    wtoken.mAppAnimator.clearAnimation();
-                    wtoken.mAppAnimator.animating = false;
-                    wtoken.removeIfPossible();
-                }
-
-                wtoken.removed = true;
-                if (wtoken.startingData != null) {
-                    startingToken = wtoken;
-                }
-                wtoken.stopFreezingScreen(true, true);
-                if (mFocusedApp == wtoken) {
-                    if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + wtoken);
-                    mFocusedApp = null;
-                    updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
-                    mInputMonitor.setFocusedAppLw(null);
-                }
-            } else {
-                Slog.w(TAG_WM, "Attempted to remove non-existing app token: " + token);
+        try {
+            synchronized(mWindowMap) {
+                mRoot.removeAppToken(token);
             }
-
-            if (!delayed && wtoken != null) {
-                wtoken.updateReportedVisibilityLocked();
-            }
-
-            // Will only remove if startingToken non null.
-            scheduleRemoveStartingWindowLocked(startingToken);
+        } finally {
+            Binder.restoreCallingIdentity(origId);
         }
-        Binder.restoreCallingIdentity(origId);
-
     }
 
     void scheduleRemoveStartingWindowLocked(AppWindowToken wtoken) {
@@ -4054,7 +3948,7 @@
     }
 
     public void positionTaskInStack(int taskId, int stackId, int position, Rect bounds,
-            Configuration config) {
+            Configuration overrideConfig) {
         synchronized (mWindowMap) {
             if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskInStack: positioning taskId=" + taskId
                     + " in stackId=" + stackId + " at " + position);
@@ -4070,7 +3964,7 @@
                         "positionTaskInStack: could not find stackId=" + stackId);
                 return;
             }
-            task.positionTaskInStack(stack, position, bounds, config);
+            task.positionTaskInStack(stack, position, bounds, overrideConfig);
             final DisplayContent displayContent = stack.getDisplayContent();
             displayContent.setLayoutNeeded();
             mWindowPlacerLocked.performSurfacePlacement();
@@ -5441,25 +5335,30 @@
         }
     }
 
-    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
-        if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked("
-                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
+    private void updateRotationUnchecked(boolean alwaysSendConfiguration,
+            boolean forceRelayout) {
+        if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked:"
+                + " alwaysSendConfiguration=" + alwaysSendConfiguration
+                + " forceRelayout=" + forceRelayout);
 
         long origId = Binder.clearCallingIdentity();
-        boolean changed;
-        synchronized(mWindowMap) {
-            changed = updateRotationUncheckedLocked(false);
-            if (!changed || forceRelayout) {
-                getDefaultDisplayContentLocked().setLayoutNeeded();
-                mWindowPlacerLocked.performSurfacePlacement();
+
+        try {
+            final boolean rotationChanged;
+            synchronized (mWindowMap) {
+                rotationChanged = updateRotationUncheckedLocked(false);
+                if (!rotationChanged || forceRelayout) {
+                    getDefaultDisplayContentLocked().setLayoutNeeded();
+                    mWindowPlacerLocked.performSurfacePlacement();
+                }
             }
-        }
 
-        if (changed || alwaysSendConfiguration) {
-            sendNewConfiguration();
+            if (rotationChanged || alwaysSendConfiguration) {
+                sendNewConfiguration();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
         }
-
-        Binder.restoreCallingIdentity(origId);
     }
 
 
@@ -5470,7 +5369,7 @@
      * Returns true if the rotation has been changed.  In this case YOU
      * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
      */
-    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
+    boolean updateRotationUncheckedLocked(boolean inTransaction) {
         if (mDeferredRotationPauseCount > 0) {
             // Rotation updates have been paused temporarily.  Defer the update until
             // updates have been resumed.
@@ -5487,6 +5386,13 @@
             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
             return false;
         }
+        if (mDisplayFrozen) {
+            // Even if the screen rotation animation has finished (e.g. isAnimating
+            // returns false), there is still some time where we haven't yet unfrozen
+            // the display. We also need to abort rotation here.
+            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, still finishing previous rotation");
+            return false;
+        }
 
         if (!mDisplayEnabled) {
             // No point choosing a rotation if the display is not enabled.
@@ -5494,12 +5400,44 @@
             return false;
         }
 
+        final DisplayContent displayContent = getDefaultDisplayContentLocked();
+        final WindowList windows = displayContent.getWindowList();
+
+        final int oldRotation = mRotation;
+        int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation);
+        boolean rotateSeamlessly = mPolicy.shouldRotateSeamlessly(oldRotation, rotation);
+
+        if (rotateSeamlessly) {
+            for (int i = windows.size() - 1; i >= 0; i--) {
+                WindowState w = windows.get(i);
+                // We can't rotate (seamlessly or not) while waiting for the last seamless rotation
+                // to complete (that is, waiting for windows to redraw). It's tempting to check
+                // w.mSeamlessRotationCount but that could be incorrect in the case of window-removal.
+                if (w.mSeamlesslyRotated) {
+                    return false;
+                }
+                // In what can only be called an unfortunate workaround we require
+                // seamlessly rotated child windows to have the TRANSFORM_TO_DISPLAY_INVERSE
+                // flag. Due to limitations in the client API, there is no way for
+                // the client to set this flag in a race free fashion. If we seamlessly rotate
+                // a window which does not have this flag, but then gains it, we will get
+                // an incorrect visual result (rotated viewfinder). This means if we want to
+                // support seamlessly rotating windows which could gain this flag, we can't
+                // rotate windows without it. This limits seamless rotation in N to camera framework
+                // users, windows without children, and native code. This is unfortunate but
+                // having the camera work is our primary goal.
+                if (w.isChildWindow() & w.isVisibleNow() &&
+                        !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse()) {
+                    rotateSeamlessly = false;
+                }
+            }
+        }
+
         // TODO: Implement forced rotation changes.
         //       Set mAltOrientation to indicate that the application is receiving
         //       an orientation that has different metrics than it expected.
         //       eg. Portrait instead of Landscape.
 
-        int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation);
         boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
                 mLastOrientation, rotation);
 
@@ -5522,8 +5460,6 @@
                 + ", lastOrientation=" + mLastOrientation);
         }
 
-        int oldRotation = mRotation;
-
         mRotation = rotation;
         mAltOrientation = altOrientation;
         mPolicy.setRotationLw(mRotation);
@@ -5532,7 +5468,6 @@
         mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
         mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
         mWaitingForConfig = true;
-        final DisplayContent displayContent = getDefaultDisplayContentLocked();
         displayContent.setLayoutNeeded();
         final int[] anim = new int[2];
         if (displayContent.isDimming()) {
@@ -5540,33 +5475,6 @@
         } else {
             mPolicy.selectRotationAnimationLw(anim);
         }
-        boolean rotateSeamlessly = mPolicy.shouldRotateSeamlessly(oldRotation, mRotation);
-        final WindowList windows = displayContent.getWindowList();
-        // We can't rotate seamlessly while an existing seamless rotation is still
-        // waiting on windows to finish drawing.
-        if (rotateSeamlessly) {
-            for (int i = windows.size() - 1; i >= 0; i--) {
-                WindowState w = windows.get(i);
-                if (w.mSeamlesslyRotated) {
-                    rotateSeamlessly = false;
-                    break;
-                }
-                // In what can only be called an unfortunate workaround we require
-                // seamlessly rotated child windows to have the TRANSFORM_TO_DISPLAY_INVERSE
-                // flag. Due to limitations in the client API, there is no way for
-                // the client to set this flag in a race free fashion. If we seamlessly rotate
-                // a window which does not have this flag, but then gains it, we will get
-                // an incorrect visual result (rotated viewfinder). This means if we want to
-                // support seamlessly rotating windows which could gain this flag, we can't
-                // rotate windows without it. This limits seamless rotation in N to camera framework
-                // users, windows without children, and native code. This is unfortunate but
-                // having the camera work is our primary goal.
-                if (w.isChildWindow() & w.isVisibleNow() &&
-                        !w.mWinAnimator.mSurfaceController.getTransformToDisplayInverse()) {
-                    rotateSeamlessly = false;
-                }
-            }
-        }
 
         if (!rotateSeamlessly) {
             startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
@@ -5579,6 +5487,10 @@
             // When we are rotating seamlessly, we allow the elements to transition
             // to their rotated state independently and without a freeze required.
             screenRotationAnimation = null;
+
+            // We have to reset this in case a window was removed before it
+            // finished seamless rotation.
+            mSeamlessRotationCount = 0;
         }
 
         // We need to update our screen size information to match the new rotation. If the rotation
@@ -6121,10 +6033,25 @@
     /**
      * Instruct the Activity Manager to fetch new configurations, update global configuration
      * and broadcast changes to config-changed listeners if appropriate.
+     * NOTE: Can't be called with the window manager lock held since it call into activity manager.
      */
     void sendNewConfiguration() {
         try {
-            mActivityManager.updateConfiguration(null);
+            final boolean configUpdated = mActivityManager.updateConfiguration(null);
+            if (!configUpdated) {
+                // Something changed (E.g. device rotation), but no configuration update is needed.
+                // E.g. changing device rotation by 180 degrees. Go ahead and perform surface
+                // placement to unfreeze the display since we froze it when the rotation was updated
+                // in updateRotationUncheckedLocked.
+                synchronized (mWindowMap) {
+                    if (mWaitingForConfig) {
+                        mWaitingForConfig = false;
+                        mLastFinishedFreezeSource = "config-unchanged";
+                        getDefaultDisplayContentLocked().setLayoutNeeded();
+                        mWindowPlacerLocked.performSurfacePlacement();
+                    }
+                }
+            }
         } catch (RemoteException e) {
         }
     }
@@ -6592,38 +6519,39 @@
 
     @Override
     public void pauseKeyDispatching(IBinder _token) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "pauseKeyDispatching()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "pauseKeyDispatching()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized (mWindowMap) {
-            WindowToken token = mTokenMap.get(_token);
-            if (token != null) {
-                mInputMonitor.pauseDispatchingLw(token);
+            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));
+                }
             }
         }
     }
 
     @Override
     public void resumeKeyDispatching(IBinder _token) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "resumeKeyDispatching()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "resumeKeyDispatching()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized (mWindowMap) {
-            WindowToken token = mTokenMap.get(_token);
-            if (token != null) {
-                mInputMonitor.resumeDispatchingLw(token);
+            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));
+                }
             }
         }
     }
 
     @Override
     public void setEventDispatching(boolean enabled) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "setEventDispatching()")) {
+        if (!checkCallingPermission(MANAGE_APP_TOKENS, "setEventDispatching()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
@@ -7507,8 +7435,8 @@
                             if (w.mSeamlesslyRotated) {
                                 layoutNeeded = true;
                                 w.setDisplayLayoutNeeded();
+                                markForSeamlessRotation(w, false);
                             }
-                            w.mSeamlesslyRotated = false;
                         }
                         if (layoutNeeded) {
                             mWindowPlacerLocked.performSurfacePlacement();
@@ -8097,10 +8025,10 @@
             } else {
                 if (DEBUG_KEEP_SCREEN_ON) {
                     Slog.d(TAG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by "
-                            + mRoot.mObsuringWindow);
+                            + mRoot.mObscuringWindow);
                 }
                 mLastWakeLockHoldingWindow = null;
-                mLastWakeLockObscuringWindow = mRoot.mObsuringWindow;
+                mLastWakeLockObscuringWindow = mRoot.mObscuringWindow;
                 mPolicy.keepScreenOnStoppedLw();
                 mHoldingScreenWakeLock.release();
             }
@@ -8514,68 +8442,25 @@
         }
     }
 
-    private static final class HideNavInputConsumer extends InputConsumerImpl
-            implements WindowManagerPolicy.InputConsumer {
-        private final InputEventReceiver mInputEventReceiver;
-
-        HideNavInputConsumer(WindowManagerService service, Looper looper,
-                             InputEventReceiver.Factory inputEventReceiverFactory) {
-            super(service, "input consumer", null);
-            mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(
-                    mClientChannel, looper);
-        }
-
-        @Override
-        public void dismiss() {
-            if (mService.removeInputConsumer()) {
-                synchronized (mService.mWindowMap) {
-                    mInputEventReceiver.dispose();
-                    disposeChannelsLw();
-                }
-            }
-        }
-    }
-
     @Override
-    public WindowManagerPolicy.InputConsumer addInputConsumer(Looper looper,
+    public WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
             InputEventReceiver.Factory inputEventReceiverFactory) {
         synchronized (mWindowMap) {
-            HideNavInputConsumer inputConsumerImpl = new HideNavInputConsumer(
-                    this, looper, inputEventReceiverFactory);
-            mInputConsumer = inputConsumerImpl;
-            mInputMonitor.updateInputWindowsLw(true);
-            return inputConsumerImpl;
-        }
-    }
-
-    boolean removeInputConsumer() {
-        synchronized (mWindowMap) {
-            if (mInputConsumer != null) {
-                mInputConsumer = null;
-                mInputMonitor.updateInputWindowsLw(true);
-                return true;
-            }
-            return false;
+            return mInputMonitor.createInputConsumer(looper, name, inputEventReceiverFactory);
         }
     }
 
     @Override
-    public void createWallpaperInputConsumer(InputChannel inputChannel) {
+    public void createInputConsumer(String name, InputChannel inputChannel) {
         synchronized (mWindowMap) {
-            mWallpaperInputConsumer = new InputConsumerImpl(this, "wallpaper input", inputChannel);
-            mWallpaperInputConsumer.mWindowHandle.hasWallpaper = true;
-            mInputMonitor.updateInputWindowsLw(true);
+            mInputMonitor.createInputConsumer(name, inputChannel);
         }
     }
 
     @Override
-    public void removeWallpaperInputConsumer() {
+    public boolean destroyInputConsumer(String name) {
         synchronized (mWindowMap) {
-            if (mWallpaperInputConsumer != null) {
-                mWallpaperInputConsumer.disposeChannelsLw();
-                mWallpaperInputConsumer = null;
-                mInputMonitor.updateInputWindowsLw(true);
-            }
+            return mInputMonitor.destroyInputConsumer(name);
         }
     }
 
@@ -8645,7 +8530,7 @@
 
     public void notifyAppRelaunching(IBinder token) {
         synchronized (mWindowMap) {
-            AppWindowToken appWindow = findAppWindowToken(token);
+            final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
             if (appWindow != null) {
                 appWindow.startRelaunching();
             }
@@ -8654,7 +8539,7 @@
 
     public void notifyAppRelaunchingFinished(IBinder token) {
         synchronized (mWindowMap) {
-            AppWindowToken appWindow = findAppWindowToken(token);
+            final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
             if (appWindow != null) {
                 appWindow.finishRelaunching();
             }
@@ -8663,7 +8548,7 @@
 
     public void notifyAppRelaunchesCleared(IBinder token) {
         synchronized (mWindowMap) {
-            final AppWindowToken appWindow = findAppWindowToken(token);
+            final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
             if (appWindow != null) {
                 appWindow.clearRelaunching();
             }
@@ -8675,32 +8560,19 @@
         return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
     }
 
-    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
+    private void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
         pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
         mPolicy.dump("    ", pw, args);
     }
 
-    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
+    private void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
         pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
         mAnimator.dumpLocked(pw, "    ", dumpAll);
     }
 
-    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
+    private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
         pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
-        if (!mTokenMap.isEmpty()) {
-            pw.println("  All tokens:");
-            Iterator<WindowToken> it = mTokenMap.values().iterator();
-            while (it.hasNext()) {
-                WindowToken token = it.next();
-                pw.print("  "); pw.print(token);
-                if (dumpAll) {
-                    pw.println(':');
-                    token.dump(pw, "    ");
-                } else {
-                    pw.println();
-                }
-            }
-        }
+        mRoot.dumpTokens(pw, dumpAll);
         mWallpaperControllerLocked.dumpTokens(pw, "  ", dumpAll);
         if (!mFinishedStarting.isEmpty()) {
             pw.println();
@@ -8728,7 +8600,7 @@
         }
     }
 
-    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
+    private void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
         pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
         for (int i=0; i<mSessions.size(); i++) {
             Session s = mSessions.valueAt(i);
@@ -8737,13 +8609,13 @@
         }
     }
 
-    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
+    private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
         pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
         dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
     }
 
-    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
+    private void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
         mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
 
@@ -9232,7 +9104,7 @@
      */
     public void setWillReplaceWindow(IBinder token, boolean animate) {
         synchronized (mWindowMap) {
-            final AppWindowToken appWindowToken = findAppWindowToken(token);
+            final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
             if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
                         + token);
@@ -9254,9 +9126,9 @@
      */
     // TODO: The s at the end of the method name is the only difference with the name of the method
     // above. We should combine them or find better names.
-    public void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
+    void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
         synchronized (mWindowMap) {
-            final AppWindowToken appWindowToken = findAppWindowToken(token);
+            final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
             if (appWindowToken == null || !appWindowToken.hasContentToDisplay()) {
                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
                         + token);
@@ -9284,7 +9156,7 @@
      */
     public void scheduleClearWillReplaceWindows(IBinder token, boolean replacing) {
         synchronized (mWindowMap) {
-            final AppWindowToken appWindowToken = findAppWindowToken(token);
+            final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
             if (appWindowToken == null) {
                 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
                         + token);
@@ -9464,6 +9336,7 @@
      */
     public int getSmallestWidthForTaskBounds(Rect bounds) {
         synchronized (mWindowMap) {
+            // TODO(multi-display): Use correct display content here
             return getDefaultDisplayContentLocked().getDockedDividerController()
                     .getSmallestWidthDpForBounds(bounds);
         }
@@ -9566,6 +9439,26 @@
         mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
     }
 
+    void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) {
+        if (seamlesslyRotated == w.mSeamlesslyRotated) {
+            return;
+        }
+        w.mSeamlesslyRotated = seamlesslyRotated;
+        if (seamlesslyRotated) {
+            mSeamlessRotationCount++;
+        } else {
+            mSeamlessRotationCount--;
+        }
+        if (mSeamlessRotationCount == 0) {
+            if (DEBUG_ORIENTATION) {
+                Slog.i(TAG, "Performing post-rotate rotation after seamless rotation");
+            }
+            if (updateRotationUncheckedLocked(false)) {
+                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+            }
+        }
+    }
+
     private final class LocalService extends WindowManagerInternal {
         @Override
         public void requestTraversalFromDisplayManager() {
@@ -9729,9 +9622,12 @@
         public void removeWindowToken(IBinder token, boolean removeWindows) {
             synchronized(mWindowMap) {
                 if (removeWindows) {
-                    final WindowToken wtoken = mTokenMap.remove(token);
-                    if (wtoken != null) {
-                        wtoken.removeAllWindows();
+                    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();
+                        }
                     }
                 }
                 WindowManagerService.this.removeWindowToken(token);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 435b1d2..fa4dbc4 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -71,6 +71,7 @@
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
@@ -157,7 +158,7 @@
     // to capture touch events in that area.
     static final int RESIZE_HANDLE_WIDTH_IN_DP = 30;
 
-    static final boolean DEBUG_DISABLE_SAVING_SURFACES = false;
+    private static final boolean DEBUG_DISABLE_SAVING_SURFACES = false;
 
     final WindowManagerService mService;
     final WindowManagerPolicy mPolicy;
@@ -182,7 +183,7 @@
     final boolean mLayoutAttached;
     final boolean mIsImWindow;
     final boolean mIsWallpaper;
-    final boolean mIsFloatingLayer;
+    private final boolean mIsFloatingLayer;
     int mSeq;
     boolean mEnforceSizeCompat;
     int mViewVisibility;
@@ -199,16 +200,16 @@
      * animation is done.
      */
     boolean mPolicyVisibilityAfterAnim = true;
-    boolean mAppOpVisibility = true;
+    private boolean mAppOpVisibility = true;
     boolean mPermanentlyHidden; // the window should never be shown again
     boolean mAppFreezing;
     boolean mHidden;    // Used to determine if to show child windows.
     boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
-    boolean mDragResizing;
-    boolean mDragResizingChangeReported;
-    int mResizeMode;
+    private boolean mDragResizing;
+    private boolean mDragResizingChangeReported;
+    private int mResizeMode;
 
-    RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
+    private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
 
     /**
      * The window size that was requested by the application.  These are in
@@ -216,8 +217,8 @@
      */
     int mRequestedWidth;
     int mRequestedHeight;
-    int mLastRequestedWidth;
-    int mLastRequestedHeight;
+    private int mLastRequestedWidth;
+    private int mLastRequestedHeight;
 
     int mLayer;
     boolean mHaveFrame;
@@ -244,8 +245,8 @@
      * coordinate space (without compatibility scale applied).
      */
     final Rect mVisibleInsets = new Rect();
-    final Rect mLastVisibleInsets = new Rect();
-    boolean mVisibleInsetsChanged;
+    private final Rect mLastVisibleInsets = new Rect();
+    private boolean mVisibleInsetsChanged;
 
     /**
      * Insets that are covered by system windows (such as the status bar) and
@@ -254,31 +255,31 @@
      */
     final Rect mContentInsets = new Rect();
     final Rect mLastContentInsets = new Rect();
-    boolean mContentInsetsChanged;
+    private boolean mContentInsetsChanged;
 
     /**
      * Insets that determine the area covered by the display overscan region.  These are in the
      * application's coordinate space (without compatibility scale applied).
      */
     final Rect mOverscanInsets = new Rect();
-    final Rect mLastOverscanInsets = new Rect();
-    boolean mOverscanInsetsChanged;
+    private final Rect mLastOverscanInsets = new Rect();
+    private boolean mOverscanInsetsChanged;
 
     /**
      * Insets that determine the area covered by the stable system windows.  These are in the
      * application's coordinate space (without compatibility scale applied).
      */
     final Rect mStableInsets = new Rect();
-    final Rect mLastStableInsets = new Rect();
-    boolean mStableInsetsChanged;
+    private final Rect mLastStableInsets = new Rect();
+    private boolean mStableInsetsChanged;
 
     /**
      * Outsets determine the area outside of the surface where we want to pretend that it's possible
      * to draw anyway.
      */
     final Rect mOutsets = new Rect();
-    final Rect mLastOutsets = new Rect();
-    boolean mOutsetsChanged = false;
+    private final Rect mLastOutsets = new Rect();
+    private boolean mOutsetsChanged = false;
 
     /**
      * Set to true if we are waiting for this window to receive its
@@ -321,14 +322,14 @@
     // "Real" frame that the application sees, in display coordinate space.
     final Rect mFrame = new Rect();
     final Rect mLastFrame = new Rect();
-    boolean mFrameSizeChanged = false;
+    private boolean mFrameSizeChanged = false;
     // Frame that is scaled to the application's coordinate space when in
     // screen size compatibility mode.
     final Rect mCompatFrame = new Rect();
 
     final Rect mContainingFrame = new Rect();
 
-    final Rect mParentFrame = new Rect();
+    private final Rect mParentFrame = new Rect();
 
     // The entire screen area of the {@link TaskStack} this window is in. Usually equal to the
     // screen area of the device.
@@ -338,11 +339,11 @@
     // is mostly a special case for TV where some displays don’t have the entire display usable.
     // {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} flag can be used to allow
     // window display contents to extend into the overscan region.
-    final Rect mOverscanFrame = new Rect();
+    private final Rect mOverscanFrame = new Rect();
 
     // The display frame minus the stable insets. This value is always constant regardless of if
     // the status bar or navigation bar is visible.
-    final Rect mStableFrame = new Rect();
+    private final Rect mStableFrame = new Rect();
 
     // The area not occupied by the status and navigation bars. So, if both status and navigation
     // bars are visible, the decor frame is equal to the stable frame.
@@ -350,7 +351,7 @@
 
     // Equal to the decor frame if the IME (e.g. keyboard) is not present. Equal to the decor frame
     // minus the area occupied by the IME if the IME is present.
-    final Rect mContentFrame = new Rect();
+    private final Rect mContentFrame = new Rect();
 
     // Legacy stuff. Generally equal to the content frame expect when the IME for older apps
     // displays hint text.
@@ -358,13 +359,13 @@
 
     // Frame that includes dead area outside of the surface but where we want to pretend that it's
     // possible to draw.
-    final Rect mOutsetFrame = new Rect();
+    private final Rect mOutsetFrame = new Rect();
 
     /**
      * Usually empty. Set to the task's tempInsetFrame. See
      *{@link android.app.IActivityManager#resizeDockedStack}.
      */
-    final Rect mInsetFrame = new Rect();
+    private final Rect mInsetFrame = new Rect();
 
     boolean mContentChanged;
 
@@ -446,7 +447,7 @@
      * or some other higher level component said so (e.g. activity manager).
      * TODO: We should either have different booleans for the removal reason or use a bit-field.
      */
-    boolean mWindowRemovalAllowed;
+    private boolean mWindowRemovalAllowed;
 
     /**
      * Temp for keeping track of windows that have been removed when
@@ -457,20 +458,17 @@
     // Input channel and input window handle used by the input dispatcher.
     final InputWindowHandle mInputWindowHandle;
     InputChannel mInputChannel;
-    InputChannel mClientChannel;
+    private InputChannel mClientChannel;
 
     // Used to improve performance of toString()
-    String mStringNameCache;
-    CharSequence mLastTitle;
-    boolean mWasExiting;
+    private String mStringNameCache;
+    private CharSequence mLastTitle;
+    private boolean mWasExiting;
 
     final WindowStateAnimator mWinAnimator;
 
     boolean mHasSurface = false;
 
-    boolean mNotOnAppsDisplay = false;
-    DisplayContent  mDisplayContent;
-
     /** When true this window can be displayed on screens owther than mOwnerUid's */
     private boolean mShowToOwnerOnly;
 
@@ -486,26 +484,26 @@
     // Whether the window was visible when we set the app to invisible last time. WM uses
     // this as a hint to restore the surface (if available) for early animation next time
     // the app is brought visible.
-    boolean mWasVisibleBeforeClientHidden;
+    private boolean mWasVisibleBeforeClientHidden;
 
     // This window will be replaced due to relaunch. This allows window manager
     // to differentiate between simple removal of a window and replacement. In the latter case it
     // will preserve the old window until the new one is drawn.
     boolean mWillReplaceWindow = false;
     // If true, the replaced window was already requested to be removed.
-    boolean mReplacingRemoveRequested = false;
+    private boolean mReplacingRemoveRequested = false;
     // Whether the replacement of the window should trigger app transition animation.
-    boolean mAnimateReplacingWindow = false;
+    private boolean mAnimateReplacingWindow = false;
     // If not null, the window that will be used to replace the old one. This is being set when
     // the window is added and unset when this window reports its first draw.
-    WindowState mReplacementWindow = null;
+    private WindowState mReplacementWindow = null;
     // For the new window in the replacement transition, if we have
     // requested to replace without animation, then we should
     // make sure we also don't apply an enter animation for
     // the new window.
     boolean mSkipEnterAnimationForSeamlessReplacement = false;
     // Whether this window is being moved via the resize API
-    boolean mMovedByResize;
+    private boolean mMovedByResize;
 
     /**
      * Wake lock for drawing.
@@ -514,7 +512,7 @@
      * who is preventing the system from suspending.
      * This lock is only acquired on first use.
      */
-    PowerManager.WakeLock mDrawLock;
+    private PowerManager.WakeLock mDrawLock;
 
     final private Rect mTmpRect = new Rect();
 
@@ -546,7 +544,7 @@
     private static final Region sEmptyRegion = new Region();
 
     /**
-     * Compares to window sub-layers and returns -1 if the first is lesser than the second in terms
+     * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
      * of z-order and 1 otherwise.
      */
     private static final Comparator<WindowState> sWindowSubLayerComparator = (w1, w2) -> {
@@ -563,7 +561,7 @@
 
     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
-           int viewVisibility, final DisplayContent displayContent, int ownerId) {
+           int viewVisibility, int ownerId) {
         mService = service;
         mSession = s;
         mClient = c;
@@ -587,7 +585,6 @@
         };
         mAttrs.copyFrom(a);
         mViewVisibility = viewVisibility;
-        mDisplayContent = displayContent;
         mPolicy = mService.mPolicy;
         mContext = mService.mContext;
         DeathRecipient deathRecipient = new DeathRecipient();
@@ -643,15 +640,10 @@
         }
         mIsFloatingLayer = mIsImWindow || mIsWallpaper;
 
-        if (mAppToken != null) {
-            final DisplayContent appDisplay = getDisplayContent();
-            mNotOnAppsDisplay = displayContent != appDisplay;
-
-            if (mAppToken.showForAllUsers) {
-                // Windows for apps that can show for all users should also show when the
-                // device is locked.
-                mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
-            }
+        if (mAppToken != null && mAppToken.showForAllUsers) {
+            // Windows for apps that can show for all users should also show when the device is
+            // locked.
+            mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
         }
 
         mWinAnimator = new WindowStateAnimator(this);
@@ -665,8 +657,7 @@
         mYOffset = 0;
         mLayer = 0;
         mInputWindowHandle = new InputWindowHandle(
-                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this,
-                displayContent.getDisplayId());
+                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this, getDisplayId());
     }
 
     void attach() {
@@ -714,6 +705,7 @@
         final Task task = getTask();
         final boolean fullscreenTask = !isInMultiWindowMode();
         final boolean windowsAreFloating = task != null && task.isFloating();
+        final DisplayContent dc = getDisplayContent();
 
         // If the task has temp inset bounds set, we have to make sure all its windows uses
         // the temp inset frame. Otherwise different display frames get applied to the main
@@ -779,8 +771,7 @@
             layoutXDiff = !mInsetFrame.isEmpty() ? mInsetFrame.left - mContainingFrame.left : 0;
             layoutYDiff = !mInsetFrame.isEmpty() ? mInsetFrame.top - mContainingFrame.top : 0;
             layoutContainingFrame = !mInsetFrame.isEmpty() ? mInsetFrame : mContainingFrame;
-            mTmpRect.set(0, 0, mDisplayContent.getDisplayInfo().logicalWidth,
-                    mDisplayContent.getDisplayInfo().logicalHeight);
+            mTmpRect.set(0, 0, dc.getDisplayInfo().logicalWidth, dc.getDisplayInfo().logicalHeight);
             subtractInsets(mDisplayFrame, layoutContainingFrame, df, mTmpRect);
             if (!layoutInParentFrame()) {
                 subtractInsets(mContainingFrame, layoutContainingFrame, pf, mTmpRect);
@@ -852,7 +843,7 @@
             mVisibleFrame.set(mContentFrame);
             mStableFrame.set(mContentFrame);
         } else if (mAttrs.type == TYPE_DOCK_DIVIDER) {
-            mDisplayContent.getDockedDividerController().positionDockedStackedDivider(mFrame);
+            dc.getDockedDividerController().positionDockedStackedDivider(mFrame);
             mContentFrame.set(mFrame);
             if (!mFrame.equals(mLastFrame)) {
                 mMovedByResize = true;
@@ -1187,20 +1178,16 @@
         }
     }
 
-    public DisplayContent getDisplayContent() {
-        if (mAppToken == null || mNotOnAppsDisplay) {
-            return mDisplayContent;
-        }
-        final TaskStack stack = getStack();
-        return stack == null ? mDisplayContent : stack.getDisplayContent();
+    DisplayContent getDisplayContent() {
+        return mToken.getDisplayContent();
     }
 
-    public DisplayInfo getDisplayInfo() {
+    DisplayInfo getDisplayInfo() {
         final DisplayContent displayContent = getDisplayContent();
         return displayContent != null ? displayContent.getDisplayInfo() : null;
     }
 
-    public int getDisplayId() {
+    int getDisplayId() {
         final DisplayContent displayContent = getDisplayContent();
         if (displayContent == null) {
             return -1;
@@ -1221,8 +1208,8 @@
         }
         // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
         // associate them with some stack to enable dimming.
-        return mAttrs.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
-                && mDisplayContent != null ? mDisplayContent.getHomeStack() : null;
+        final DisplayContent dc = getDisplayContent();
+        return mAttrs.type >= FIRST_SYSTEM_WINDOW && dc != null ? dc.getHomeStack() : null;
     }
 
     /**
@@ -2000,12 +1987,12 @@
     }
 
     void scheduleAnimationIfDimming() {
-        if (mDisplayContent == null) {
+        final DisplayContent dc = getDisplayContent();
+        if (dc == null) {
             return;
         }
         final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
-        if (dimLayerUser != null && mDisplayContent.mDimLayerController.isDimming(
-                dimLayerUser, mWinAnimator)) {
+        if (dimLayerUser != null && dc.mDimLayerController.isDimming(dimLayerUser, mWinAnimator)) {
             // Force an animation pass just to update the mDimLayer layer.
             mService.scheduleAnimationLocked();
         }
@@ -2118,16 +2105,17 @@
             return;
         }
 
+        final DisplayContent dc = getDisplayContent();
         if (!mAnimatingExit && mAppDied) {
             // If app died visible, apply a dim over the window to indicate that it's inactive
-            mDisplayContent.mDimLayerController.applyDimAbove(getDimLayerUser(), mWinAnimator);
+            dc.mDimLayerController.applyDimAbove(getDimLayerUser(), mWinAnimator);
         } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0
-                && mDisplayContent != null && !mAnimatingExit && isVisibleUnchecked()) {
-            mDisplayContent.mDimLayerController.applyDimBehind(getDimLayerUser(), mWinAnimator);
+                && dc != null && !mAnimatingExit && isVisibleUnchecked()) {
+            dc.mDimLayerController.applyDimBehind(getDimLayerUser(), mWinAnimator);
         }
     }
 
-    DimLayer.DimLayerUser getDimLayerUser() {
+    private DimLayer.DimLayerUser getDimLayerUser() {
         Task task = getTask();
         if (task != null) {
             return task;
@@ -2186,8 +2174,9 @@
     }
 
     void setDisplayLayoutNeeded() {
-        if (mDisplayContent != null) {
-            mDisplayContent.setLayoutNeeded();
+        final DisplayContent dc = getDisplayContent();
+        if (dc != null) {
+            dc.setLayoutNeeded();
         }
     }
 
@@ -2908,18 +2897,19 @@
     @Override
     public boolean isDimming() {
         final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
-        return dimLayerUser != null && mDisplayContent != null &&
-                mDisplayContent.mDimLayerController.isDimming(dimLayerUser, mWinAnimator);
+        final DisplayContent dc = getDisplayContent();
+        return dimLayerUser != null && dc != null
+                && dc.mDimLayerController.isDimming(dimLayerUser, mWinAnimator);
     }
 
-    public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
+    void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
         mShowToOwnerOnly = showToOwnerOnly;
     }
 
     boolean isHiddenFromUserLocked() {
         // Child windows are evaluated based on their parent window.
         final WindowState win = getTopParentWindow();
-        if (win.mAttrs.type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
+        if (win.mAttrs.type < FIRST_SYSTEM_WINDOW
                 && win.mAppToken != null && win.mAppToken.showForAllUsers) {
 
             // All window frames that are fullscreen extend above status bar, but some don't extend
@@ -2993,7 +2983,7 @@
      * Report a focus change.  Must be called with no locks held, and consistently
      * from the same serialized thread (such as dispatched from a handler).
      */
-    public void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) {
+    void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) {
         try {
             mClient.windowFocusChanged(focused, inTouchMode);
         } catch (RemoteException e) {
@@ -3021,9 +3011,7 @@
             return mAppToken.mFrozenMergedConfig.peek();
         }
 
-        // TODO: Remove when all windows' hierarchies will start from same root.
-        return mAppToken != null
-                ? super.getConfiguration() : getDisplayContent().getConfiguration();
+        return super.getConfiguration();
     }
 
     void reportResized() {
@@ -3038,7 +3026,7 @@
             } else {
                 newConfig = null;
             }
-            if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING)
+            if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING)
                 Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
 
             final Rect frame = mFrame;
@@ -3047,7 +3035,7 @@
             final Rect visibleInsets = mLastVisibleInsets;
             final Rect stableInsets = mLastStableInsets;
             final Rect outsets = mLastOutsets;
-            final boolean reportDraw = mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
+            final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING;
             if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
                     && mClient instanceof IWindow.Stub) {
                 // To prevent deadlock simulate one-way call if win.mClient is a local object.
@@ -3105,7 +3093,7 @@
         if (StackId.useWindowFrameForBackdrop(getStackId()) || !resizing) {
             return frame;
         }
-        DisplayInfo displayInfo = getDisplayInfo();
+        final DisplayInfo displayInfo = getDisplayInfo();
         mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
         return mTmpRect;
     }
@@ -3214,7 +3202,7 @@
      * @return Whether we reported "resize while not drag resizing" to the application.
      * @see #isResizedWhileNotDragResizing()
      */
-    boolean isResizedWhileNotDragResizingReported() {
+    private boolean isResizedWhileNotDragResizingReported() {
         return mResizedWhileNotDragResizingReported;
     }
 
@@ -3222,7 +3210,7 @@
         return mResizeMode;
     }
 
-    boolean computeDragResizing() {
+    private boolean computeDragResizing() {
         final Task task = getTask();
         if (task == null) {
             return false;
@@ -3240,7 +3228,7 @@
         // and the bounds we clip this window to might be different. In order to avoid holes, we
         // simulate that we are still resizing so the app fills the hole with the resizing
         // background.
-        return (mDisplayContent.mDividerControllerLocked.isResizing()
+        return (getDisplayContent().mDividerControllerLocked.isResizing()
                         || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) &&
                 !task.inFreeformWorkspace() && !isGoneForLayoutLw();
 
@@ -3256,7 +3244,7 @@
         if (task != null && task.isDragResizing()) {
             mResizeMode = task.getDragResizeMode();
         } else {
-            mResizeMode = mDragResizing && mDisplayContent.mDividerControllerLocked.isResizing()
+            mResizeMode = mDragResizing && getDisplayContent().mDividerControllerLocked.isResizing()
                     ? DRAG_RESIZE_MODE_DOCKED_DIVIDER
                     : DRAG_RESIZE_MODE_FREEFORM;
         }
@@ -3276,9 +3264,6 @@
                 if (stack != null) {
                     pw.print(" stackId="); pw.print(stack.mStackId);
                 }
-                if (mNotOnAppsDisplay) {
-                    pw.print(" mNotOnAppsDisplay="); pw.print(mNotOnAppsDisplay);
-                }
                 pw.print(" mSession="); pw.print(mSession);
                 pw.print(" mClient="); pw.println(mClient.asBinder());
         pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid);
@@ -3664,9 +3649,10 @@
     }
 
     void requestUpdateWallpaperIfNeeded() {
-        if (mDisplayContent != null && (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
-            mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-            mDisplayContent.setLayoutNeeded();
+        final DisplayContent dc = getDisplayContent();
+        if (dc != null && (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
+            dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+            dc.setLayoutNeeded();
             mService.mWindowPlacerLocked.requestTraversal();
         }
 
@@ -3692,12 +3678,12 @@
         return winY;
     }
 
-    void transferDimToReplacement() {
+    private void transferDimToReplacement() {
         final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
-        if (dimLayerUser != null && mDisplayContent != null) {
-            mDisplayContent.mDimLayerController.applyDim(dimLayerUser,
-                    mReplacementWindow.mWinAnimator,
-                    (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? true : false);
+        final DisplayContent dc = getDisplayContent();
+        if (dimLayerUser != null && dc != null) {
+            dc.mDimLayerController.applyDim(dimLayerUser,
+                    mReplacementWindow.mWinAnimator, (mAttrs.flags & FLAG_DIM_BEHIND) != 0);
         }
     }
 
@@ -3795,13 +3781,13 @@
         }
 
         if (mAttrs.type == TYPE_INPUT_METHOD) {
-            mDisplayContent.mDividerControllerLocked.resetImeHideRequested();
+            getDisplayContent().mDividerControllerLocked.resetImeHideRequested();
         }
 
         return true;
     }
 
-    void logPerformShow(String prefix) {
+    private void logPerformShow(String prefix) {
         if (DEBUG_VISIBILITY
                 || (DEBUG_STARTING_WINDOW && mAttrs.type == TYPE_APPLICATION_STARTING)) {
             Slog.v(TAG, prefix + this
@@ -3811,11 +3797,11 @@
                     + " during animation: policyVis=" + mPolicyVisibility
                     + " parentHidden=" + isParentWindowHidden()
                     + " tok.hiddenRequested="
-                    + (mAppToken != null ? mAppToken.hiddenRequested : false)
-                    + " tok.hidden=" + (mAppToken != null ? mAppToken.hidden : false)
+                    + (mAppToken != null && mAppToken.hiddenRequested)
+                    + " tok.hidden=" + (mAppToken != null && mAppToken.hidden)
                     + " animating=" + mWinAnimator.mAnimating
                     + " tok animating="
-                    + (mWinAnimator.mAppAnimator != null ? mWinAnimator.mAppAnimator.animating : false)
+                    + (mWinAnimator.mAppAnimator != null && mWinAnimator.mAppAnimator.animating)
                     + " Callers=" + Debug.getCallers(4));
         }
     }
@@ -3873,13 +3859,8 @@
     }
 
     @Override
-    int rebuildWindowList(DisplayContent dc, int addIndex) {
-        final DisplayContent winDisplayContent = getDisplayContent();
-        if (winDisplayContent == dc || winDisplayContent == null) {
-            mDisplayContent = dc;
-            return reAddWindow(addIndex);
-        }
-        return addIndex;
+    int rebuildWindowList(int addIndex) {
+        return reAddWindow(addIndex);
     }
 
     // TODO: come-up with a better name for this method that represents what it does.
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index dc83ac0..53fb99b 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1350,7 +1350,7 @@
         // If we are undergoing seamless rotation, the surface has already
         // been set up to persist at it's old location. We need to freeze
         // updates until a resize occurs.
-        w.mSeamlesslyRotated = w.mSeamlesslyRotated && !mSurfaceResized;
+        mService.markForSeamlessRotation(w, w.mSeamlesslyRotated && !mSurfaceResized);
 
         calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect);
 
@@ -1750,7 +1750,7 @@
         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
 
         if (mWin.mAttrs.type == TYPE_INPUT_METHOD) {
-            mWin.mDisplayContent.adjustForImeIfNeeded();
+            mWin.getDisplayContent().adjustForImeIfNeeded();
             if (isEntrance) {
                 mWin.setDisplayLayoutNeeded();
                 mService.mWindowPlacerLocked.requestTraversal();
@@ -1936,24 +1936,8 @@
         // Compute a transform matrix to undo the coordinate space transformation,
         // and present the window at the same physical position it previously occupied.
         final int deltaRotation = DisplayContent.deltaRotation(newRotation, oldRotation);
-        switch (deltaRotation) {
-        case Surface.ROTATION_0:
-            transform.reset();
-            break;
-        case Surface.ROTATION_270:
-            transform.setRotate(270, 0, 0);
-            transform.postTranslate(0, displayHeight);
-            transform.postTranslate(y, 0);
-            break;
-        case Surface.ROTATION_180:
-            transform.reset();
-            break;
-        case Surface.ROTATION_90:
-            transform.setRotate(90, 0, 0);
-            transform.postTranslate(displayWidth, 0);
-            transform.postTranslate(-y, x);
-            break;
-        }
+        DisplayContent.createRotationMatrix(deltaRotation, x, y, displayWidth, displayHeight,
+                transform);
 
         // We have two cases:
         //  1. Windows with NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY:
@@ -1991,7 +1975,7 @@
             cropRect.set(0, 0, w.mRequestedWidth, w.mRequestedWidth + w.mRequestedHeight);
             mSurfaceController.setCropInTransaction(cropRect, false);
         } else {
-            w.mSeamlesslyRotated = true;
+            mService.markForSeamlessRotation(w, true);
             transform.getValues(mService.mTmpFloats);
 
             float DsDx = mService.mTmpFloats[Matrix.MSCALE_X];
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 668e1b4..285a75c 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -9,7 +9,17 @@
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
 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.AppTransition.TRANSIT_ACTIVITY_CLOSE;
+import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_CLOSE;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_BACK;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
+import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_CLOSE;
+import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
+import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_OPEN;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
@@ -216,14 +226,6 @@
         final int dw = displayInfo.logicalWidth;
         final int dh = displayInfo.logicalHeight;
 
-        if (mService.mInputConsumer != null) {
-            mService.mInputConsumer.layout(dw, dh);
-        }
-
-        if (mService.mWallpaperInputConsumer != null) {
-            mService.mWallpaperInputConsumer.layout(dw, dh);
-        }
-
         final int N = windows.size();
         int i;
 
@@ -370,6 +372,7 @@
         }
 
         // Window frames may have changed. Tell the input dispatcher about it.
+        mService.mInputMonitor.layoutInputConsumers(dw, dh);
         mService.mInputMonitor.setUpdateInputWindowsNeededLw();
         if (updateInputWindows) {
             mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
@@ -405,8 +408,7 @@
 
         mService.mRoot.mWallpaperMayChange = false;
 
-        // The top-most window will supply the layout params,
-        // and we will determine it below.
+        // The top-most window will supply the layout params, and we will determine it below.
         LayoutParams animLp = null;
         int bestAnimLayer = -1;
         boolean fullscreenAnim = false;
@@ -415,21 +417,19 @@
         int i;
         for (i = 0; i < appsCount; i++) {
             final AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
-            // Clearing the mAnimatingExit flag before entering animation. It's set to
-            // true if app window is removed, or window relayout to invisible.
-            // This also affects window visibility. We need to clear it *before*
-            // maybeUpdateTransitToWallpaper() as the transition selection depends on
-            // wallpaper target visibility.
+            // Clearing the mAnimatingExit flag before entering animation. It's set to true if app
+            // window is removed, or window relayout to invisible. This also affects window
+            // visibility. We need to clear it *before* maybeUpdateTransitToWallpaper() as the
+            // transition selection depends on wallpaper target visibility.
             wtoken.clearAnimatingFlags();
 
         }
+
         // Adjust wallpaper before we pull the lower/upper target, since pending changes
         // (like the clearAnimatingFlags() above) might affect wallpaper target result.
-        if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
-                mWallpaperControllerLocked.adjustWallpaperWindows()) {
-            mService.mLayersController.assignLayersLocked(windows);
-            displayContent.setLayoutNeeded();
-        }
+        // Or, the opening app window should be a wallpaper target.
+        mWallpaperControllerLocked.adjustWallpaperWindowsForAppTransitionIfNeeded(displayContent,
+                mService.mOpeningApps, windows);
 
         final WindowState lowerWallpaperTarget =
                 mWallpaperControllerLocked.getLowerWallpaperTarget();
@@ -447,15 +447,11 @@
             upperWallpaperAppToken = upperWallpaperTarget.mAppToken;
         }
 
-        // Do a first pass through the tokens for two
-        // things:
-        // (1) Determine if both the closing and opening
-        // app token sets are wallpaper targets, in which
-        // case special animations are needed
-        // (since the wallpaper needs to stay static
-        // behind them).
-        // (2) Find the layout params of the top-most
-        // application window in the tokens, which is
+        // Do a first pass through the tokens for two things:
+        // (1) Determine if both the closing and opening app token sets are wallpaper targets, in
+        // which case special animations are needed (since the wallpaper needs to stay static behind
+        // them).
+        // (2) Find the layout params of the top-most application window in the tokens, which is
         // what will control the animation theme.
         final int closingAppsCount = mService.mClosingApps.size();
         appsCount = closingAppsCount + mService.mOpeningApps.size();
@@ -496,10 +492,8 @@
         transit = maybeUpdateTransitToWallpaper(transit, openingAppHasWallpaper,
                 closingAppHasWallpaper, lowerWallpaperTarget, upperWallpaperTarget);
 
-        // If all closing windows are obscured, then there is
-        // no need to do an animation.  This is the case, for
-        // example, when this transition is being done behind
-        // the lock screen.
+        // If all closing windows are obscured, then there is no need to do an animation. This is
+        // the case, for example, when this transition is being done behind the lock screen.
         if (!mService.mPolicy.allowAppAnimationsLw()) {
             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                     "Animations disallowed by keyguard or dream.");
@@ -721,9 +715,8 @@
             WindowState upperWallpaperTarget) {
         // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
         final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
-        final WindowState oldWallpaper =
-                mWallpaperControllerLocked.isWallpaperTargetAnimating()
-                        ? null : wallpaperTarget;
+        final WindowState oldWallpaper = mWallpaperControllerLocked.isWallpaperTargetAnimating()
+                ? null : wallpaperTarget;
         final ArraySet<AppWindowToken> openingApps = mService.mOpeningApps;
         final ArraySet<AppWindowToken> closingApps = mService.mClosingApps;
         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
@@ -735,18 +728,17 @@
                         + ", closingApps=" + closingApps);
         mService.mAnimateWallpaperWithTarget = false;
         if (closingAppHasWallpaper && openingAppHasWallpaper) {
-            if (DEBUG_APP_TRANSITIONS)
-                Slog.v(TAG, "Wallpaper animation!");
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
             switch (transit) {
-                case AppTransition.TRANSIT_ACTIVITY_OPEN:
-                case AppTransition.TRANSIT_TASK_OPEN:
-                case AppTransition.TRANSIT_TASK_TO_FRONT:
-                    transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
+                case TRANSIT_ACTIVITY_OPEN:
+                case TRANSIT_TASK_OPEN:
+                case TRANSIT_TASK_TO_FRONT:
+                    transit = TRANSIT_WALLPAPER_INTRA_OPEN;
                     break;
-                case AppTransition.TRANSIT_ACTIVITY_CLOSE:
-                case AppTransition.TRANSIT_TASK_CLOSE:
-                case AppTransition.TRANSIT_TASK_TO_BACK:
-                    transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
+                case TRANSIT_ACTIVITY_CLOSE:
+                case TRANSIT_TASK_CLOSE:
+                case TRANSIT_TASK_TO_BACK:
+                    transit = TRANSIT_WALLPAPER_INTRA_CLOSE;
                     break;
             }
             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
@@ -755,17 +747,15 @@
                 && !openingApps.contains(oldWallpaper.mAppToken)
                 && closingApps.contains(oldWallpaper.mAppToken)) {
             // We are transitioning from an activity with a wallpaper to one without.
-            transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
-            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                    "New transit away from wallpaper: "
+            transit = TRANSIT_WALLPAPER_CLOSE;
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit away from wallpaper: "
                     + AppTransition.appTransitionToString(transit));
         } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw() &&
                 openingApps.contains(wallpaperTarget.mAppToken)) {
             // We are transitioning from an activity without
             // a wallpaper to now showing the wallpaper
-            transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
-            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                    "New transit into wallpaper: "
+            transit = TRANSIT_WALLPAPER_OPEN;
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit into wallpaper: "
                     + AppTransition.appTransitionToString(transit));
         } else {
             mService.mAnimateWallpaperWithTarget = true;
@@ -774,7 +764,7 @@
     }
 
     private void processApplicationsAnimatingInPlace(int transit) {
-        if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
+        if (transit == TRANSIT_TASK_IN_PLACE) {
             // Find the focused window
             final WindowState win = mService.getDefaultDisplayContentLocked().findFocusedWindow();
             if (win != null) {
@@ -899,6 +889,6 @@
     public void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + "mTraversalScheduled=" + mTraversalScheduled);
         pw.println(prefix + "mHoldScreenWindow=" + mService.mRoot.mHoldScreenWindow);
-        pw.println(prefix + "mObsuringWindow=" + mService.mRoot.mObsuringWindow);
+        pw.println(prefix + "mObscuringWindow=" + mService.mRoot.mObscuringWindow);
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 177652c..218972a 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -21,9 +21,11 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
+import android.view.DisplayInfo;
 
 import java.io.PrintWriter;
 
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
@@ -77,12 +79,16 @@
     // windows will be put to the bottom of the list.
     boolean sendingToBottom;
 
-    WindowToken(WindowManagerService service, IBinder _token, int type, boolean _explicit) {
+    // The display this token is on.
+    private DisplayContent mDisplayContent;
+
+    WindowToken(WindowManagerService service, IBinder _token, int type, boolean _explicit,
+            DisplayContent dc) {
         mService = service;
         token = _token;
         windowType = type;
         explicit = _explicit;
-        mService.mTokenMap.put(token, this);
+        onDisplayChanged(dc);
     }
 
     void removeAllWindows() {
@@ -104,15 +110,11 @@
         final int count = mChildren.size();
         boolean changed = false;
         boolean delayed = false;
-        DisplayContent displayContent = null;
 
         for (int i = 0; i < count; i++) {
             final WindowState win = mChildren.get(i);
             if (win.mWinAnimator.isAnimationSet()) {
                 delayed = true;
-                // TODO: This is technically wrong as a token can have windows on multi-displays
-                // currently. That will change moving forward though.
-                displayContent = win.getDisplayContent();
             }
             changed |= win.onSetAppExiting();
         }
@@ -124,8 +126,8 @@
             mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /*updateInputWindows*/);
         }
 
-        if (delayed && displayContent != null) {
-            displayContent.mExitingTokens.add(this);
+        if (delayed) {
+            mDisplayContent.mExitingTokens.add(this);
         }
     }
 
@@ -169,25 +171,41 @@
     void addWindow(final WindowState win) {
         if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindow: win=" + win + " Callers=" + Debug.getCallers(5));
 
-        final DisplayContent dc = win.getDisplayContent();
         if (!win.isChildWindow()) {
             int tokenWindowsPos = 0;
-            if (dc != null) {
-                if (asAppWindowToken() != null) {
-                    tokenWindowsPos = dc.addAppWindowToWindowList(win);
-                } else {
-                    dc.addNonAppWindowToWindowList(win);
-                }
+            if (asAppWindowToken() != null) {
+                tokenWindowsPos = mDisplayContent.addAppWindowToWindowList(win);
+            } else {
+                mDisplayContent.addNonAppWindowToWindowList(win);
             }
             if (!mChildren.contains(win)) {
                 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
                 addChild(win, tokenWindowsPos);
             }
-        } else if (dc != null) {
-            dc.addChildWindowToWindowList(win);
+        } else {
+            mDisplayContent.addChildWindowToWindowList(win);
         }
     }
 
+    void addImeWindow(WindowState win) {
+        int pos = mService.findDesiredInputMethodWindowIndexLocked(true);
+
+        if (pos < 0) {
+            addWindow(win);
+            mService.moveInputMethodDialogsLocked(pos);
+            return;
+        }
+
+        if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+                "Adding input method window " + win + " at " + pos);
+        mDisplayContent.addToWindowList(win, pos);
+        if (!mChildren.contains(win)) {
+            addChild(win, null);
+        }
+        mService.mWindowsChanged = true;
+        mService.moveInputMethodDialogsLocked(pos + 1);
+    }
+
     /** Return the first window in the token window list that isn't a starting window or null. */
     WindowState getFirstNonStartingWindow() {
         final int count = mChildren.size();
@@ -217,6 +235,18 @@
         return null;
     }
 
+    /** Return true if this token has a window that wants the wallpaper displayed behind it. */
+    boolean windowsCanBeWallpaperTarget() {
+        for (int j = mChildren.size() - 1; j >= 0; j--) {
+            final WindowState w = mChildren.get(j);
+            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     void hideWallpaperToken(boolean wasDeferred, String reason) {
         for (int j = mChildren.size() - 1; j >= 0; j--) {
             final WindowState wallpaper = mChildren.get(j);
@@ -253,11 +283,15 @@
         }
     }
 
-    void updateWallpaperVisibility(int dw, int dh, boolean visible, DisplayContent displayContent) {
+    void updateWallpaperVisibility(boolean visible) {
+        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
+
         if (hidden == visible) {
             hidden = !visible;
             // Need to do a layout to ensure the wallpaper now has the correct size.
-            displayContent.setLayoutNeeded();
+            mDisplayContent.setLayoutNeeded();
         }
 
         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
@@ -280,7 +314,7 @@
                     "Wallpaper token " + token + " hidden=" + !visible);
             hidden = !visible;
             // Need to do a layout to ensure the wallpaper now has the correct size.
-            mService.getDefaultDisplayContentLocked().setLayoutNeeded();
+            mDisplayContent.setLayoutNeeded();
         }
 
         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
@@ -387,6 +421,33 @@
         return null;
     }
 
+    DisplayContent getDisplayContent() {
+        return mDisplayContent;
+    }
+
+    @Override
+    void removeImmediately() {
+        super.removeImmediately();
+        if (mDisplayContent != null) {
+            mDisplayContent.removeWindowToken(token);
+            mService.mRoot.removeWindowTokenIfPossible(token);
+        }
+    }
+
+    void onDisplayChanged(DisplayContent dc) {
+        if (mDisplayContent == dc) {
+            return;
+        }
+
+        if (mDisplayContent != null) {
+            mDisplayContent.removeWindowToken(token);
+        }
+        mDisplayContent = dc;
+        mDisplayContent.setWindowToken(token, this);
+
+        super.onDisplayChanged(dc);
+    }
+
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("windows="); pw.println(mChildren);
         pw.print(prefix); pw.print("windowType="); pw.print(windowType);
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 9459517..d328ade 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -7,7 +7,6 @@
 LOCAL_SRC_FILES += \
     $(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_am_BatteryStatsService.cpp \
-    $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
     $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_HardwarePropertiesManagerService.cpp \
@@ -65,4 +64,9 @@
     libEGL \
     libGLESv2 \
     libnetutils \
-
+    libhidl \
+    libhwbinder \
+    libutils \
+    android.hardware.power@1.0 \
+    android.hardware.vibrator@1.0 \
+    android.hardware.light@2.0 \
diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
deleted file mode 100644
index d004e30..0000000
--- a/services/core/jni/com_android_server_AssetAtlasService.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#define LOG_TAG "AssetAtlasService"
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android/graphics/GraphicsJNI.h"
-
-#include <android_view_GraphicBuffer.h>
-#include <cutils/log.h>
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-// Disable warnings for Skia.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <SkCanvas.h>
-#include <SkBitmap.h>
-#pragma GCC diagnostic pop
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-// Defines
-// ----------------------------------------------------------------------------
-
-// Defines how long to wait for the GPU when uploading the atlas
-// This timeout is defined in nanoseconds (see EGL_KHR_fence_sync extension)
-#define FENCE_TIMEOUT 2000000000
-
-// ----------------------------------------------------------------------------
-// Canvas management
-// ----------------------------------------------------------------------------
-
-#define CLEANUP_GL_AND_RETURN(result) \
-    if (fence != EGL_NO_SYNC_KHR) eglDestroySyncKHR(display, fence); \
-    if (image) eglDestroyImageKHR(display, image); \
-    if (texture) glDeleteTextures(1, &texture); \
-    if (surface != EGL_NO_SURFACE) eglDestroySurface(display, surface); \
-    if (context != EGL_NO_CONTEXT) eglDestroyContext(display, context); \
-    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); \
-    eglReleaseThread(); \
-    eglTerminate(display); \
-    return result;
-
-static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject,
-        jobject graphicBuffer, jobject bitmapHandle) {
-
-    SkBitmap bitmap;
-    GraphicsJNI::getSkBitmap(env, bitmapHandle, &bitmap);
-    SkAutoLockPixels alp(bitmap);
-
-    // The goal of this method is to copy the bitmap into the GraphicBuffer
-    // using the GPU to swizzle the texture content
-    sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
-
-    if (buffer != NULL) {
-        EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        if (display == EGL_NO_DISPLAY) return JNI_FALSE;
-
-        EGLint major;
-        EGLint minor;
-        if (!eglInitialize(display, &major, &minor)) {
-            ALOGW("Could not initialize EGL");
-            return JNI_FALSE;
-        }
-
-        // We're going to use a 1x1 pbuffer surface later on
-        // The configuration doesn't really matter for what we're trying to do
-        EGLint configAttrs[] = {
-                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-                EGL_RED_SIZE, 8,
-                EGL_GREEN_SIZE, 8,
-                EGL_BLUE_SIZE, 8,
-                EGL_ALPHA_SIZE, 0,
-                EGL_DEPTH_SIZE, 0,
-                EGL_STENCIL_SIZE, 0,
-                EGL_NONE
-        };
-        EGLConfig configs[1];
-        EGLint configCount;
-        if (!eglChooseConfig(display, configAttrs, configs, 1, &configCount)) {
-            ALOGW("Could not select EGL configuration");
-            eglReleaseThread();
-            eglTerminate(display);
-            return JNI_FALSE;
-        }
-        if (configCount <= 0) {
-            ALOGW("Could not find EGL configuration");
-            eglReleaseThread();
-            eglTerminate(display);
-            return JNI_FALSE;
-        }
-
-        // These objects are initialized below but the default "null"
-        // values are used to cleanup properly at any point in the
-        // initialization sequence
-        GLuint texture = 0;
-        EGLImageKHR image = EGL_NO_IMAGE_KHR;
-        EGLSurface surface = EGL_NO_SURFACE;
-        EGLSyncKHR fence = EGL_NO_SYNC_KHR;
-
-        EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-        EGLContext context = eglCreateContext(display, configs[0], EGL_NO_CONTEXT, attrs);
-        if (context == EGL_NO_CONTEXT) {
-            ALOGW("Could not create EGL context");
-            CLEANUP_GL_AND_RETURN(JNI_FALSE);
-        }
-
-        // Create the 1x1 pbuffer
-        EGLint surfaceAttrs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
-        surface = eglCreatePbufferSurface(display, configs[0], surfaceAttrs);
-        if (surface == EGL_NO_SURFACE) {
-            ALOGW("Could not create EGL surface");
-            CLEANUP_GL_AND_RETURN(JNI_FALSE);
-        }
-
-        if (!eglMakeCurrent(display, surface, surface, context)) {
-            ALOGW("Could not change current EGL context");
-            CLEANUP_GL_AND_RETURN(JNI_FALSE);
-        }
-
-        // We use an EGLImage to access the content of the GraphicBuffer
-        // The EGL image is later bound to a 2D texture
-        EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer->getNativeBuffer();
-        EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
-        image = eglCreateImageKHR(display, EGL_NO_CONTEXT,
-                EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
-        if (image == EGL_NO_IMAGE_KHR) {
-            ALOGW("Could not create EGL image");
-            CLEANUP_GL_AND_RETURN(JNI_FALSE);
-        }
-
-        glGenTextures(1, &texture);
-        glBindTexture(GL_TEXTURE_2D, texture);
-        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
-        if (glGetError() != GL_NO_ERROR) {
-            ALOGW("Could not create/bind texture");
-            CLEANUP_GL_AND_RETURN(JNI_FALSE);
-        }
-
-        // Upload the content of the bitmap in the GraphicBuffer
-        glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap.bytesPerPixel());
-        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
-                GL_RGBA, GL_UNSIGNED_BYTE, bitmap.getPixels());
-        if (glGetError() != GL_NO_ERROR) {
-            ALOGW("Could not upload to texture");
-            CLEANUP_GL_AND_RETURN(JNI_FALSE);
-        }
-
-        // The fence is used to wait for the texture upload to finish
-        // properly. We cannot rely on glFlush() and glFinish() as
-        // some drivers completely ignore these API calls
-        fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL);
-        if (fence == EGL_NO_SYNC_KHR) {
-            ALOGW("Could not create sync fence %#x", eglGetError());
-            CLEANUP_GL_AND_RETURN(JNI_FALSE);
-        }
-
-        // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
-        // pipeline flush (similar to what a glFlush() would do.)
-        EGLint waitStatus = eglClientWaitSyncKHR(display, fence,
-                EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
-        if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
-            ALOGW("Failed to wait for the fence %#x", eglGetError());
-            CLEANUP_GL_AND_RETURN(JNI_FALSE);
-        }
-
-        CLEANUP_GL_AND_RETURN(JNI_TRUE);
-    }
-
-    return JNI_FALSE;
-}
-
-// ----------------------------------------------------------------------------
-// JNI Glue
-// ----------------------------------------------------------------------------
-
-#define FIND_CLASS(var, className) \
-        var = env->FindClass(className); \
-        LOG_FATAL_IF(! (var), "Unable to find class " className);
-
-#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
-        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
-        LOG_FATAL_IF(!(var), "Unable to find method " methodName);
-
-const char* const kClassPathName = "com/android/server/AssetAtlasService";
-
-static const JNINativeMethod gMethods[] = {
-    { "nUploadAtlas", "(Landroid/view/GraphicBuffer;Landroid/graphics/Bitmap;)Z",
-            (void*) com_android_server_AssetAtlasService_upload },
-};
-
-int register_android_server_AssetAtlasService(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
-}
-
-};
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 03fbd19..cc52260 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -16,6 +16,9 @@
 
 #define LOG_TAG "VibratorService"
 
+#include <android/hardware/vibrator/1.0/IVibrator.h>
+#include <android/hardware/vibrator/1.0/types.h>
+
 #include "jni.h"
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
@@ -26,32 +29,27 @@
 
 #include <stdio.h>
 
+using android::hardware::getService;
+using android::hardware::vibrator::V1_0::IVibrator;
+using android::hardware::vibrator::V1_0::Status;
+
 namespace android
 {
 
-static hw_module_t *gVibraModule = NULL;
-static vibrator_device_t *gVibraDevice = NULL;
+static sp<IVibrator> mHal;
 
 static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)
 {
-    if (gVibraModule != NULL) {
+    /* TODO(b/31632518) */
+    if (mHal != nullptr) {
         return;
     }
-
-    int err = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, (hw_module_t const**)&gVibraModule);
-
-    if (err) {
-        ALOGE("Couldn't load %s module (%s)", VIBRATOR_HARDWARE_MODULE_ID, strerror(-err));
-    } else {
-        if (gVibraModule) {
-            vibrator_open(gVibraModule, &gVibraDevice);
-        }
-    }
+    mHal = IVibrator::getService("vibrator");
 }
 
 static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */)
 {
-    if (gVibraModule && gVibraDevice) {
+    if (mHal != nullptr) {
         return JNI_TRUE;
     } else {
         return JNI_FALSE;
@@ -60,10 +58,10 @@
 
 static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
 {
-    if (gVibraDevice) {
-        int err = gVibraDevice->vibrator_on(gVibraDevice, timeout_ms);
-        if (err != 0) {
-            ALOGE("The hw module failed in vibrator_on: %s", strerror(-err));
+    if (mHal != nullptr) {
+        Status retStatus = mHal->on(timeout_ms);
+        if (retStatus == Status::ERR) {
+            ALOGE("vibratorOn command failed.");
         }
     } else {
         ALOGW("Tried to vibrate but there is no vibrator device.");
@@ -72,10 +70,10 @@
 
 static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
 {
-    if (gVibraDevice) {
-        int err = gVibraDevice->vibrator_off(gVibraDevice);
-        if (err != 0) {
-            ALOGE("The hw module failed in vibrator_off(): %s", strerror(-err));
+    if (mHal != nullptr) {
+        Status retStatus = mHal->off();
+        if (retStatus == Status::ERR) {
+            ALOGE("vibratorOff command failed.");
         }
     } else {
         ALOGW("Tried to stop vibrating but there is no vibrator device.");
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index ecdc71e..b22d5e7 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "BatteryStatsService"
 //#define LOG_NDEBUG 0
 
+#include <android/hardware/power/1.0/IPower.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <jni.h>
 
@@ -26,8 +27,6 @@
 #include <cutils/log.h>
 #include <utils/misc.h>
 #include <utils/Log.h>
-#include <hardware/hardware.h>
-#include <hardware/power.h>
 #include <suspend/autosuspend.h>
 
 #include <inttypes.h>
@@ -41,6 +40,14 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::power::V1_0::IPower;
+using android::hardware::power::V1_0::PowerStatePlatformSleepState;
+using android::hardware::power::V1_0::PowerStateVoter;
+using android::hardware::power::V1_0::Status;
+using android::hardware::hidl_vec;
+
 namespace android
 {
 
@@ -49,7 +56,7 @@
 
 static bool wakeup_init = false;
 static sem_t wakeup_sem;
-extern struct power_module* gPowerModule;
+extern sp<IPower> gPowerHal;
 
 static void wakeup_callback(bool success)
 {
@@ -174,86 +181,34 @@
 }
 
 static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
-    int num_modes = -1;
-    char *output = (char*)env->GetDirectBufferAddress(outBuf), *offset = output;
+    char *output = (char*)env->GetDirectBufferAddress(outBuf);
+    char *offset = output;
     int remaining = (int)env->GetDirectBufferCapacity(outBuf);
-    power_state_platform_sleep_state_t *list;
-    size_t *voter_list;
     int total_added = -1;
 
     if (outBuf == NULL) {
         jniThrowException(env, "java/lang/NullPointerException", "null argument");
-        goto error;
+        return -1;
     }
 
-    if (!gPowerModule) {
-        ALOGE("%s: gPowerModule not loaded", POWER_HARDWARE_MODULE_ID);
-        goto error;
+    if (gPowerHal == nullptr) {
+        ALOGE("gPowerHal not loaded");
+        return -1;
     }
 
-    if (! (gPowerModule->get_platform_low_power_stats && gPowerModule->get_number_of_platform_modes
-       && gPowerModule->get_voter_list)) {
-        ALOGE("%s: Missing API", POWER_HARDWARE_MODULE_ID);
-        goto error;
-    }
+    gPowerHal->getPlatformLowPowerStats(
+        [&offset, &remaining, &total_added](hidl_vec<PowerStatePlatformSleepState> states,
+                Status status) {
+            if (status != Status::SUCCESS)
+                return;
+            for (size_t i = 0; i < states.size(); i++) {
+                int added;
+                const PowerStatePlatformSleepState& state = states[i];
 
-    if (gPowerModule->get_number_of_platform_modes) {
-        num_modes = gPowerModule->get_number_of_platform_modes(gPowerModule);
-    }
-
-    if (num_modes < 1) {
-        ALOGE("%s: Platform does not even have one low power mode", POWER_HARDWARE_MODULE_ID);
-        goto error;
-    }
-
-    list = (power_state_platform_sleep_state_t *)calloc(num_modes,
-        sizeof(power_state_platform_sleep_state_t));
-    if (!list) {
-        ALOGE("%s: power_state_platform_sleep_state_t allocation failed", POWER_HARDWARE_MODULE_ID);
-        goto error;
-    }
-
-    voter_list = (size_t *)calloc(num_modes, sizeof(*voter_list));
-    if (!voter_list) {
-        ALOGE("%s: voter_list allocation failed", POWER_HARDWARE_MODULE_ID);
-        goto err_free;
-    }
-
-    gPowerModule->get_voter_list(gPowerModule, voter_list);
-
-    for (int i = 0; i < num_modes; i++) {
-        list[i].voters = (power_state_voter_t *)calloc(voter_list[i],
-                         sizeof(power_state_voter_t));
-        if (!list[i].voters) {
-            ALOGE("%s: voter_t allocation failed", POWER_HARDWARE_MODULE_ID);
-            goto err_free;
-        }
-    }
-
-    if (!gPowerModule->get_platform_low_power_stats(gPowerModule, list)) {
-        for (int i = 0; i < num_modes; i++) {
-            int added;
-
-            added = snprintf(offset, remaining,
-                    "state_%d name=%s time=%" PRIu64 " count=%" PRIu64 " ",
-                    i + 1, list[i].name, list[i].residency_in_msec_since_boot,
-                    list[i].total_transitions);
-            if (added < 0) {
-                break;
-            }
-            if (added > remaining) {
-                added = remaining;
-            }
-            offset += added;
-            remaining -= added;
-            total_added += added;
-
-            for (unsigned int j = 0; j < list[i].number_of_voters; j++) {
                 added = snprintf(offset, remaining,
-                        "voter_%d name=%s time=%" PRIu64 " count=%" PRIu64 " ",
-                        j + 1, list[i].voters[j].name,
-                        list[i].voters[j].total_time_in_msec_voted_for_since_boot,
-                        list[i].voters[j].total_number_of_times_voted_since_boot);
+                    "state_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " ",
+                    i + 1, state.name.c_str(), state.residencyInMsecSinceBoot,
+                    state.totalTransitions);
                 if (added < 0) {
                     break;
                 }
@@ -263,27 +218,37 @@
                 offset += added;
                 remaining -= added;
                 total_added += added;
-            }
 
-            if (remaining <= 0) {
-                /* rewrite NULL character*/
-                offset--;
-                total_added--;
-                ALOGE("%s module: buffer not enough", POWER_HARDWARE_MODULE_ID);
-                break;
+                for (size_t j = 0; j < state.voters.size(); j++) {
+                    const PowerStateVoter& voter = state.voters[j];
+                    added = snprintf(offset, remaining,
+                            "voter_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " ",
+                            j + 1, voter.name.c_str(),
+                            voter.totalTimeInMsecVotedForSinceBoot,
+                            voter.totalNumberOfTimesVotedSinceBoot);
+                    if (added < 0) {
+                        break;
+                    }
+                    if (added > remaining) {
+                        added = remaining;
+                    }
+                    offset += added;
+                    remaining -= added;
+                    total_added += added;
+                }
+
+                if (remaining <= 0) {
+                    /* rewrite NULL character*/
+                    offset--;
+                    total_added--;
+                    ALOGE("PowerHal: buffer not enough");
+                    break;
+                }
             }
         }
-    }
+    );
     *offset = 0;
     total_added += 1;
-
-err_free:
-    for (int i = 0; i < num_modes; i++) {
-        free(list[i].voters);
-    }
-    free(list);
-    free(voter_list);
-error:
     return total_added;
 }
 
diff --git a/services/core/jni/com_android_server_lights_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
index c8e3946..e6072bb 100644
--- a/services/core/jni/com_android_server_lights_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -20,136 +20,105 @@
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
 
+#include <android/hardware/light/2.0/ILight.h>
+#include <android/hardware/light/2.0/types.h>
 #include <utils/misc.h>
 #include <utils/Log.h>
-#include <hardware/hardware.h>
-#include <hardware/lights.h>
-
+#include <map>
 #include <stdio.h>
 
-namespace android
-{
+namespace android {
 
-// These values must correspond with the LIGHT_ID constants in
-// LightsService.java
-enum {
-    LIGHT_INDEX_BACKLIGHT = 0,
-    LIGHT_INDEX_KEYBOARD = 1,
-    LIGHT_INDEX_BUTTONS = 2,
-    LIGHT_INDEX_BATTERY = 3,
-    LIGHT_INDEX_NOTIFICATIONS = 4,
-    LIGHT_INDEX_ATTENTION = 5,
-    LIGHT_INDEX_BLUETOOTH = 6,
-    LIGHT_INDEX_WIFI = 7,
-    LIGHT_COUNT
-};
+using ILight     = ::android::hardware::light::V2_0::ILight;
+using Brightness = ::android::hardware::light::V2_0::Brightness;
+using Flash      = ::android::hardware::light::V2_0::Flash;
+using Type       = ::android::hardware::light::V2_0::Type;
+using LightState = ::android::hardware::light::V2_0::LightState;
 
-struct Devices {
-    light_device_t* lights[LIGHT_COUNT];
-};
+static sp<ILight> gLight;
 
-static light_device_t* get_device(hw_module_t* module, char const* name)
-{
-    int err;
-    hw_device_t* device;
-    err = module->methods->open(module, name, &device);
-    if (err == 0) {
-        return (light_device_t*)device;
-    } else {
-        return NULL;
-    }
-}
+static bool validate(jint light, jint flash, jint brightness) {
+    bool valid = true;
 
-static jlong init_native(JNIEnv* /* env */, jobject /* clazz */)
-{
-    int err;
-    hw_module_t* module;
-    Devices* devices;
-    
-    devices = (Devices*)malloc(sizeof(Devices));
-
-    err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
-    if (err == 0) {
-        devices->lights[LIGHT_INDEX_BACKLIGHT]
-                = get_device(module, LIGHT_ID_BACKLIGHT);
-        devices->lights[LIGHT_INDEX_KEYBOARD]
-                = get_device(module, LIGHT_ID_KEYBOARD);
-        devices->lights[LIGHT_INDEX_BUTTONS]
-                = get_device(module, LIGHT_ID_BUTTONS);
-        devices->lights[LIGHT_INDEX_BATTERY]
-                = get_device(module, LIGHT_ID_BATTERY);
-        devices->lights[LIGHT_INDEX_NOTIFICATIONS]
-                = get_device(module, LIGHT_ID_NOTIFICATIONS);
-        devices->lights[LIGHT_INDEX_ATTENTION]
-                = get_device(module, LIGHT_ID_ATTENTION);
-        devices->lights[LIGHT_INDEX_BLUETOOTH]
-                = get_device(module, LIGHT_ID_BLUETOOTH);
-        devices->lights[LIGHT_INDEX_WIFI]
-                = get_device(module, LIGHT_ID_WIFI);
-    } else {
-        memset(devices, 0, sizeof(Devices));
+    if (light < 0 || light >= static_cast<int>(Type::COUNT)) {
+        ALOGE("Invalid light parameter %d.", light);
+        valid = false;
     }
 
-    return (jlong)devices;
+    if (flash != static_cast<int>(Flash::NONE) &&
+        flash != static_cast<int>(Flash::TIMED) &&
+        flash != static_cast<int>(Flash::HARDWARE)) {
+        ALOGE("Invalid flash parameter %d.", flash);
+        valid = false;
+    }
+
+    if (brightness != static_cast<int>(Brightness::USER) &&
+        brightness != static_cast<int>(Brightness::SENSOR) &&
+        brightness != static_cast<int>(Brightness::LOW_PERSISTENCE)) {
+        ALOGE("Invalid brightness parameter %d.", brightness);
+        valid = false;
+    }
+
+    return valid;
 }
 
-static void finalize_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr)
-{
-    Devices* devices = (Devices*)ptr;
-    if (devices == NULL) {
+static void setLight_native(
+        JNIEnv* /* env */,
+        jobject /* clazz */,
+        jint light,
+        jint colorARGB,
+        jint flashMode,
+        jint onMS,
+        jint offMS,
+        jint brightnessMode) {
+
+    if (!validate(light, flashMode, brightnessMode)) {
         return;
     }
 
-    free(devices);
-}
-
-static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
-        jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
-{
-    Devices* devices = (Devices*)ptr;
-    light_state_t state;
-
-    if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
-        return ;
+    // TODO(b/31632518)
+    if (gLight == nullptr) {
+        gLight = ILight::getService("light");
     }
 
-    uint32_t version = devices->lights[light]->common.version;
+    if (gLight == nullptr) {
+        ALOGE("LightService unable to get ILight interface.");
+        return;
+    }
 
-    memset(&state, 0, sizeof(light_state_t));
+    Type type = static_cast<Type>(light);
+    Flash flash = static_cast<Flash>(flashMode);
+    Brightness brightness = static_cast<Brightness>(brightnessMode);
 
-    if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
-        if (light != LIGHT_INDEX_BACKLIGHT) {
+    LightState state{};
+
+    if (brightnessMode == static_cast<int>(Brightness::LOW_PERSISTENCE)) {
+        if (light != static_cast<int>(Type::BACKLIGHT)) {
             ALOGE("Cannot set low-persistence mode for non-backlight device.");
             return;
         }
-        if (version < LIGHTS_DEVICE_API_VERSION_2_0) {
-            // HAL impl has not been upgraded to support this.
-            return;
-        }
+        state.flashMode = Flash::NONE;
     } else {
         // Only set non-brightness settings when not in low-persistence mode
         state.color = colorARGB;
-        state.flashMode = flashMode;
-        state.flashOnMS = onMS;
-        state.flashOffMS = offMS;
+        state.flashMode = flash;
+        state.flashOnMs = onMS;
+        state.flashOffMs = offMS;
     }
 
-    state.brightnessMode = brightnessMode;
+    state.brightnessMode = brightness;
 
     {
         ALOGD_IF_SLOW(50, "Excessive delay setting light");
-        devices->lights[light]->set_light(devices->lights[light], &state);
+        gLight->setLight(type, state);
     }
 }
 
 static const JNINativeMethod method_table[] = {
-    { "init_native", "()J", (void*)init_native },
-    { "finalize_native", "(J)V", (void*)finalize_native },
-    { "setLight_native", "(JIIIIII)V", (void*)setLight_native },
+    { "setLight_native", "(IIIIII)V", (void*)setLight_native },
 };
 
-int register_android_server_LightsService(JNIEnv *env)
-{
+int register_android_server_LightsService(JNIEnv *env) {
     return jniRegisterNativeMethods(env, "com/android/server/lights/LightsService",
             method_table, NELEM(method_table));
 }
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index e8d4c58..25e819c 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1087,6 +1087,7 @@
             method_name,
             "([B)V");
     env_->CallVoidMethod(object_, method, array);
+    env_->DeleteLocalRef(array);
 }
 
 jobject JavaObject::get() {
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 048ef76..b2372a3 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -18,6 +18,7 @@
 
 //#define LOG_NDEBUG 0
 
+#include <android/hardware/power/1.0/IPower.h>
 #include "JNIHelp.h"
 #include "jni.h"
 
@@ -37,6 +38,13 @@
 
 #include "com_android_server_power_PowerManagerService.h"
 
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::power::V1_0::IPower;
+using android::hardware::power::V1_0::PowerHint;
+using android::hardware::power::V1_0::Feature;
+using android::hardware::hidl_vec;
+
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -48,8 +56,7 @@
 // ----------------------------------------------------------------------------
 
 static jobject gPowerManagerServiceObj;
-struct power_module* gPowerModule;
-
+sp<IPower> gPowerHal;
 static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];
 
 // Throttling interval for user activity calls.
@@ -69,8 +76,8 @@
 
 void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
     // Tell the power HAL when user activity occurs.
-    if (gPowerModule && gPowerModule->powerHint) {
-        gPowerModule->powerHint(gPowerModule, POWER_HINT_INTERACTION, NULL);
+    if (gPowerHal != nullptr) {
+        gPowerHal->powerHint(PowerHint::INTERACTION, 0);
     }
 
     if (gPowerManagerServiceObj) {
@@ -99,16 +106,13 @@
 }
 
 // ----------------------------------------------------------------------------
-
+//TODO(b/31632518)
 static void nativeInit(JNIEnv* env, jobject obj) {
     gPowerManagerServiceObj = env->NewGlobalRef(obj);
 
-    status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID,
-            (hw_module_t const**)&gPowerModule);
-    if (!err) {
-        gPowerModule->init(gPowerModule);
-    } else {
-        ALOGE("Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
+    gPowerHal = IPower::getService("power");
+    if (gPowerHal == nullptr) {
+        ALOGE("Couldn't load PowerHAL module");
     }
 }
 
@@ -123,13 +127,13 @@
 }
 
 static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
-    if (gPowerModule) {
+    if (gPowerHal != nullptr) {
         if (enable) {
             ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on");
-            gPowerModule->setInteractive(gPowerModule, true);
+            gPowerHal->setInteractive(true);
         } else {
             ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off");
-            gPowerModule->setInteractive(gPowerModule, false);
+            gPowerHal->setInteractive(false);
         }
     }
 }
@@ -145,13 +149,11 @@
 }
 
 static void nativeSendPowerHint(JNIEnv *env, jclass clazz, jint hintId, jint data) {
-    int data_param = data;
-
-    if (gPowerModule && gPowerModule->powerHint) {
+    if (gPowerHal != nullptr) {
         if(data)
-            gPowerModule->powerHint(gPowerModule, (power_hint_t)hintId, &data_param);
+            gPowerHal->powerHint((PowerHint)hintId, data);
         else {
-            gPowerModule->powerHint(gPowerModule, (power_hint_t)hintId, NULL);
+            gPowerHal->powerHint((PowerHint)hintId, 0);
         }
     }
 }
@@ -159,8 +161,8 @@
 static void nativeSetFeature(JNIEnv *env, jclass clazz, jint featureId, jint data) {
     int data_param = data;
 
-    if (gPowerModule && gPowerModule->setFeature) {
-        gPowerModule->setFeature(gPowerModule, (feature_t)featureId, data_param);
+    if (gPowerHal != nullptr) {
+        gPowerHal->setFeature((Feature)featureId, data_param ? true : false);
     }
 }
 
@@ -215,7 +217,7 @@
         gLastEventTime[i] = LLONG_MIN;
     }
     gPowerManagerServiceObj = NULL;
-    gPowerModule = NULL;
+    gPowerHal = NULL;
     return 0;
 }
 
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 327019d..d69c37f 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -21,7 +21,6 @@
 
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
-int register_android_server_AssetAtlasService(JNIEnv* env);
 int register_android_server_BatteryStatsService(JNIEnv* env);
 int register_android_server_ConsumerIrService(JNIEnv *env);
 int register_android_server_InputApplicationHandle(JNIEnv* env);
@@ -76,7 +75,6 @@
     register_android_server_location_GnssLocationProvider(env);
     register_android_server_location_FlpHardwareProvider(env);
     register_android_server_connectivity_Vpn(env);
-    register_android_server_AssetAtlasService(env);
     register_android_server_ConsumerIrService(env);
     register_android_server_BatteryStatsService(env);
     register_android_server_hdmi_HdmiCecController(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0c57179..88d8dd0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -221,6 +221,7 @@
     private static final String ATTR_PERMISSION_POLICY = "permission-policy";
     private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED =
             "device-provisioning-config-applied";
+    private static final String ATTR_DEVICE_PAIRED = "device-paired";
 
     private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer";
     private static final String ATTR_APPLICATION_RESTRICTIONS_MANAGER
@@ -301,6 +302,7 @@
     private static final int CODE_NONSYSTEM_USER_EXISTS = 5;
     private static final int CODE_ACCOUNTS_NOT_EMPTY = 6;
     private static final int CODE_NOT_SYSTEM_USER = 7;
+    private static final int CODE_HAS_PAIRED = 8;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({ CODE_OK, CODE_HAS_DEVICE_OWNER, CODE_USER_HAS_PROFILE_OWNER, CODE_USER_NOT_RUNNING,
@@ -344,6 +346,11 @@
      */
     boolean mHasFeature;
 
+    /**
+     * Whether or not this device is a watch.
+     */
+    boolean mIsWatch;
+
     private final SecurityLogMonitor mSecurityLogMonitor;
 
     private final AtomicBoolean mRemoteBugreportServiceIsActive = new AtomicBoolean();
@@ -424,6 +431,7 @@
         int mPasswordOwner = -1;
         long mLastMaximumTimeToLock = -1;
         boolean mUserSetupComplete = false;
+        boolean mPaired = false;
         int mUserProvisioningState;
         int mPermissionPolicy;
 
@@ -496,12 +504,6 @@
                     }
                 });
             }
-            // STOPSHIP: Remove this code once all dogfood devices are fixed. See b/31754835
-            if (Intent.ACTION_BOOT_COMPLETED.equals(action) && !mOwners.hasDeviceOwner()
-                    && !isBackupServiceEnabledInternal()) {
-                setBackupServiceEnabledInternal(true);
-                Slog.w(LOG_TAG, "Fix backup for device that is not in Device Owner mode.");
-            }
             if (Intent.ACTION_USER_UNLOCKED.equals(action)
                     || Intent.ACTION_USER_STARTED.equals(action)
                     || KeyChain.ACTION_TRUST_STORE_CHANGED.equals(action)) {
@@ -617,7 +619,7 @@
         static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
         long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
 
-        long strongAuthUnlockTimeout = DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+        long strongAuthUnlockTimeout = 0; // admin doesn't participate by default
 
         static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
         int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
@@ -1621,6 +1623,8 @@
 
         mHasFeature = mContext.getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
+        mIsWatch = mContext.getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_WATCH);
         if (!mHasFeature) {
             // Skip the rest of the initialization
             return;
@@ -2221,6 +2225,10 @@
                 out.attribute(null, ATTR_SETUP_COMPLETE,
                         Boolean.toString(true));
             }
+            if (policy.mPaired) {
+                out.attribute(null, ATTR_DEVICE_PAIRED,
+                        Boolean.toString(true));
+            }
             if (policy.mDeviceProvisioningConfigApplied) {
                 out.attribute(null, ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED,
                         Boolean.toString(true));
@@ -2385,6 +2393,10 @@
             if (userSetupComplete != null && Boolean.toString(true).equals(userSetupComplete)) {
                 policy.mUserSetupComplete = true;
             }
+            String paired = parser.getAttributeValue(null, ATTR_DEVICE_PAIRED);
+            if (paired != null && Boolean.toString(true).equals(paired)) {
+                policy.mPaired = true;
+            }
             String deviceProvisioningConfigApplied = parser.getAttributeValue(null,
                     ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED);
             if (deviceProvisioningConfigApplied != null
@@ -2619,7 +2631,7 @@
         // Register an observer for watching for user setup complete.
         new SetupContentObserver(mHandler).register();
         // Initialize the user setup state, to handle the upgrade case.
-        updateUserSetupComplete();
+        updateUserSetupCompleteAndPaired();
 
         List<String> packageList;
         synchronized (this) {
@@ -4254,10 +4266,15 @@
             return;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
-        Preconditions.checkArgument(timeoutMs >= MINIMUM_STRONG_AUTH_TIMEOUT_MS,
-                "Timeout must not be lower than the minimum strong auth timeout.");
-        Preconditions.checkArgument(timeoutMs <= DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS,
-                "Timeout must not be higher than the default strong auth timeout.");
+        Preconditions.checkArgument(timeoutMs >= 0, "Timeout must not be a negative number.");
+        // timeoutMs with value 0 means that the admin doesn't participate
+        // timeoutMs is clamped to the interval in case the internal constants change in the future
+        if (timeoutMs != 0 && timeoutMs < MINIMUM_STRONG_AUTH_TIMEOUT_MS) {
+            timeoutMs = MINIMUM_STRONG_AUTH_TIMEOUT_MS;
+        }
+        if (timeoutMs > DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS) {
+            timeoutMs = DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+        }
 
         final int userHandle = mInjector.userHandleGetCallingUserId();
         synchronized (this) {
@@ -4273,7 +4290,7 @@
     /**
      * Return a single admin's strong auth unlock timeout or minimum value (strictest) of all
      * admins if who is null.
-     * Returns default timeout if not configured.
+     * Returns 0 if not configured for the provided admin.
      */
     @Override
     public long getRequiredStrongAuthTimeout(ComponentName who, int userId, boolean parent) {
@@ -4284,9 +4301,7 @@
         synchronized (this) {
             if (who != null) {
                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId, parent);
-                return admin != null ? Math.max(admin.strongAuthUnlockTimeout,
-                        MINIMUM_STRONG_AUTH_TIMEOUT_MS)
-                        : DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
+                return admin != null ? admin.strongAuthUnlockTimeout : 0;
             }
 
             // Return the strictest policy across all participating admins.
@@ -4294,8 +4309,10 @@
 
             long strongAuthUnlockTimeout = DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
             for (int i = 0; i < admins.size(); i++) {
-                strongAuthUnlockTimeout = Math.min(admins.get(i).strongAuthUnlockTimeout,
-                        strongAuthUnlockTimeout);
+                final long timeout = admins.get(i).strongAuthUnlockTimeout;
+                if (timeout != 0) { // take only participating admins into account
+                    strongAuthUnlockTimeout = Math.min(timeout, strongAuthUnlockTimeout);
+                }
             }
             return Math.max(strongAuthUnlockTimeout, MINIMUM_STRONG_AUTH_TIMEOUT_MS);
         }
@@ -6152,6 +6169,13 @@
         return getUserData(userHandle).mUserSetupComplete;
     }
 
+    private boolean hasPaired(int userHandle) {
+        if (!mHasFeature) {
+            return true;
+        }
+        return getUserData(userHandle).mPaired;
+    }
+
     @Override
     public int getUserProvisioningState() {
         if (!mHasFeature) {
@@ -6436,6 +6460,9 @@
             case CODE_ACCOUNTS_NOT_EMPTY:
                 throw new IllegalStateException("Not allowed to set the device owner because there "
                         + "are already some accounts on the device");
+            case CODE_HAS_PAIRED:
+                throw new IllegalStateException("Not allowed to set the device owner because this "
+                        + "device has already paired");
             default:
                 throw new IllegalStateException("Unknown @DeviceOwnerPreConditionCode " + code);
         }
@@ -8187,14 +8214,15 @@
     }
 
     /**
-     * We need to update the internal state of whether a user has completed setup once. After
-     * that, we ignore any changes that reset the Settings.Secure.USER_SETUP_COMPLETE changes
-     * as we don't trust any apps that might try to reset it.
+     * We need to update the internal state of whether a user has completed setup or a
+     * device has paired once. After that, we ignore any changes that reset the
+     * Settings.Secure.USER_SETUP_COMPLETE or Settings.Secure.DEVICE_PAIRED change
+     * as we don't trust any apps that might try to reset them.
      * <p>
      * Unfortunately, we don't know which user's setup state was changed, so we write all of
      * them.
      */
-    void updateUserSetupComplete() {
+    void updateUserSetupCompleteAndPaired() {
         List<UserInfo> users = mUserManager.getUsers(true);
         final int N = users.size();
         for (int i = 0; i < N; i++) {
@@ -8209,6 +8237,16 @@
                     }
                 }
             }
+            if (mIsWatch && mInjector.settingsSecureGetIntForUser(Settings.Secure.DEVICE_PAIRED, 0,
+                    userHandle) != 0) {
+                DevicePolicyData policy = getUserData(userHandle);
+                if (!policy.mPaired) {
+                    policy.mPaired = true;
+                    synchronized (this) {
+                        saveSettingsLocked(userHandle);
+                    }
+                }
+            }
         }
     }
 
@@ -8218,6 +8256,7 @@
                 Settings.Secure.USER_SETUP_COMPLETE);
         private final Uri mDeviceProvisioned = Settings.Global.getUriFor(
                 Settings.Global.DEVICE_PROVISIONED);
+        private final Uri mPaired = Settings.Secure.getUriFor(Settings.Secure.DEVICE_PAIRED);
 
         public SetupContentObserver(Handler handler) {
             super(handler);
@@ -8226,12 +8265,15 @@
         void register() {
             mInjector.registerContentObserver(mUserSetupComplete, false, this, UserHandle.USER_ALL);
             mInjector.registerContentObserver(mDeviceProvisioned, false, this, UserHandle.USER_ALL);
+            if (mIsWatch) {
+                mInjector.registerContentObserver(mPaired, false, this, UserHandle.USER_ALL);
+            }
         }
 
         @Override
         public void onChange(boolean selfChange, Uri uri) {
-            if (mUserSetupComplete.equals(uri)) {
-                updateUserSetupComplete();
+            if (mUserSetupComplete.equals(uri) || (mIsWatch && mPaired.equals(uri))) {
+                updateUserSetupCompleteAndPaired();
             } else if (mDeviceProvisioned.equals(uri)) {
                 synchronized (DevicePolicyManagerService.this) {
                     // Set PROPERTY_DEVICE_OWNER_PRESENT, for the SUW case where setting the property
@@ -8540,15 +8582,16 @@
                 final PackageManager packageManager = mContext.getPackageManager();
                 switch (grantState) {
                     case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: {
-                        packageManager.grantRuntimePermission(packageName, permission, user);
+                        mInjector.getPackageManagerInternal().grantRuntimePermission(packageName,
+                                permission, user.getIdentifier(), true /* override policy */);
                         packageManager.updatePermissionFlags(permission, packageName,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
                     } break;
 
                     case DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED: {
-                        packageManager.revokeRuntimePermission(packageName,
-                                permission, user);
+                        mInjector.getPackageManagerInternal().revokeRuntimePermission(packageName,
+                                permission, user.getIdentifier(), true /* override policy */);
                         packageManager.updatePermissionFlags(permission, packageName,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
@@ -8620,19 +8663,13 @@
             }
             synchronized (this) {
                 if (mOwners.hasDeviceOwner()) {
-                    if (!mInjector.userManagerIsSplitSystemUser()) {
-                        // Only split-system-user systems support managed-profiles in combination with
-                        // device-owner.
-                        return false;
-                    }
-                    if (mOwners.getDeviceOwnerUserId() != UserHandle.USER_SYSTEM) {
-                        // Only system device-owner supports managed-profiles. Non-system device-owner
-                        // doesn't.
-                        return false;
-                    }
-                    if (callingUserId == UserHandle.USER_SYSTEM) {
-                        // Managed-profiles cannot be setup on the system user, only regular users.
-                        return false;
+                    // STOPSHIP Only allow creating a managed profile if allowed by the device
+                    // owner. http://b/31952368
+                    if (mInjector.userManagerIsSplitSystemUser()) {
+                        if (callingUserId == UserHandle.USER_SYSTEM) {
+                            // Managed-profiles cannot be setup on the system user.
+                            return false;
+                        }
                     }
                 }
             }
@@ -8692,6 +8729,9 @@
         if (!mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
             return CODE_USER_NOT_RUNNING;
         }
+        if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
+            return CODE_HAS_PAIRED;
+        }
         if (isAdb) {
             // if shell command runs after user setup completed check device status. Otherwise, OK.
             if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
@@ -9357,16 +9397,13 @@
             return true;
         }
         synchronized (this) {
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
-            return isBackupServiceEnabledInternal();
-        }
-    }
-    private boolean isBackupServiceEnabledInternal() {
-        try {
-            IBackupManager ibm = mInjector.getIBackupManager();
-            return ibm != null && ibm.isBackupServiceActive(UserHandle.USER_SYSTEM);
-        } catch (RemoteException e) {
-            throw new IllegalStateException("Failed requesting backup service state.", e);
+            try {
+                getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+                IBackupManager ibm = mInjector.getIBackupManager();
+                return ibm != null && ibm.isBackupServiceActive(UserHandle.USER_SYSTEM);
+            } catch (RemoteException e) {
+                throw new IllegalStateException("Failed requesting backup service state.", e);
+            }
         }
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 769b5ee..deb5238 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -747,7 +747,6 @@
         LocationManagerService location = null;
         CountryDetectorService countryDetector = null;
         ILockSettings lockSettings = null;
-        AssetAtlasService atlas = null;
         MediaRouterService mediaRouter = null;
 
         // Bring up services needed for UI.
@@ -1235,17 +1234,6 @@
                 traceEnd();
             }
 
-            if (!disableNonCoreServices && ZygoteInit.PRELOAD_RESOURCES) {
-                traceBeginAndSlog("StartAssetAtlasService");
-                try {
-                    atlas = new AssetAtlasService(context);
-                    ServiceManager.addService(AssetAtlasService.ASSET_ATLAS_SERVICE, atlas);
-                } catch (Throwable e) {
-                    reportWtf("starting AssetAtlasService", e);
-                }
-                traceEnd();
-            }
-
             if (!disableNonCoreServices) {
                 traceBeginAndSlog("AddGraphicsStatsService");
                 ServiceManager.addService(GraphicsStatsService.GRAPHICS_STATS_SERVICE,
@@ -1465,7 +1453,6 @@
         final CountryDetectorService countryDetectorF = countryDetector;
         final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
         final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService;
-        final AssetAtlasService atlasF = atlas;
         final InputManagerService inputManagerF = inputManager;
         final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
         final MediaRouterService mediaRouterF = mediaRouter;
@@ -1583,13 +1570,6 @@
                     reportWtf("Notifying CommonTimeManagementService running", e);
                 }
                 traceEnd();
-                traceBeginAndSlog("MakeAtlasServiceReady");
-                try {
-                    if (atlasF != null) atlasF.systemRunning();
-                } catch (Throwable e) {
-                    reportWtf("Notifying AssetAtlasService running", e);
-                }
-                traceEnd();
                 traceBeginAndSlog("MakeInputManagerServiceReady");
                 try {
                     // TODO(BT) Pass parameter to input manager
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 4c75452..a8356dc 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -283,14 +283,20 @@
         mReceiveThread.start();
     }
 
-    // Returns seconds since Unix Epoch.
-    // TODO: use SystemClock.elapsedRealtime() instead
+    // Returns seconds since device boot.
     private static long curTime() {
-        return System.currentTimeMillis() / DateUtils.SECOND_IN_MILLIS;
+        return SystemClock.elapsedRealtime() / DateUtils.SECOND_IN_MILLIS;
+    }
+
+    public static class InvalidRaException extends Exception {
+        public InvalidRaException(String m) {
+            super(m);
+        }
     }
 
     // A class to hold information about an RA.
-    private class Ra {
+    @VisibleForTesting
+    class Ra {
         // From RFC4861:
         private static final int ICMP6_RA_HEADER_LEN = 16;
         private static final int ICMP6_RA_CHECKSUM_OFFSET =
@@ -362,7 +368,7 @@
             } catch (UnsupportedOperationException e) {
                 // array() failed. Cannot happen, mPacket is array-backed and read-write.
                 return "???";
-            } catch (ClassCastException | UnknownHostException e) {
+            } catch (ClassCastException|UnknownHostException e) {
                 // Cannot happen.
                 return "???";
             }
@@ -372,16 +378,16 @@
         // TODO: Make this static once RA is its own class.
         private void prefixOptionToString(StringBuffer sb, int offset) {
             String prefix = IPv6AddresstoString(offset + 16);
-            int length = uint8(mPacket.get(offset + 2));
-            long valid = mPacket.getInt(offset + 4);
-            long preferred = mPacket.getInt(offset + 8);
+            int length = getUint8(mPacket, offset + 2);
+            long valid = getUint32(mPacket, offset + 4);
+            long preferred = getUint32(mPacket, offset + 8);
             sb.append(String.format("%s/%d %ds/%ds ", prefix, length, valid, preferred));
         }
 
         private void rdnssOptionToString(StringBuffer sb, int offset) {
-            int optLen = uint8(mPacket.get(offset + 1)) * 8;
+            int optLen = getUint8(mPacket, offset + 1) * 8;
             if (optLen < 24) return;  // Malformed or empty.
-            long lifetime = uint32(mPacket.getInt(offset + 4));
+            long lifetime = getUint32(mPacket, offset + 4);
             int numServers = (optLen - 8) / 16;
             sb.append("DNS ").append(lifetime).append("s");
             for (int server = 0; server < numServers; server++) {
@@ -395,7 +401,7 @@
                 sb.append(String.format("RA %s -> %s %ds ",
                         IPv6AddresstoString(IPV6_SRC_ADDR_OFFSET),
                         IPv6AddresstoString(IPV6_DEST_ADDR_OFFSET),
-                        uint16(mPacket.getShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET))));
+                        getUint16(mPacket, ICMP6_RA_ROUTER_LIFETIME_OFFSET)));
                 for (int i: mPrefixOptionOffsets) {
                     prefixOptionToString(sb, i);
                 }
@@ -403,7 +409,7 @@
                     rdnssOptionToString(sb, i);
                 }
                 return sb.toString();
-            } catch (BufferUnderflowException | IndexOutOfBoundsException e) {
+            } catch (BufferUnderflowException|IndexOutOfBoundsException e) {
                 return "<Malformed RA>";
             }
         }
@@ -436,16 +442,20 @@
         // Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException
         // (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with
         // specifications.
-        Ra(byte[] packet, int length) {
+        Ra(byte[] packet, int length) throws InvalidRaException {
+            if (length < ICMP6_RA_OPTION_OFFSET) {
+                throw new InvalidRaException("Not an ICMP6 router advertisement");
+            }
+
             mPacket = ByteBuffer.wrap(Arrays.copyOf(packet, length));
             mLastSeen = curTime();
 
             // Sanity check packet in case a packet arrives before we attach RA filter
             // to our packet socket. b/29586253
             if (getUint16(mPacket, ETH_ETHERTYPE_OFFSET) != ETH_P_IPV6 ||
-                    uint8(mPacket.get(IPV6_NEXT_HEADER_OFFSET)) != IPPROTO_ICMPV6 ||
-                    uint8(mPacket.get(ICMP6_TYPE_OFFSET)) != ICMP6_ROUTER_ADVERTISEMENT) {
-                throw new IllegalArgumentException("Not an ICMP6 router advertisement");
+                    getUint8(mPacket, IPV6_NEXT_HEADER_OFFSET) != IPPROTO_ICMPV6 ||
+                    getUint8(mPacket, ICMP6_TYPE_OFFSET) != ICMP6_ROUTER_ADVERTISEMENT) {
+                throw new InvalidRaException("Not an ICMP6 router advertisement");
             }
 
 
@@ -466,8 +476,8 @@
             mPacket.position(ICMP6_RA_OPTION_OFFSET);
             while (mPacket.hasRemaining()) {
                 final int position = mPacket.position();
-                final int optionType = uint8(mPacket.get(position));
-                final int optionLength = uint8(mPacket.get(position + 1)) * 8;
+                final int optionType = getUint8(mPacket, position);
+                final int optionLength = getUint8(mPacket, position + 1) * 8;
                 long lifetime;
                 switch (optionType) {
                     case ICMP6_PREFIX_OPTION_TYPE:
@@ -511,7 +521,7 @@
                         break;
                 }
                 if (optionLength <= 0) {
-                    throw new IllegalArgumentException(String.format(
+                    throw new InvalidRaException(String.format(
                         "Invalid option length opt=%d len=%d", optionType, optionLength));
                 }
                 mPacket.position(position + optionLength);
@@ -552,10 +562,10 @@
                 final long optionLifetime;
                 switch (lifetimeLength) {
                     case 2:
-                        optionLifetime = uint16(byteBuffer.getShort(offset));
+                        optionLifetime = getUint16(byteBuffer, offset);
                         break;
                     case 4:
-                        optionLifetime = uint32(byteBuffer.getInt(offset));
+                        optionLifetime = getUint32(byteBuffer, offset);
                         break;
                     default:
                         throw new IllegalStateException("bogus lifetime size " + lifetimeLength);
@@ -925,8 +935,8 @@
             // Execution will reach the end of the program if no filters match, which will pass the
             // packet to the AP.
             program = gen.generate();
-        } catch (IllegalInstructionException e) {
-            Log.e(TAG, "Program failed to generate: ", e);
+        } catch (IllegalInstructionException|IllegalStateException e) {
+            Log.e(TAG, "Failed to generate APF program.", e);
             return;
         }
         mLastTimeInstalledProgram = curTime();
@@ -972,7 +982,8 @@
      * if the current APF program should be updated.
      * @return a ProcessRaResult enum describing what action was performed.
      */
-    private synchronized ProcessRaResult processRa(byte[] packet, int length) {
+    @VisibleForTesting
+    synchronized ProcessRaResult processRa(byte[] packet, int length) {
         if (VDBG) hexDump("Read packet = ", packet, length);
 
         // Have we seen this RA before?
@@ -1011,7 +1022,7 @@
         try {
             ra = new Ra(packet, length);
         } catch (Exception e) {
-            Log.e(TAG, "Error parsing RA: " + e);
+            Log.e(TAG, "Error parsing RA", e);
             return ProcessRaResult.PARSE_ERROR;
         }
         // Ignore 0 lifetime RAs.
@@ -1150,7 +1161,11 @@
         return i & 0xffffffffL;
     }
 
-    private static long getUint16(ByteBuffer buffer, int position) {
+    private static int getUint8(ByteBuffer buffer, int position) {
+        return uint8(buffer.get(position));
+    }
+
+    private static int getUint16(ByteBuffer buffer, int position) {
         return uint16(buffer.getShort(position));
     }
 
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index 9aa66fe..ef4bc02 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -7,6 +7,7 @@
 import android.os.Build;
 import android.os.SystemProperties;
 import android.system.OsConstants;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.UnsupportedEncodingException;
 import java.net.Inet4Address;
@@ -14,9 +15,8 @@
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.nio.charset.StandardCharsets;
 import java.nio.ShortBuffer;
-
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -725,7 +725,8 @@
      * A subset of the optional parameters are parsed and are stored
      * in object fields.
      */
-    public static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType) throws ParseException
+    @VisibleForTesting
+    static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType) throws ParseException
     {
         // bootp parameters
         int transactionId;
@@ -894,8 +895,12 @@
                         + 64    // skip server host name (64 chars)
                         + 128); // skip boot file name (128 chars)
 
-        int dhcpMagicCookie = packet.getInt();
+        // Ensure this is a DHCP packet with a magic cookie, and not BOOTP. http://b/31850211
+        if (packet.remaining() < 4) {
+            throw new ParseException(DhcpErrorEvent.DHCP_NO_COOKIE, "not a DHCP message");
+        }
 
+        int dhcpMagicCookie = packet.getInt();
         if (dhcpMagicCookie != DHCP_MAGIC_COOKIE) {
             throw new ParseException(DhcpErrorEvent.DHCP_BAD_MAGIC_COOKIE,
                     "Bad magic cookie 0x%08x, should be 0x%08x",
@@ -1090,7 +1095,13 @@
     public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType)
             throws ParseException {
         ByteBuffer buffer = ByteBuffer.wrap(packet, 0, length).order(ByteOrder.BIG_ENDIAN);
-        return decodeFullPacket(buffer, pktType);
+        try {
+            return decodeFullPacket(buffer, pktType);
+        } catch (ParseException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new ParseException(DhcpErrorEvent.PARSING_ERROR, e.getMessage());
+        }
     }
 
     /**
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index ee67d95..01d9304 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -33,6 +33,7 @@
 import android.net.dhcp.DhcpClient;
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.IpManagerEvent;
+import android.net.util.AvoidBadWifiTracker;
 import android.os.INetworkManagementService;
 import android.os.Message;
 import android.os.RemoteException;
@@ -396,6 +397,7 @@
     private final NetlinkTracker mNetlinkTracker;
     private final WakeupMessage mProvisioningTimeoutAlarm;
     private final WakeupMessage mDhcpActionTimeoutAlarm;
+    private final AvoidBadWifiTracker mAvoidBadWifiTracker;
     private final LocalLog mLocalLog;
     private final MessageHandlingLogger mMsgStateLogger;
     private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
@@ -470,6 +472,8 @@
             Log.e(mTag, "Couldn't register NetlinkTracker: " + e.toString());
         }
 
+        mAvoidBadWifiTracker = new AvoidBadWifiTracker(mContext, getHandler());
+
         resetLinkProperties();
 
         mProvisioningTimeoutAlarm = new WakeupMessage(mContext, getHandler(),
@@ -670,7 +674,7 @@
     // object that is a correct and complete assessment of what changed, taking
     // account of the asymmetries described in the comments in this function.
     // Then switch to using it everywhere (IpReachabilityMonitor, etc.).
-    private static ProvisioningChange compareProvisioning(
+    private ProvisioningChange compareProvisioning(
             LinkProperties oldLp, LinkProperties newLp) {
         ProvisioningChange delta;
 
@@ -697,6 +701,25 @@
             delta = ProvisioningChange.LOST_PROVISIONING;
         }
 
+        final boolean lostIPv6 = oldLp.isIPv6Provisioned() && !newLp.isIPv6Provisioned();
+        final boolean lostIPv4Address = oldLp.hasIPv4Address() && !newLp.hasIPv4Address();
+        final boolean lostIPv6Router = oldLp.hasIPv6DefaultRoute() && !newLp.hasIPv6DefaultRoute();
+
+        // If bad wifi avoidance is disabled, then ignore IPv6 loss of
+        // provisioning. Otherwise, when a hotspot that loses Internet
+        // access sends out a 0-lifetime RA to its clients, the clients
+        // will disconnect and then reconnect, avoiding the bad hotspot,
+        // instead of getting stuck on the bad hotspot. http://b/31827713 .
+        //
+        // This is incorrect because if the hotspot then regains Internet
+        // access with a different prefix, TCP connections on the
+        // deprecated addresses will remain stuck.
+        //
+        // Note that we can still be disconnected by IpReachabilityMonitor
+        // if the IPv6 default gateway (but not the IPv6 DNS servers; see
+        // accompanying code in IpReachabilityMonitor) is unreachable.
+        final boolean ignoreIPv6ProvisioningLoss = !mAvoidBadWifiTracker.currentValue();
+
         // Additionally:
         //
         // Partial configurations (e.g., only an IPv4 address with no DNS
@@ -709,8 +732,7 @@
         // Because on such a network isProvisioned() will always return false,
         // delta will never be LOST_PROVISIONING. So check for loss of
         // provisioning here too.
-        if ((oldLp.hasIPv4Address() && !newLp.hasIPv4Address()) ||
-                (oldLp.isIPv6Provisioned() && !newLp.isIPv6Provisioned())) {
+        if (lostIPv4Address || (lostIPv6 && !ignoreIPv6ProvisioningLoss)) {
             delta = ProvisioningChange.LOST_PROVISIONING;
         }
 
@@ -719,8 +741,7 @@
         // If the previous link properties had a global IPv6 address and an
         // IPv6 default route then also consider the loss of that default route
         // to be a loss of provisioning. See b/27962810.
-        if (oldLp.hasGlobalIPv6Address() && oldLp.hasIPv6DefaultRoute() &&
-                !newLp.hasIPv6DefaultRoute()) {
+        if (oldLp.hasGlobalIPv6Address() && (lostIPv6Router && !ignoreIPv6ProvisioningLoss)) {
             delta = ProvisioningChange.LOST_PROVISIONING;
         }
 
@@ -1165,7 +1186,8 @@
                             public void notifyLost(InetAddress ip, String logMsg) {
                                 mCallback.onReachabilityLost(logMsg);
                             }
-                        });
+                        },
+                        mAvoidBadWifiTracker);
             }
         }
 
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index c6da3c3..a883e28 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -34,6 +34,7 @@
 import android.net.netlink.StructNdaCacheInfo;
 import android.net.netlink.StructNdMsg;
 import android.net.netlink.StructNlMsgHdr;
+import android.net.util.AvoidBadWifiTracker;
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.system.ErrnoException;
@@ -42,15 +43,16 @@
 import android.util.Log;
 
 import java.io.InterruptedIOException;
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.NetworkInterface;
 import java.net.SocketAddress;
 import java.net.SocketException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -149,6 +151,7 @@
     private final String mInterfaceName;
     private final int mInterfaceIndex;
     private final Callback mCallback;
+    private final AvoidBadWifiTracker mAvoidBadWifiTracker;
     private final NetlinkSocketObserver mNetlinkSocketObserver;
     private final Thread mObserverThread;
     private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
@@ -160,8 +163,7 @@
     private Map<InetAddress, Short> mIpWatchList = new HashMap<>();
     @GuardedBy("mLock")
     private int mIpWatchListVersion;
-    @GuardedBy("mLock")
-    private boolean mRunning;
+    private volatile boolean mRunning;
     // Time in milliseconds of the last forced probe request.
     private volatile long mLastProbeTimeMs;
 
@@ -219,8 +221,12 @@
         return errno;
     }
 
-    public IpReachabilityMonitor(Context context, String ifName, Callback callback)
-                throws IllegalArgumentException {
+    public IpReachabilityMonitor(Context context, String ifName, Callback callback) {
+        this(context, ifName, callback, null);
+    }
+
+    public IpReachabilityMonitor(Context context, String ifName, Callback callback,
+            AvoidBadWifiTracker tracker) throws IllegalArgumentException {
         mInterfaceName = ifName;
         int ifIndex = -1;
         try {
@@ -232,13 +238,14 @@
         mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock(
                 PowerManager.PARTIAL_WAKE_LOCK, TAG + "." + mInterfaceName);
         mCallback = callback;
+        mAvoidBadWifiTracker = tracker;
         mNetlinkSocketObserver = new NetlinkSocketObserver();
         mObserverThread = new Thread(mNetlinkSocketObserver);
         mObserverThread.start();
     }
 
     public void stop() {
-        synchronized (mLock) { mRunning = false; }
+        mRunning = false;
         clearLinkProperties();
         mNetlinkSocketObserver.clearNetlinkSocket();
     }
@@ -273,12 +280,6 @@
         }
     }
 
-    private boolean stillRunning() {
-        synchronized (mLock) {
-            return mRunning;
-        }
-    }
-
     private static boolean isOnLink(List<RouteInfo> routes, InetAddress ip) {
         for (RouteInfo route : routes) {
             if (!route.hasGateway() && route.matches(ip)) {
@@ -355,7 +356,11 @@
                         whatIfLp.removeRoute(route);
                     }
                 }
-                whatIfLp.removeDnsServer(ip);
+
+                if (avoidingBadLinks() || !(ip instanceof Inet6Address)) {
+                    // We should do this unconditionally, but alas we cannot: b/31827713.
+                    whatIfLp.removeDnsServer(ip);
+                }
             }
 
             delta = LinkProperties.compareProvisioning(mLinkProperties, whatIfLp);
@@ -373,13 +378,17 @@
         logNudFailed(delta);
     }
 
+    private boolean avoidingBadLinks() {
+        return (mAvoidBadWifiTracker != null) ? mAvoidBadWifiTracker.currentValue() : true;
+    }
+
     public void probeAll() {
-        Set<InetAddress> ipProbeList = new HashSet<InetAddress>();
+        final List<InetAddress> ipProbeList;
         synchronized (mLock) {
-            ipProbeList.addAll(mIpWatchList.keySet());
+            ipProbeList = new ArrayList<>(mIpWatchList.keySet());
         }
 
-        if (!ipProbeList.isEmpty() && stillRunning()) {
+        if (!ipProbeList.isEmpty() && mRunning) {
             // Keep the CPU awake long enough to allow all ARP/ND
             // probes a reasonable chance at success. See b/23197666.
             //
@@ -390,7 +399,7 @@
         }
 
         for (InetAddress target : ipProbeList) {
-            if (!stillRunning()) {
+            if (!mRunning) {
                 break;
             }
             final int returnValue = probeNeighbor(mInterfaceIndex, target);
@@ -435,21 +444,21 @@
         @Override
         public void run() {
             if (VDBG) { Log.d(TAG, "Starting observing thread."); }
-            synchronized (mLock) { mRunning = true; }
+            mRunning = true;
 
             try {
                 setupNetlinkSocket();
             } catch (ErrnoException | SocketException e) {
                 Log.e(TAG, "Failed to suitably initialize a netlink socket", e);
-                synchronized (mLock) { mRunning = false; }
+                mRunning = false;
             }
 
-            ByteBuffer byteBuffer;
-            while (stillRunning()) {
+            while (mRunning) {
+                final ByteBuffer byteBuffer;
                 try {
                     byteBuffer = recvKernelReply();
                 } catch (ErrnoException e) {
-                    if (stillRunning()) { Log.w(TAG, "ErrnoException: ", e); }
+                    if (mRunning) { Log.w(TAG, "ErrnoException: ", e); }
                     break;
                 }
                 final long whenMs = SystemClock.elapsedRealtime();
@@ -461,7 +470,7 @@
 
             clearNetlinkSocket();
 
-            synchronized (mLock) { mRunning = false; }
+            mRunning = false; // Not a no-op when ErrnoException happened.
             if (VDBG) { Log.d(TAG, "Finishing observing thread."); }
         }
 
diff --git a/services/net/java/android/net/util/AvoidBadWifiTracker.java b/services/net/java/android/net/util/AvoidBadWifiTracker.java
new file mode 100644
index 0000000..c14e811
--- /dev/null
+++ b/services/net/java/android/net/util/AvoidBadWifiTracker.java
@@ -0,0 +1,139 @@
+/*
+ * 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.util;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.R;
+
+import static android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI;
+
+/**
+ * A class to encapsulate management of the "Smart Networking" capability of
+ * avoiding bad Wi-Fi when, for example upstream connectivity is lost or
+ * certain critical link failures occur.
+ *
+ * This enables the device to switch to another form of connectivity, like
+ * mobile, if it's available and working.
+ *
+ * The Runnable |cb|, if given, is called on the supplied Handler's thread
+ * whether the computed "avoid bad wifi" value changes.
+ *
+ * Disabling this reverts the device to a level of networking sophistication
+ * circa 2012-13 by disabling disparate code paths each of which contribute to
+ * maintaining continuous, working Internet connectivity.
+ *
+ * @hide
+ */
+public class AvoidBadWifiTracker {
+    private static String TAG = AvoidBadWifiTracker.class.getSimpleName();
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final Runnable mReevaluateRunnable;
+    private final SettingObserver mSettingObserver;
+    private volatile boolean mAvoidBadWifi = true;
+
+    public AvoidBadWifiTracker(Context ctx, Handler handler) {
+        this(ctx, handler, null);
+    }
+
+    public AvoidBadWifiTracker(Context ctx, Handler handler, Runnable cb) {
+        mContext = ctx;
+        mHandler = handler;
+        mReevaluateRunnable = () -> { if (update() && cb != null) cb.run(); };
+        mSettingObserver = new SettingObserver();
+
+        final IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+        mContext.registerReceiverAsUser(new BroadcastReceiver() {
+            public void onReceive(Context context, Intent intent) {
+                reevaluate();
+            }
+        }, UserHandle.ALL, intentFilter, null, null);
+
+        update();
+    }
+
+    public boolean currentValue() {
+        return mAvoidBadWifi;
+    }
+
+    /**
+     * Whether the device or carrier configuration disables avoiding bad wifi by default.
+     */
+    public boolean configRestrictsAvoidBadWifi() {
+        return (mContext.getResources().getInteger(R.integer.config_networkAvoidBadWifi) == 0);
+    }
+
+    /**
+     * Whether we should display a notification when wifi becomes unvalidated.
+     */
+    public boolean shouldNotifyWifiUnvalidated() {
+        return configRestrictsAvoidBadWifi() && getSettingsValue() == null;
+    }
+
+    public String getSettingsValue() {
+        final ContentResolver resolver = mContext.getContentResolver();
+        return Settings.Global.getString(resolver, NETWORK_AVOID_BAD_WIFI);
+    }
+
+    @VisibleForTesting
+    public void reevaluate() {
+        mHandler.post(mReevaluateRunnable);
+    }
+
+    public boolean update() {
+        final boolean settingAvoidBadWifi = "1".equals(getSettingsValue());
+        final boolean prev = mAvoidBadWifi;
+        mAvoidBadWifi = settingAvoidBadWifi || !configRestrictsAvoidBadWifi();
+        return mAvoidBadWifi != prev;
+    }
+
+    private class SettingObserver extends ContentObserver {
+        private final Uri mUri = Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI);
+
+        public SettingObserver() {
+            super(null);
+            final ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(mUri, false, this);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            Slog.wtf(TAG, "Should never be reached.");
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            if (!mUri.equals(uri)) return;
+            reevaluate();
+        }
+    }
+}
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 1feb816..6558b6e 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -728,7 +728,8 @@
                 @Override
                 public void onPackageModified(String packageName) {
                     if (!mUserManager.isUserUnlockingOrUnlocked(getChangingUserId())) return;
-                    UserState userState = getOrCreateUserStateLocked(getChangingUserId(), false);
+                    UserState userState = getOrCreateUserStateLocked(getChangingUserId(), false,
+                            false /* enforceUserUnlockingOrUnlocked */);
 
                     synchronized (mLock) {
                         if (hadPrintService(userState, packageName)
@@ -743,7 +744,8 @@
                 @Override
                 public void onPackageRemoved(String packageName, int uid) {
                     if (!mUserManager.isUserUnlockingOrUnlocked(getChangingUserId())) return;
-                    UserState userState = getOrCreateUserStateLocked(getChangingUserId(), false);
+                    UserState userState = getOrCreateUserStateLocked(getChangingUserId(), false,
+                            false /* enforceUserUnlockingOrUnlocked */);
 
                     synchronized (mLock) {
                         if (hadPrintService(userState, packageName)) {
@@ -762,8 +764,8 @@
                         // A background user/profile's print jobs are running but there is
                         // no UI shown. Hence, if the packages of such a user change we need
                         // to handle it as the change may affect ongoing print jobs.
-                        UserState userState = getOrCreateUserStateLocked(getChangingUserId(),
-                                false);
+                        UserState userState = getOrCreateUserStateLocked(getChangingUserId(), false,
+                                false /* enforceUserUnlockingOrUnlocked */);
                         boolean stoppedSomePackages = false;
 
                         List<PrintServiceInfo> enabledServices = userState
@@ -799,7 +801,7 @@
                     synchronized (mLock) {
                         if (hasPrintService(packageName)) {
                             UserState userState = getOrCreateUserStateLocked(getChangingUserId(),
-                                    false);
+                                    false, false /* enforceUserUnlockingOrUnlocked */);
                             userState.updateIfNeededLocked();
                         }
                     }
@@ -810,9 +812,14 @@
             monitor.register(mContext, BackgroundThread.getHandler().getLooper(),
                     UserHandle.ALL, true);
         }
-
         private UserState getOrCreateUserStateLocked(int userId, boolean lowPriority) {
-            if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
+            return getOrCreateUserStateLocked(userId, lowPriority,
+                    true /* enforceUserUnlockingOrUnlocked */);
+        }
+
+        private UserState getOrCreateUserStateLocked(int userId, boolean lowPriority,
+                boolean enforceUserUnlockingOrUnlocked) {
+            if (enforceUserUnlockingOrUnlocked && !mUserManager.isUserUnlockingOrUnlocked(userId)) {
                 throw new IllegalStateException(
                         "User " + userId + " must be unlocked for printing to be available");
             }
@@ -840,7 +847,8 @@
 
                     UserState userState;
                     synchronized (mLock) {
-                        userState = getOrCreateUserStateLocked(userId, true);
+                        userState = getOrCreateUserStateLocked(userId, true,
+                                false /*enforceUserUnlockingOrUnlocked */);
                         userState.updateIfNeededLocked();
                     }
                     // This is the first time we switch to this user after boot, so
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 514f095..3548f28 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -44,6 +44,7 @@
     <uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" />
     <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
+    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/services/tests/servicestests/src/android/net/apf/ApfTest.java b/services/tests/servicestests/src/android/net/apf/ApfTest.java
index f7c61d1..37807b2 100644
--- a/services/tests/servicestests/src/android/net/apf/ApfTest.java
+++ b/services/tests/servicestests/src/android/net/apf/ApfTest.java
@@ -16,10 +16,6 @@
 
 package android.net.apf;
 
-import static android.system.OsConstants.*;
-
-import com.android.frameworks.servicestests.R;
-
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkUtils;
@@ -37,6 +33,10 @@
 import android.system.Os;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
+import static android.system.OsConstants.*;
+
+import com.android.frameworks.servicestests.R;
+import com.android.internal.util.HexDump;
 
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
@@ -54,6 +54,7 @@
 import java.net.NetworkInterface;
 import java.nio.ByteBuffer;
 import java.util.List;
+import java.util.Random;
 
 import libcore.io.IoUtils;
 import libcore.io.Streams;
@@ -1146,6 +1147,39 @@
         buffer.position(original);
     }
 
+    public void testRaParsing() throws Exception {
+        final int maxRandomPacketSize = 512;
+        final Random r = new Random();
+        MockIpManagerCallback cb = new MockIpManagerCallback();
+        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog);
+        for (int i = 0; i < 1000; i++) {
+            byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
+            r.nextBytes(packet);
+            try {
+                apfFilter.new Ra(packet, packet.length);
+            } catch (ApfFilter.InvalidRaException e) {
+            } catch (Exception e) {
+                throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
+            }
+        }
+    }
+
+    public void testRaProcessing() throws Exception {
+        final int maxRandomPacketSize = 512;
+        final Random r = new Random();
+        MockIpManagerCallback cb = new MockIpManagerCallback();
+        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog);
+        for (int i = 0; i < 1000; i++) {
+            byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
+            r.nextBytes(packet);
+            try {
+                apfFilter.processRa(packet, packet.length);
+            } catch (Exception e) {
+                throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
+            }
+        }
+    }
+
     /**
      * Call the APF interpreter the run {@code program} on {@code packet} pretending the
      * filter was installed {@code filter_age} seconds ago.
diff --git a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
index f8eaf7d..bc8baa1 100644
--- a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
@@ -16,24 +16,22 @@
 
 package android.net.dhcp;
 
-import android.net.NetworkUtils;
 import android.net.DhcpResults;
 import android.net.LinkAddress;
+import android.net.NetworkUtils;
+import android.net.metrics.DhcpErrorEvent;
 import android.system.OsConstants;
 import android.test.suitebuilder.annotation.SmallTest;
 import com.android.internal.util.HexDump;
-
 import java.net.Inet4Address;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-
-import junit.framework.TestCase;
-import libcore.util.HexEncoding;
 import java.util.Arrays;
+import java.util.Random;
+import junit.framework.TestCase;
 
 import static android.net.dhcp.DhcpPacket.*;
 
-
 public class DhcpPacketTest extends TestCase {
 
     private static Inet4Address SERVER_ADDR = v4Address("192.0.2.1");
@@ -285,7 +283,7 @@
         // TODO: Turn all of these into golden files. This will probably require modifying
         // Android.mk appropriately, making this into an AndroidTestCase, and adding code to read
         // the golden files from the test APK's assets via mContext.getAssets().
-        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+        final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // IP header.
             "451001480000000080118849c0a89003c0a89ff7" +
             // UDP header.
@@ -304,8 +302,7 @@
             "0000000000000000000000000000000000000000000000000000000000000000" +
             // Options
             "638253633501023604c0a89003330400001c200104fffff0000304c0a89ffe06080808080808080404" +
-            "3a0400000e103b040000189cff00000000000000000000"
-        ).toCharArray(), false));
+            "3a0400000e103b040000189cff00000000000000000000"));
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
         assertTrue(offerPacket instanceof DhcpOfferPacket);  // Implicitly checks it's non-null.
@@ -316,7 +313,7 @@
 
     @SmallTest
     public void testOffer2() throws Exception {
-        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+        final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // IP header.
             "450001518d0600004011144dc0a82b01c0a82bf7" +
             // UDP header.
@@ -335,8 +332,7 @@
             "0000000000000000000000000000000000000000000000000000000000000000" +
             // Options
             "638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
-            "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"
-        ).toCharArray(), false));
+            "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"));
 
         assertEquals(337, packet.limit());
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
@@ -347,6 +343,185 @@
         assertTrue(dhcpResults.hasMeteredHint());
     }
 
+    @SmallTest
+    public void testBadIpPacket() throws Exception {
+        final byte[] packet = HexDump.hexStringToByteArray(
+            // IP header.
+            "450001518d0600004011144dc0a82b01c0a82bf7");
+
+        try {
+            DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L3);
+        } catch (DhcpPacket.ParseException expected) {
+            assertDhcpErrorCodes(DhcpErrorEvent.L3_TOO_SHORT, expected.errorCode);
+            return;
+        }
+        fail("Dhcp packet parsing should have failed");
+    }
+
+    @SmallTest
+    public void testBadDhcpPacket() throws Exception {
+        final byte[] packet = HexDump.hexStringToByteArray(
+            // IP header.
+            "450001518d0600004011144dc0a82b01c0a82bf7" +
+            // UDP header.
+            "00430044013d9ac7" +
+            // BOOTP header.
+            "02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000");
+
+        try {
+            DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L3);
+        } catch (DhcpPacket.ParseException expected) {
+            assertDhcpErrorCodes(DhcpErrorEvent.L3_TOO_SHORT, expected.errorCode);
+            return;
+        }
+        fail("Dhcp packet parsing should have failed");
+    }
+
+    @SmallTest
+    public void testBadTruncatedOffer() throws Exception {
+        final byte[] packet = HexDump.hexStringToByteArray(
+            // IP header.
+            "450001518d0600004011144dc0a82b01c0a82bf7" +
+            // UDP header.
+            "00430044013d9ac7" +
+            // BOOTP header.
+            "02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
+            // MAC address.
+            "30766ff2a90c00000000000000000000" +
+            // Server name.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // File, missing one byte
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "00000000000000000000000000000000000000000000000000000000000000");
+
+        try {
+            DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L3);
+        } catch (DhcpPacket.ParseException expected) {
+            assertDhcpErrorCodes(DhcpErrorEvent.L3_TOO_SHORT, expected.errorCode);
+            return;
+        }
+        fail("Dhcp packet parsing should have failed");
+    }
+
+    @SmallTest
+    public void testBadOfferWithoutACookie() throws Exception {
+        final byte[] packet = HexDump.hexStringToByteArray(
+            // IP header.
+            "450001518d0600004011144dc0a82b01c0a82bf7" +
+            // UDP header.
+            "00430044013d9ac7" +
+            // BOOTP header.
+            "02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
+            // MAC address.
+            "30766ff2a90c00000000000000000000" +
+            // Server name.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // File.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000"
+            // No options
+            );
+
+        try {
+            DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L3);
+        } catch (DhcpPacket.ParseException expected) {
+            assertDhcpErrorCodes(DhcpErrorEvent.DHCP_NO_COOKIE, expected.errorCode);
+            return;
+        }
+        fail("Dhcp packet parsing should have failed");
+    }
+
+    @SmallTest
+    public void testOfferWithBadCookie() throws Exception {
+        final byte[] packet = HexDump.hexStringToByteArray(
+            // IP header.
+            "450001518d0600004011144dc0a82b01c0a82bf7" +
+            // UDP header.
+            "00430044013d9ac7" +
+            // BOOTP header.
+            "02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
+            // MAC address.
+            "30766ff2a90c00000000000000000000" +
+            // Server name.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // File.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // Bad cookie
+            "DEADBEEF3501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
+            "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff");
+
+        try {
+            DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L3);
+        } catch (DhcpPacket.ParseException expected) {
+            assertDhcpErrorCodes(DhcpErrorEvent.DHCP_BAD_MAGIC_COOKIE, expected.errorCode);
+            return;
+        }
+        fail("Dhcp packet parsing should have failed");
+    }
+
+    private void assertDhcpErrorCodes(int expected, int got) {
+        assertEquals(Integer.toHexString(expected), Integer.toHexString(got));
+    }
+
+    public void testTruncatedOfferPackets() throws Exception {
+        final byte[] packet = HexDump.hexStringToByteArray(
+            // IP header.
+            "450001518d0600004011144dc0a82b01c0a82bf7" +
+            // UDP header.
+            "00430044013d9ac7" +
+            // BOOTP header.
+            "02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
+            // MAC address.
+            "30766ff2a90c00000000000000000000" +
+            // Server name.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // File.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // Options
+            "638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
+            "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff");
+
+        for (int len = 0; len < packet.length; len++) {
+            try {
+                DhcpPacket.decodeFullPacket(packet, len, ENCAP_L3);
+            } catch (ParseException e) {
+                if (e.errorCode == DhcpErrorEvent.PARSING_ERROR) {
+                    fail(String.format("bad truncated packet of length %d", len));
+                }
+            }
+        }
+    }
+
+    public void testRandomPackets() throws Exception {
+        final int maxRandomPacketSize = 512;
+        final Random r = new Random();
+        for (int i = 0; i < 10000; i++) {
+            byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
+            r.nextBytes(packet);
+            try {
+                DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L3);
+            } catch (ParseException e) {
+                if (e.errorCode == DhcpErrorEvent.PARSING_ERROR) {
+                    fail("bad packet: " + HexDump.toHexString(packet));
+                }
+            }
+        }
+    }
+
     private byte[] mtuBytes(int mtu) {
         // 0x1a02: option 26, length 2. 0xff: no more options.
         if (mtu > Short.MAX_VALUE - Short.MIN_VALUE) {
@@ -354,7 +529,7 @@
                 String.format("Invalid MTU %d, must be 16-bit unsigned", mtu));
         }
         String hexString = String.format("1a02%04xff", mtu);
-        return HexEncoding.decode(hexString.toCharArray(), false);
+        return HexDump.hexStringToByteArray(hexString);
     }
 
     private void checkMtu(ByteBuffer packet, int expectedMtu, byte[] mtuBytes) throws Exception {
@@ -372,7 +547,7 @@
 
     @SmallTest
     public void testMtu() throws Exception {
-        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+        final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // IP header.
             "451001480000000080118849c0a89003c0a89ff7" +
             // UDP header.
@@ -391,8 +566,7 @@
             "0000000000000000000000000000000000000000000000000000000000000000" +
             // Options
             "638253633501023604c0a89003330400001c200104fffff0000304c0a89ffe06080808080808080404" +
-            "3a0400000e103b040000189cff00000000"
-        ).toCharArray(), false));
+            "3a0400000e103b040000189cff00000000"));
 
         checkMtu(packet, 0, null);
         checkMtu(packet, 0, mtuBytes(1501));
@@ -409,7 +583,7 @@
 
     @SmallTest
     public void testBadHwaddrLength() throws Exception {
-        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+        final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // IP header.
             "450001518d0600004011144dc0a82b01c0a82bf7" +
             // UDP header.
@@ -428,8 +602,7 @@
             "0000000000000000000000000000000000000000000000000000000000000000" +
             // Options
             "638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
-            "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"
-        ).toCharArray(), false));
+            "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"));
         String expectedClientMac = "30766FF2A90C";
 
         final int hwAddrLenOffset = 20 + 8 + 2;
@@ -486,7 +659,7 @@
         //    store any information in the overloaded fields).
         //
         // For now, we just check that it parses correctly.
-        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+        final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // Ethernet header.
             "b4cef6000000e80462236e300800" +
             // IP header.
@@ -507,8 +680,7 @@
             "0000000000000000000000000000000000000000000000000000000000000000" +
             // Options
             "638253633501023604010101010104ffff000033040000a8c03401030304ac1101010604ac110101" +
-            "0000000000000000000000000000000000000000000000ff000000"
-        ).toCharArray(), false));
+            "0000000000000000000000000000000000000000000000ff000000"));
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
         assertTrue(offerPacket instanceof DhcpOfferPacket);
@@ -519,7 +691,7 @@
 
     @SmallTest
     public void testBug2111() throws Exception {
-        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+        final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // IP header.
             "4500014c00000000ff119beac3eaf3880a3f5d04" +
             // UDP header. TODO: fix invalid checksum (due to MAC address obfuscation).
@@ -538,8 +710,7 @@
             "0000000000000000000000000000000000000000000000000000000000000000" +
             // Options.
             "638253633501023604c00002fe33040000bfc60104fffff00003040a3f50010608c0000201c0000202" +
-            "0f0f646f6d61696e3132332e636f2e756b0000000000ff00000000"
-        ).toCharArray(), false));
+            "0f0f646f6d61696e3132332e636f2e756b0000000000ff00000000"));
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
         assertTrue(offerPacket instanceof DhcpOfferPacket);
@@ -550,7 +721,7 @@
 
     @SmallTest
     public void testBug2136() throws Exception {
-        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+        final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // Ethernet header.
             "bcf5ac000000d0c7890000000800" +
             // IP header.
@@ -571,8 +742,7 @@
             "0000000000000000000000000000000000000000000000000000000000000000" +
             // Options.
             "6382536335010236040a20ff80330400001c200104fffff00003040a20900106089458413494584135" +
-            "0f0b6c616e63732e61632e756b000000000000000000ff00000000"
-        ).toCharArray(), false));
+            "0f0b6c616e63732e61632e756b000000000000000000ff00000000"));
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
         assertTrue(offerPacket instanceof DhcpOfferPacket);
@@ -584,7 +754,7 @@
 
     @SmallTest
     public void testUdpServerAnySourcePort() throws Exception {
-        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+        final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // Ethernet header.
             "9cd917000000001c2e0000000800" +
             // IP header.
@@ -606,8 +776,7 @@
             "0000000000000000000000000000000000000000000000000000000000000000" +
             // Options.
             "6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" +
-            "d18180060f0777766d2e6564751c040a0fffffff000000"
-        ).toCharArray(), false));
+            "d18180060f0777766d2e6564751c040a0fffffff000000"));
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
         assertTrue(offerPacket instanceof DhcpOfferPacket);
@@ -620,7 +789,7 @@
 
     @SmallTest
     public void testUdpInvalidDstPort() throws Exception {
-        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+        final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // Ethernet header.
             "9cd917000000001c2e0000000800" +
             // IP header.
@@ -642,8 +811,7 @@
             "0000000000000000000000000000000000000000000000000000000000000000" +
             // Options.
             "6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" +
-            "d18180060f0777766d2e6564751c040a0fffffff000000"
-        ).toCharArray(), false));
+            "d18180060f0777766d2e6564751c040a0fffffff000000"));
 
         try {
             DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
@@ -653,7 +821,7 @@
 
     @SmallTest
     public void testMultipleRouters() throws Exception {
-        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+        final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // Ethernet header.
             "fc3d93000000" + "081735000000" + "0800" +
             // IP header.
@@ -674,8 +842,7 @@
             "0000000000000000000000000000000000000000000000000000000000000000" +
             // Options.
             "638253633501023604c0abbd023304000070803a04000038403b04000062700104ffffff00" +
-            "0308c0a8bd01ffffff0006080808080808080404ff000000000000"
-        ).toCharArray(), false));
+            "0308c0a8bd01ffffff0006080808080808080404ff000000000000"));
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
         assertTrue(offerPacket instanceof DhcpOfferPacket);
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 257341b..0f180af 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -53,6 +53,7 @@
 import android.net.NetworkRequest;
 import android.net.RouteInfo;
 import android.net.metrics.IpConnectivityLog;
+import android.net.util.AvoidBadWifiTracker;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -600,10 +601,23 @@
         }
     }
 
-    private class WrappedConnectivityService extends ConnectivityService {
-        private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
+    private class WrappedAvoidBadWifiTracker extends AvoidBadWifiTracker {
         public boolean configRestrictsAvoidBadWifi;
 
+        public WrappedAvoidBadWifiTracker(Context c, Handler h, Runnable r) {
+            super(c, h, r);
+        }
+
+        @Override
+        public boolean configRestrictsAvoidBadWifi() {
+            return configRestrictsAvoidBadWifi;
+        }
+    }
+
+    private class WrappedConnectivityService extends ConnectivityService {
+        public WrappedAvoidBadWifiTracker wrappedAvoidBadWifiTracker;
+        private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
+
         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
                 INetworkStatsService statsService, INetworkPolicyManager policyManager,
                 IpConnectivityLog log) {
@@ -653,14 +667,20 @@
         }
 
         @Override
-        public WakeupMessage makeWakeupMessage(
-                Context context, Handler handler, String cmdName, int cmd, Object obj) {
-            return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
+        public AvoidBadWifiTracker createAvoidBadWifiTracker(
+                Context c, Handler h, Runnable r) {
+            final WrappedAvoidBadWifiTracker tracker = new WrappedAvoidBadWifiTracker(c, h, r);
+            return tracker;
+        }
+
+        public WrappedAvoidBadWifiTracker getAvoidBadWifiTracker() {
+            return (WrappedAvoidBadWifiTracker) mAvoidBadWifiTracker;
         }
 
         @Override
-        public boolean configRestrictsAvoidBadWifi() {
-            return configRestrictsAvoidBadWifi;
+        public WakeupMessage makeWakeupMessage(
+                Context context, Handler handler, String cmdName, int cmd, Object obj) {
+            return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
         }
 
         public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
@@ -2049,46 +2069,48 @@
     @SmallTest
     public void testAvoidBadWifiSetting() throws Exception {
         final ContentResolver cr = mServiceContext.getContentResolver();
+        final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
         final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
 
-        mService.configRestrictsAvoidBadWifi = false;
+        tracker.configRestrictsAvoidBadWifi = false;
         String[] values = new String[] {null, "0", "1"};
         for (int i = 0; i < values.length; i++) {
             Settings.Global.putInt(cr, settingName, 1);
-            mService.updateNetworkAvoidBadWifi();
+            tracker.reevaluate();
             mService.waitForIdle();
             String msg = String.format("config=false, setting=%s", values[i]);
             assertTrue(msg, mService.avoidBadWifi());
-            assertFalse(msg, mService.shouldNotifyWifiUnvalidated());
+            assertFalse(msg, tracker.shouldNotifyWifiUnvalidated());
         }
 
-        mService.configRestrictsAvoidBadWifi = true;
+        tracker.configRestrictsAvoidBadWifi = true;
 
         Settings.Global.putInt(cr, settingName, 0);
-        mService.updateNetworkAvoidBadWifi();
+        tracker.reevaluate();
         mService.waitForIdle();
         assertFalse(mService.avoidBadWifi());
-        assertFalse(mService.shouldNotifyWifiUnvalidated());
+        assertFalse(tracker.shouldNotifyWifiUnvalidated());
 
         Settings.Global.putInt(cr, settingName, 1);
-        mService.updateNetworkAvoidBadWifi();
+        tracker.reevaluate();
         mService.waitForIdle();
         assertTrue(mService.avoidBadWifi());
-        assertFalse(mService.shouldNotifyWifiUnvalidated());
+        assertFalse(tracker.shouldNotifyWifiUnvalidated());
 
         Settings.Global.putString(cr, settingName, null);
-        mService.updateNetworkAvoidBadWifi();
+        tracker.reevaluate();
         mService.waitForIdle();
         assertFalse(mService.avoidBadWifi());
-        assertTrue(mService.shouldNotifyWifiUnvalidated());
+        assertTrue(tracker.shouldNotifyWifiUnvalidated());
     }
 
     @SmallTest
     public void testAvoidBadWifi() throws Exception {
-        ContentResolver cr = mServiceContext.getContentResolver();
+        final ContentResolver cr = mServiceContext.getContentResolver();
+        final WrappedAvoidBadWifiTracker tracker = mService.getAvoidBadWifiTracker();
 
         // Pretend we're on a carrier that restricts switching away from bad wifi.
-        mService.configRestrictsAvoidBadWifi = true;
+        tracker.configRestrictsAvoidBadWifi = true;
 
         // File a request for cell to ensure it doesn't go down.
         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
@@ -2107,7 +2129,7 @@
         mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
 
         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
-        mService.updateNetworkAvoidBadWifi();
+        tracker.reevaluate();
 
         // Bring up validated cell.
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -2138,14 +2160,14 @@
 
         // Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
         // that we switch back to cell.
-        mService.configRestrictsAvoidBadWifi = false;
-        mService.updateNetworkAvoidBadWifi();
+        tracker.configRestrictsAvoidBadWifi = false;
+        tracker.reevaluate();
         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
         assertEquals(mCm.getActiveNetwork(), cellNetwork);
 
         // Switch back to a restrictive carrier.
-        mService.configRestrictsAvoidBadWifi = true;
-        mService.updateNetworkAvoidBadWifi();
+        tracker.configRestrictsAvoidBadWifi = true;
+        tracker.reevaluate();
         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
 
@@ -2173,7 +2195,7 @@
 
         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
-        mService.updateNetworkAvoidBadWifi();
+        tracker.reevaluate();
 
         // We now switch to cell.
         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
@@ -2186,11 +2208,11 @@
         // Simulate the user turning the cellular fallback setting off and then on.
         // We switch to wifi and then to cell.
         Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
-        mService.updateNetworkAvoidBadWifi();
+        tracker.reevaluate();
         defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
-        mService.updateNetworkAvoidBadWifi();
+        tracker.reevaluate();
         defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
         assertEquals(mCm.getActiveNetwork(), cellNetwork);
 
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
new file mode 100644
index 0000000..5b565a7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
@@ -0,0 +1,341 @@
+
+/*
+ * 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.accounts;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.database.Cursor;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Pair;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for {@link AccountsDb}.
+ * <p>Run with:<pre>
+ * m FrameworksServicesTests &&
+ * adb install \
+ * -r out/target/product/marlin/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
+ * adb shell am instrument -e class com.android.server.accounts.AccountsDbTest \
+ * -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ * </pre>
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class AccountsDbTest {
+    private static final String PREN_DB = "pren.db";
+    private static final String DE_DB = "de.db";
+    private static final String CE_DB = "ce.db";
+
+    private AccountsDb mAccountsDb;
+    private File preNDb;
+    private File deDb;
+    private File ceDb;
+
+    @Before
+    public void setUp() {
+        Context context = InstrumentationRegistry.getContext();
+        preNDb = new File(context.getCacheDir(), PREN_DB);
+        ceDb = new File(context.getCacheDir(), CE_DB);
+        deDb = new File(context.getCacheDir(), DE_DB);
+        deleteDbFiles();
+        mAccountsDb = AccountsDb.create(context, 0, preNDb, deDb);
+    }
+
+    @After
+    public void tearDown() {
+        deleteDbFiles();
+    }
+
+    private void deleteDbFiles() {
+        AccountsDb.deleteDbFileWarnIfFailed(preNDb);
+        AccountsDb.deleteDbFileWarnIfFailed(ceDb);
+        AccountsDb.deleteDbFileWarnIfFailed(deDb);
+    }
+
+    @Test
+    public void testCeNotAvailableInitially() {
+        Account account = new Account("name", "example.com");
+        long id = mAccountsDb.insertCeAccount(account, "");
+        assertEquals("Insert into CE should fail until CE database is attached", -1, id);
+    }
+
+    @Test
+    public void testDeAccountInsertFindDelete() {
+        Account account = new Account("name", "example.com");
+        long accId = 1;
+        mAccountsDb.insertDeAccount(account, accId);
+        long actualId = mAccountsDb.findDeAccountId(account);
+        assertEquals(accId, actualId);
+        // Delete and verify that account no longer exists
+        mAccountsDb.deleteDeAccount(accId);
+        actualId = mAccountsDb.findDeAccountId(account);
+        assertEquals(-1, actualId);
+    }
+
+    @Test
+    public void testCeAccountInsertFindDelete() {
+        mAccountsDb.attachCeDatabase(ceDb);
+        Account account = new Account("name", "example.com");
+        long accId = mAccountsDb.insertCeAccount(account, "password");
+        long actualId = mAccountsDb.findCeAccountId(account);
+        assertEquals(accId, actualId);
+        // Delete and verify that account no longer exists
+        mAccountsDb.deleteCeAccount(accId);
+        actualId = mAccountsDb.findCeAccountId(account);
+        assertEquals(-1, actualId);
+    }
+
+    @Test
+    public void testAuthTokenInsertFindDelete() {
+        mAccountsDb.attachCeDatabase(ceDb);
+        Account account = new Account("name", "example.com");
+        long accId = mAccountsDb.insertCeAccount(account, "password");
+        mAccountsDb.insertDeAccount(account, accId);
+        long authTokenId = mAccountsDb.insertAuthToken(accId, "type", "token");
+        Map<String, String> authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account);
+        assertEquals(1, authTokensByAccount.size());
+        try (Cursor cursor = mAccountsDb.findAuthtokenForAllAccounts(account.type, "token")) {
+            assertTrue(cursor.moveToNext());
+        }
+        try (Cursor cursor = mAccountsDb.findAuthtokenForAllAccounts(account.type, "nosuchtoken")) {
+            assertFalse(cursor.moveToNext());
+        }
+        mAccountsDb.deleteAuthToken(String.valueOf(authTokenId));
+        // Verify that token no longer exists
+        authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account);
+        assertEquals(0, authTokensByAccount.size());
+    }
+
+    @Test
+    public void testAuthTokenDeletes() {
+        mAccountsDb.attachCeDatabase(ceDb);
+        // 1st account
+        Account account = new Account("name", "example.com");
+        long accId = mAccountsDb.insertCeAccount(account, "password");
+        mAccountsDb.insertDeAccount(account, accId);
+        mAccountsDb.insertAuthToken(accId, "type", "token");
+        mAccountsDb.insertAuthToken(accId, "type2", "token2");
+        // 2nd account
+        Account account2 = new Account("name", "example2.com");
+        long accId2 = mAccountsDb.insertCeAccount(account2, "password");
+        mAccountsDb.insertDeAccount(account2, accId);
+        mAccountsDb.insertAuthToken(accId2, "type", "token");
+
+        mAccountsDb.deleteAuthTokensByAccountId(accId2);
+        Map<String, String> authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account2);
+        assertEquals(0, authTokensByAccount.size());
+        // Authtokens from account 1 are still there
+        authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account);
+        assertEquals(2, authTokensByAccount.size());
+
+        // Delete authtokens from account 1 and verify
+        mAccountsDb.deleteAuthtokensByAccountIdAndType(accId, "type");
+        authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account);
+        assertEquals(1, authTokensByAccount.size());
+        mAccountsDb.deleteAuthtokensByAccountIdAndType(accId, "type2");
+        authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account);
+        assertEquals(0, authTokensByAccount.size());
+    }
+
+    @Test
+    public void testExtrasInsertFindDelete() {
+        mAccountsDb.attachCeDatabase(ceDb);
+        Account account = new Account("name", "example.com");
+        long accId = mAccountsDb.insertCeAccount(account, "password");
+        mAccountsDb.insertDeAccount(account, accId);
+        String extraKey = "extra_key";
+        String extraValue = "extra_value";
+        long extraId = mAccountsDb.insertExtra(accId, extraKey, extraValue);
+        // Test find methods
+        long actualExtraId = mAccountsDb.findExtrasIdByAccountId(accId, extraKey);
+        assertEquals(extraId, actualExtraId);
+        Map<String, String> extras = mAccountsDb.findUserExtrasForAccount(account);
+        assertEquals(1, extras.size());
+        assertEquals(extraValue, extras.get(extraKey));
+        // Test update
+        String newExtraValue = "extra_value2";
+        mAccountsDb.updateExtra(extraId, newExtraValue);
+        String newValue = mAccountsDb.findUserExtrasForAccount(account).get(extraKey);
+        assertEquals(newExtraValue, newValue);
+
+        // Delete account and verify that extras cascade removed
+        mAccountsDb.deleteCeAccount(accId);
+        actualExtraId = mAccountsDb.findExtrasIdByAccountId(accId, extraKey);
+        assertEquals(-1, actualExtraId);
+    }
+
+    @Test
+    public void testGrantsInsertFindDelete() {
+        mAccountsDb.attachCeDatabase(ceDb);
+        Account account = new Account("name", "example.com");
+        long accId = mAccountsDb.insertCeAccount(account, "password");
+        mAccountsDb.insertDeAccount(account, accId);
+        int testUid = 100500;
+        long grantId = mAccountsDb.insertGrant(accId, "tokenType", testUid);
+        assertTrue(grantId > 0);
+        List<Integer> allUidGrants = mAccountsDb.findAllUidGrants();
+        List<Integer> expectedUids = Arrays.asList(testUid);
+        assertEquals(expectedUids, allUidGrants);
+
+        long matchingGrantsCount = mAccountsDb.findMatchingGrantsCount(
+                testUid, "tokenType", account);
+        assertEquals(1, matchingGrantsCount);
+        // Test nonexistent type
+        matchingGrantsCount = mAccountsDb.findMatchingGrantsCount(
+                testUid, "noSuchType", account);
+        assertEquals(0, matchingGrantsCount);
+
+        matchingGrantsCount = mAccountsDb.findMatchingGrantsCountAnyToken(testUid, account);
+        assertEquals(1, matchingGrantsCount);
+
+        List<Pair<String, Integer>> allAccountGrants = mAccountsDb.findAllAccountGrants();
+        assertEquals(1, allAccountGrants.size());
+        assertEquals(account.name, allAccountGrants.get(0).first);
+        assertEquals(testUid, (int)allAccountGrants.get(0).second);
+
+        mAccountsDb.deleteGrantsByUid(testUid);
+        allUidGrants = mAccountsDb.findAllUidGrants();
+        assertTrue("Test grants should be removed", allUidGrants.isEmpty());
+    }
+
+    @Test
+    public void testSharedAccountsInsertFindDelete() {
+        Account account = new Account("name", "example.com");
+        long accId = 0;
+        mAccountsDb.insertDeAccount(account, accId);
+        long sharedAccId = mAccountsDb.insertSharedAccount(account);
+        long foundSharedAccountId = mAccountsDb.findSharedAccountId(account);
+        assertEquals(sharedAccId, foundSharedAccountId);
+        List<Account> sharedAccounts = mAccountsDb.getSharedAccounts();
+        List<Account> expectedList = Arrays.asList(account);
+        assertEquals(expectedList, sharedAccounts);
+
+        // Delete and verify
+        mAccountsDb.deleteSharedAccount(account);
+        foundSharedAccountId = mAccountsDb.findSharedAccountId(account);
+        assertEquals(-1, foundSharedAccountId);
+    }
+
+    @Test
+    public void testMetaInsertFindDelete() {
+        int testUid = 100500;
+        String authenticatorType = "authType";
+        mAccountsDb.insertOrReplaceMetaAuthTypeAndUid(authenticatorType, testUid);
+        Map<String, Integer> metaAuthUid = mAccountsDb.findMetaAuthUid();
+        assertEquals(1, metaAuthUid.size());
+        assertEquals(testUid, (int)metaAuthUid.get(authenticatorType));
+
+        // Delete and verify
+        boolean deleteResult = mAccountsDb.deleteMetaByAuthTypeAndUid(authenticatorType, testUid);
+        assertTrue(deleteResult);
+        metaAuthUid = mAccountsDb.findMetaAuthUid();
+        assertEquals(0, metaAuthUid.size());
+    }
+
+    @Test
+    public void testUpdateDeAccountLastAuthenticatedTime() {
+        Account account = new Account("name", "example.com");
+        long accId = 1;
+        mAccountsDb.insertDeAccount(account, accId);
+        long now = System.currentTimeMillis();
+        mAccountsDb.updateAccountLastAuthenticatedTime(account);
+        long time = mAccountsDb.findAccountLastAuthenticatedTime(account);
+        assertTrue("LastAuthenticatedTime should be current", time >= now);
+    }
+
+    @Test
+    public void testRenameAccount() {
+        mAccountsDb.attachCeDatabase(ceDb);
+        Account account = new Account("name", "example.com");
+        long accId = mAccountsDb.insertCeAccount(account, "password");
+        mAccountsDb.insertDeAccount(account, accId);
+        mAccountsDb.renameDeAccount(accId, "newName", "name");
+        Account newAccount = mAccountsDb.findAllDeAccounts().get(accId);
+        assertEquals("newName", newAccount.name);
+
+        String prevName = mAccountsDb.findDeAccountPreviousName(newAccount);
+        assertEquals("name", prevName);
+        mAccountsDb.renameCeAccount(accId, "newName");
+        long foundAccId = mAccountsDb.findCeAccountId(account);
+        assertEquals("Account shouldn't be found under the old name", -1, foundAccId);
+        foundAccId = mAccountsDb.findCeAccountId(newAccount);
+        assertEquals(accId, foundAccId);
+    }
+
+    @Test
+    public void testUpdateCeAccountPassword() {
+        mAccountsDb.attachCeDatabase(ceDb);
+        Account account = new Account("name", "example.com");
+        long accId = mAccountsDb.insertCeAccount(account, "password");
+        String newPassword = "newPassword";
+        mAccountsDb.updateCeAccountPassword(accId, newPassword);
+        String actualPassword = mAccountsDb
+                .findAccountPasswordByNameAndType(account.name, account.type);
+        assertEquals(newPassword, actualPassword);
+    }
+
+    @Test
+    public void testFindCeAccountsNotInDe() {
+        mAccountsDb.attachCeDatabase(ceDb);
+        Account account = new Account("name", "example.com");
+        long accId = mAccountsDb.insertCeAccount(account, "password");
+        mAccountsDb.insertDeAccount(account, accId);
+
+        Account accountNotInDe = new Account("name2", "example.com");
+        mAccountsDb.insertCeAccount(accountNotInDe, "password");
+
+        List<Account> ceAccounts = mAccountsDb.findCeAccountsNotInDe();
+        List<Account> expectedList = Arrays.asList(accountNotInDe);
+        assertEquals(expectedList, ceAccounts);
+    }
+
+    @Test
+    public void testCrossDbTransactions() {
+        mAccountsDb.attachCeDatabase(ceDb);
+        mAccountsDb.beginTransaction();
+        Account account = new Account("name", "example.com");
+        long accId;
+        accId = mAccountsDb.insertCeAccount(account, "password");
+        accId = mAccountsDb.insertDeAccount(account, accId);
+        long actualId = mAccountsDb.findCeAccountId(account);
+        assertEquals(accId, actualId);
+        actualId = mAccountsDb.findDeAccountId(account);
+        assertEquals(accId, actualId);
+        mAccountsDb.endTransaction();
+        // Verify that records were removed
+        actualId = mAccountsDb.findCeAccountId(account);
+        assertEquals(-1, actualId);
+        actualId = mAccountsDb.findDeAccountId(account);
+        assertEquals(-1, actualId);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ConfigurationContainerTests.java b/services/tests/servicestests/src/com/android/server/am/ConfigurationContainerTests.java
new file mode 100644
index 0000000..92c442e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ConfigurationContainerTests.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.res.Configuration;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test class for {@link ConfigurationContainer}. Mostly duplicates configuration tests from
+ * {@link com.android.server.wm.WindowContainerTests}.
+ *
+ * Build: mmma -j32 frameworks/base/services/tests/servicestests
+ * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * Run: adb shell am instrument -w -e class com.android.server.am.ConfigurationContainerTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ConfigurationContainerTests {
+
+    @Test
+    public void testConfigurationInit() throws Exception {
+        // Check root container initial config.
+        final TestConfigurationContainer root = new TestConfigurationContainer();
+        assertEquals(Configuration.EMPTY, root.getOverrideConfiguration());
+        assertEquals(Configuration.EMPTY, root.getMergedOverrideConfiguration());
+        assertEquals(Configuration.EMPTY, root.getConfiguration());
+
+        // Check child initial config.
+        final TestConfigurationContainer child1 = root.addChild();
+        assertEquals(Configuration.EMPTY, child1.getOverrideConfiguration());
+        assertEquals(Configuration.EMPTY, child1.getMergedOverrideConfiguration());
+        assertEquals(Configuration.EMPTY, child1.getConfiguration());
+
+        // Check child initial config if root has overrides.
+        final Configuration rootOverrideConfig = new Configuration();
+        rootOverrideConfig.fontScale = 1.3f;
+        root.onOverrideConfigurationChanged(rootOverrideConfig);
+        final TestConfigurationContainer child2 = root.addChild();
+        assertEquals(Configuration.EMPTY, child2.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, child2.getMergedOverrideConfiguration());
+        assertEquals(rootOverrideConfig, child2.getConfiguration());
+
+        // Check child initial config if root has parent config set.
+        final Configuration rootParentConfig = new Configuration();
+        rootParentConfig.fontScale = 0.8f;
+        rootParentConfig.orientation = SCREEN_ORIENTATION_LANDSCAPE;
+        root.onConfigurationChanged(rootParentConfig);
+        final Configuration rootFullConfig = new Configuration(rootParentConfig);
+        rootFullConfig.updateFrom(rootOverrideConfig);
+
+        final TestConfigurationContainer child3 = root.addChild();
+        assertEquals(Configuration.EMPTY, child3.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, child3.getMergedOverrideConfiguration());
+        assertEquals(rootFullConfig, child3.getConfiguration());
+    }
+
+    @Test
+    public void testConfigurationChangeOnAddRemove() throws Exception {
+        // Init root's config.
+        final TestConfigurationContainer root = new TestConfigurationContainer();
+        final Configuration rootOverrideConfig = new Configuration();
+        rootOverrideConfig.fontScale = 1.3f;
+        root.onOverrideConfigurationChanged(rootOverrideConfig);
+
+        // Init child's config.
+        final TestConfigurationContainer child = root.addChild();
+        final Configuration childOverrideConfig = new Configuration();
+        childOverrideConfig.densityDpi = 320;
+        child.onOverrideConfigurationChanged(childOverrideConfig);
+
+        // Check configuration update when child is removed from parent.
+        root.removeChild(child);
+        assertEquals(childOverrideConfig, child.getOverrideConfiguration());
+        assertEquals(childOverrideConfig, child.getMergedOverrideConfiguration());
+        assertEquals(childOverrideConfig, child.getConfiguration());
+
+        // It may be paranoia... but let's check if parent's config didn't change after removal.
+        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getConfiguration());
+
+        // Check configuration update when child is added to parent.
+        final Configuration mergedOverrideConfig = new Configuration(root.getConfiguration());
+        mergedOverrideConfig.updateFrom(childOverrideConfig);
+        root.addChild(child);
+        assertEquals(childOverrideConfig, child.getOverrideConfiguration());
+        assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration());
+        assertEquals(mergedOverrideConfig, child.getConfiguration());
+    }
+
+    @Test
+    public void testConfigurationChangePropagation() throws Exception {
+        // Builds 3-level vertical hierarchy with one configuration container on each level.
+        // In addition to different overrides on each level, everyone in hierarchy will have one
+        // common overridden value - orientation;
+
+        // Init root's config.
+        final TestConfigurationContainer root = new TestConfigurationContainer();
+        final Configuration rootOverrideConfig = new Configuration();
+        rootOverrideConfig.fontScale = 1.3f;
+        rootOverrideConfig.orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+        root.onOverrideConfigurationChanged(rootOverrideConfig);
+
+        // Init children.
+        final TestConfigurationContainer child1 = root.addChild();
+        final Configuration childOverrideConfig1 = new Configuration();
+        childOverrideConfig1.densityDpi = 320;
+        childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE;
+        child1.onOverrideConfigurationChanged(childOverrideConfig1);
+
+        final TestConfigurationContainer child2 = child1.addChild();
+        final Configuration childOverrideConfig2 = new Configuration();
+        childOverrideConfig2.screenWidthDp = 150;
+        childOverrideConfig2.orientation = SCREEN_ORIENTATION_PORTRAIT;
+        child2.onOverrideConfigurationChanged(childOverrideConfig2);
+
+        // Check configuration on all levels when root override is updated.
+        rootOverrideConfig.smallestScreenWidthDp = 200;
+        root.onOverrideConfigurationChanged(rootOverrideConfig);
+
+        final Configuration mergedOverrideConfig1 = new Configuration(rootOverrideConfig);
+        mergedOverrideConfig1.updateFrom(childOverrideConfig1);
+        final Configuration mergedConfig1 = new Configuration(mergedOverrideConfig1);
+
+        final Configuration mergedOverrideConfig2 = new Configuration(mergedOverrideConfig1);
+        mergedOverrideConfig2.updateFrom(childOverrideConfig2);
+        final Configuration mergedConfig2 = new Configuration(mergedOverrideConfig2);
+
+        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getConfiguration());
+
+        assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
+        assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
+        assertEquals(mergedConfig1, child1.getConfiguration());
+
+        assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
+        assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
+        assertEquals(mergedConfig2, child2.getConfiguration());
+
+        // Check configuration on all levels when root parent config is updated.
+        final Configuration rootParentConfig = new Configuration();
+        rootParentConfig.screenHeightDp = 100;
+        rootParentConfig.orientation = SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+        root.onConfigurationChanged(rootParentConfig);
+        final Configuration mergedRootConfig = new Configuration(rootParentConfig);
+        mergedRootConfig.updateFrom(rootOverrideConfig);
+
+        mergedConfig1.setTo(mergedRootConfig);
+        mergedConfig1.updateFrom(mergedOverrideConfig1);
+
+        mergedConfig2.setTo(mergedConfig1);
+        mergedConfig2.updateFrom(mergedOverrideConfig2);
+
+        assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+        assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
+        assertEquals(mergedRootConfig, root.getConfiguration());
+
+        assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
+        assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
+        assertEquals(mergedConfig1, child1.getConfiguration());
+
+        assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
+        assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
+        assertEquals(mergedConfig2, child2.getConfiguration());
+    }
+
+    /**
+     * Contains minimal implementation of {@link ConfigurationContainer}'s abstract behavior needed
+     * for testing.
+     */
+    private class TestConfigurationContainer
+            extends ConfigurationContainer<TestConfigurationContainer> {
+        private List<TestConfigurationContainer> mChildren = new ArrayList<>();
+        private TestConfigurationContainer mParent;
+
+        TestConfigurationContainer addChild(TestConfigurationContainer childContainer) {
+            childContainer.mParent = this;
+            childContainer.onParentChanged();
+            mChildren.add(childContainer);
+            return childContainer;
+        }
+
+        TestConfigurationContainer addChild() {
+            return addChild(new TestConfigurationContainer());
+        }
+
+        void removeChild(TestConfigurationContainer child) {
+            child.mParent = null;
+            child.onParentChanged();
+        }
+
+        @Override
+        protected int getChildCount() {
+            return mChildren.size();
+        }
+
+        @Override
+        protected TestConfigurationContainer getChildAt(int index) {
+            return mChildren.get(index);
+        }
+
+        @Override
+        protected ConfigurationContainer getParent() {
+            return mParent;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java b/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 63d5d9fb..9e2fd62 100644
--- a/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -158,7 +158,8 @@
 
     void log(int netId, int[] latencies) {
         for (int l : latencies) {
-            mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l);
+            mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null, 0,
+                    0);
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/VpnTest.java b/services/tests/servicestests/src/com/android/server/connectivity/VpnTest.java
index 5d8b843..b51b277 100644
--- a/services/tests/servicestests/src/com/android/server/connectivity/VpnTest.java
+++ b/services/tests/servicestests/src/com/android/server/connectivity/VpnTest.java
@@ -25,9 +25,11 @@
 
 import android.annotation.UserIdInt;
 import android.app.AppOpsManager;
+import android.app.NotificationManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.net.NetworkInfo.DetailedState;
 import android.net.UidRange;
 import android.os.INetworkManagementService;
 import android.os.Looper;
@@ -43,6 +45,8 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -88,14 +92,18 @@
     @Mock private PackageManager mPackageManager;
     @Mock private INetworkManagementService mNetService;
     @Mock private AppOpsManager mAppOps;
+    @Mock private NotificationManager mNotificationManager;
 
     @Override
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         setMockedPackages(mPackages);
+        when(mContext.getPackageName()).thenReturn(Vpn.class.getPackage().getName());
         when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
         when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
+        when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
+                .thenReturn(mNotificationManager);
         doNothing().when(mNetService).registerObserver(any());
     }
 
@@ -103,7 +111,7 @@
     public void testRestrictedProfilesAreAddedToVpn() {
         setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB);
 
-        final Vpn vpn = new MockVpn(primaryUser.id);
+        final Vpn vpn = spyVpn(primaryUser.id);
         final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
                 null, null);
 
@@ -117,7 +125,7 @@
     public void testManagedProfilesAreNotAddedToVpn() {
         setMockedUsers(primaryUser, managedProfileA);
 
-        final Vpn vpn = new MockVpn(primaryUser.id);
+        final Vpn vpn = spyVpn(primaryUser.id);
         final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
                 null, null);
 
@@ -130,7 +138,7 @@
     public void testAddUserToVpnOnlyAddsOneUser() {
         setMockedUsers(primaryUser, restrictedProfileA, managedProfileA);
 
-        final Vpn vpn = new MockVpn(primaryUser.id);
+        final Vpn vpn = spyVpn(primaryUser.id);
         final Set<UidRange> ranges = new ArraySet<>();
         vpn.addUserToRanges(ranges, primaryUser.id, null, null);
 
@@ -141,7 +149,7 @@
 
     @SmallTest
     public void testUidWhiteAndBlacklist() throws Exception {
-        final Vpn vpn = new MockVpn(primaryUser.id);
+        final Vpn vpn = spyVpn(primaryUser.id);
         final UidRange user = UidRange.createForUser(primaryUser.id);
         final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
 
@@ -166,15 +174,15 @@
 
     @SmallTest
     public void testLockdownChangingPackage() throws Exception {
-        final MockVpn vpn = new MockVpn(primaryUser.id);
+        final Vpn vpn = spyVpn(primaryUser.id);
         final UidRange user = UidRange.createForUser(primaryUser.id);
 
         // Default state.
-        vpn.assertUnblocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
+        assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
 
         // Set always-on without lockdown.
         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false));
-        vpn.assertUnblocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
+        assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
 
         // Set always-on with lockdown.
         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true));
@@ -182,8 +190,8 @@
             new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
             new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
         }));
-        vpn.assertBlocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
-        vpn.assertUnblocked(user.start + PKG_UIDS[1]);
+        assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
+        assertUnblocked(vpn, user.start + PKG_UIDS[1]);
 
         // Switch to another app.
         assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true));
@@ -195,13 +203,13 @@
             new UidRange(user.start, user.start + PKG_UIDS[3] - 1),
             new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
         }));
-        vpn.assertBlocked(user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
-        vpn.assertUnblocked(user.start + PKG_UIDS[3]);
+        assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
+        assertUnblocked(vpn, user.start + PKG_UIDS[3]);
     }
 
     @SmallTest
     public void testLockdownAddingAProfile() throws Exception {
-        final MockVpn vpn = new MockVpn(primaryUser.id);
+        final Vpn vpn = spyVpn(primaryUser.id);
         setMockedUsers(primaryUser);
 
         // Make a copy of the restricted profile, as we're going to mark it deleted halfway through.
@@ -220,7 +228,7 @@
         }));
 
         // Verify restricted user isn't affected at first.
-        vpn.assertUnblocked(profile.start + PKG_UIDS[0]);
+        assertUnblocked(vpn, profile.start + PKG_UIDS[0]);
 
         // Add the restricted user.
         setMockedUsers(primaryUser, tempProfile);
@@ -239,24 +247,53 @@
         }));
     }
 
+    @SmallTest
+    public void testNotificationShownForAlwaysOnApp() {
+        final Vpn vpn = spyVpn(primaryUser.id);
+        final InOrder order = inOrder(vpn);
+        setMockedUsers(primaryUser);
+
+        // Don't show a notification for regular disconnected states.
+        vpn.updateState(DetailedState.DISCONNECTED, TAG);
+        order.verify(vpn).updateAlwaysOnNotificationInternal(false);
+
+        // Start showing a notification for disconnected once always-on.
+        vpn.setAlwaysOnPackage(PKGS[0], false);
+        order.verify(vpn).updateAlwaysOnNotificationInternal(true);
+
+        // Stop showing the notification once connected.
+        vpn.updateState(DetailedState.CONNECTED, TAG);
+        order.verify(vpn).updateAlwaysOnNotificationInternal(false);
+
+        // Show the notification if we disconnect again.
+        vpn.updateState(DetailedState.DISCONNECTED, TAG);
+        order.verify(vpn).updateAlwaysOnNotificationInternal(true);
+
+        // Notification should be cleared after unsetting always-on package.
+        vpn.setAlwaysOnPackage(null, false);
+        order.verify(vpn).updateAlwaysOnNotificationInternal(false);
+    }
+
     /**
-     * A subclass of {@link Vpn} with some of the fields pre-mocked.
+     * Mock some methods of vpn object.
      */
-    private class MockVpn extends Vpn {
-        public MockVpn(@UserIdInt int userId) {
-            super(Looper.myLooper(), mContext, mNetService, userId);
-        }
+    private Vpn spyVpn(@UserIdInt int userId) {
+        final Vpn vpn = spy(new Vpn(Looper.myLooper(), mContext, mNetService, userId));
 
-        public void assertBlocked(int... uids) {
-            for (int uid : uids) {
-                assertTrue("Uid " + uid + " should be blocked", isBlockingUid(uid));
-            }
-        }
+        // Block calls to the NotificationManager or PendingIntent#getActivity.
+        doNothing().when(vpn).updateAlwaysOnNotificationInternal(anyBoolean());
+        return vpn;
+    }
 
-        public void assertUnblocked(int... uids) {
-            for (int uid : uids) {
-                assertFalse("Uid " + uid + " should not be blocked", isBlockingUid(uid));
-            }
+    private static void assertBlocked(Vpn vpn, int... uids) {
+        for (int uid : uids) {
+            assertTrue("Uid " + uid + " should be blocked", vpn.isBlockingUid(uid));
+        }
+    }
+
+    private static void assertUnblocked(Vpn vpn, int... uids) {
+        for (int uid : uids) {
+            assertFalse("Uid " + uid + " should not be blocked", vpn.isBlockingUid(uid));
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 01b2c3b..56ff621 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1915,6 +1915,61 @@
         verifyScreenTimeoutCall(Integer.MAX_VALUE, false);
     }
 
+    public void testSetRequiredStrongAuthTimeout_DeviceOwner() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        setupDeviceOwner();
+        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+
+        final long MINIMUM_STRONG_AUTH_TIMEOUT_MS = 1 * 60 * 60 * 1000; // 1h
+        final long ONE_MINUTE = 60 * 1000;
+
+        // aggregation should be the default if unset by any admin
+        assertEquals(dpm.getRequiredStrongAuthTimeout(null),
+                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+
+        // admin not participating by default
+        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
+
+        //clamping from the top
+        dpm.setRequiredStrongAuthTimeout(admin1,
+                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS + ONE_MINUTE);
+        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1),
+                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+        assertEquals(dpm.getRequiredStrongAuthTimeout(null),
+                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+
+        // 0 means default
+        dpm.setRequiredStrongAuthTimeout(admin1, 0);
+        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
+        assertEquals(dpm.getRequiredStrongAuthTimeout(null),
+                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+
+        // clamping from the bottom
+        dpm.setRequiredStrongAuthTimeout(admin1, MINIMUM_STRONG_AUTH_TIMEOUT_MS - ONE_MINUTE);
+        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MINIMUM_STRONG_AUTH_TIMEOUT_MS);
+        assertEquals(dpm.getRequiredStrongAuthTimeout(null), MINIMUM_STRONG_AUTH_TIMEOUT_MS);
+
+        // value within range
+        dpm.setRequiredStrongAuthTimeout(admin1, MINIMUM_STRONG_AUTH_TIMEOUT_MS + ONE_MINUTE);
+        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MINIMUM_STRONG_AUTH_TIMEOUT_MS
+                + ONE_MINUTE);
+        assertEquals(dpm.getRequiredStrongAuthTimeout(null), MINIMUM_STRONG_AUTH_TIMEOUT_MS
+                + ONE_MINUTE);
+
+        // reset to default
+        dpm.setRequiredStrongAuthTimeout(admin1, 0);
+        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
+        assertEquals(dpm.getRequiredStrongAuthTimeout(null),
+                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+
+        // negative value
+        try {
+            dpm.setRequiredStrongAuthTimeout(admin1, -ONE_MINUTE);
+            fail("Didn't throw IllegalArgumentException");
+        } catch (IllegalArgumentException iae) {
+        }
+    }
+
     private void verifyScreenTimeoutCall(Integer expectedTimeout,
             boolean shouldStayOnWhilePluggedInBeCleared) {
         if (expectedTimeout == null) {
diff --git a/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java
new file mode 100644
index 0000000..ec1fdad
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.notification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SnoozeHelperTest {
+    @Mock SnoozeHelper.Callback mCallback;
+    @Mock AlarmManager mAm;
+    @Mock ManagedServices.UserProfiles mUserProfiles;
+
+    private SnoozeHelper mSnoozeHelper;
+
+    private Context getContext() {
+        return InstrumentationRegistry.getTargetContext();
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mSnoozeHelper = new SnoozeHelper(getContext(), mCallback, mUserProfiles);
+        mSnoozeHelper.setAlarmManager(mAm);
+    }
+
+    @Test
+    public void testSnooze() throws Exception {
+        NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+        mSnoozeHelper.snooze(r , UserHandle.USER_SYSTEM, 1000);
+        verify(mAm, times(1)).setExactAndAllowWhileIdle(
+                anyInt(), eq((long) 1000), any(PendingIntent.class));
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
+    }
+
+    @Test
+    public void testCancelByApp() throws Exception {
+        NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+        NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.SYSTEM);
+        mSnoozeHelper.snooze(r , UserHandle.USER_SYSTEM, 1000);
+        mSnoozeHelper.snooze(r2 , UserHandle.USER_SYSTEM, 1000);
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
+
+        mSnoozeHelper.cancel(UserHandle.USER_SYSTEM, r.sbn.getPackageName(), "one", 1);
+        // 3 = one for each snooze, above + one for cancel itself.
+        verify(mAm, times(3)).cancel(any(PendingIntent.class));
+        assertFalse(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
+    }
+
+    @Test
+    public void testCancelAllForUser() throws Exception {
+        NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+        NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.SYSTEM);
+        NotificationRecord r3 = getNotificationRecord("pkg", 3, "three", UserHandle.ALL);
+        mSnoozeHelper.snooze(r , UserHandle.USER_SYSTEM, 1000);
+        mSnoozeHelper.snooze(r2 , UserHandle.USER_SYSTEM, 1000);
+        mSnoozeHelper.snooze(r3 , UserHandle.USER_ALL, 1000);
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_ALL, r3.sbn.getPackageName(), r3.getKey()));
+
+        mSnoozeHelper.cancel(UserHandle.USER_SYSTEM, false);
+        // 5 = once for each snooze above (3) + once for each notification canceled (2).
+        verify(mAm, times(5)).cancel(any(PendingIntent.class));
+        assertFalse(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
+        assertFalse(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_ALL, r3.sbn.getPackageName(), r3.getKey()));
+    }
+
+    @Test
+    public void testCancelAllByApp() throws Exception {
+        NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+        NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.SYSTEM);
+        NotificationRecord r3 = getNotificationRecord("pkg2", 3, "three", UserHandle.SYSTEM);
+        mSnoozeHelper.snooze(r , UserHandle.USER_SYSTEM, 1000);
+        mSnoozeHelper.snooze(r2 , UserHandle.USER_SYSTEM, 1000);
+        mSnoozeHelper.snooze(r3 , UserHandle.USER_SYSTEM, 1000);
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r3.sbn.getPackageName(), r3.getKey()));
+
+        mSnoozeHelper.cancel(UserHandle.USER_SYSTEM, "pkg2");
+        // 4 = once for each snooze above (3) + once for each notification canceled (1).
+        verify(mAm, times(4)).cancel(any(PendingIntent.class));
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
+        assertTrue(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r2.sbn.getPackageName(), r2.getKey()));
+        assertFalse(mSnoozeHelper.isSnoozed(
+                UserHandle.USER_SYSTEM, r3.sbn.getPackageName(), r3.getKey()));
+    }
+
+    @Test
+    public void testRepost() throws Exception {
+        NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+        mSnoozeHelper.snooze(r , UserHandle.USER_SYSTEM, 1000);
+        NotificationRecord r2 = getNotificationRecord("pkg", 2, "one", UserHandle.ALL);
+        mSnoozeHelper.snooze(r2 , UserHandle.USER_ALL, 1000);
+        mSnoozeHelper.repost(r.sbn.getPackageName(), r.getKey(), UserHandle.USER_SYSTEM);
+        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r);
+    }
+
+    @Test
+    public void testUpdate() throws Exception {
+        NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+        mSnoozeHelper.snooze(r , UserHandle.USER_SYSTEM, 1000);
+        r.getNotification().category = "NEW CATEGORY";
+
+        mSnoozeHelper.update(UserHandle.USER_SYSTEM, r);
+        verify(mCallback, never()).repost(anyInt(), any(NotificationRecord.class));
+
+        mSnoozeHelper.repost(r.sbn.getPackageName(), r.getKey(), UserHandle.USER_SYSTEM);
+        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r);
+    }
+
+    private NotificationRecord getNotificationRecord(String pkg, int id, String tag,
+            UserHandle user) {
+        Notification n = new Notification.Builder(getContext())
+                .setContentTitle("A")
+                .setGroup("G")
+                .setSortKey("A")
+                .setWhen(1205)
+                .build();
+        return new NotificationRecord(getContext(), new StatusBarNotification(
+                pkg, pkg, id, tag, 0, 0, 0, n, user),
+                new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name"));
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 53c6a33..bd2bb6c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -115,14 +115,14 @@
         Settings settings =
                 new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object());
         assertThat(settings.readLPw(createFakeUsers()), is(true));
-        assertThat(settings.peekPackageLPr(PACKAGE_NAME_3), is(notNullValue()));
-        assertThat(settings.peekPackageLPr(PACKAGE_NAME_1), is(notNullValue()));
+        assertThat(settings.getPackageLPr(PACKAGE_NAME_3), is(notNullValue()));
+        assertThat(settings.getPackageLPr(PACKAGE_NAME_1), is(notNullValue()));
 
-        PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
+        PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_1);
         assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DEFAULT));
         assertThat(ps.getNotLaunched(0), is(true));
 
-        ps = settings.peekPackageLPr(PACKAGE_NAME_2);
+        ps = settings.getPackageLPr(PACKAGE_NAME_2);
         assertThat(ps.getStopped(0), is(false));
         assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER));
         assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_DEFAULT));
@@ -141,7 +141,7 @@
         settings = new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object());
         assertThat(settings.readLPw(createFakeUsers()), is(true));
 
-        PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_2);
+        PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_2);
         assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER));
         assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_DEFAULT));
     }
@@ -155,7 +155,7 @@
         assertThat(settings.readLPw(createFakeUsers()), is(true));
 
         // Enable/Disable a package
-        PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1);
+        PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_1);
         ps.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0, null);
         ps.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 1, null);
         assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED));
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 6a434ca..1f0422b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.app.ActivityManager;
 import android.os.Bundle;
@@ -46,16 +47,24 @@
     private static final int REMOVE_TIMEOUT_MILLIS = 60 * 1000; // 60 seconds
     private static final int SWITCH_USER_TIMEOUT_MILLIS = 40 * 1000; // 40 seconds
 
+    // Packages which are used during tests.
+    private static final String[] PACKAGES = new String[] {
+            "com.android.egg",
+            "com.android.retaildemo"
+    };
+
     private final Object mUserRemoveLock = new Object();
     private final Object mUserSwitchLock = new Object();
 
     private UserManager mUserManager = null;
+    private PackageManager mPackageManager;
     private List<Integer> usersToRemove;
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
         mUserManager = UserManager.get(getContext());
+        mPackageManager = getContext().getPackageManager();
 
         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
         filter.addAction(Intent.ACTION_USER_SWITCHED);
@@ -185,6 +194,81 @@
         assertFalse(mUserManager.isManagedProfile());
     }
 
+    // Verify that disallowed packages are not installed in the managed profile.
+    @MediumTest
+    public void testAddManagedProfile_withDisallowedPackages() throws Exception {
+        final int primaryUserId = mUserManager.getPrimaryUser().id;
+        UserInfo userInfo1 = createProfileForUser("Managed1",
+                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+        // Verify that the packagesToVerify are installed by default.
+        for (String pkg : PACKAGES) {
+            assertTrue("Package should be installed in managed profile: " + pkg,
+                    isPackageInstalledForUser(pkg, userInfo1.id));
+        }
+        removeUser(userInfo1.id);
+
+        UserInfo userInfo2 = createProfileForUser("Managed2",
+                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId, PACKAGES);
+        // Verify that the packagesToVerify are not installed by default.
+        for (String pkg : PACKAGES) {
+            assertFalse("Package should not be installed in managed profile when disallowed: "
+                    + pkg, isPackageInstalledForUser(pkg, userInfo2.id));
+        }
+    }
+
+    // Verify that if any packages are disallowed to install during creation of managed profile can
+    // still be installed later.
+    @MediumTest
+    public void testAddManagedProfile_disallowedPackagesInstalledLater() throws Exception {
+        final int primaryUserId = mUserManager.getPrimaryUser().id;
+        UserInfo userInfo = createProfileForUser("Managed",
+                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId, PACKAGES);
+        // Verify that the packagesToVerify are not installed by default.
+        for (String pkg : PACKAGES) {
+            assertFalse("Package should not be installed in managed profile when disallowed: "
+                    + pkg, isPackageInstalledForUser(pkg, userInfo.id));
+        }
+
+        // Verify that the disallowed packages during profile creation can be installed now.
+        for (String pkg : PACKAGES) {
+            assertEquals("Package could not be installed: " + pkg,
+                    PackageManager.INSTALL_SUCCEEDED,
+                    mPackageManager.installExistingPackageAsUser(pkg, userInfo.id));
+        }
+    }
+
+    // Make sure createProfile would fail if we have DISALLOW_ADD_USER.
+    @MediumTest
+    public void testCreateProfileForUser_disallowAddUser() throws Exception {
+        final int primaryUserId = mUserManager.getPrimaryUser().id;
+        final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
+        mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
+        try {
+            UserInfo userInfo = createProfileForUser("Managed",
+                    UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+            assertNull(userInfo);
+        } finally {
+            mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
+                    primaryUserHandle);
+        }
+    }
+
+    // Make sure createProfileEvenWhenDisallowedForUser bypass DISALLOW_ADD_USER.
+    @MediumTest
+    public void testCreateProfileForUserEvenWhenDisallowed() throws Exception {
+        final int primaryUserId = mUserManager.getPrimaryUser().id;
+        final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
+        mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
+        try {
+            UserInfo userInfo = createProfileEvenWhenDisallowedForUser("Managed",
+                    UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+            assertNotNull(userInfo);
+        } finally {
+            mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
+                    primaryUserHandle);
+        }
+    }
+
     @MediumTest
     public void testAddRestrictedProfile() throws Exception {
         UserInfo userInfo = createRestrictedProfile("Profile");
@@ -357,6 +441,14 @@
         switchUser(startUser);
     }
 
+    private boolean isPackageInstalledForUser(String packageName, int userId) {
+        try {
+            return mPackageManager.getPackageInfoAsUser(packageName, 0, userId) != null;
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+
     private void switchUser(int userId) {
         synchronized (mUserSwitchLock) {
             ActivityManager am = getContext().getSystemService(ActivityManager.class);
@@ -401,7 +493,23 @@
     }
 
     private UserInfo createProfileForUser(String name, int flags, int userHandle) {
-        UserInfo profile = mUserManager.createProfileForUser(name, flags, userHandle);
+        return createProfileForUser(name, flags, userHandle, null);
+    }
+
+    private UserInfo createProfileForUser(String name, int flags, int userHandle,
+            String[] disallowedPackages) {
+        UserInfo profile = mUserManager.createProfileForUser(
+                name, flags, userHandle, disallowedPackages);
+        if (profile != null) {
+            usersToRemove.add(profile.id);
+        }
+        return profile;
+    }
+
+    private UserInfo createProfileEvenWhenDisallowedForUser(String name, int flags,
+            int userHandle) {
+        UserInfo profile = mUserManager.createProfileForUserEvenWhenDisallowed(
+                name, flags, userHandle, null);
         if (profile != null) {
             usersToRemove.add(profile.id);
         }
diff --git a/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java b/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java
new file mode 100644
index 0000000..d378b7c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java
@@ -0,0 +1,210 @@
+/**
+ * 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.utils;
+
+import static com.android.server.utils.PriorityDump.dump;
+
+import static org.junit.Assert.assertSame;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.verify;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import com.android.server.utils.PriorityDump.PriorityDumper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+@SmallTest
+@Presubmit
+@RunWith(JUnit4.class)
+public class PriorityDumpTest {
+
+    private static final String[] EMPTY_ARGS = {};
+
+    @Mock
+    private PriorityDumper mDumper;
+    @Mock
+    private PrintWriter mPw;
+
+    private final FileDescriptor mFd = FileDescriptor.err;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testNullArgs() {
+        dump(mDumper, mFd, mPw, null);
+        verify(mDumper).dump(same(mFd), same(mPw), eq(null));
+    }
+
+    @Test
+    public void testNoArgs() {
+        dump(mDumper, mFd, mPw, EMPTY_ARGS);
+        verify(mDumper).dump(same(mFd), same(mPw), same(EMPTY_ARGS));
+    }
+
+    @Test
+    public void testNonPriorityArgs() {
+        final String[] args = {
+                "--dumb_priority"
+        };
+        dump(mDumper, mFd, mPw, args);
+        verify(mDumper).dump(same(mFd), same(mPw), same(args));
+    }
+
+    @Test
+    public void testMissingPriority() {
+        final String[] args = {
+                "--dump_priority"
+        };
+        dump(mDumper, mFd, mPw, args);
+        verify(mDumper).dump(same(mFd), same(mPw), same(args));
+    }
+
+    @Test
+    public void testInvalidPriorityNoExtraArgs() {
+        final String[] args = {
+                "--dump_priority", "SUPER_HIGH"
+        };
+        dump(mDumper, mFd, mPw, args);
+        verify(mDumper).dump(same(mFd), same(mPw), same(args));
+    }
+
+    @Test
+    public void testInvalidPriorityExtraArgs() {
+        final String[] args = {
+                "--dump_priority", "SUPER_HIGH", "--high", "--five"
+        };
+        dump(mDumper, mFd, mPw, args);
+        verify(mDumper).dump(same(mFd), same(mPw), same(args));
+    }
+
+    @Test
+    public void testNoPriorityCallsAllMethods() {
+        final String[] args = {
+                "1", "2", "3"
+        };
+
+        // Cannot use mDumper here because it would mock the dump() call.
+        final FakeDumper fakeDumper = new FakeDumper();
+
+        dump(fakeDumper, mFd, mPw, args);
+
+        assertSame(mFd, fakeDumper.criticalFd);
+        assertSame(mPw, fakeDumper.criticalPw);
+        assertSame(args, fakeDumper.criticalArgs);
+        assertSame(mFd, fakeDumper.highFd);
+        assertSame(mPw, fakeDumper.highPw);
+        assertSame(args, fakeDumper.highArgs);
+        assertSame(mFd, fakeDumper.normalFd);
+        assertSame(mPw, fakeDumper.normalPw);
+        assertSame(args, fakeDumper.normalArgs);
+    }
+
+    @Test
+    public void testCriticalNoExtraArgs() {
+        dump(mDumper, mFd, mPw, new String[] {
+                "--dump_priority", "CRITICAL"
+        });
+        verify(mDumper).dumpCritical(same(mFd), same(mPw), eq(EMPTY_ARGS));
+    }
+
+    @Test
+    public void testCriticalExtraArgs() {
+        dump(mDumper, mFd, mPw, new String[] {
+                "--dump_priority", "CRITICAL", "--high", "--five"
+        });
+        verify(mDumper).dumpCritical(same(mFd), same(mPw), eq(new String[] {
+                "--high", "--five"
+        }));
+    }
+
+    @Test
+    public void testHighNoExtraArgs() {
+        dump(mDumper, mFd, mPw, new String[] {
+                "--dump_priority", "HIGH"
+        });
+        verify(mDumper).dumpHigh(same(mFd), same(mPw), eq(EMPTY_ARGS));
+    }
+
+    @Test
+    public void testHighExtraArgs() {
+        dump(mDumper, mFd, mPw, new String[] {
+                "--dump_priority", "HIGH", "--high", "--five"
+        });
+        verify(mDumper).dumpHigh(same(mFd), same(mPw), eq(new String[] {
+                "--high", "--five"
+        }));
+    }
+
+    @Test
+    public void testNormalNoExtraArgs() {
+        dump(mDumper, mFd, mPw, new String[] {
+                "--dump_priority", "NORMAL"
+        });
+        verify(mDumper).dumpNormal(same(mFd), same(mPw), eq(EMPTY_ARGS));
+    }
+
+    @Test
+    public void testNormalExtraArgs() {
+        dump(mDumper, mFd, mPw, new String[] {
+                "--dump_priority", "NORMAL", "--high", "--five"
+        });
+        verify(mDumper).dumpNormal(same(mFd), same(mPw), eq(new String[] {
+                "--high", "--five"
+        }));
+    }
+
+    private final class FakeDumper implements PriorityDumper {
+
+        String[] criticalArgs, highArgs, normalArgs;
+        FileDescriptor criticalFd, highFd, normalFd;
+        PrintWriter criticalPw, highPw, normalPw;
+
+        @Override
+        public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
+            criticalFd = fd;
+            criticalPw = pw;
+            criticalArgs = args;
+        }
+
+        @Override
+        public void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args) {
+            highFd = fd;
+            highPw = pw;
+            highArgs = args;
+        }
+
+        @Override
+        public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
+            normalFd = fd;
+            normalPw = pw;
+            normalArgs = args;
+        }
+    }
+}
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 7f171fb..0f898e5 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
@@ -303,6 +303,31 @@
 
         WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
         assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
+        assertEquals(null, mWebViewUpdateServiceImpl.getCurrentWebViewPackage());
+
+        // Now install a package
+        String singlePackage = "singlePackage";
+        packages = new WebViewProviderInfo[]{
+            new WebViewProviderInfo(singlePackage, "", true, false, null)};
+        setupWithPackages(packages);
+        setEnabledAndValidPackageInfos(packages);
+
+        mWebViewUpdateServiceImpl.packageStateChanged(singlePackage,
+                WebViewUpdateService.PACKAGE_ADDED, 0);
+
+        checkPreparationPhasesForPackage(singlePackage, 1 /* number of finished preparations */);
+        assertEquals(singlePackage,
+                mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName);
+
+        // Remove the package again
+        mTestSystemImpl.removePackageInfo(singlePackage);
+        mWebViewUpdateServiceImpl.packageStateChanged(singlePackage,
+                WebViewUpdateService.PACKAGE_ADDED, 0);
+
+        // Package removed - ensure our interface states that there is no package
+        response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
+        assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
+        assertEquals(null, mWebViewUpdateServiceImpl.getCurrentWebViewPackage());
     }
 
     public void testFailListingInvalidWebviewPackage() {
@@ -395,7 +420,8 @@
         Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
                 Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
 
-        assertEquals(firstPackage, mWebViewUpdateServiceImpl.getCurrentWebViewPackageName());
+        assertEquals(firstPackage,
+                mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName);
 
         new Thread(new Runnable() {
             @Override
@@ -1243,4 +1269,42 @@
 
         checkPreparationPhasesForPackage(primaryPackage, 3 /* third preparation phase */);
     }
+
+    public void testGetCurrentWebViewPackage() {
+        PackageInfo firstPackage = createPackageInfo("first", true /* enabled */,
+                        true /* valid */, true /* installed */);
+        firstPackage.versionCode = 100;
+        firstPackage.versionName = "first package version";
+        WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+            new WebViewProviderInfo(firstPackage.packageName, "", true, false, null)};
+        setupWithPackages(packages, true);
+        mTestSystemImpl.setPackageInfo(firstPackage);
+
+        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+        Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
+                Mockito.argThat(new IsPackageInfoWithName(firstPackage.packageName)));
+
+        mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
+
+        // Ensure the API is correct before running waitForAndGetProvider
+        assertEquals(firstPackage.packageName,
+                mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName);
+        assertEquals(firstPackage.versionCode,
+                mWebViewUpdateServiceImpl.getCurrentWebViewPackage().versionCode);
+        assertEquals(firstPackage.versionName,
+                mWebViewUpdateServiceImpl.getCurrentWebViewPackage().versionName);
+
+        WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
+        assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
+        assertEquals(firstPackage.packageName, response.packageInfo.packageName);
+
+        // Ensure the API is still correct after running waitForAndGetProvider
+        assertEquals(firstPackage.packageName,
+                mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName);
+        assertEquals(firstPackage.versionCode,
+                mWebViewUpdateServiceImpl.getCurrentWebViewPackage().versionCode);
+        assertEquals(firstPackage.versionName,
+                mWebViewUpdateServiceImpl.getCurrentWebViewPackage().versionName);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 27d9d10..74e8c9d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -76,15 +76,14 @@
     private WindowState createWindow(WindowState parent, int type, WindowToken token) {
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
 
-        return new WindowState(sWm, null, mIWindow, token, parent, 0, 0, attrs, 0,
-                sWm.getDefaultDisplayContentLocked(), 0);
+        return new WindowState(sWm, null, mIWindow, token, parent, 0, 0, attrs, 0, 0);
     }
 
     /* Used so we can gain access to some protected members of the {@link AppWindowToken} class */
     private class TestAppWindowToken extends AppWindowToken {
 
         TestAppWindowToken() {
-            super(sWm, null, false);
+            super(sWm, null, false, sWm.getDefaultDisplayContentLocked());
         }
 
         int getWindowsCount() {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 1259e0f..3df1df9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -58,7 +58,8 @@
     public void setUp() throws Exception {
         final Context context = InstrumentationRegistry.getTargetContext();
         sWm = TestWindowManagerPolicy.getWindowManagerService(context);
-        mWindowToken = new WindowToken(sWm, new Binder(), 0, false);
+        mWindowToken = new WindowToken(sWm, new Binder(), 0, false,
+                sWm.getDefaultDisplayContentLocked());
     }
 
     @Test
@@ -162,7 +163,6 @@
     private WindowState createWindow(WindowState parent, int type) {
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
 
-        return new WindowState(sWm, null, mIWindow, mWindowToken, parent, 0, 0, attrs, 0,
-                sWm.getDefaultDisplayContentLocked(), 0);
+        return new WindowState(sWm, null, mIWindow, mWindowToken, parent, 0, 0, attrs, 0, 0);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
index 3279886..1a4dff9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -157,15 +157,14 @@
     private WindowState createWindow(WindowState parent, int type, WindowToken token) {
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
 
-        return new WindowState(mWm, null, mIWindow, token, parent, 0, 0, attrs, 0,
-                mWm.getDefaultDisplayContentLocked(), 0);
+        return new WindowState(mWm, null, mIWindow, token, parent, 0, 0, attrs, 0, 0);
     }
 
     /* Used so we can gain access to some protected members of the {@link WindowToken} class */
     private class TestWindowToken extends WindowToken {
 
         TestWindowToken() {
-            super(mWm, null, 0, false);
+            super(mWm, null, 0, false, mWm.getDefaultDisplayContentLocked());
         }
 
         int getWindowsCount() {
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 220626a..af8c314 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -84,6 +84,14 @@
     private static final String USB_CONFIG_PROPERTY = "sys.usb.config";
 
     /**
+     * The property which stores the current build type (user/userdebug/eng).
+     */
+    private static final String BUILD_TYPE_PROPERTY = "ro.build.type";
+
+    private static final String BUILD_TYPE_USERDEBUG = "userdebug";
+    private static final String BUILD_TYPE_ENG = "eng";
+
+    /**
      * The non-persistent property which stores the current USB actual state.
      */
     private static final String USB_STATE_PROPERTY = "sys.usb.state";
@@ -109,9 +117,8 @@
     private static final int MSG_SYSTEM_READY = 3;
     private static final int MSG_BOOT_COMPLETED = 4;
     private static final int MSG_USER_SWITCHED = 5;
-    private static final int MSG_SET_USB_DATA_UNLOCKED = 6;
-    private static final int MSG_UPDATE_USER_RESTRICTIONS = 7;
-    private static final int MSG_UPDATE_HOST_STATE = 8;
+    private static final int MSG_UPDATE_USER_RESTRICTIONS = 6;
+    private static final int MSG_UPDATE_HOST_STATE = 7;
 
     private static final int AUDIO_MODE_SOURCE = 1;
 
@@ -291,7 +298,7 @@
 
         if (functions != null) {
             mAccessoryModeRequestTime = SystemClock.elapsedRealtime();
-            setCurrentFunctions(functions);
+            setCurrentFunctions(functions, false);
         }
     }
 
@@ -340,14 +347,27 @@
                 // Restore default functions.
                 mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
                         UsbManager.USB_FUNCTION_NONE);
-                if (UsbManager.USB_FUNCTION_NONE.equals(mCurrentFunctions)) {
-                    mCurrentFunctions = UsbManager.USB_FUNCTION_MTP;
-                }
                 mCurrentFunctionsApplied = mCurrentFunctions.equals(
                         SystemProperties.get(USB_STATE_PROPERTY));
                 mAdbEnabled = UsbManager.containsFunction(getDefaultFunctions(),
                         UsbManager.USB_FUNCTION_ADB);
-                setEnabledFunctions(null, false);
+
+                /**
+                 * Remove MTP from persistent config, to bring usb to a good state
+                 * after fixes to b/31814300. This block can be removed after the update
+                 */
+                String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
+                if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)) {
+                    SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
+                            UsbManager.removeFunction(persisted, UsbManager.USB_FUNCTION_MTP));
+                }
+
+                String buildType = SystemProperties.get(BUILD_TYPE_PROPERTY);
+                if (buildType.equals(BUILD_TYPE_USERDEBUG) || buildType.equals(BUILD_TYPE_ENG)) {
+                    setAdbEnabled(true);
+                }
+
+                setEnabledFunctions(null, false, false);
 
                 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
                 updateState(state);
@@ -379,6 +399,14 @@
             sendMessage(m);
         }
 
+        public void sendMessage(int what, Object arg, boolean arg1) {
+            removeMessages(what);
+            Message m = Message.obtain(this, what);
+            m.obj = arg;
+            m.arg1 = (arg1 ? 1 : 0);
+            sendMessage(m);
+        }
+
         public void updateState(String state) {
             int connected, configured;
 
@@ -443,29 +471,24 @@
             return waitForState(config);
         }
 
-        private void setUsbDataUnlocked(boolean enable) {
-            if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked: " + enable);
-            mUsbDataUnlocked = enable;
-            updateUsbNotification();
-            updateUsbStateBroadcastIfNeeded();
-            setEnabledFunctions(mCurrentFunctions, true);
-        }
-
         private void setAdbEnabled(boolean enable) {
             if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
             if (enable != mAdbEnabled) {
                 mAdbEnabled = enable;
+                String oldFunctions = mCurrentFunctions;
 
-                // Due to the persist.sys.usb.config property trigger, changing adb state requires
-                // persisting default function
-                String oldFunctions = getDefaultFunctions();
-                String newFunctions = applyAdbFunction(oldFunctions);
-                if (!oldFunctions.equals(newFunctions)) {
-                    SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunctions);
+                // Persist the adb setting
+                String newFunction = applyAdbFunction(SystemProperties.get(
+                            USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_NONE));
+                SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY, newFunction);
+
+                // Remove mtp from the config if file transfer is not enabled
+                if (oldFunctions.equals(UsbManager.USB_FUNCTION_MTP) && 
+                        !mUsbDataUnlocked && enable) {
+                    oldFunctions = UsbManager.USB_FUNCTION_NONE;
                 }
 
-                // After persisting them use the lock-down aware function set
-                setEnabledFunctions(mCurrentFunctions, false);
+                setEnabledFunctions(oldFunctions, true, mUsbDataUnlocked);
                 updateAdbNotification();
             }
 
@@ -477,10 +500,17 @@
         /**
          * Evaluates USB function policies and applies the change accordingly.
          */
-        private void setEnabledFunctions(String functions, boolean forceRestart) {
+        private void setEnabledFunctions(String functions, boolean forceRestart,
+                boolean usbDataUnlocked) {
             if (DEBUG) Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
                     + "forceRestart=" + forceRestart);
 
+            if (usbDataUnlocked != mUsbDataUnlocked) {
+                mUsbDataUnlocked = usbDataUnlocked;
+                updateUsbNotification();
+                forceRestart = true;
+            }
+
             // Try to set the enabled functions.
             final String oldFunctions = mCurrentFunctions;
             final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
@@ -517,7 +547,8 @@
         }
 
         private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
-            if (functions == null) {
+            if (functions == null || applyAdbFunction(functions)
+                    .equals(UsbManager.USB_FUNCTION_NONE)) {
                 functions = getDefaultFunctions();
             }
             functions = applyAdbFunction(functions);
@@ -583,7 +614,7 @@
                 // make sure accessory mode is off
                 // and restore default functions
                 Slog.d(TAG, "exited USB accessory mode");
-                setEnabledFunctions(null, false);
+                setEnabledFunctions(null, false, false);
 
                 if (mCurrentAccessory != null) {
                     if (mBootCompleted) {
@@ -600,10 +631,6 @@
             if (mBroadcastedIntent == null) {
                 for (String key : keySet) {
                     if (intent.getBooleanExtra(key, false)) {
-                        // MTP function is enabled by default.
-                        if (UsbManager.USB_FUNCTION_MTP.equals(key)) {
-                            continue;
-                        }
                         return true;
                     }
                 }
@@ -716,10 +743,7 @@
                 case MSG_UPDATE_STATE:
                     mConnected = (msg.arg1 == 1);
                     mConfigured = (msg.arg2 == 1);
-                    if (!mConnected) {
-                        // When a disconnect occurs, relock access to sensitive user data
-                        mUsbDataUnlocked = false;
-                    }
+
                     updateUsbNotification();
                     updateAdbNotification();
                     if (UsbManager.containsFunction(mCurrentFunctions,
@@ -727,7 +751,7 @@
                         updateCurrentAccessory();
                     } else if (!mConnected) {
                         // restore defaults when USB is disconnected
-                        setEnabledFunctions(null, false);
+                        setEnabledFunctions(null, false, false);
                     }
                     if (mBootCompleted) {
                         updateUsbStateBroadcastIfNeeded();
@@ -750,13 +774,10 @@
                     break;
                 case MSG_SET_CURRENT_FUNCTIONS:
                     String functions = (String)msg.obj;
-                    setEnabledFunctions(functions, false);
+                    setEnabledFunctions(functions, false, msg.arg1 == 1);
                     break;
                 case MSG_UPDATE_USER_RESTRICTIONS:
-                    setEnabledFunctions(mCurrentFunctions, false);
-                    break;
-                case MSG_SET_USB_DATA_UNLOCKED:
-                    setUsbDataUnlocked(msg.arg1 == 1);
+                    setEnabledFunctions(mCurrentFunctions, false, mUsbDataUnlocked);
                     break;
                 case MSG_SYSTEM_READY:
                     updateUsbNotification();
@@ -784,8 +805,7 @@
                             Slog.v(TAG, "Current user switched to " + mCurrentUser
                                     + "; resetting USB host stack for MTP or PTP");
                             // avoid leaking sensitive data from previous user
-                            mUsbDataUnlocked = false;
-                            setEnabledFunctions(mCurrentFunctions, true);
+                            setEnabledFunctions(mCurrentFunctions, true, false);
                         }
                         mCurrentUser = msg.arg1;
                     }
@@ -969,14 +989,10 @@
         return UsbManager.containsFunction(SystemProperties.get(USB_CONFIG_PROPERTY), function);
     }
 
-    public void setCurrentFunctions(String functions) {
-        if (DEBUG) Slog.d(TAG, "setCurrentFunctions(" + functions + ")");
-        mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions);
-    }
-
-    public void setUsbDataUnlocked(boolean unlocked) {
-        if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked(" + unlocked + ")");
-        mHandler.sendMessage(MSG_SET_USB_DATA_UNLOCKED, unlocked);
+    public void setCurrentFunctions(String functions, boolean usbDataUnlocked) {
+        if (DEBUG) Slog.d(TAG, "setCurrentFunctions(" + functions + ", " +
+				usbDataUnlocked + ")");
+        mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, usbDataUnlocked);
     }
 
     private void readOemUsbOverrideConfig() {
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index b789e17..af78c05 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -16,6 +16,7 @@
 
 package com.android.server.usb;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index cc0fb8d..e03a14f 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -34,6 +34,7 @@
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbInterface;
 import android.hardware.usb.UsbManager;
+import android.os.AsyncTask;
 import android.os.Environment;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -42,6 +43,7 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.Immutable;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.FastXmlSerializer;
@@ -60,7 +62,9 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import libcore.io.IoUtils;
 
@@ -87,14 +91,24 @@
     private final UserManager mUserManager;
     private final @NonNull UsbSettingsManager mSettingsManager;
 
-    // Maps DeviceFilter to user preferred application package
+    /** Maps DeviceFilter to user preferred application package */
+    @GuardedBy("mLock")
     private final HashMap<DeviceFilter, UserPackage> mDevicePreferenceMap = new HashMap<>();
-    // Maps AccessoryFilter to user preferred application package
+
+    /** Maps AccessoryFilter to user preferred application package */
+    @GuardedBy("mLock")
     private final HashMap<AccessoryFilter, UserPackage> mAccessoryPreferenceMap = new HashMap<>();
 
     private final Object mLock = new Object();
 
     /**
+     * If a async task to persist the mDevicePreferenceMap and mAccessoryPreferenceMap is currently
+     * scheduled.
+     */
+    @GuardedBy("mLock")
+    private boolean mIsWriteSettingsScheduled;
+
+    /**
      * A package of a user.
      */
     @Immutable
@@ -591,6 +605,42 @@
                 });
     }
 
+    /**
+     * Remove all defaults for a user.
+     *
+     * @param userToRemove The user the defaults belong to.
+     */
+    void removeAllDefaultsForUser(@NonNull UserHandle userToRemove) {
+        synchronized (mLock) {
+            boolean needToPersist = false;
+            Iterator<Map.Entry<DeviceFilter, UserPackage>> devicePreferenceIt = mDevicePreferenceMap
+                    .entrySet().iterator();
+            while (devicePreferenceIt.hasNext()) {
+                Map.Entry<DeviceFilter, UserPackage> entry = devicePreferenceIt.next();
+
+                if (entry.getValue().user.equals(userToRemove)) {
+                    devicePreferenceIt.remove();
+                    needToPersist = true;
+                }
+            }
+
+            Iterator<Map.Entry<AccessoryFilter, UserPackage>> accessoryPreferenceIt =
+                    mAccessoryPreferenceMap.entrySet().iterator();
+            while (accessoryPreferenceIt.hasNext()) {
+                Map.Entry<AccessoryFilter, UserPackage> entry = accessoryPreferenceIt.next();
+
+                if (entry.getValue().user.equals(userToRemove)) {
+                    accessoryPreferenceIt.remove();
+                    needToPersist = true;
+                }
+            }
+
+            if (needToPersist) {
+                scheduleWriteSettingsLocked();
+            }
+        }
+    }
+
     private void readPreference(XmlPullParser parser)
             throws XmlPullParserException, IOException {
         String packageName = null;
@@ -657,7 +707,7 @@
                 IoUtils.closeQuietly(fis);
             }
 
-            writeSettingsLocked();
+            scheduleWriteSettingsLocked();
 
             // Success or failure, we delete single-user file
             sSingleUserSettingsFile.delete();
@@ -695,48 +745,68 @@
         }
     }
 
-    private void writeSettingsLocked() {
-        if (DEBUG) Slog.v(TAG, "writeSettingsLocked()");
-
-        FileOutputStream fos = null;
-        try {
-            fos = mSettingsFile.startWrite();
-
-            FastXmlSerializer serializer = new FastXmlSerializer();
-            serializer.setOutput(fos, StandardCharsets.UTF_8.name());
-            serializer.startDocument(null, true);
-            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-            serializer.startTag(null, "settings");
-
-            for (DeviceFilter filter : mDevicePreferenceMap.keySet()) {
-                serializer.startTag(null, "preference");
-                serializer.attribute(null, "package", mDevicePreferenceMap.get(filter).packageName);
-                serializer.attribute(null, "user",
-                        String.valueOf(getSerial(mDevicePreferenceMap.get(filter).user)));
-                filter.write(serializer);
-                serializer.endTag(null, "preference");
-            }
-
-            for (AccessoryFilter filter : mAccessoryPreferenceMap.keySet()) {
-                serializer.startTag(null, "preference");
-                serializer.attribute(null, "package",
-                        mAccessoryPreferenceMap.get(filter).packageName);
-                serializer.attribute(null, "user",
-                        String.valueOf(getSerial(mAccessoryPreferenceMap.get(filter).user)));
-                filter.write(serializer);
-                serializer.endTag(null, "preference");
-            }
-
-            serializer.endTag(null, "settings");
-            serializer.endDocument();
-
-            mSettingsFile.finishWrite(fos);
-        } catch (IOException e) {
-            Slog.e(TAG, "Failed to write settings", e);
-            if (fos != null) {
-                mSettingsFile.failWrite(fos);
-            }
+    /**
+     * Schedule a async task to persist {@link #mDevicePreferenceMap} and
+     * {@link #mAccessoryPreferenceMap}. If a task is already scheduled but not completed, do
+     * nothing as the currently scheduled one will do the work.
+     * <p>Called with {@link #mLock} held.</p>
+     * <p>In the uncommon case that the system crashes in between the scheduling and the write the
+     * update is lost.</p>
+     */
+    private void scheduleWriteSettingsLocked() {
+        if (mIsWriteSettingsScheduled) {
+            return;
+        } else {
+            mIsWriteSettingsScheduled = true;
         }
+
+        AsyncTask.execute(() -> {
+            synchronized (mLock) {
+                FileOutputStream fos = null;
+                try {
+                    fos = mSettingsFile.startWrite();
+
+                    FastXmlSerializer serializer = new FastXmlSerializer();
+                    serializer.setOutput(fos, StandardCharsets.UTF_8.name());
+                    serializer.startDocument(null, true);
+                    serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
+                                    true);
+                    serializer.startTag(null, "settings");
+
+                    for (DeviceFilter filter : mDevicePreferenceMap.keySet()) {
+                        serializer.startTag(null, "preference");
+                        serializer.attribute(null, "package",
+                                mDevicePreferenceMap.get(filter).packageName);
+                        serializer.attribute(null, "user",
+                                String.valueOf(getSerial(mDevicePreferenceMap.get(filter).user)));
+                        filter.write(serializer);
+                        serializer.endTag(null, "preference");
+                    }
+
+                    for (AccessoryFilter filter : mAccessoryPreferenceMap.keySet()) {
+                        serializer.startTag(null, "preference");
+                        serializer.attribute(null, "package",
+                                mAccessoryPreferenceMap.get(filter).packageName);
+                        serializer.attribute(null, "user", String.valueOf(
+                                        getSerial(mAccessoryPreferenceMap.get(filter).user)));
+                        filter.write(serializer);
+                        serializer.endTag(null, "preference");
+                    }
+
+                    serializer.endTag(null, "settings");
+                    serializer.endDocument();
+
+                    mSettingsFile.finishWrite(fos);
+                } catch (IOException e) {
+                    Slog.e(TAG, "Failed to write settings", e);
+                    if (fos != null) {
+                        mSettingsFile.failWrite(fos);
+                    }
+                }
+
+                mIsWriteSettingsScheduled = false;
+            }
+        });
     }
 
     // Checks to see if a package matches a device or accessory.
@@ -1141,7 +1211,7 @@
             }
 
             if (changed) {
-                writeSettingsLocked();
+                scheduleWriteSettingsLocked();
             }
         }
     }
@@ -1178,7 +1248,7 @@
                 }
             }
             if (changed) {
-                writeSettingsLocked();
+                scheduleWriteSettingsLocked();
             }
         }
     }
@@ -1204,7 +1274,7 @@
                 }
             }
             if (changed) {
-                writeSettingsLocked();
+                scheduleWriteSettingsLocked();
             }
         }
     }
@@ -1237,7 +1307,7 @@
 
         synchronized (mLock) {
             if (clearPackageDefaultsLocked(userPackage)) {
-                writeSettingsLocked();
+                scheduleWriteSettingsLocked();
             }
         }
     }
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 02c7214..a87ac9e 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.usb;
 
+import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
@@ -83,7 +84,7 @@
 
         @Override
         public void onStopUser(int userHandle) {
-            mUsbService.onStopUser(userHandle);
+            mUsbService.onStopUser(UserHandle.of(userHandle));
         }
     }
 
@@ -177,10 +178,10 @@
     /**
      * Execute operations when a user is stopped.
      *
-     * @param stoppedUserId The id of the used that is stopped
+     * @param stoppedUser The user that is stopped
      */
-    private void onStopUser(@UserIdInt int stoppedUserId) {
-        mSettingsManager.remove(stoppedUserId);
+    private void onStopUser(@NonNull UserHandle stoppedUser) {
+        mSettingsManager.remove(stoppedUser);
     }
 
     public void systemReady() {
@@ -371,7 +372,7 @@
     }
 
     @Override
-    public void setCurrentFunction(String function) {
+    public void setCurrentFunction(String function, boolean usbDataUnlocked) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
         if (!isSupportedCurrentFunction(function)) {
@@ -381,7 +382,7 @@
         }
 
         if (mDeviceManager != null) {
-            mDeviceManager.setCurrentFunctions(function);
+            mDeviceManager.setCurrentFunctions(function, usbDataUnlocked);
         } else {
             throw new IllegalStateException("USB device mode not supported");
         }
@@ -404,12 +405,6 @@
     }
 
     @Override
-    public void setUsbDataUnlocked(boolean unlocked) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-        mDeviceManager.setUsbDataUnlocked(unlocked);
-    }
-
-    @Override
     public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
         mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index b251d26..24d5f09 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -108,11 +108,26 @@
     /**
      * Remove the settings for a user.
      *
-     * @param userIdToRemove The user o remove
+     * @param userToRemove The user to remove
      */
-    void remove(@UserIdInt int userIdToRemove) {
+    void remove(@NonNull UserHandle userToRemove) {
         synchronized (mSettingsByUser) {
-            mSettingsByUser.remove(userIdToRemove);
+            mSettingsByUser.remove(userToRemove.getIdentifier());
+        }
+
+        synchronized (mSettingsByProfileGroup) {
+            if (mSettingsByProfileGroup.indexOfKey(userToRemove.getIdentifier()) >= 0) {
+                // The user to remove is the parent user of the group. The parent is the last user
+                // that gets removed. All state will be removed with the user
+                mSettingsByProfileGroup.remove(userToRemove.getIdentifier());
+            } else {
+                // We cannot find the parent user of the user that is removed, hence try to remove
+                // it from all profile groups.
+                int numProfileGroups = mSettingsByProfileGroup.size();
+                for (int i = 0; i < numProfileGroups; i++) {
+                    mSettingsByProfileGroup.valueAt(i).removeAllDefaultsForUser(userToRemove);
+                }
+            }
         }
     }
 
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
index 0dcd152..610f9bc 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -29,6 +29,8 @@
 
 import java.util.Locale;
 import java.util.UUID;
+import java.util.List;
+import java.util.ArrayList;
 
 /**
  * Helper to manage the database of the sound models that have been registered on the device.
@@ -40,7 +42,7 @@
     static final boolean DBG = false;
 
     private static final String NAME = "sound_model.db";
-    private static final int VERSION = 5;
+    private static final int VERSION = 6;
 
     public static interface SoundModelContract {
         public static final String TABLE = "sound_model";
@@ -58,15 +60,19 @@
     // Table Create Statement
     private static final String CREATE_TABLE_SOUND_MODEL = "CREATE TABLE "
             + SoundModelContract.TABLE + "("
-            + SoundModelContract.KEY_MODEL_UUID + " TEXT PRIMARY KEY,"
-            + SoundModelContract.KEY_VENDOR_UUID + " TEXT, "
+            + SoundModelContract.KEY_MODEL_UUID + " TEXT,"
+            + SoundModelContract.KEY_VENDOR_UUID + " TEXT,"
             + SoundModelContract.KEY_KEYPHRASE_ID + " INTEGER,"
             + SoundModelContract.KEY_TYPE + " INTEGER,"
             + SoundModelContract.KEY_DATA + " BLOB,"
             + SoundModelContract.KEY_RECOGNITION_MODES + " INTEGER,"
             + SoundModelContract.KEY_LOCALE + " TEXT,"
             + SoundModelContract.KEY_HINT_TEXT + " TEXT,"
-            + SoundModelContract.KEY_USERS + " TEXT" + ")";
+            + SoundModelContract.KEY_USERS + " TEXT,"
+            + "PRIMARY KEY (" + SoundModelContract.KEY_KEYPHRASE_ID + ","
+                              + SoundModelContract.KEY_LOCALE + ","
+                              + SoundModelContract.KEY_USERS + ")"
+            + ")";
 
     public DatabaseHelper(Context context) {
         super(context, NAME, null, VERSION);
@@ -93,6 +99,44 @@
                 oldVersion++;
             }
         }
+        if (oldVersion == 5) {
+            // We need to enforce the new primary key constraint that the
+            // keyphrase id, locale, and users are unique. We have to first pull
+            // everything out of the database, remove duplicates, create the new
+            // table, then push everything back in.
+            String selectQuery = "SELECT * FROM " + SoundModelContract.TABLE;
+            Cursor c = db.rawQuery(selectQuery, null);
+            List<SoundModelRecord> old_records = new ArrayList<SoundModelRecord>();
+            try {
+                if (c.moveToFirst()) {
+                    do {
+                        try {
+                            old_records.add(new SoundModelRecord(5, c));
+                        } catch (Exception e) {
+                            Slog.e(TAG, "Failed to extract V5 record", e);
+                        }
+                    } while (c.moveToNext());
+                }
+            } finally {
+                c.close();
+            }
+            db.execSQL("DROP TABLE IF EXISTS " + SoundModelContract.TABLE);
+            onCreate(db);
+            for (SoundModelRecord record : old_records) {
+                if (!record.violatesV6PrimaryKeyConstraint(old_records)) {
+                    try {
+                        long return_value = record.writeToDatabase(6, db);
+                        if (return_value == -1) {
+                            Slog.e(TAG, "Database write failed " + record.modelUuid + ": "
+                                    + return_value);
+                        }
+                    } catch (Exception e) {
+                        Slog.e(TAG, "Failed to update V6 record " + record.modelUuid, e);
+                    }
+                }
+            }
+            oldVersion++;
+        }
     }
 
     /**
@@ -279,4 +323,73 @@
         }
         return users;
     }
+
+    private static class SoundModelRecord {
+        public final String modelUuid;
+        public final String vendorUuid;
+        public final int keyphraseId;
+        public final int type;
+        public final byte[] data;
+        public final int recognitionModes;
+        public final String locale;
+        public final String hintText;
+        public final String users;
+
+        public SoundModelRecord(int version, Cursor c) {
+            modelUuid = c.getString(c.getColumnIndex(SoundModelContract.KEY_MODEL_UUID));
+            if (version >= 5) {
+                vendorUuid = c.getString(c.getColumnIndex(SoundModelContract.KEY_VENDOR_UUID));
+            } else {
+                vendorUuid = null;
+            }
+            keyphraseId = c.getInt(c.getColumnIndex(SoundModelContract.KEY_KEYPHRASE_ID));
+            type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE));
+            data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
+            recognitionModes = c.getInt(c.getColumnIndex(SoundModelContract.KEY_RECOGNITION_MODES));
+            locale = c.getString(c.getColumnIndex(SoundModelContract.KEY_LOCALE));
+            hintText = c.getString(c.getColumnIndex(SoundModelContract.KEY_HINT_TEXT));
+            users = c.getString(c.getColumnIndex(SoundModelContract.KEY_USERS));
+        }
+
+        // Check to see if this record conflicts with some other record in the list of records.
+        public boolean violatesV6PrimaryKeyConstraint(List<SoundModelRecord> records) {
+            for (SoundModelRecord record : records) {
+                if (this == record) {
+                    continue;
+                }
+                if (keyphraseId == record.keyphraseId
+                        && stringComparisonHelper(locale, record.locale)
+                        && stringComparisonHelper(users, record.users)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public long writeToDatabase(int version, SQLiteDatabase db) {
+            ContentValues values = new ContentValues();
+            values.put(SoundModelContract.KEY_MODEL_UUID, modelUuid);
+            if (version >= 5) {
+                values.put(SoundModelContract.KEY_VENDOR_UUID, vendorUuid);
+            }
+            values.put(SoundModelContract.KEY_KEYPHRASE_ID, keyphraseId);
+            values.put(SoundModelContract.KEY_TYPE, type);
+            values.put(SoundModelContract.KEY_DATA, data);
+            values.put(SoundModelContract.KEY_RECOGNITION_MODES, recognitionModes);
+            values.put(SoundModelContract.KEY_LOCALE, locale);
+            values.put(SoundModelContract.KEY_HINT_TEXT, hintText);
+            values.put(SoundModelContract.KEY_USERS, users);
+
+            return db.insertWithOnConflict(
+                       SoundModelContract.TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
+        }
+
+        // Helper for checking string equality - including the case when they are null.
+        static private boolean stringComparisonHelper(String a, String b) {
+          if (a != null) {
+            return a.equals(b);
+          }
+          return a == b;
+        }
+    }
 }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index a04034e..e8976a7 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1100,7 +1100,7 @@
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
-                pw.println("Permission Denial: can't dump PowerManager from from pid="
+                pw.println("Permission Denial: can't dump voiceinteraction from from pid="
                         + Binder.getCallingPid()
                         + ", uid=" + Binder.getCallingUid());
                 return;
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index a965342..ecda3cd 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -18,9 +18,15 @@
 
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.telecom.Logging.EventManager;
+import android.telecom.Logging.Session;
+import android.telecom.Logging.SessionManager;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.IllegalFormatException;
@@ -31,24 +37,270 @@
  *
  * @hide
  */
-final public class Log {
+public class Log {
 
-    // Generic tag for all Telecom Framework logging
-    private static final String TAG = "TelecomFramework";
+    private static final long EXTENDED_LOGGING_DURATION_MILLIS = 60000 * 30; // 30 minutes
 
-    public static final boolean FORCE_LOGGING = false; /* STOP SHIP if true */
+    private static final int EVENTS_TO_CACHE = 10;
+    private static final int EVENTS_TO_CACHE_DEBUG = 20;
+
+    // Generic tag for all Telecom logging
+    @VisibleForTesting
+    public static String TAG = "TelecomFramework";
+
+    private static final boolean FORCE_LOGGING = false; /* STOP SHIP if true */
     public static final boolean DEBUG = isLoggable(android.util.Log.DEBUG);
     public static final boolean INFO = isLoggable(android.util.Log.INFO);
     public static final boolean VERBOSE = isLoggable(android.util.Log.VERBOSE);
     public static final boolean WARN = isLoggable(android.util.Log.WARN);
     public static final boolean ERROR = isLoggable(android.util.Log.ERROR);
 
+    // Used to synchronize singleton logging lazy initialization
+    private static final Object sSingletonSync = new Object();
+    private static EventManager sEventManager;
+    private static SessionManager sSessionManager;
+
+    /**
+     * Tracks whether user-activated extended logging is enabled.
+     */
+    private static boolean sIsUserExtendedLoggingEnabled = false;
+
+    /**
+     * The time when user-activated extended logging should be ended.  Used to determine when
+     * extended logging should automatically be disabled.
+     */
+    private static long sUserExtendedLoggingStopTime = 0;
+
+    private Log() {
+    }
+
+    public static void d(String prefix, String format, Object... args) {
+        if (sIsUserExtendedLoggingEnabled) {
+            maybeDisableLogging();
+            android.util.Slog.i(TAG, buildMessage(prefix, format, args));
+        } else if (DEBUG) {
+            android.util.Slog.d(TAG, buildMessage(prefix, format, args));
+        }
+    }
+
+    public static void d(Object objectPrefix, String format, Object... args) {
+        if (sIsUserExtendedLoggingEnabled) {
+            maybeDisableLogging();
+            android.util.Slog.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+        } else if (DEBUG) {
+            android.util.Slog.d(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+        }
+    }
+
+    public static void i(String prefix, String format, Object... args) {
+        if (INFO) {
+            android.util.Slog.i(TAG, buildMessage(prefix, format, args));
+        }
+    }
+
+    public static void i(Object objectPrefix, String format, Object... args) {
+        if (INFO) {
+            android.util.Slog.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+        }
+    }
+
+    public static void v(String prefix, String format, Object... args) {
+        if (sIsUserExtendedLoggingEnabled) {
+            maybeDisableLogging();
+            android.util.Slog.i(TAG, buildMessage(prefix, format, args));
+        } else if (VERBOSE) {
+            android.util.Slog.v(TAG, buildMessage(prefix, format, args));
+        }
+    }
+
+    public static void v(Object objectPrefix, String format, Object... args) {
+        if (sIsUserExtendedLoggingEnabled) {
+            maybeDisableLogging();
+            android.util.Slog.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+        } else if (VERBOSE) {
+            android.util.Slog.v(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+        }
+    }
+
+    public static void w(String prefix, String format, Object... args) {
+        if (WARN) {
+            android.util.Slog.w(TAG, buildMessage(prefix, format, args));
+        }
+    }
+
+    public static void w(Object objectPrefix, String format, Object... args) {
+        if (WARN) {
+            android.util.Slog.w(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+        }
+    }
+
+    public static void e(String prefix, Throwable tr, String format, Object... args) {
+        if (ERROR) {
+            android.util.Slog.e(TAG, buildMessage(prefix, format, args), tr);
+        }
+    }
+
+    public static void e(Object objectPrefix, Throwable tr, String format, Object... args) {
+        if (ERROR) {
+            android.util.Slog.e(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
+                    tr);
+        }
+    }
+
+    public static void wtf(String prefix, Throwable tr, String format, Object... args) {
+        android.util.Slog.wtf(TAG, buildMessage(prefix, format, args), tr);
+    }
+
+    public static void wtf(Object objectPrefix, Throwable tr, String format, Object... args) {
+        android.util.Slog.wtf(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
+                tr);
+    }
+
+    public static void wtf(String prefix, String format, Object... args) {
+        String msg = buildMessage(prefix, format, args);
+        android.util.Slog.wtf(TAG, msg, new IllegalStateException(msg));
+    }
+
+    public static void wtf(Object objectPrefix, String format, Object... args) {
+        String msg = buildMessage(getPrefixFromObject(objectPrefix), format, args);
+        android.util.Slog.wtf(TAG, msg, new IllegalStateException(msg));
+    }
+
+    /**
+     * The ease of use methods below only act mostly as proxies to the Session and Event Loggers.
+     * They also control the lazy loaders of the singleton instances, which will never be loaded if
+     * the proxy methods aren't used.
+     *
+     * Please see each method's documentation inside of their respective implementations in the
+     * loggers.
+     */
+
+    public static void startSession(String shortMethodName) {
+        getSessionManager().startSession(shortMethodName, null);
+    }
+
+    public static void startSession(String shortMethodName, String callerIdentification) {
+        getSessionManager().startSession(shortMethodName, callerIdentification);
+    }
+
+    public static Session createSubsession() {
+        return getSessionManager().createSubsession();
+    }
+
+    public static void cancelSubsession(Session subsession) {
+        getSessionManager().cancelSubsession(subsession);
+    }
+
+    public static void continueSession(Session subsession, String shortMethodName) {
+        getSessionManager().continueSession(subsession, shortMethodName);
+    }
+
+    public static void endSession() {
+        getSessionManager().endSession();
+    }
+
+    public static String getSessionId() {
+        // If the Session logger has not been initialized, then there have been no sessions logged.
+        // Don't load it now!
+        synchronized (sSingletonSync) {
+            if (sSessionManager != null) {
+                return getSessionManager().getSessionId();
+            } else {
+                return "";
+            }
+        }
+    }
+
+    public static void addEvent(EventManager.Loggable recordEntry, String event) {
+        getEventManager().event(recordEntry, event, null);
+    }
+
+    public static void addEvent(EventManager.Loggable recordEntry, String event, Object data) {
+        getEventManager().event(recordEntry, event, data);
+    }
+
+    public static void addEvent(EventManager.Loggable recordEntry, String event, String format,
+            Object... args) {
+        getEventManager().event(recordEntry, event, format, args);
+    }
+
+    public static void registerEventListener(EventManager.EventListener e) {
+        getEventManager().registerEventListener(e);
+    }
+
+    public static void addRequestResponsePair(EventManager.TimedEventPair p) {
+        getEventManager().addRequestResponsePair(p);
+    }
+
+    public static void dumpEvents(IndentingPrintWriter pw) {
+        // If the Events logger has not been initialized, then there have been no events logged.
+        // Don't load it now!
+        synchronized (sSingletonSync) {
+            if (sEventManager != null) {
+                getEventManager().dumpEvents(pw);
+            } else {
+                pw.println("No Historical Events Logged.");
+            }
+        }
+    }
+
+    /**
+     * Enable or disable extended telecom logging.
+     *
+     * @param isExtendedLoggingEnabled {@code true} if extended logging should be enabled,
+     *          {@code false} if it should be disabled.
+     */
+    public static void setIsExtendedLoggingEnabled(boolean isExtendedLoggingEnabled) {
+        // If the state hasn't changed, bail early.
+        if (sIsUserExtendedLoggingEnabled == isExtendedLoggingEnabled) {
+            return;
+        }
+
+        if (sEventManager != null) {
+            sEventManager.changeEventCacheSize(isExtendedLoggingEnabled ?
+                    EVENTS_TO_CACHE_DEBUG : EVENTS_TO_CACHE);
+        }
+
+        sIsUserExtendedLoggingEnabled = isExtendedLoggingEnabled;
+        if (sIsUserExtendedLoggingEnabled) {
+            sUserExtendedLoggingStopTime = System.currentTimeMillis()
+                    + EXTENDED_LOGGING_DURATION_MILLIS;
+        } else {
+            sUserExtendedLoggingStopTime = 0;
+        }
+    }
+
+    private static EventManager getEventManager() {
+        // Checking for null again outside of synchronization because we only need to synchronize
+        // during the lazy loading of the events logger. We don't need to synchronize elsewhere.
+        if (sEventManager == null) {
+            synchronized (sSingletonSync) {
+                if (sEventManager == null) {
+                    sEventManager = new EventManager(Log::getSessionId);
+                    return sEventManager;
+                }
+            }
+        }
+        return sEventManager;
+    }
+
+    private static SessionManager getSessionManager() {
+        // Checking for null again outside of synchronization because we only need to synchronize
+        // during the lazy loading of the session logger. We don't need to synchronize elsewhere.
+        if (sSessionManager == null) {
+            synchronized (sSingletonSync) {
+                if (sSessionManager == null) {
+                    sSessionManager = new SessionManager();
+                    return sSessionManager;
+                }
+            }
+        }
+        return sSessionManager;
+    }
+
     private static MessageDigest sMessageDigest;
-    private static final Object sMessageDigestLock = new Object();
 
-    private Log() {}
-
-    public static void initMd5Sum() {
+    static void initMd5Sum() {
         new AsyncTask<Void, Void, Void>() {
             @Override
             public Void doInBackground(Void... args) {
@@ -58,96 +310,69 @@
                 } catch (NoSuchAlgorithmException e) {
                     md = null;
                 }
-                synchronized (sMessageDigestLock) {
-                    sMessageDigest = md;
-                }
+                sMessageDigest = md;
                 return null;
             }
         }.execute();
     }
 
+    public static void setTag(String tag) {
+        TAG = tag;
+    }
+
+    /**
+     * If user enabled extended logging is enabled and the time limit has passed, disables the
+     * extended logging.
+     */
+    private static void maybeDisableLogging() {
+        if (!sIsUserExtendedLoggingEnabled) {
+            return;
+        }
+
+        if (sUserExtendedLoggingStopTime < System.currentTimeMillis()) {
+            sUserExtendedLoggingStopTime = 0;
+            sIsUserExtendedLoggingEnabled = false;
+        }
+    }
+
     public static boolean isLoggable(int level) {
         return FORCE_LOGGING || android.util.Log.isLoggable(TAG, level);
     }
 
-    public static void d(String prefix, String format, Object... args) {
-        if (DEBUG) {
-            android.util.Log.d(TAG, buildMessage(prefix, format, args));
+    public static String piiHandle(Object pii) {
+        if (pii == null || VERBOSE) {
+            return String.valueOf(pii);
         }
-    }
 
-    public static void d(Object objectPrefix, String format, Object... args) {
-        if (DEBUG) {
-            android.util.Log.d(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+        StringBuilder sb = new StringBuilder();
+        if (pii instanceof Uri) {
+            Uri uri = (Uri) pii;
+            String scheme = uri.getScheme();
+
+            if (!TextUtils.isEmpty(scheme)) {
+                sb.append(scheme).append(":");
+            }
+
+            String textToObfuscate = uri.getSchemeSpecificPart();
+            if (PhoneAccount.SCHEME_TEL.equals(scheme)) {
+                for (int i = 0; i < textToObfuscate.length(); i++) {
+                    char c = textToObfuscate.charAt(i);
+                    sb.append(PhoneNumberUtils.isDialable(c) ? "*" : c);
+                }
+            } else if (PhoneAccount.SCHEME_SIP.equals(scheme)) {
+                for (int i = 0; i < textToObfuscate.length(); i++) {
+                    char c = textToObfuscate.charAt(i);
+                    if (c != '@' && c != '.') {
+                        c = '*';
+                    }
+                    sb.append(c);
+                }
+            } else {
+                sb.append(pii(pii));
+            }
         }
-    }
 
-    public static void i(String prefix, String format, Object... args) {
-        if (INFO) {
-            android.util.Log.i(TAG, buildMessage(prefix, format, args));
-        }
-    }
-
-    public static void i(Object objectPrefix, String format, Object... args) {
-        if (INFO) {
-            android.util.Log.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
-        }
-    }
-
-    public static void v(String prefix, String format, Object... args) {
-        if (VERBOSE) {
-            android.util.Log.v(TAG, buildMessage(prefix, format, args));
-        }
-    }
-
-    public static void v(Object objectPrefix, String format, Object... args) {
-        if (VERBOSE) {
-            android.util.Log.v(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
-        }
-    }
-
-    public static void w(String prefix, String format, Object... args) {
-        if (WARN) {
-            android.util.Log.w(TAG, buildMessage(prefix, format, args));
-        }
-    }
-
-    public static void w(Object objectPrefix, String format, Object... args) {
-        if (WARN) {
-            android.util.Log.w(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
-        }
-    }
-
-    public static void e(String prefix, Throwable tr, String format, Object... args) {
-        if (ERROR) {
-            android.util.Log.e(TAG, buildMessage(prefix, format, args), tr);
-        }
-    }
-
-    public static void e(Object objectPrefix, Throwable tr, String format, Object... args) {
-        if (ERROR) {
-            android.util.Log.e(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
-                    tr);
-        }
-    }
-
-    public static void wtf(String prefix, Throwable tr, String format, Object... args) {
-        android.util.Log.wtf(TAG, buildMessage(prefix, format, args), tr);
-    }
-
-    public static void wtf(Object objectPrefix, Throwable tr, String format, Object... args) {
-        android.util.Log.wtf(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
-                tr);
-    }
-
-    public static void wtf(String prefix, String format, Object... args) {
-        String msg = buildMessage(prefix, format, args);
-        android.util.Log.wtf(TAG, msg, new IllegalStateException(msg));
-    }
-
-    public static void wtf(Object objectPrefix, String format, Object... args) {
-        String msg = buildMessage(getPrefixFromObject(objectPrefix), format, args);
-        android.util.Log.wtf(TAG, msg, new IllegalStateException(msg));
+        return sb.toString();
     }
 
     /**
@@ -158,47 +383,18 @@
     public static String pii(Object pii) {
         if (pii == null || VERBOSE) {
             return String.valueOf(pii);
-        } if (pii instanceof Uri) {
-            return piiUri((Uri) pii);
         }
         return "[" + secureHash(String.valueOf(pii).getBytes()) + "]";
     }
 
-    private static String piiUri(Uri handle) {
-        StringBuilder sb = new StringBuilder();
-        String scheme = handle.getScheme();
-        if (!TextUtils.isEmpty(scheme)) {
-            sb.append(scheme).append(":");
-        }
-        String value = handle.getSchemeSpecificPart();
-        if (!TextUtils.isEmpty(value)) {
-            for (int i = 0; i < value.length(); i++) {
-                char c = value.charAt(i);
-                if (PhoneNumberUtils.isStartsPostDial(c)) {
-                    sb.append(c);
-                } else if (PhoneNumberUtils.isDialable(c)) {
-                    sb.append("*");
-                } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
-                    sb.append("*");
-                } else {
-                    sb.append(c);
-                }
-            }
-        }
-        return sb.toString();
-
-    }
-
     private static String secureHash(byte[] input) {
-        synchronized (sMessageDigestLock) {
-            if (sMessageDigest != null) {
-                sMessageDigest.reset();
-                sMessageDigest.update(input);
-                byte[] result = sMessageDigest.digest();
-                return encodeHex(result);
-            } else {
-                return "Uninitialized SHA1";
-            }
+        if (sMessageDigest != null) {
+            sMessageDigest.reset();
+            sMessageDigest.update(input);
+            byte[] result = sMessageDigest.digest();
+            return encodeHex(result);
+        } else {
+            return "Uninitialized SHA1";
         }
     }
 
@@ -221,15 +417,19 @@
     }
 
     private static String buildMessage(String prefix, String format, Object... args) {
+        // Incorporate thread ID and calling method into prefix
+        String sessionName = getSessionId();
+        String sessionPostfix = TextUtils.isEmpty(sessionName) ? "" : ": " + sessionName;
+
         String msg;
         try {
             msg = (args == null || args.length == 0) ? format
                     : String.format(Locale.US, format, args);
         } catch (IllegalFormatException ife) {
-            wtf("Log", ife, "IllegalFormatException: formatString='%s' numArgs=%d", format,
+            e("Log", ife, "IllegalFormatException: formatString='%s' numArgs=%d", format,
                     args.length);
             msg = format + " (An error occurred while formatting the message.)";
         }
-        return String.format(Locale.US, "%s: %s", prefix, msg);
+        return String.format(Locale.US, "%s: %s%s", prefix, msg, sessionPostfix);
     }
 }
diff --git a/telecomm/java/android/telecom/Logging/EventManager.java b/telecomm/java/android/telecom/Logging/EventManager.java
new file mode 100644
index 0000000..0849804
--- /dev/null
+++ b/telecomm/java/android/telecom/Logging/EventManager.java
@@ -0,0 +1,377 @@
+/*
+ * 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.telecom.Logging;
+
+import android.annotation.NonNull;
+import android.telecom.Log;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.IllegalFormatException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * A utility class that provides the ability to define Events that a subsystem deems important, and
+ * then relate those events to other events so that information can be extracted. For example, a
+ * START and FINISH event can be defined and when a START and then FINISH occurs in a sequence, the
+ * time it took to complete that sequence can be saved to be retrieved later.
+ * @hide
+ */
+
+public class EventManager {
+
+    public static final String TAG = "Logging.Events";
+    @VisibleForTesting
+    public static final int DEFAULT_EVENTS_TO_CACHE = 10;  // Arbitrarily chosen.
+
+    public interface Loggable {
+        /**
+         * @return a unique String ID that will allow the Event to be recognized later in the logs.
+         */
+        String getId();
+
+        /**
+         * @return Formatted information about the state that will be printed out later in the logs.
+         */
+        String getDescription();
+    }
+
+    private final Map<Loggable, EventRecord> mCallEventRecordMap = new HashMap<>();
+    private LinkedBlockingQueue<EventRecord> mEventRecords =
+            new LinkedBlockingQueue<>(DEFAULT_EVENTS_TO_CACHE);
+
+    private List<EventListener> mEventListeners = new ArrayList<>();
+
+    public interface EventListener {
+        /**
+         * Notifies the implementation of this method that a new event record has been added.
+         * @param eventRecord Reference to the recently added EventRecord
+         */
+        void eventRecordAdded(EventRecord eventRecord);
+    }
+
+    private SessionManager.ISessionIdQueryHandler mSessionIdHandler;
+    /**
+     * Maps from request events to a list of possible response events. Used to track
+     * end-to-end timing for critical user-facing operations in Telecom.
+     */
+    private final Map<String, List<TimedEventPair>> requestResponsePairs = new HashMap<>();
+
+    private static final Object mSync = new Object();
+
+    /**
+     * Stores the various events.
+     * Also stores all request-response pairs amongst the events.
+     */
+    public static class TimedEventPair {
+        private static final long DEFAULT_TIMEOUT = 3000L;
+
+        String mRequest;
+        String mResponse;
+        String mName;
+        long mTimeoutMillis = DEFAULT_TIMEOUT;
+
+        public TimedEventPair(String request, String response, String name) {
+            this.mRequest = request;
+            this.mResponse = response;
+            this.mName = name;
+        }
+
+        public TimedEventPair(String request, String response, String name, long timeoutMillis) {
+            this.mRequest = request;
+            this.mResponse = response;
+            this.mName = name;
+            this.mTimeoutMillis = timeoutMillis;
+        }
+    }
+
+    public void addRequestResponsePair(TimedEventPair p) {
+        if (requestResponsePairs.containsKey(p.mRequest)) {
+            requestResponsePairs.get(p.mRequest).add(p);
+        } else {
+            ArrayList<TimedEventPair> responses = new ArrayList<>();
+            responses.add(p);
+            requestResponsePairs.put(p.mRequest, responses);
+        }
+    }
+
+    public static class Event {
+        public String eventId;
+        public String sessionId;
+        public long time;
+        public Object data;
+
+        public Event(String eventId, String sessionId, long time, Object data) {
+            this.eventId = eventId;
+            this.sessionId = sessionId;
+            this.time = time;
+            this.data = data;
+        }
+    }
+
+    public class EventRecord {
+        public class EventTiming extends TimedEvent<String> {
+            public String name;
+            public long time;
+
+            public EventTiming(String name, long time) {
+                this.name = name;
+                this.time = time;
+            }
+
+            public String getKey() {
+                return name;
+            }
+
+            public long getTime() {
+                return time;
+            }
+        }
+
+        private class PendingResponse {
+            String requestEventId;
+            long requestEventTimeMillis;
+            long timeoutMillis;
+            String name;
+
+            public PendingResponse(String requestEventId, long requestEventTimeMillis,
+                    long timeoutMillis, String name) {
+                this.requestEventId = requestEventId;
+                this.requestEventTimeMillis = requestEventTimeMillis;
+                this.timeoutMillis = timeoutMillis;
+                this.name = name;
+            }
+        }
+
+        private final DateFormat sDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
+        private final List<Event> mEvents = new LinkedList<>();
+        private final Loggable mRecordEntry;
+
+        public EventRecord(Loggable recordEntry) {
+            mRecordEntry = recordEntry;
+        }
+
+        public Loggable getRecordEntry() {
+            return mRecordEntry;
+        }
+
+        public void addEvent(String event, String sessionId, Object data) {
+            mEvents.add(new Event(event, sessionId, System.currentTimeMillis(), data));
+            Log.i("Event", "RecordEntry %s: %s, %s", mRecordEntry.getId(), event, data);
+        }
+
+        public List<Event> getEvents() {
+            return mEvents;
+        }
+
+        public List<EventTiming> extractEventTimings() {
+            if (mEvents == null) {
+                return Collections.emptyList();
+            }
+
+            LinkedList<EventTiming> result = new LinkedList<>();
+            Map<String, PendingResponse> pendingResponses = new HashMap<>();
+            for (Event event : mEvents) {
+                if (requestResponsePairs.containsKey(event.eventId)) {
+                    // This event expects a response, so add that expected response to the maps
+                    // of pending events.
+                    for (EventManager.TimedEventPair p : requestResponsePairs.get(event.eventId)) {
+                        pendingResponses.put(p.mResponse, new PendingResponse(event.eventId,
+                                event.time, p.mTimeoutMillis, p.mName));
+                    }
+                }
+
+                PendingResponse pendingResponse = pendingResponses.remove(event.eventId);
+                if (pendingResponse != null) {
+                    long elapsedTime = event.time - pendingResponse.requestEventTimeMillis;
+                    if (elapsedTime < pendingResponse.timeoutMillis) {
+                        result.add(new EventTiming(pendingResponse.name, elapsedTime));
+                    }
+                }
+            }
+
+            return result;
+        }
+
+        public void dump(IndentingPrintWriter pw) {
+            pw.print(mRecordEntry.getDescription());
+
+            pw.increaseIndent();
+            for (Event event : mEvents) {
+                pw.print(sDateFormat.format(new Date(event.time)));
+                pw.print(" - ");
+                pw.print(event.eventId);
+                if (event.data != null) {
+                    pw.print(" (");
+                    Object data = event.data;
+
+                    if (data instanceof Loggable) {
+                        // If the data is another Loggable, then change the data to the
+                        // Entry's Event ID instead.
+                        EventRecord record = mCallEventRecordMap.get(data);
+                        if (record != null) {
+                            data = "RecordEntry " + record.mRecordEntry.getId();
+                        }
+                    }
+
+                    pw.print(data);
+                    pw.print(")");
+                }
+                if (!TextUtils.isEmpty(event.sessionId)) {
+                    pw.print(":");
+                    pw.print(event.sessionId);
+                }
+                pw.println();
+            }
+
+            pw.println("Timings (average for this call, milliseconds):");
+            pw.increaseIndent();
+            Map<String, Double> avgEventTimings = EventTiming.averageTimings(extractEventTimings());
+            List<String> eventNames = new ArrayList<>(avgEventTimings.keySet());
+            Collections.sort(eventNames);
+            for (String eventName : eventNames) {
+                pw.printf("%s: %.2f\n", eventName, avgEventTimings.get(eventName));
+            }
+            pw.decreaseIndent();
+            pw.decreaseIndent();
+        }
+    }
+
+    public EventManager(@NonNull SessionManager.ISessionIdQueryHandler l) {
+        mSessionIdHandler = l;
+    }
+
+    public void event(Loggable recordEntry, String event, Object data) {
+        String currentSessionID = mSessionIdHandler.getSessionId();
+
+        if (recordEntry == null) {
+            Log.i(TAG, "Non-call EVENT: %s, %s", event, data);
+            return;
+        }
+        synchronized (mEventRecords) {
+            if (!mCallEventRecordMap.containsKey(recordEntry)) {
+                EventRecord newRecord = new EventRecord(recordEntry);
+                addEventRecord(newRecord);
+            }
+
+            EventRecord record = mCallEventRecordMap.get(recordEntry);
+            record.addEvent(event, currentSessionID, data);
+        }
+    }
+
+    public void event(Loggable recordEntry, String event, String format, Object... args) {
+        String msg;
+        try {
+            msg = (args == null || args.length == 0) ? format
+                    : String.format(Locale.US, format, args);
+        } catch (IllegalFormatException ife) {
+            Log.e("Log", ife, "IllegalFormatException: formatString='%s' numArgs=%d", format,
+                    args.length);
+            msg = format + " (An error occurred while formatting the message.)";
+        }
+
+        event(recordEntry, event, msg);
+    }
+
+    public void dumpEvents(IndentingPrintWriter pw) {
+        pw.println("Historical Events:");
+        pw.increaseIndent();
+        for (EventRecord eventRecord : mEventRecords) {
+            eventRecord.dump(pw);
+        }
+        pw.decreaseIndent();
+    }
+
+    public void changeEventCacheSize(int newSize) {
+
+        // Resize the event queue.
+        LinkedBlockingQueue<EventRecord> oldEventLog = mEventRecords;
+        mEventRecords = new LinkedBlockingQueue<>(newSize);
+        mCallEventRecordMap.clear();
+
+        oldEventLog.forEach((newRecord -> {
+            Loggable recordEntry = newRecord.getRecordEntry();
+            // Copy the existing queue into the new one.
+            // First remove the oldest entry if no new ones exist.
+            if (mEventRecords.remainingCapacity() == 0) {
+                EventRecord record = mEventRecords.poll();
+                if (record != null) {
+                    mCallEventRecordMap.remove(record.getRecordEntry());
+                }
+            }
+
+            // Now add a new entry
+            mEventRecords.add(newRecord);
+            mCallEventRecordMap.put(recordEntry, newRecord);
+
+            // Don't worry about notifying mEventListeners, since we are just resizing the records.
+        }));
+    }
+
+    public void registerEventListener(EventListener e) {
+        if (e != null) {
+            synchronized (mSync) {
+                mEventListeners.add(e);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    public LinkedBlockingQueue<EventRecord> getEventRecords() {
+        return mEventRecords;
+    }
+
+    @VisibleForTesting
+    public Map<Loggable, EventRecord> getCallEventRecordMap() {
+        return mCallEventRecordMap;
+    }
+
+    private void addEventRecord(EventRecord newRecord) {
+        Loggable recordEntry = newRecord.getRecordEntry();
+
+        // First remove the oldest entry if no new ones exist.
+        if (mEventRecords.remainingCapacity() == 0) {
+            EventRecord record = mEventRecords.poll();
+            if (record != null) {
+                mCallEventRecordMap.remove(record.getRecordEntry());
+            }
+        }
+
+        // Now add a new entry
+        mEventRecords.add(newRecord);
+        mCallEventRecordMap.put(recordEntry, newRecord);
+
+        // TODO: Add Implementation of this in Telecom for Analytics
+        synchronized (mSync) {
+            for (EventListener l : mEventListeners) {
+                l.eventRecordAdded(newRecord);
+            }
+        }
+    }
+}
diff --git a/telecomm/java/android/telecom/Logging/Session.java b/telecomm/java/android/telecom/Logging/Session.java
new file mode 100644
index 0000000..510abdd
--- /dev/null
+++ b/telecomm/java/android/telecom/Logging/Session.java
@@ -0,0 +1,250 @@
+/*
+ * 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.telecom.Logging;
+
+import android.annotation.NonNull;
+
+import java.util.ArrayList;
+
+/**
+ * The session that stores information about a thread's point of entry into the Telecom code that
+ * persists until the thread exits Telecom.
+ * @hide
+ */
+public class Session {
+
+    public static final String START_SESSION = "START_SESSION";
+    public static final String CREATE_SUBSESSION = "CREATE_SUBSESSION";
+    public static final String CONTINUE_SUBSESSION = "CONTINUE_SUBSESSION";
+    public static final String END_SUBSESSION = "END_SUBSESSION";
+    public static final String END_SESSION = "END_SESSION";
+
+    /**
+     * Initial value of mExecutionEndTimeMs and the final value of {@link #getLocalExecutionTime()}
+     * if the Session is canceled.
+     */
+    public static final int UNDEFINED = -1;
+
+    private String mSessionId;
+    private String mShortMethodName;
+    private long mExecutionStartTimeMs;
+    private long mExecutionEndTimeMs = UNDEFINED;
+    private Session mParentSession;
+    private ArrayList<Session> mChildSessions;
+    private boolean mIsCompleted = false;
+    private int mChildCounter = 0;
+    // True if this is a subsession that has been started from the same thread as the parent
+    // session. This can happen if Log.startSession(...) is called multiple times on the same
+    // thread in the case of one Telecom entry point method calling another entry point method.
+    // In this case, we can just make this subsession "invisible," but still keep track of it so
+    // that the Log.endSession() calls match up.
+    private boolean mIsStartedFromActiveSession = false;
+    // Optionally provided info about the method/class/component that started the session in order
+    // to make Logging easier. This info will be provided in parentheses along with the session.
+    private String mOwnerInfo;
+
+    public Session(String sessionId, String shortMethodName, long startTimeMs, long threadID,
+            boolean isStartedFromActiveSession, String ownerInfo) {
+        setSessionId(sessionId);
+        setShortMethodName(shortMethodName);
+        mExecutionStartTimeMs = startTimeMs;
+        mParentSession = null;
+        mChildSessions = new ArrayList<>(5);
+        mIsStartedFromActiveSession = isStartedFromActiveSession;
+        mOwnerInfo = ownerInfo;
+    }
+
+    public void setSessionId(@NonNull String sessionId) {
+        if (sessionId == null) {
+            mSessionId = "?";
+        }
+        mSessionId = sessionId;
+    }
+
+    public String getShortMethodName() {
+        return mShortMethodName;
+    }
+
+    public void setShortMethodName(String shortMethodName) {
+        if (shortMethodName == null) {
+            shortMethodName = "";
+        }
+        mShortMethodName = shortMethodName;
+    }
+
+    public void setParentSession(Session parentSession) {
+        mParentSession = parentSession;
+    }
+
+    public void addChild(Session childSession) {
+        if (childSession != null) {
+            mChildSessions.add(childSession);
+        }
+    }
+
+    public void removeChild(Session child) {
+        if (child != null) {
+            mChildSessions.remove(child);
+        }
+    }
+
+    public long getExecutionStartTimeMilliseconds() {
+        return mExecutionStartTimeMs;
+    }
+
+    public void setExecutionStartTimeMs(long startTimeMs) {
+        mExecutionStartTimeMs = startTimeMs;
+    }
+
+    public Session getParentSession() {
+        return mParentSession;
+    }
+
+    public ArrayList<Session> getChildSessions() {
+        return mChildSessions;
+    }
+
+    public boolean isSessionCompleted() {
+        return mIsCompleted;
+    }
+
+    public boolean isStartedFromActiveSession() {
+        return mIsStartedFromActiveSession;
+    }
+
+    // Mark this session complete. This will be deleted by Log when all subsessions are complete
+    // as well.
+    public void markSessionCompleted(long executionEndTimeMs) {
+        mExecutionEndTimeMs = executionEndTimeMs;
+        mIsCompleted = true;
+    }
+
+    public long getLocalExecutionTime() {
+        if (mExecutionEndTimeMs == UNDEFINED) {
+            return UNDEFINED;
+        }
+        return mExecutionEndTimeMs - mExecutionStartTimeMs;
+    }
+
+    public synchronized String getNextChildId() {
+        return String.valueOf(mChildCounter++);
+    }
+
+    // Builds full session id recursively
+    private String getFullSessionId() {
+        // Cache mParentSession locally to prevent a concurrency problem where
+        // Log.endParentSessions() is called while a logging statement is running (Log.i, for
+        // example) and setting mParentSession to null in a different thread after the null check
+        // occurred.
+        Session parentSession = mParentSession;
+        if (parentSession == null) {
+            return mSessionId;
+        } else {
+            return parentSession.getFullSessionId() + "_" + mSessionId;
+        }
+    }
+
+    // Print out the full Session tree from any subsession node
+    public String printFullSessionTree() {
+        // Get to the top of the tree
+        Session topNode = this;
+        while (topNode.getParentSession() != null) {
+            topNode = topNode.getParentSession();
+        }
+        return topNode.printSessionTree();
+    }
+
+    // Recursively move down session tree using DFS, but print out each node when it is reached.
+    public String printSessionTree() {
+        StringBuilder sb = new StringBuilder();
+        printSessionTree(0, sb);
+        return sb.toString();
+    }
+
+    private void printSessionTree(int tabI, StringBuilder sb) {
+        sb.append(toString());
+        for (Session child : mChildSessions) {
+            sb.append("\n");
+            for (int i = 0; i <= tabI; i++) {
+                sb.append("\t");
+            }
+            child.printSessionTree(tabI + 1, sb);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mSessionId != null ? mSessionId.hashCode() : 0;
+        result = 31 * result + (mShortMethodName != null ? mShortMethodName.hashCode() : 0);
+        result = 31 * result + (int) (mExecutionStartTimeMs ^ (mExecutionStartTimeMs >>> 32));
+        result = 31 * result + (int) (mExecutionEndTimeMs ^ (mExecutionEndTimeMs >>> 32));
+        result = 31 * result + (mParentSession != null ? mParentSession.hashCode() : 0);
+        result = 31 * result + (mChildSessions != null ? mChildSessions.hashCode() : 0);
+        result = 31 * result + (mIsCompleted ? 1 : 0);
+        result = 31 * result + mChildCounter;
+        result = 31 * result + (mIsStartedFromActiveSession ? 1 : 0);
+        result = 31 * result + (mOwnerInfo != null ? mOwnerInfo.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Session session = (Session) o;
+
+        if (mExecutionStartTimeMs != session.mExecutionStartTimeMs) return false;
+        if (mExecutionEndTimeMs != session.mExecutionEndTimeMs) return false;
+        if (mIsCompleted != session.mIsCompleted) return false;
+        if (mChildCounter != session.mChildCounter) return false;
+        if (mIsStartedFromActiveSession != session.mIsStartedFromActiveSession) return false;
+        if (mSessionId != null ?
+                !mSessionId.equals(session.mSessionId) : session.mSessionId != null)
+            return false;
+        if (mShortMethodName != null ? !mShortMethodName.equals(session.mShortMethodName)
+                : session.mShortMethodName != null)
+            return false;
+        if (mParentSession != null ? !mParentSession.equals(session.mParentSession)
+                : session.mParentSession != null)
+            return false;
+        if (mChildSessions != null ? !mChildSessions.equals(session.mChildSessions)
+                : session.mChildSessions != null)
+            return false;
+        return mOwnerInfo != null ? mOwnerInfo.equals(session.mOwnerInfo)
+                : session.mOwnerInfo == null;
+
+    }
+
+    @Override
+    public String toString() {
+        if (mParentSession != null && mIsStartedFromActiveSession) {
+            // Log.startSession was called from within another active session. Use the parent's
+            // Id instead of the child to reduce confusion.
+            return mParentSession.toString();
+        } else {
+            StringBuilder methodName = new StringBuilder();
+            methodName.append(mShortMethodName);
+            if (mOwnerInfo != null && !mOwnerInfo.isEmpty()) {
+                methodName.append("(InCall package: ");
+                methodName.append(mOwnerInfo);
+                methodName.append(")");
+            }
+            return methodName.toString() + "@" + getFullSessionId();
+        }
+    }
+}
diff --git a/telecomm/java/android/telecom/Logging/SessionManager.java b/telecomm/java/android/telecom/Logging/SessionManager.java
new file mode 100644
index 0000000..90daee0
--- /dev/null
+++ b/telecomm/java/android/telecom/Logging/SessionManager.java
@@ -0,0 +1,353 @@
+/*
+ * 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.telecom.Logging;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Process;
+import android.provider.Settings;
+import android.util.Base64;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * TODO: Create better Sessions Documentation
+ * @hide
+ */
+
+public class SessionManager {
+
+    // Currently using 3 letters, So don't exceed 64^3
+    private static final long SESSION_ID_ROLLOVER_THRESHOLD = 262144;
+
+    // This parameter can be overridden in Telecom's Timeouts class.
+    public static final long DEFAULT_SESSION_TIMEOUT_MS = 30000L; // 30 seconds
+
+    private static String LOGGING_TAG = "Logging";
+
+    private static final String TIMEOUTS_PREFIX = "telecom.";
+
+    // Synchronized in all method calls
+    private int sCodeEntryCounter = 0;
+    private Context mContext;
+
+    @VisibleForTesting
+    public ConcurrentHashMap<Integer, Session> mSessionMapper = new ConcurrentHashMap<>(100);
+    @VisibleForTesting
+    public Handler mSessionCleanupHandler = new Handler(Looper.getMainLooper());
+    @VisibleForTesting
+    public java.lang.Runnable mCleanStaleSessions = () ->
+            cleanupStaleSessions(getSessionCleanupTimeoutMs());
+
+    // Overridden in LogTest to skip query to ContentProvider
+    private interface ISessionCleanupTimeoutMs {
+        long get();
+    }
+
+    // Overridden in tests to provide test Thread IDs
+    public interface ICurrentThreadId {
+        int get();
+    }
+
+    @VisibleForTesting
+    public ICurrentThreadId mCurrentThreadId = Process::myTid;
+
+    @VisibleForTesting
+    public ISessionCleanupTimeoutMs mSessionCleanupTimeoutMs = () -> {
+        // mContext may be null in some cases, such as testing. For these cases, use the
+        // default value.
+        if (mContext == null) {
+            return DEFAULT_SESSION_TIMEOUT_MS;
+        }
+        return getCleanupTimeout(mContext);
+    };
+
+    // Usage is synchronized on this class.
+    private List<ISessionListener> mSessionListeners = new ArrayList<>();
+
+    public interface ISessionListener {
+        /**
+         * This method is run when a full Session has completed.
+         * @param sessionName The name of the Session that has completed.
+         * @param timeMs The time it took to complete in ms.
+         */
+        void sessionComplete(String sessionName, long timeMs);
+    }
+
+    public interface ISessionIdQueryHandler {
+        String getSessionId();
+    }
+
+    public void setContext(Context context) {
+        mContext = context;
+    }
+
+    public SessionManager() {
+    }
+
+    private long getSessionCleanupTimeoutMs() {
+        return mSessionCleanupTimeoutMs.get();
+    }
+
+    private synchronized void resetStaleSessionTimer() {
+        mSessionCleanupHandler.removeCallbacksAndMessages(null);
+        // Will be null in Log Testing
+        if (mCleanStaleSessions != null) {
+            mSessionCleanupHandler.postDelayed(mCleanStaleSessions, getSessionCleanupTimeoutMs());
+        }
+    }
+
+    /**
+     * Call at an entry point to the Telecom code to track the session. This code must be
+     * accompanied by a Log.endSession().
+     */
+    public synchronized void startSession(String shortMethodName,
+            String callerIdentification) {
+        resetStaleSessionTimer();
+        int threadId = getCallingThreadId();
+        Session activeSession = mSessionMapper.get(threadId);
+        // We have called startSession within an active session that has not ended... Register this
+        // session as a subsession.
+        if (activeSession != null) {
+            Session childSession = createSubsession(true);
+            continueSession(childSession, shortMethodName);
+            return;
+        }
+        Session newSession = new Session(getNextSessionID(), shortMethodName,
+                System.currentTimeMillis(), threadId, false, callerIdentification);
+        mSessionMapper.put(threadId, newSession);
+
+        android.util.Slog.v(LOGGING_TAG, Session.START_SESSION);
+    }
+
+
+    /**
+     * Notifies the logging system that a subsession will be run at a later point and
+     * allocates the resources. Returns a session object that must be used in
+     * Log.continueSession(...) to start the subsession.
+     */
+    public Session createSubsession() {
+        return createSubsession(false);
+    }
+
+    private synchronized Session createSubsession(boolean isStartedFromActiveSession) {
+        int threadId = getCallingThreadId();
+        Session threadSession = mSessionMapper.get(threadId);
+        if (threadSession == null) {
+            android.util.Slog.d(LOGGING_TAG, "Log.createSubsession was called with no session " +
+                    "active.");
+            return null;
+        }
+        // Start execution time of the session will be overwritten in continueSession(...).
+        Session newSubsession = new Session(threadSession.getNextChildId(),
+                threadSession.getShortMethodName(), System.currentTimeMillis(), threadId,
+                isStartedFromActiveSession, null);
+        threadSession.addChild(newSubsession);
+        newSubsession.setParentSession(threadSession);
+
+        if (!isStartedFromActiveSession) {
+            android.util.Slog.v(LOGGING_TAG, Session.CREATE_SUBSESSION + " " +
+                    newSubsession.toString());
+        } else {
+            android.util.Slog.v(LOGGING_TAG, Session.CREATE_SUBSESSION +
+                    " (Invisible subsession)");
+        }
+        return newSubsession;
+    }
+
+    /**
+     * Cancels a subsession that had Log.createSubsession() called on it, but will never have
+     * Log.continueSession(...) called on it due to an error. Allows the subsession to be cleaned
+     * gracefully instead of being removed by the mSessionCleanupHandler forcefully later.
+     */
+    public synchronized void cancelSubsession(Session subsession) {
+        if (subsession == null) {
+            return;
+        }
+
+        subsession.markSessionCompleted(Session.UNDEFINED);
+        endParentSessions(subsession);
+    }
+
+    /**
+     * Starts the subsession that was created in Log.CreateSubsession. The Log.endSession() method
+     * must be called at the end of this method. The full session will complete when all
+     * subsessions are completed.
+     */
+    public synchronized void continueSession(Session subsession, String shortMethodName) {
+        if (subsession == null) {
+            return;
+        }
+        resetStaleSessionTimer();
+        String callingMethodName = subsession.getShortMethodName();
+        subsession.setShortMethodName(callingMethodName + "->" + shortMethodName);
+        subsession.setExecutionStartTimeMs(System.currentTimeMillis());
+        Session parentSession = subsession.getParentSession();
+        if (parentSession == null) {
+            android.util.Slog.d(LOGGING_TAG, "Log.continueSession was called with no session " +
+                    "active for method " + shortMethodName);
+            return;
+        }
+
+        mSessionMapper.put(getCallingThreadId(), subsession);
+        if (!subsession.isStartedFromActiveSession()) {
+            android.util.Slog.v(LOGGING_TAG, Session.CONTINUE_SUBSESSION);
+        } else {
+            android.util.Slog.v(LOGGING_TAG, Session.CONTINUE_SUBSESSION +
+                    " (Invisible Subsession) with Method " + shortMethodName);
+        }
+    }
+
+    /**
+     * Ends the current session/subsession. Must be called after a Log.startSession(...) and
+     * Log.continueSession(...) call.
+     */
+    public synchronized void endSession() {
+        int threadId = getCallingThreadId();
+        Session completedSession = mSessionMapper.get(threadId);
+        if (completedSession == null) {
+            android.util.Slog.w(LOGGING_TAG, "Log.endSession was called with no session active.");
+            return;
+        }
+
+        completedSession.markSessionCompleted(System.currentTimeMillis());
+        if (!completedSession.isStartedFromActiveSession()) {
+            android.util.Slog.v(LOGGING_TAG, Session.END_SUBSESSION + " (dur: " +
+                    completedSession.getLocalExecutionTime() + " mS)");
+        } else {
+            android.util.Slog.v(LOGGING_TAG, Session.END_SUBSESSION +
+                    " (Invisible Subsession) (dur: " + completedSession.getLocalExecutionTime() +
+                    " ms)");
+        }
+        // Remove after completed so that reference still exists for logging the end events
+        Session parentSession = completedSession.getParentSession();
+        mSessionMapper.remove(threadId);
+        endParentSessions(completedSession);
+        // If this subsession was started from a parent session using Log.startSession, return the
+        // ThreadID back to the parent after completion.
+        if (parentSession != null && !parentSession.isSessionCompleted() &&
+                completedSession.isStartedFromActiveSession()) {
+            mSessionMapper.put(threadId, parentSession);
+        }
+    }
+
+    // Recursively deletes all complete parent sessions of the current subsession if it is a leaf.
+    private void endParentSessions(Session subsession) {
+        // Session is not completed or not currently a leaf, so we can not remove because a child is
+        // still running
+        if (!subsession.isSessionCompleted() || subsession.getChildSessions().size() != 0) {
+            return;
+        }
+
+        Session parentSession = subsession.getParentSession();
+        if (parentSession != null) {
+            subsession.setParentSession(null);
+            parentSession.removeChild(subsession);
+            endParentSessions(parentSession);
+        } else {
+            // All of the subsessions have been completed and it is time to report on the full
+            // running time of the session.
+            long fullSessionTimeMs =
+                    System.currentTimeMillis() - subsession.getExecutionStartTimeMilliseconds();
+            android.util.Slog.d(LOGGING_TAG, Session.END_SESSION + " (dur: " + fullSessionTimeMs
+                    + " ms): " + subsession.toString());
+            // TODO: Add analytics hook
+            for (ISessionListener l : mSessionListeners) {
+                l.sessionComplete(subsession.getShortMethodName(), fullSessionTimeMs);
+            }
+        }
+    }
+
+    public String getSessionId() {
+        Session currentSession = mSessionMapper.get(getCallingThreadId());
+        return currentSession != null ? currentSession.toString() : "";
+    }
+
+    public synchronized void registerSessionListener(ISessionListener l) {
+        if (l != null) {
+            mSessionListeners.add(l);
+        }
+    }
+
+    private synchronized String getNextSessionID() {
+        Integer nextId = sCodeEntryCounter++;
+        if (nextId >= SESSION_ID_ROLLOVER_THRESHOLD) {
+            restartSessionCounter();
+            nextId = sCodeEntryCounter++;
+        }
+        return getBase64Encoding(nextId);
+    }
+
+    @VisibleForTesting
+    public synchronized void restartSessionCounter() {
+        sCodeEntryCounter = 0;
+    }
+
+    @VisibleForTesting
+    public String getBase64Encoding(int number) {
+        byte[] idByteArray = ByteBuffer.allocate(4).putInt(number).array();
+        idByteArray = Arrays.copyOfRange(idByteArray, 2, 4);
+        return Base64.encodeToString(idByteArray, Base64.NO_WRAP | Base64.NO_PADDING);
+    }
+
+    public int getCallingThreadId() {
+        return mCurrentThreadId.get();
+    }
+
+    @VisibleForTesting
+    private synchronized void cleanupStaleSessions(long timeoutMs) {
+        String logMessage = "Stale Sessions Cleaned:\n";
+        boolean isSessionsStale = false;
+        long currentTimeMs = System.currentTimeMillis();
+        // Remove references that are in the Session Mapper (causing GC to occur) on
+        // sessions that are lasting longer than LOGGING_SESSION_TIMEOUT_MS.
+        // If this occurs, then there is most likely a Session active that never had
+        // Log.endSession called on it.
+        for (Iterator<ConcurrentHashMap.Entry<Integer, Session>> it =
+             mSessionMapper.entrySet().iterator(); it.hasNext(); ) {
+            ConcurrentHashMap.Entry<Integer, Session> entry = it.next();
+            Session session = entry.getValue();
+            if (currentTimeMs - session.getExecutionStartTimeMilliseconds() > timeoutMs) {
+                it.remove();
+                logMessage += session.printFullSessionTree() + "\n";
+                isSessionsStale = true;
+            }
+        }
+        if (isSessionsStale) {
+            android.util.Slog.w(LOGGING_TAG, logMessage);
+        } else {
+            android.util.Slog.v(LOGGING_TAG, "No stale logging sessions needed to be cleaned...");
+        }
+    }
+
+    /**
+     * Returns the amount of time after a Logging session has been started that Telecom is set to
+     * perform a sweep to check and make sure that the session is still not incomplete (stale).
+     */
+    private long getCleanupTimeout(Context context) {
+        return Settings.Secure.getLong(context.getContentResolver(), TIMEOUTS_PREFIX +
+                "stale_session_cleanup_timeout_millis", DEFAULT_SESSION_TIMEOUT_MS);
+    }
+}
diff --git a/telecomm/java/android/telecom/Logging/TimedEvent.java b/telecomm/java/android/telecom/Logging/TimedEvent.java
new file mode 100644
index 0000000..6785e92
--- /dev/null
+++ b/telecomm/java/android/telecom/Logging/TimedEvent.java
@@ -0,0 +1,50 @@
+/*
+ * 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.telecom.Logging;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @hide
+ */
+public abstract class TimedEvent<T> {
+    public abstract long getTime();
+    public abstract T getKey();
+
+    public static <T> Map<T, Double> averageTimings(Collection<? extends TimedEvent<T>> events) {
+        HashMap<T, Integer> counts = new HashMap<>();
+        HashMap<T, Double> result = new HashMap<>();
+
+        for (TimedEvent<T> entry : events) {
+            if (counts.containsKey(entry.getKey())) {
+                counts.put(entry.getKey(), counts.get(entry.getKey()) + 1);
+                result.put(entry.getKey(), result.get(entry.getKey()) + entry.getTime());
+            } else {
+                counts.put(entry.getKey(), 1);
+                result.put(entry.getKey(), (double) entry.getTime());
+            }
+        }
+
+        for (Map.Entry<T, Double> entry : result.entrySet()) {
+            result.put(entry.getKey(), entry.getValue() / counts.get(entry.getKey()));
+        }
+
+        return result;
+    }
+}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index d5bc45e..04d680e 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -57,6 +57,13 @@
     // system image, that can be added in packages/apps/CarrierConfig.
 
     /**
+     * This flag specifies whether VoLTE availability is based on provisioning. By default this is
+     * false.
+     */
+    public static final String
+            KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
+
+    /**
      * Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED
      * events from the Sim.
      * If true, this will prevent the IccNetworkDepersonalizationPanel from being shown, and
@@ -214,6 +221,14 @@
             KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
 
     /**
+     * List of RIL radio technologies (See {@link ServiceState} {@code RIL_RADIO_TECHNOLOGY_*}
+     * constants) which support only a single data connection at a time. Some carriers do not
+     * support multiple pdp on UMTS.
+     */
+    public static final String
+            KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
+
+    /**
      * Override the platform's notion of a network operator being considered roaming.
      * Value is string array of MCCMNCs to be considered roaming for 3GPP RATs.
      */
@@ -753,6 +768,16 @@
     public static final String KEY_CARRIER_ADDITIONAL_CBS_CHANNELS_STRINGS =
             "carrier_additional_cbs_channels_strings";
 
+    /**
+      * Indicates whether STK LAUNCH_BROWSER command is disabled.
+      * If {@code true}, then the browser will not be launched
+      * on UI for the LAUNCH_BROWSER STK command.
+      * @hide
+      */
+    public static final String KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL =
+            "stk_disable_launch_browser_bool";
+
+
     // These variables are used by the MMS service and exposed through another API, {@link
     // SmsManager}. The variable names and string values are copied from there.
     public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
@@ -1088,6 +1113,8 @@
         sDefaults.putBoolean(KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL, false);
         sDefaults.putBoolean(KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
         sDefaults.putBoolean(KEY_HIDE_SIM_LOCK_SETTINGS_BOOL, false);
+
+        sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false);
         sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false);
         sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
         sDefaults.putBoolean(KEY_PREFER_2G_BOOL, true);
@@ -1141,6 +1168,15 @@
         sDefaults.putStringArray(KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
                 new String[]{"default", "mms", "dun", "supl"});
 
+        sDefaults.putIntArray(KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY,
+                new int[]{
+                    4, /* IS95A */
+                    5, /* IS95B */
+                    6, /* 1xRTT */
+                    7, /* EVDO_0 */
+                    8, /* EVDO_A */
+                    12 /* EVDO_B */
+                });
         sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
@@ -1229,6 +1265,7 @@
         sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false);
         sDefaults.putStringArray(FILTERED_CNAP_NAMES_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
+        sDefaults.putBoolean(KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL, false);
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index 05cb31e..d4104bd 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -176,13 +176,13 @@
                     // However, if there is any code that this Handler calls (such as in
                     // super.handleMessage) that DOES place unexpected messages on the
                     // queue, then we need pass these messages on.
-                    if (DBG) Rlog.d(LOG_TAG, "Unexpected command (CookieWrapper is null): " + msg.what +
+                    Rlog.i(LOG_TAG, "Unexpected command (CookieWrapper is null): " + msg.what +
                             " ignored by CallerInfoWorkerHandler, passing onto parent.");
 
                     super.handleMessage(msg);
                 } else {
 
-                    if (DBG) Rlog.d(LOG_TAG, "Processing event: " + cw.event + " token (arg1): " + msg.arg1 +
+                    Rlog.d(LOG_TAG, "Processing event: " + cw.event + " token (arg1): " + msg.arg1 +
                         " command: " + msg.what + " query URI: " + sanitizeUriToString(args.uri));
 
                     switch (cw.event) {
@@ -239,7 +239,7 @@
          */
         @Override
         protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
-            if (DBG) Rlog.d(LOG_TAG, "##### onQueryComplete() #####   query complete for token: " + token);
+            Rlog.d(LOG_TAG, "##### onQueryComplete() #####   query complete for token: " + token);
 
             //get the cookie and notify the listener.
             CookieWrapper cw = (CookieWrapper) cookie;
@@ -248,7 +248,7 @@
                 // from within this code.
                 // However, if there is any code that calls this method, we should
                 // check the parameters to make sure they're viable.
-                if (DBG) Rlog.d(LOG_TAG, "Cookie is null, ignoring onQueryComplete() request.");
+                Rlog.i(LOG_TAG, "Cookie is null, ignoring onQueryComplete() request.");
                 if (cursor != null) {
                     cursor.close();
                 }
@@ -333,9 +333,11 @@
 
             //notify the listener that the query is complete.
             if (cw.listener != null) {
-                if (DBG) Rlog.d(LOG_TAG, "notifying listener: " + cw.listener.getClass().toString() +
+                Rlog.d(LOG_TAG, "notifying listener: " + cw.listener.getClass().toString() +
                              " for token: " + token + mCallerInfo);
                 cw.listener.onQueryComplete(token, cw.cookie, mCallerInfo);
+            } else {
+                Rlog.w(LOG_TAG, "There is no listener to notify for this query.");
             }
 
             if (cursor != null) {
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index a91e9be..891b8a1a 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -462,4 +462,5 @@
     int RIL_UNSOL_STK_CC_ALPHA_NOTIFY = 1044;
     int RIL_UNSOL_LCEDATA_RECV = 1045;
     int RIL_UNSOL_PCO_DATA = 1046;
+    int RIL_UNSOL_MODEM_RESTART = 1047;
 }
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index a4aab7c..da27ea9 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -87,6 +87,11 @@
     }
 
     private Test[] mTests = new Test[] {
+            new Test("cancel all") {
+                public void run() {
+                    mNM.cancelAll();
+                }
+            },
             new Test("Phone call") {
                 public void run()
                 {
diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk
index f65d109..be9a541 100644
--- a/tests/UiBench/Android.mk
+++ b/tests/UiBench/Android.mk
@@ -2,6 +2,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := 24
+LOCAL_MIN_SDK_VERSION := 21
 
 # omit gradle 'build' dir
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml
index cb5f6c7..29154aa 100644
--- a/tests/UiBench/AndroidManifest.xml
+++ b/tests/UiBench/AndroidManifest.xml
@@ -102,10 +102,18 @@
         <activity
             android:name=".SlowBindRecyclerViewActivity"
             android:label="General/Slow Bind RecyclerView" >
-        <intent-filter>
-            <action android:name="android.intent.action.MAIN" />
-            <category android:name="com.android.test.uibench.TEST" />
-        </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.uibench.TEST" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".SlowNestedRecyclerViewActivity"
+            android:label="General/Slow Nested RecyclerView" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.uibench.TEST" />
+            </intent-filter>
         </activity>
         <activity
             android:name=".ActivityTransition"
@@ -141,6 +149,14 @@
                 <category android:name="com.android.test.uibench.TEST" />
             </intent-filter>
         </activity>
+        <activity
+            android:name=".RenderingJitter"
+            android:label="Rendering/Jitter" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.uibench.TEST" />
+            </intent-filter>
+        </activity>
 
         <!-- Inflation -->
         <activity
diff --git a/tests/UiBench/res/layout/rendering_jitter.xml b/tests/UiBench/res/layout/rendering_jitter.xml
new file mode 100644
index 0000000..aaa7551
--- /dev/null
+++ b/tests/UiBench/res/layout/rendering_jitter.xml
@@ -0,0 +1,56 @@
+<?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">
+
+    <TextView android:id="@+id/jitter_mma"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="true" />
+
+    <TextView android:id="@+id/totalish_mma"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="true" />
+
+    <TextView android:id="@+id/ui_frametime_mma"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="true" />
+
+    <TextView android:id="@+id/rt_frametime_mma"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="true" />
+
+    <TextView android:id="@+id/total_mma"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="true" />
+
+    <View android:layout_width="match_parent"
+        android:layout_height="0px"
+        android:layout_weight="1" />
+
+    <view class="com.android.test.uibench.RenderingJitter$PointGraphView"
+        android:id="@+id/graph"
+        android:layout_height="200dp"
+        android:layout_width="match_parent" />
+
+</LinearLayout>
diff --git a/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java b/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java
new file mode 100644
index 0000000..e2a9bcb
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java
@@ -0,0 +1,366 @@
+/*
+ * 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.test.uibench;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.FrameMetrics;
+import android.view.View;
+import android.view.Window;
+import android.view.Window.OnFrameMetricsAvailableListener;
+import android.view.animation.AnimationUtils;
+import android.widget.TextView;
+
+public class RenderingJitter extends Activity {
+    private TextView mJitterReport;
+    private TextView mUiFrameTimeReport;
+    private TextView mRenderThreadTimeReport;
+    private TextView mTotalFrameTimeReport;
+    private TextView mMostlyTotalFrameTimeReport;
+    private PointGraphView mGraph;
+
+    private static Handler sMetricsHandler;
+    static {
+        HandlerThread thread = new HandlerThread("frameMetricsListener");
+        thread.start();
+        sMetricsHandler = new Handler(thread.getLooper());
+    }
+
+    private Handler mUpdateHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case R.id.jitter_mma:
+                    mJitterReport.setText((CharSequence) msg.obj);
+                    break;
+                case R.id.totalish_mma:
+                    mMostlyTotalFrameTimeReport.setText((CharSequence) msg.obj);
+                    break;
+                case R.id.ui_frametime_mma:
+                    mUiFrameTimeReport.setText((CharSequence) msg.obj);
+                    break;
+                case R.id.rt_frametime_mma:
+                    mRenderThreadTimeReport.setText((CharSequence) msg.obj);
+                    break;
+                case R.id.total_mma:
+                    mTotalFrameTimeReport.setText((CharSequence) msg.obj);
+                    break;
+                case R.id.graph:
+                    mGraph.addJitterSample(msg.arg1, msg.arg2);
+                    break;
+            }
+        }
+    };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.rendering_jitter);
+        View content = findViewById(android.R.id.content);
+        content.setBackground(new AnimatedBackgroundDrawable());
+        content.setKeepScreenOn(true);
+        mJitterReport = (TextView) findViewById(R.id.jitter_mma);
+        mMostlyTotalFrameTimeReport = (TextView) findViewById(R.id.totalish_mma);
+        mUiFrameTimeReport = (TextView) findViewById(R.id.ui_frametime_mma);
+        mRenderThreadTimeReport = (TextView) findViewById(R.id.rt_frametime_mma);
+        mTotalFrameTimeReport = (TextView) findViewById(R.id.total_mma);
+        mGraph = (PointGraphView) findViewById(R.id.graph);
+        mJitterReport.setText("abcdefghijklmnopqrstuvwxyz");
+        mMostlyTotalFrameTimeReport.setText("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+        mUiFrameTimeReport.setText("0123456789");
+        mRenderThreadTimeReport.setText(",.!()[]{};");
+        getWindow().addOnFrameMetricsAvailableListener(mMetricsListener, sMetricsHandler);
+    }
+
+    public static final class PointGraphView extends View {
+        private static final float[] JITTER_LINES_MS = {
+                .5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 5.0f
+        };
+        private static final String[] JITTER_LINES_LABELS = makeLabels(JITTER_LINES_MS);
+        private static final int[] JITTER_LINES_COLORS = new int[] {
+                0xFF00E676, 0xFFFFF176, 0xFFFDD835, 0xFFFBC02D, 0xFFF9A825,
+                0xFFF57F17, 0xFFDD2C00
+        };
+        private Paint mPaint = new Paint();
+        private float[] mJitterYs = new float[JITTER_LINES_MS.length];
+        private float mLabelWidth;
+        private float mLabelHeight;
+        private float mDensity;
+        private float mGraphScale;
+        private float mGraphMaxMs;
+
+        private float[] mJitterPoints;
+        private float[] mJitterAvgPoints;
+
+        public PointGraphView(Context context, AttributeSet attrs) {
+            super(context, attrs);
+            setWillNotDraw(false);
+            mDensity = context.getResources().getDisplayMetrics().density;
+            mPaint.setTextSize(dp(10));
+            Rect textBounds = new Rect();
+            mPaint.getTextBounds("8.8", 0, 3, textBounds);
+            mLabelWidth = textBounds.width() + dp(2);
+            mLabelHeight = textBounds.height();
+        }
+
+        public void addJitterSample(int jitterUs, int jitterUsAvg) {
+            for (int i = 1; i < mJitterPoints.length - 2; i += 2) {
+                mJitterPoints[i] = mJitterPoints[i + 2];
+                mJitterAvgPoints[i] = mJitterAvgPoints[i + 2];
+            }
+            mJitterPoints[mJitterPoints.length - 1] =
+                    getHeight() - mGraphScale * (jitterUs / 1000.0f);
+            mJitterAvgPoints[mJitterAvgPoints.length - 1] =
+                    getHeight() - mGraphScale * (jitterUsAvg / 1000.0f);
+            invalidate();
+        }
+
+        private float dp(float dp) {
+            return mDensity * dp;
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            canvas.drawColor(0x90000000);
+            int h = getHeight();
+            int w = getWidth();
+            mPaint.setColor(Color.WHITE);
+            mPaint.setStrokeWidth(dp(1));
+            canvas.drawLine(mLabelWidth, 0, mLabelWidth, h, mPaint);
+            for (int i = 0; i < JITTER_LINES_LABELS.length; i++) {
+                canvas.drawText(JITTER_LINES_LABELS[i],
+                        0, (float) Math.floor(mJitterYs[i] + mLabelHeight * .5f), mPaint);
+            }
+            for (int i = 0; i < JITTER_LINES_LABELS.length; i++) {
+                mPaint.setColor(JITTER_LINES_COLORS[i]);
+                canvas.drawLine(mLabelWidth, mJitterYs[i], w, mJitterYs[i], mPaint);
+            }
+            mPaint.setStrokeWidth(dp(2));
+            mPaint.setColor(Color.WHITE);
+            canvas.drawPoints(mJitterPoints, mPaint);
+            mPaint.setColor(0xFF2196F3);
+            canvas.drawPoints(mJitterAvgPoints, mPaint);
+        }
+
+        @Override
+        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+            super.onSizeChanged(w, h, oldw, oldh);
+            int graphWidth = (int) ((w - mLabelWidth - dp(1)) / mDensity);
+            float[] oldJitterPoints = mJitterPoints;
+            float[] oldJitterAvgPoints = mJitterAvgPoints;
+            mJitterPoints = new float[graphWidth * 2];
+            mJitterAvgPoints = new float[graphWidth * 2];
+            for (int i = 0; i < mJitterPoints.length; i += 2) {
+                mJitterPoints[i] = mLabelWidth + (i / 2 + 1) * mDensity;
+                mJitterAvgPoints[i] = mJitterPoints[i];
+            }
+            if (oldJitterPoints != null) {
+                int newIndexShift = Math.max(mJitterPoints.length - oldJitterPoints.length, 0);
+                int oldIndexShift = oldJitterPoints.length - mJitterPoints.length;
+                for (int i = 1 + newIndexShift; i < mJitterPoints.length; i += 2) {
+                    mJitterPoints[i] = oldJitterPoints[i + oldIndexShift];
+                    mJitterAvgPoints[i] = oldJitterAvgPoints[i + oldIndexShift];
+                }
+            }
+            mGraphMaxMs = JITTER_LINES_MS[JITTER_LINES_MS.length - 1] + .5f;
+            mGraphScale = (h / mGraphMaxMs);
+            for (int i = 0; i < JITTER_LINES_MS.length; i++) {
+                mJitterYs[i] = (float) Math.floor(h - mGraphScale * JITTER_LINES_MS[i]);
+            }
+        }
+
+        private static String[] makeLabels(float[] divisions) {
+            String[] ret = new String[divisions.length];
+            for (int i = 0; i < divisions.length; i++) {
+                ret[i] = Float.toString(divisions[i]);
+            }
+            return ret;
+        }
+    }
+
+    private final OnFrameMetricsAvailableListener mMetricsListener = new OnFrameMetricsAvailableListener() {
+        private final static double WEIGHT = 40;
+        private long mPreviousFrameTotal;
+        private double mJitterMma;
+        private double mUiFrametimeMma;
+        private double mRtFrametimeMma;
+        private double mTotalFrametimeMma;
+        private double mMostlyTotalFrametimeMma;
+        private boolean mNeedsFirstValues = true;
+
+        @Override
+        public void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics,
+                int dropCountSinceLastInvocation) {
+            if (frameMetrics.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1) {
+                return;
+            }
+
+            long uiDuration = frameMetrics.getMetric(FrameMetrics.INPUT_HANDLING_DURATION)
+                    + frameMetrics.getMetric(FrameMetrics.ANIMATION_DURATION)
+                    + frameMetrics.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION)
+                    + frameMetrics.getMetric(FrameMetrics.DRAW_DURATION);
+            long rtDuration = frameMetrics.getMetric(FrameMetrics.SYNC_DURATION)
+                    + frameMetrics.getMetric(FrameMetrics.COMMAND_ISSUE_DURATION);
+            long totalDuration = frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION);
+            long jitter = Math.abs(totalDuration - mPreviousFrameTotal);
+            if (mNeedsFirstValues) {
+                mJitterMma = 0;
+                mUiFrametimeMma = uiDuration;
+                mRtFrametimeMma = rtDuration;
+                mTotalFrametimeMma = totalDuration;
+                mMostlyTotalFrametimeMma = uiDuration + rtDuration;
+                mNeedsFirstValues = false;
+            } else {
+                mJitterMma = add(mJitterMma, jitter);
+                mUiFrametimeMma = add(mUiFrametimeMma, uiDuration);
+                mRtFrametimeMma = add(mRtFrametimeMma, rtDuration);
+                mTotalFrametimeMma = add(mTotalFrametimeMma, totalDuration);
+                mMostlyTotalFrametimeMma = add(mMostlyTotalFrametimeMma, uiDuration + rtDuration);
+            }
+            mPreviousFrameTotal = totalDuration;
+            mUpdateHandler.obtainMessage(R.id.jitter_mma,
+                    String.format("Jitter: %.3fms", toMs(mJitterMma))).sendToTarget();
+            mUpdateHandler.obtainMessage(R.id.totalish_mma,
+                    String.format("CPU-total duration: %.3fms", toMs(mMostlyTotalFrametimeMma))).sendToTarget();
+            mUpdateHandler.obtainMessage(R.id.ui_frametime_mma,
+                    String.format("UI duration: %.3fms", toMs(mUiFrametimeMma))).sendToTarget();
+            mUpdateHandler.obtainMessage(R.id.rt_frametime_mma,
+                    String.format("RT duration: %.3fms", toMs(mRtFrametimeMma))).sendToTarget();
+            mUpdateHandler.obtainMessage(R.id.total_mma,
+                    String.format("Total duration: %.3fms", toMs(mTotalFrametimeMma))).sendToTarget();
+            mUpdateHandler.obtainMessage(R.id.graph, (int) (jitter / 1000),
+                    (int) (mJitterMma / 1000)).sendToTarget();
+        }
+
+        double add(double previous, double today) {
+            return (((WEIGHT - 1) * previous) + today) / WEIGHT;
+        }
+
+        double toMs(double val) {
+            return val / 1000000;
+        }
+    };
+
+    private static final class AnimatedBackgroundDrawable extends Drawable {
+        private static final int FROM_COLOR = 0xFF18FFFF;
+        private static final int TO_COLOR = 0xFF40C4FF;
+        private static final int DURATION = 1400;
+
+        private final Paint mPaint;
+        private boolean mReverse;
+        private long mStartTime;
+        private int mColor;
+
+        private boolean mReverseX;
+        private boolean mReverseY;
+        private float mX;
+        private float mY;
+        private float mRadius;
+        private float mMoveStep = 10.0f;
+
+        public AnimatedBackgroundDrawable() {
+            mPaint = new Paint();
+            mPaint.setColor(0xFFFFFF00);
+            mPaint.setAntiAlias(true);
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            stepColor();
+            canvas.drawColor(mColor);
+
+            mX += (mReverseX ? -mMoveStep : mMoveStep);
+            mY += (mReverseY ? -mMoveStep : mMoveStep);
+            clampXY();
+            canvas.drawCircle(mX, mY, mRadius, mPaint);
+
+            invalidateSelf();
+        }
+
+        private void clampXY() {
+            if (mX <= mRadius) {
+                mReverseX = false;
+                mX = mRadius;
+            }
+            if (mY <= mRadius) {
+                mReverseY = false;
+                mY = mRadius;
+            }
+            float maxX = getBounds().width() - mRadius;
+            if (mX >= maxX) {
+                mReverseX = true;
+                mX = maxX;
+            }
+            float maxY = getBounds().height() - mRadius;
+            if (mY >= maxY) {
+                mReverseY = true;
+                mY = maxY;
+            }
+        }
+
+        @Override
+        protected void onBoundsChange(Rect bounds) {
+            super.onBoundsChange(bounds);
+            mMoveStep = Math.min(bounds.width(), bounds.height()) / 130.0f;
+            mRadius = Math.min(bounds.width(), bounds.height()) / 20.0f;
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter colorFilter) {
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.OPAQUE;
+        }
+
+        private void stepColor() {
+            if (mStartTime == 0) {
+                mStartTime = AnimationUtils.currentAnimationTimeMillis();
+            }
+            float frac = (AnimationUtils.currentAnimationTimeMillis() - mStartTime)
+                    / (float) DURATION;
+            if (frac > 1.0f) frac = 1.0f;
+            int dest = mReverse ? FROM_COLOR : TO_COLOR;
+            int src = mReverse ? TO_COLOR : FROM_COLOR;
+            int r = (int) (Color.red(src) + (Color.red(dest) - Color.red(src)) * frac);
+            int g = (int) (Color.green(src) + (Color.green(dest) - Color.green(src)) * frac);
+            int b = (int) (Color.blue(src) + (Color.blue(dest) - Color.blue(src)) * frac);
+            mColor = Color.rgb(r, g, b);
+            if (frac == 1.0f) {
+                mStartTime = 0;
+                mReverse = !mReverse;
+            }
+        }
+    }
+}
diff --git a/tests/UiBench/src/com/android/test/uibench/SlowNestedRecyclerViewActivity.java b/tests/UiBench/src/com/android/test/uibench/SlowNestedRecyclerViewActivity.java
new file mode 100644
index 0000000..305c051
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/SlowNestedRecyclerViewActivity.java
@@ -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.
+ */
+package com.android.test.uibench;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.InsetDrawable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.test.uibench.recyclerview.RvCompatListActivity;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+public class SlowNestedRecyclerViewActivity extends RvCompatListActivity {
+    private static final int OUTER_ITEM_COUNT = 100;
+    private static final int INNER_ITEM_COUNT = 20;
+
+    private static final long INNER_ITEM_CREATE_NS = TimeUnit.MILLISECONDS.toNanos(6);
+    private static final long INNER_ITEM_BIND_NS = TimeUnit.MILLISECONDS.toNanos(1);
+    private static final long INNER_ITEM_ATTACH_NS = TimeUnit.MILLISECONDS.toNanos(1);
+
+    private static final long OUTER_ITEM_CREATE_NS = TimeUnit.MILLISECONDS.toNanos(3);
+    private static final long OUTER_ITEM_BIND_NS = TimeUnit.MILLISECONDS.toNanos(1);
+    private static final long OUTER_ITEM_ATTACH_NS = TimeUnit.MILLISECONDS.toNanos(1);
+
+    private SizeData mSizeData;
+
+    private static class SizeData {
+        final int innerItemWidth;
+        final int innerItemHeight;
+        final int headerHeight;
+
+        SizeData(Resources resources) {
+            innerItemWidth = (int) (resources.getDisplayMetrics().widthPixels / 3.3f);
+            innerItemHeight = (int) (innerItemWidth * 1.6f);
+            headerHeight = (int) (resources.getDisplayMetrics().heightPixels * 0.5f);
+        }
+    }
+
+    private SizeData getSizeData(Resources resources) {
+        if (mSizeData == null) {
+            mSizeData = new SizeData(resources);
+        }
+        return mSizeData;
+    }
+
+    @Override
+    protected RecyclerView.LayoutManager createLayoutManager(Context context) {
+        return new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
+    }
+
+    @Override
+    protected RecyclerView.Adapter createAdapter() {
+        return new OuterAdapter();
+    }
+
+    private class InnerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+        @Override
+        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            final long start = System.nanoTime();
+
+            final float density = parent.getResources().getDisplayMetrics().density;
+            View view = new View(parent.getContext()) {
+                @Override
+                protected void onAttachedToWindow() {
+                    final long start = System.nanoTime();
+                    super.onAttachedToWindow();
+                    while (System.nanoTime() - start < INNER_ITEM_ATTACH_NS);
+                }
+            };
+
+            SizeData sizeData = getSizeData(parent.getResources());
+            view.setMinimumWidth(sizeData.innerItemWidth);
+            view.setMinimumHeight(sizeData.innerItemHeight);
+
+            GradientDrawable bg = new GradientDrawable();
+            bg.setCornerRadius(10 * density);
+            bg.setColor(Color.BLACK);
+            final int pad = (int)(10 * density);
+            view.setPadding(pad, pad, pad, pad);
+            view.setBackgroundDrawable(new InsetDrawable(bg, pad));
+            RecyclerView.ViewHolder holder = new RecyclerView.ViewHolder(view) {};
+
+            while (System.nanoTime() - start < INNER_ITEM_CREATE_NS);
+            return holder;
+        }
+
+        @Override
+        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+            final long start = System.nanoTime();
+            while (System.nanoTime() - start < INNER_ITEM_BIND_NS);
+        }
+
+        @Override
+        public int getItemCount() { return INNER_ITEM_COUNT; }
+    }
+
+    private class OuterAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+        static final int TYPE_HEADER = 0;
+        static final int TYPE_RECYCLER = 1;
+
+        ArrayList<InnerAdapter> mAdapters = new ArrayList<>();
+        RecyclerView.RecycledViewPool mSharedPool = new RecyclerView.RecycledViewPool();
+
+        OuterAdapter() {
+            for (int i = 0; i < OUTER_ITEM_COUNT; i++) {
+                mAdapters.add(new InnerAdapter());
+            }
+        }
+
+        @Override
+        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            SizeData sizeData = getSizeData(parent.getResources());
+            if (viewType == TYPE_HEADER) {
+                View view = new View(parent.getContext());
+                view.setMinimumHeight(sizeData.headerHeight);
+                return new RecyclerView.ViewHolder(view) {};
+            } else {
+                final long start = System.nanoTime();
+
+                RecyclerView rv = new RecyclerView(parent.getContext()) {
+                    @Override
+                    protected void onAttachedToWindow() {
+                        final long start = System.nanoTime();
+                        super.onAttachedToWindow();
+                        while (System.nanoTime() - start < OUTER_ITEM_ATTACH_NS);
+
+                    }
+                };
+
+                rv.setLayoutParams(new RecyclerView.LayoutParams(
+                        ViewGroup.LayoutParams.MATCH_PARENT, sizeData.innerItemHeight));
+                rv.setLayoutManager(new LinearLayoutManager(parent.getContext(),
+                        LinearLayoutManager.HORIZONTAL, false));
+                rv.setRecycledViewPool(mSharedPool);
+                RecyclerView.ViewHolder holder = new RecyclerView.ViewHolder(rv) {};
+
+                while (System.nanoTime() - start < OUTER_ITEM_CREATE_NS);
+                return holder;
+            }
+        }
+
+        @Override
+        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+            if (getItemViewType(position) == TYPE_RECYCLER) {
+                final long start = System.nanoTime();
+                ((RecyclerView)holder.itemView).setAdapter(mAdapters.get(position));
+                while (System.nanoTime() - start < OUTER_ITEM_BIND_NS);
+            }
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            return position == 0 ? TYPE_HEADER : TYPE_RECYCLER;
+        }
+
+        @Override
+        public int getItemCount() {
+            return mAdapters.size();
+        }
+    }
+}
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index aea16c7..5f586a1 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -833,6 +833,7 @@
         bpp = 4;
     } else {
         printf("Unknown color type %d.\n", color_type);
+        return;
     }
 
     for (j = 0; j < h; j++) {
diff --git a/tools/aapt/ZipEntry.cpp b/tools/aapt/ZipEntry.cpp
index 54a8e9c..5339285 100644
--- a/tools/aapt/ZipEntry.cpp
+++ b/tools/aapt/ZipEntry.cpp
@@ -23,9 +23,10 @@
 #include "ZipEntry.h"
 #include <utils/Log.h>
 
+#include <assert.h>
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
+#include <time.h>
 
 using namespace android;
 
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index b57d4db..6bfedf3 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -161,7 +161,7 @@
 cFlags := -Wall -Werror -Wno-unused-parameter -UNDEBUG
 cFlags_darwin := -D_DARWIN_UNLIMITED_STREAMS
 cFlags_windows := -Wno-maybe-uninitialized # Incorrectly marking use of Maybe.value() as error.
-cppFlags := -std=c++11 -Wno-missing-field-initializers -fno-exceptions -fno-rtti
+cppFlags := -Wno-missing-field-initializers -fno-exceptions -fno-rtti
 protoIncludes := $(call generated-sources-dir-for,STATIC_LIBRARIES,libaapt2,HOST)
 
 # ==========================================================
diff --git a/tools/aapt2/compile/NinePatch.cpp b/tools/aapt2/compile/NinePatch.cpp
index 408ecf7..0fc1c5d 100644
--- a/tools/aapt2/compile/NinePatch.cpp
+++ b/tools/aapt2/compile/NinePatch.cpp
@@ -598,6 +598,9 @@
                                        (const int32_t*) verticalStretchRegions.data(),
                                        regionColors.data(),
                                        buffer.get());
+    // Convert to file endianness.
+    reinterpret_cast<android::Res_png_9patch*>(buffer.get())->deviceToFile();
+
     *outLen = data.serializedSize();
     return buffer;
 }
@@ -661,7 +664,9 @@
 }
 
 ::std::ostream& operator<<(::std::ostream& out, const NinePatch& ninePatch) {
-    return out << "padding: " << ninePatch.padding
+    return out << "horizontalStretch:" << util::joiner(ninePatch.horizontalStretchRegions, " ")
+            << " verticalStretch:" << util::joiner(ninePatch.verticalStretchRegions, " ")
+            << " padding: " << ninePatch.padding
             << ", bounds: " << ninePatch.layoutBounds
             << ", outline: " << ninePatch.outline
             << " rad=" << ninePatch.outlineRadius
diff --git a/tools/aapt2/compile/NinePatch_test.cpp b/tools/aapt2/compile/NinePatch_test.cpp
index ac4ee02..3106ff8 100644
--- a/tools/aapt2/compile/NinePatch_test.cpp
+++ b/tools/aapt2/compile/NinePatch_test.cpp
@@ -168,6 +168,14 @@
         (uint8_t*) WHITE WHITE WHITE WHITE WHITE,
 };
 
+static uint8_t* kStretchAndPadding5x5[] = {
+        (uint8_t*) WHITE WHITE BLACK WHITE WHITE,
+        (uint8_t*) WHITE RED   RED   RED   WHITE,
+        (uint8_t*) BLACK RED   RED   RED   BLACK,
+        (uint8_t*) WHITE RED   RED   RED   WHITE,
+        (uint8_t*) WHITE WHITE BLACK WHITE WHITE,
+};
+
 TEST(NinePatchTest, Minimum3x3) {
     std::string err;
     EXPECT_EQ(nullptr, NinePatch::create(k2x2, 2, 2, &err));
@@ -319,4 +327,32 @@
     EXPECT_EQ(3.4142f, ninePatch->outlineRadius);
 }
 
+::testing::AssertionResult bigEndianOne(uint8_t* cursor) {
+    if (cursor[0] == 0 && cursor[1] == 0 && cursor[2] == 0 && cursor[3] == 1) {
+        return ::testing::AssertionSuccess();
+    }
+    return ::testing::AssertionFailure() << "Not BigEndian 1";
+}
+
+TEST(NinePatchTest, SerializePngEndianness) {
+    std::string err;
+    std::unique_ptr<NinePatch> ninePatch = NinePatch::create(kStretchAndPadding5x5, 5, 5, &err);
+    ASSERT_NE(nullptr, ninePatch);
+
+    size_t len;
+    std::unique_ptr<uint8_t[]> data = ninePatch->serializeBase(&len);
+    ASSERT_NE(nullptr, data);
+    ASSERT_NE(0u, len);
+
+    // Skip past wasDeserialized + numXDivs + numYDivs + numColors + xDivsOffset + yDivsOffset
+    // (12 bytes)
+    uint8_t* cursor = data.get() + 12;
+
+    // Check that padding is big-endian. Expecting value 1.
+    EXPECT_TRUE(bigEndianOne(cursor));
+    EXPECT_TRUE(bigEndianOne(cursor + 4));
+    EXPECT_TRUE(bigEndianOne(cursor + 8));
+    EXPECT_TRUE(bigEndianOne(cursor + 12));
+}
+
 } // namespace aapt
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index bcfe3bf..090cee8 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -601,14 +601,6 @@
         return Arrays.equals(argb1, argb2);
     }
 
-    // Only used by AssetAtlasService, which we don't care about.
-    @LayoutlibDelegate
-    /*package*/ static long nativeRefPixelRef(long nativeBitmap) {
-        // Hack: This is called by Bitmap.refSkPixelRef() and LayoutLib uses that method to get
-        // the native pointer from a Bitmap. So, we return nativeBitmap here.
-        return nativeBitmap;
-    }
-
     // ---- Private delegate/helper methods ----
 
     private Bitmap_Delegate(BufferedImage image, Config config) {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index f4f92ec..09ab657 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -612,10 +612,13 @@
         throws RemoteException {}
 
     @Override
-    public void createWallpaperInputConsumer(InputChannel inputChannel) throws RemoteException {}
+    public void createInputConsumer(String name, InputChannel inputChannel)
+            throws RemoteException {}
 
     @Override
-    public void removeWallpaperInputConsumer() throws RemoteException {}
+    public boolean destroyInputConsumer(String name) throws RemoteException {
+        return false;
+    }
 
     @Override
     public Bitmap screenshotWallpaper() throws RemoteException {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index feed045..91a783a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -358,7 +358,8 @@
                     mMeasuredScreenWidth, MeasureSpec.EXACTLY,
                     mMeasuredScreenHeight, MeasureSpec.EXACTLY);
             mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
-            mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
+            mSystemViewInfoList =
+                    visitAllChildren(mViewRoot, 0, 0, params.getExtendedViewInfoMode(),
                     false);
 
             return SUCCESS.createResult();
@@ -521,7 +522,8 @@
                         mMeasuredScreenHeight);
             }
 
-            mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
+            mSystemViewInfoList =
+                    visitAllChildren(mViewRoot, 0, 0, params.getExtendedViewInfoMode(),
                     false);
 
             // success!
@@ -1242,20 +1244,22 @@
      * bounds of all the views.
      *
      * @param view the root View
-     * @param offset an offset for the view bounds.
+     * @param hOffset horizontal offset for the view bounds.
+     * @param vOffset vertical offset for the view bounds.
      * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
      * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
      *                       content frame.
      *
      * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
      */
-    private ViewInfo visit(View view, int offset, boolean setExtendedInfo,
+    private ViewInfo visit(View view, int hOffset, int vOffset, boolean setExtendedInfo,
             boolean isContentFrame) {
-        ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame);
+        ViewInfo result = createViewInfo(view, hOffset, vOffset, setExtendedInfo, isContentFrame);
 
         if (view instanceof ViewGroup) {
             ViewGroup group = ((ViewGroup) view);
-            result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset,
+            result.setChildren(visitAllChildren(group, isContentFrame ? 0 : hOffset,
+                    isContentFrame ? 0 : vOffset,
                     setExtendedInfo, isContentFrame));
         }
         return result;
@@ -1267,20 +1271,22 @@
      * the children of the {@code mContentRoot}.
      *
      * @param viewGroup the root View
-     * @param offset an offset from the top for the content view frame.
+     * @param hOffset horizontal offset from the top for the content view frame.
+     * @param vOffset vertical offset from the top for the content view frame.
      * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
      * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
      *                       content frame. {@code false} if the {@code ViewInfo} to be created is
      *                       part of the system decor.
      */
-    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
+    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int hOffset, int vOffset,
             boolean setExtendedInfo, boolean isContentFrame) {
         if (viewGroup == null) {
             return null;
         }
 
         if (!isContentFrame) {
-            offset += viewGroup.getTop();
+            vOffset += viewGroup.getTop();
+            hOffset += viewGroup.getLeft();
         }
 
         int childCount = viewGroup.getChildCount();
@@ -1288,7 +1294,8 @@
             List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount);
             List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount);
             for (int i = 0; i < childCount; i++) {
-                ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset,
+                ViewInfo[] childViewInfo =
+                        visitContentRoot(viewGroup.getChildAt(i), hOffset, vOffset,
                         setExtendedInfo);
                 childrenWithoutOffset.add(childViewInfo[0]);
                 childrenWithOffset.add(childViewInfo[1]);
@@ -1298,7 +1305,7 @@
         } else {
             List<ViewInfo> children = new ArrayList<ViewInfo>(childCount);
             for (int i = 0; i < childCount; i++) {
-                children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo,
+                children.add(visit(viewGroup.getChildAt(i), hOffset, vOffset, setExtendedInfo,
                         isContentFrame));
             }
             return children;
@@ -1317,16 +1324,18 @@
      *         index 1 is with the offset.
      */
     @NonNull
-    private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) {
+    private ViewInfo[] visitContentRoot(View view, int hOffset, int vOffset,
+            boolean setExtendedInfo) {
         ViewInfo[] result = new ViewInfo[2];
         if (view == null) {
             return result;
         }
 
-        result[0] = createViewInfo(view, 0, setExtendedInfo, true);
-        result[1] = createViewInfo(view, offset, setExtendedInfo, true);
+        result[0] = createViewInfo(view, 0, 0, setExtendedInfo, true);
+        result[1] = createViewInfo(view, hOffset, vOffset, setExtendedInfo, true);
         if (view instanceof ViewGroup) {
-            List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true);
+            List<ViewInfo> children =
+                    visitAllChildren((ViewGroup) view, 0, 0, setExtendedInfo, true);
             result[0].setChildren(children);
             result[1].setChildren(children);
         }
@@ -1337,9 +1346,12 @@
      * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
      * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
      * set.
-     * @param offset an offset for the view bounds. Used only if view is part of the content frame.
+     * @param hOffset horizontal offset for the view bounds. Used only if view is part of the
+     * content frame.
+     * @param vOffset vertial an offset for the view bounds. Used only if view is part of the
+     * content frame.
      */
-    private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo,
+    private ViewInfo createViewInfo(View view, int hOffset, int vOffset, boolean setExtendedInfo,
             boolean isContentFrame) {
         if (view == null) {
             return null;
@@ -1355,9 +1367,9 @@
             // The view is part of the layout added by the user. Hence,
             // the ViewCookie may be obtained only through the Context.
             result = new ViewInfo(view.getClass().getName(),
-                    getContext().getViewKey(view),
-                    -scrollX + view.getLeft(), -scrollY + view.getTop() + offset,
-                    -scrollX + view.getRight(), -scrollY + view.getBottom() + offset,
+                    getContext().getViewKey(view), -scrollX + view.getLeft() + hOffset,
+                    -scrollY + view.getTop() + vOffset, -scrollX + view.getRight() + hOffset,
+                    -scrollY + view.getBottom() + vOffset,
                     view, view.getLayoutParams());
         } else {
             // We are part of the system decor.
diff --git a/tools/streaming_proto/Android.mk b/tools/streaming_proto/Android.mk
new file mode 100644
index 0000000..5a54fd1
--- /dev/null
+++ b/tools/streaming_proto/Android.mk
@@ -0,0 +1,41 @@
+#
+# 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)
+
+# ==========================================================
+# Build the host executable: protoc-gen-javastream
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := protoc-gen-javastream
+LOCAL_SRC_FILES := \
+    Errors.cpp \
+    string_utils.cpp \
+    main.cpp
+LOCAL_SHARED_LIBRARIES := \
+    libprotoc
+include $(BUILD_HOST_EXECUTABLE)
+
+# ==========================================================
+# Build the java test
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, test) \
+    $(call all-proto-files-under, test)
+LOCAL_MODULE := StreamingProtoTest
+LOCAL_PROTOC_OPTIMIZE_TYPE := stream
+include $(BUILD_JAVA_LIBRARY)
+
diff --git a/tools/streaming_proto/Errors.cpp b/tools/streaming_proto/Errors.cpp
new file mode 100644
index 0000000..91c6b92
--- /dev/null
+++ b/tools/streaming_proto/Errors.cpp
@@ -0,0 +1,87 @@
+#include "Errors.h"
+
+#include <stdlib.h>
+
+namespace android {
+namespace javastream_proto {
+
+Errors ERRORS;
+
+const string UNKNOWN_FILE;
+const int UNKNOWN_LINE = 0;
+
+Error::Error()
+{
+}
+
+Error::Error(const Error& that)
+    :filename(that.filename),
+     lineno(that.lineno),
+     message(that.message)
+{
+}
+
+Error::Error(const string& f, int l, const char* m)
+    :filename(f),
+     lineno(l),
+     message(m)
+{
+}
+
+Errors::Errors()
+    :m_errors()
+{
+}
+
+Errors::~Errors()
+{
+}
+
+void
+Errors::Add(const string& filename, int lineno, const char* format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    AddImpl(filename, lineno, format, args);
+    va_end(args);
+}
+
+void
+Errors::AddImpl(const string& filename, int lineno, const char* format, va_list args)
+{
+    va_list args2;
+    va_copy(args2, args);
+    int message_size = vsnprintf((char*)NULL, 0, format, args2);
+    va_end(args2);
+
+    char* buffer = new char[message_size+1];
+    vsnprintf(buffer, message_size, format, args);
+    Error error(filename, lineno, buffer);
+    delete[] buffer;
+
+    m_errors.push_back(error);
+}
+
+void
+Errors::Print() const
+{
+    for (vector<Error>::const_iterator it = m_errors.begin(); it != m_errors.end(); it++) {
+        if (it->filename == UNKNOWN_FILE) {
+            fprintf(stderr, "%s", it->message.c_str());
+        } else if (it->lineno == UNKNOWN_LINE) {
+            fprintf(stderr, "%s:%s", it->filename.c_str(), it->message.c_str());
+        } else {
+            fprintf(stderr, "%s:%d:%s", it->filename.c_str(), it->lineno, it->message.c_str());
+        }
+    }
+}
+
+bool
+Errors::HasErrors() const
+{
+    return m_errors.size() > 0;
+}
+
+} // namespace javastream_proto
+} // namespace android
+
diff --git a/tools/streaming_proto/Errors.h b/tools/streaming_proto/Errors.h
new file mode 100644
index 0000000..109195a
--- /dev/null
+++ b/tools/streaming_proto/Errors.h
@@ -0,0 +1,48 @@
+#include <stdio.h>
+
+#include <string>
+#include <vector>
+
+namespace android {
+namespace javastream_proto {
+
+using namespace std;
+
+struct Error
+{
+    Error();
+    explicit Error(const Error& that);
+    Error(const string& filename, int lineno, const char* message);
+
+    string filename;
+    int lineno;
+    string message;
+};
+
+class Errors
+{
+public:
+    Errors();
+    ~Errors();
+
+    // Add an error
+    void Add(const string& filename, int lineno, const char* format, ...);
+
+    // Print the errors to stderr if there are any.
+    void Print() const;
+
+    bool HasErrors() const;
+
+private:
+    // The errors that have been added
+    vector<Error> m_errors;
+    void AddImpl(const string& filename, int lineno, const char* format, va_list ap);
+};
+
+extern Errors ERRORS;
+extern const string UNKNOWN_FILE;
+extern const int UNKNOWN_LINE;
+
+
+} // namespace javastream_proto
+} // namespace android
diff --git a/tools/streaming_proto/main.cpp b/tools/streaming_proto/main.cpp
new file mode 100644
index 0000000..d286213
--- /dev/null
+++ b/tools/streaming_proto/main.cpp
@@ -0,0 +1,391 @@
+#include "Errors.h"
+
+#include "string_utils.h"
+
+#include "google/protobuf/compiler/plugin.pb.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/text_format.h"
+
+#include <stdio.h>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <map>
+
+using namespace android::javastream_proto;
+using namespace google::protobuf;
+using namespace google::protobuf::compiler;
+using namespace google::protobuf::io;
+using namespace std;
+
+const int FIELD_TYPE_SHIFT = 32;
+const uint64_t FIELD_TYPE_DOUBLE = 1L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_FLOAT = 2L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_INT32 = 3L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_INT64 = 4L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_UINT32 = 5L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_UINT64 = 6L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_SINT32 = 7L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_SINT64 = 8L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_FIXED32 = 9L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_FIXED64 = 10L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_SFIXED32 = 11L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_SFIXED64 = 12L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_BOOL = 13L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_STRING = 14L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_BYTES = 15L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_ENUM = 16L << FIELD_TYPE_SHIFT;
+const uint64_t FIELD_TYPE_OBJECT = 17L << FIELD_TYPE_SHIFT;
+
+const int FIELD_COUNT_SHIFT = 40;
+const uint64_t FIELD_COUNT_SINGLE = 1L << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_REPEATED = 2L << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_PACKED = 5L << FIELD_COUNT_SHIFT;
+
+
+/**
+ * See if this is the file for this request, and not one of the imported ones.
+ */
+static bool
+should_generate_for_file(const CodeGeneratorRequest& request, const string& file)
+{
+    const int N = request.file_to_generate_size();
+    for (int i=0; i<N; i++) {
+        if (request.file_to_generate(i) == file) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/**
+ * If the descriptor gives us a class name, use that. Otherwise make one up from
+ * the filename of the .proto file.
+ */
+static string
+make_outer_class_name(const FileDescriptorProto& file_descriptor)
+{
+    string name = file_descriptor.options().java_outer_classname();
+    if (name.size() == 0) {
+        name = to_camel_case(file_base_name(file_descriptor.name()));
+        if (name.size() == 0) {
+            ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE,
+                    "Unable to make an outer class name for file: %s",
+                    file_descriptor.name().c_str());
+            name = "Unknown";
+        }
+    }
+    return name;
+}
+
+/**
+ * Figure out the package name that we are generating.
+ */
+static string
+make_java_package(const FileDescriptorProto& file_descriptor) {
+    if (file_descriptor.options().has_java_package()) {
+        return file_descriptor.options().java_package();
+    } else {
+        return file_descriptor.package();
+    }
+}
+
+/**
+ * Figure out the name of the file we are generating.
+ */
+static string
+make_file_name(const FileDescriptorProto& file_descriptor)
+{
+    string const package = make_java_package(file_descriptor);
+    string result;
+    if (package.size() > 0) {
+        result = replace_string(package, '.', '/');
+        result += '/';
+    }
+
+    result += make_outer_class_name(file_descriptor);
+    result += ".java";
+
+    return result;
+}
+
+static string
+indent_more(const string& indent)
+{
+    return indent + "    ";
+}
+
+/**
+ * Write the constants for an enum.
+ */
+static void
+write_enum(stringstream& text, const EnumDescriptorProto& enu, const string& indent)
+{
+    const int N = enu.value_size();
+    text << indent << "// enum " << enu.name() << endl;
+    for (int i=0; i<N; i++) {
+        const EnumValueDescriptorProto& value = enu.value(i);
+        text << indent << "public static final int "
+                << make_constant_name(value.name())
+                << " = " << value.number() << ";" << endl;
+    }
+    text << endl;
+}
+
+/**
+ * Get the string name for a field.
+ */
+static string
+get_proto_type(const FieldDescriptorProto& field)
+{
+    switch (field.type()) {
+        case FieldDescriptorProto::TYPE_DOUBLE:
+            return "double";
+        case FieldDescriptorProto::TYPE_FLOAT:
+            return "float";
+        case FieldDescriptorProto::TYPE_INT64:
+            return "int64";
+        case FieldDescriptorProto::TYPE_UINT64:
+            return "uint64";
+        case FieldDescriptorProto::TYPE_INT32:
+            return "int32";
+        case FieldDescriptorProto::TYPE_FIXED64:
+            return "fixed64";
+        case FieldDescriptorProto::TYPE_FIXED32:
+            return "fixed32";
+        case FieldDescriptorProto::TYPE_BOOL:
+            return "bool";
+        case FieldDescriptorProto::TYPE_STRING:
+            return "string";
+        case FieldDescriptorProto::TYPE_GROUP:
+            return "group<unsupported!>";
+        case FieldDescriptorProto::TYPE_MESSAGE:
+            return field.type_name();
+        case FieldDescriptorProto::TYPE_BYTES:
+            return "bytes";
+        case FieldDescriptorProto::TYPE_UINT32:
+            return "uint32";
+        case FieldDescriptorProto::TYPE_ENUM:
+            return field.type_name();
+        case FieldDescriptorProto::TYPE_SFIXED32:
+            return "sfixed32";
+        case FieldDescriptorProto::TYPE_SFIXED64:
+            return "sfixed64";
+        case FieldDescriptorProto::TYPE_SINT32:
+            return "sint32";
+        case FieldDescriptorProto::TYPE_SINT64:
+            return "sint64";
+        default:
+            // won't happen
+            return "void";
+    }
+}
+
+static uint64_t
+get_field_id(const FieldDescriptorProto& field)
+{
+    // Number
+    uint64_t result = (uint32_t)field.number();
+
+    // Type
+    switch (field.type()) {
+        case FieldDescriptorProto::TYPE_DOUBLE:
+            result |= FIELD_TYPE_DOUBLE;
+        case FieldDescriptorProto::TYPE_FLOAT:
+            result |= FIELD_TYPE_FLOAT;
+        case FieldDescriptorProto::TYPE_INT64:
+            result |= FIELD_TYPE_INT64;
+        case FieldDescriptorProto::TYPE_UINT64:
+            result |= FIELD_TYPE_UINT64;
+        case FieldDescriptorProto::TYPE_INT32:
+            result |= FIELD_TYPE_INT32;
+        case FieldDescriptorProto::TYPE_FIXED64:
+            result |= FIELD_TYPE_FIXED64;
+        case FieldDescriptorProto::TYPE_FIXED32:
+            result |= FIELD_TYPE_FIXED32;
+        case FieldDescriptorProto::TYPE_BOOL:
+            result |= FIELD_TYPE_BOOL;
+        case FieldDescriptorProto::TYPE_STRING:
+            result |= FIELD_TYPE_STRING;
+        case FieldDescriptorProto::TYPE_MESSAGE:
+            result |= FIELD_TYPE_OBJECT;
+        case FieldDescriptorProto::TYPE_BYTES:
+            result |= FIELD_TYPE_BYTES;
+        case FieldDescriptorProto::TYPE_UINT32:
+            result |= FIELD_TYPE_UINT32;
+        case FieldDescriptorProto::TYPE_ENUM:
+            result |= FIELD_TYPE_ENUM;
+        case FieldDescriptorProto::TYPE_SFIXED32:
+            result |= FIELD_TYPE_SFIXED32;
+        case FieldDescriptorProto::TYPE_SFIXED64:
+            result |= FIELD_TYPE_SFIXED64;
+        case FieldDescriptorProto::TYPE_SINT32:
+            result |= FIELD_TYPE_SINT32;
+        case FieldDescriptorProto::TYPE_SINT64:
+            result |= FIELD_TYPE_SINT64;
+        default:
+            ;
+    }
+
+    // Count
+    if (field.options().packed()) {
+        result |= FIELD_COUNT_PACKED;
+    } else if (field.label() == FieldDescriptorProto::LABEL_REPEATED) {
+        result |= FIELD_COUNT_REPEATED;
+    } else {
+        result |= FIELD_COUNT_SINGLE;
+    }
+
+    return result;
+}
+
+/**
+ * Write a field.
+ */
+static void
+write_field(stringstream& text, const FieldDescriptorProto& field, const string& indent)
+{
+    string optional_comment = field.label() == FieldDescriptorProto::LABEL_OPTIONAL
+            ? "optional " : "";
+    string repeated_comment = field.label() == FieldDescriptorProto::LABEL_REPEATED
+            ? "repeated " : "";
+    string proto_type = get_proto_type(field);
+    string packed_comment = field.options().packed()
+            ? " [packed=true]" : "";
+    text << indent << "// " << optional_comment << repeated_comment << proto_type << ' '
+            << field.name() << " = " << field.number() << packed_comment << ';' << endl;
+
+    text << indent << "public static final long " << make_constant_name(field.name()) << " = 0x";
+
+    ios::fmtflags fmt(text.flags());
+    text << setfill('0') << setw(16) << hex << get_field_id(field);
+    text.flags(fmt);
+
+    text << "L;" << endl;
+
+    text << endl;
+}
+
+/**
+ * Write a Message constants class.
+ */
+static void
+write_message(stringstream& text, const DescriptorProto& message, const string& indent)
+{
+    int N;
+    const string indented = indent_more(indent);
+
+    text << indent << "// message " << message.name() << endl;
+    text << indent << "public final class " << message.name() << " {" << endl;
+    text << endl;
+
+    // Enums
+    N = message.enum_type_size();
+    for (int i=0; i<N; i++) {
+        write_enum(text, message.enum_type(i), indented);
+    }
+
+    // Nested classes
+    N = message.nested_type_size();
+    for (int i=0; i<N; i++) {
+        write_message(text, message.nested_type(i), indented);
+    }
+
+    // Fields
+    N = message.field_size();
+    for (int i=0; i<N; i++) {
+        write_field(text, message.field(i), indented);
+    }
+
+    text << indent << "}" << endl;
+    text << endl;
+}
+
+/**
+ * Write the contents of a file.
+ */
+static void
+write_file(stringstream& text, const FileDescriptorProto& file_descriptor)
+{
+    string const package_name = make_java_package(file_descriptor);
+    string const outer_class_name = make_outer_class_name(file_descriptor);
+
+    text << "// Generated by protoc-gen-javastream. DO NOT MODIFY." << endl;
+    text << "// source: " << file_descriptor.name() << endl << endl;
+
+    if (package_name.size() > 0) {
+        if (package_name.size() > 0) {
+            text << "package " << package_name << ";" << endl;
+            text << endl;
+        }
+    }
+
+    // This bit of policy is android api rules specific: Raw proto classes
+    // must never be in the API, but they should all be available for testing.
+    text << "/** @hide */" << endl;
+    text << "@android.annotation.TestApi" << endl;
+
+    text << "public final class " << outer_class_name << " {" << endl;
+    text << endl;
+
+    int N;
+    const string indented = indent_more("");
+    
+    N = file_descriptor.enum_type_size();
+    for (int i=0; i<N; i++) {
+        write_enum(text, file_descriptor.enum_type(i), indented);
+    }
+
+    N = file_descriptor.message_type_size();
+    for (int i=0; i<N; i++) {
+        write_message(text, file_descriptor.message_type(i), indented);
+    }
+
+    text << "}" << endl;
+}
+
+/**
+ * Main.
+ */
+int
+main(int argc, char const*const* argv)
+{
+    (void)argc;
+    (void)argv;
+
+    GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+    CodeGeneratorRequest request;
+    CodeGeneratorResponse response;
+
+    // Read the request
+    request.ParseFromIstream(&cin);
+
+    // Build the files we need.
+    const int N = request.proto_file_size();
+    for (int i=0; i<N; i++) {
+        const FileDescriptorProto& file_descriptor = request.proto_file(i);
+        if (should_generate_for_file(request, file_descriptor.name())) {
+            // Generate the text
+            stringstream text;
+            write_file(text, file_descriptor);
+
+            // Put the text in the response
+            CodeGeneratorResponse::File* file_response = response.add_file();
+            file_response->set_name(make_file_name(file_descriptor));
+            file_response->set_content(text.str());
+
+            cerr << "writing file: " << file_response->name() << endl;
+        }
+    }
+
+    // If we had errors, don't write the response. Print the errors and exit.
+    if (ERRORS.HasErrors()) {
+        ERRORS.Print();
+        return 1;
+    }
+
+    // If we didn't have errors, write the response and exit happily.
+    response.SerializeToOstream(&cout);
+    return 0;
+}
diff --git a/tools/streaming_proto/string_utils.cpp b/tools/streaming_proto/string_utils.cpp
new file mode 100644
index 0000000..cc738c4
--- /dev/null
+++ b/tools/streaming_proto/string_utils.cpp
@@ -0,0 +1,95 @@
+
+#include "string_utils.h"
+#include <iostream>
+
+namespace android {
+namespace javastream_proto {
+
+using namespace std;
+
+string
+to_camel_case(const string& str)
+{
+    string result;
+    const int N = str.size();
+    result.reserve(N);
+    bool capitalize_next = true;
+    for (int i=0; i<N; i++) {
+        char c = str[i];
+        if (c == '_') {
+            capitalize_next = true;
+        } else {
+            if (capitalize_next && c >= 'a' && c <= 'z') {
+                c = 'A' + c - 'a';
+                capitalize_next = false;
+            } else if (c >= 'A' && c <= 'Z') {
+                capitalize_next = false;
+            } else if (c >= '0' && c <= '9') {
+                capitalize_next = true;
+            } else {
+                // All other characters (e.g. non-latin) count as capital.
+                capitalize_next = false;
+            }
+            result += c;
+        }
+    }
+    return result;
+}
+
+string
+make_constant_name(const string& str)
+{
+    string result;
+    const int N = str.size();
+    bool underscore_next = false;
+    for (int i=0; i<N; i++) {
+        char c = str[i];
+        if (c >= 'A' && c <= 'Z') {
+            if (underscore_next) {
+                result += '_';
+                underscore_next = false;
+            }
+        } else if (c >= 'a' && c <= 'z') {
+            c = 'A' + c - 'a';
+            underscore_next = true;
+        } else if (c == '_') {
+            underscore_next = false;
+        }
+        result += c;
+    }
+    return result;
+}
+
+string
+file_base_name(const string& str)
+{
+    size_t start = str.rfind('/');
+    if (start == string::npos) {
+        start = 0;
+    } else {
+        start++;
+    }
+    size_t end = str.find('.', start);
+    if (end == string::npos) {
+        end = str.size();
+    }
+    return str.substr(start, end-start);
+}
+
+string
+replace_string(const string& str, const char replace, const char with)
+{
+    string result(str);
+    const int N = result.size();
+    for (int i=0; i<N; i++) {
+        if (result[i] == replace) {
+            result[i] = with;
+        }
+    }
+    return result;
+}
+
+} // namespace javastream_proto
+} // namespace android
+
+
diff --git a/tools/streaming_proto/string_utils.h b/tools/streaming_proto/string_utils.h
new file mode 100644
index 0000000..ffe83ca
--- /dev/null
+++ b/tools/streaming_proto/string_utils.h
@@ -0,0 +1,32 @@
+#include <string>
+
+namespace android {
+namespace javastream_proto {
+
+using namespace std;
+
+/**
+ * Capitalizes the string, removes underscores and makes the next letter
+ * capitalized, and makes the letter following numbers capitalized.
+ */
+string to_camel_case(const string& str);
+
+/**
+ * Capitalize and insert underscores for CamelCase.
+ */
+string make_constant_name(const string& str);
+
+/**
+ * Returns the part of a file name that isn't a path and isn't a type suffix.
+ */
+string file_base_name(const string& str);
+
+/**
+ * Replace all occurances of 'replace' with 'with'.
+ */
+string replace_string(const string& str, const char replace, const char with);
+
+
+} // namespace javastream_proto
+} // namespace android
+
diff --git a/core/tests/coretests/src/android/print/mockservice/SettingsActivity.java b/tools/streaming_proto/test/imported.proto
similarity index 69%
rename from core/tests/coretests/src/android/print/mockservice/SettingsActivity.java
rename to tools/streaming_proto/test/imported.proto
index fb76e67..05c8f0c 100644
--- a/core/tests/coretests/src/android/print/mockservice/SettingsActivity.java
+++ b/tools/streaming_proto/test/imported.proto
@@ -14,15 +14,13 @@
  * limitations under the License.
  */
 
-package android.print.mockservice;
+syntax = "proto2";
 
-import android.app.Activity;
-import android.os.Bundle;
+package com.android.streaming_proto_test;
 
-public class SettingsActivity extends Activity {
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
-}
+/**
+ * Message that is used from the other file.
+ */
+message ImportedMessage {
+    optional int32 data = 1;
+};
diff --git a/tools/streaming_proto/test/src/com/android/streaming_proto_test/Main.java b/tools/streaming_proto/test/src/com/android/streaming_proto_test/Main.java
new file mode 100644
index 0000000..1246f53
--- /dev/null
+++ b/tools/streaming_proto/test/src/com/android/streaming_proto_test/Main.java
@@ -0,0 +1,7 @@
+package com.android.streaming_proto_test;
+
+public class Main {
+    public void main(String[] argv) {
+        System.out.println("hello world");
+    }
+}
diff --git a/tools/streaming_proto/test/test.proto b/tools/streaming_proto/test/test.proto
new file mode 100644
index 0000000..de80ed6
--- /dev/null
+++ b/tools/streaming_proto/test/test.proto
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/tools/streaming_proto/test/imported.proto";
+
+package com.android.streaming_proto_test;
+
+/**
+ * Enum that outside the scope of any classes.
+ */
+enum Outside {
+    OUTSIDE_0 = 0;
+    OUTSIDE_1 = 1;
+};
+
+message Sibling {
+    optional int32 int32_field = 1;
+}
+
+/**
+ * Message with all of the field types.
+ */
+message All {
+    /**
+     * Enum that is inside the scope of a class.
+     */
+    enum Inside {
+        option allow_alias = true;
+        INSIDE_0 = 0;
+        INSIDE_1 = 1;
+        INSIDE_1A = 1;
+    };
+
+    /**
+     * Message that is recursive.
+     */
+    message Nested {
+        optional int32 data = 10001;
+        optional Nested nested = 10002;
+    };
+
+    optional double double_field = 10;
+    repeated double double_field_repeated = 11;
+    repeated double double_field_packed = 12 [packed=true];
+
+    optional float float_field = 20;
+    repeated float float_field_repeated = 21;
+    repeated float float_field_packed = 22 [packed=true];
+
+    optional int32 int32_field = 30;
+    repeated int32 int32_field_repeated = 31;
+    repeated int32 int32_field_packed = 32 [packed=true];
+
+    optional int64 int64_field = 40;
+    repeated int64 int64_field_repeated = 41;
+    repeated int64 int64_field_packed = 42 [packed=true];
+
+    optional uint32 uint32_field = 50;
+    repeated uint32 uint32_field_repeated = 51;
+    repeated uint32 uint32_field_packed = 52 [packed=true];
+
+    optional uint64 uint64_field = 60;
+    repeated uint64 uint64_field_repeated = 61;
+    repeated uint64 uint64_field_packed = 62 [packed=true];
+
+    optional sint32 sint32_field = 70;
+    repeated sint32 sint32_field_repeated = 71;
+    repeated sint32 sint32_field_packed = 72 [packed=true];
+
+    optional sint64 sint64_field = 80;
+    repeated sint64 sint64_field_repeated = 81;
+    repeated sint64 sint64_field_packed = 82 [packed=true];
+
+    optional fixed32 fixed32_field = 90;
+    repeated fixed32 fixed32_field_repeated = 91;
+    repeated fixed32 fixed32_field_packed = 92 [packed=true];
+
+    optional fixed64 fixed64_field = 100;
+    repeated fixed64 fixed64_field_repeated = 101;
+    repeated fixed64 fixed64_field_packed = 102 [packed=true];
+
+    optional sfixed32 sfixed32_field = 110;
+    repeated sfixed32 sfixed32_field_repeated = 111;
+    repeated sfixed32 sfixed32_field_packed = 112 [packed=true];
+
+    optional sfixed64 sfixed64_field = 120;
+    repeated sfixed64 sfixed64_field_repeated = 121;
+    repeated sfixed64 sfixed64_field_packed = 122 [packed=true];
+
+    optional bool bool_field = 130;
+    repeated bool bool_field_repeated = 131;
+    repeated bool bool_field_packed = 132 [packed=true];
+
+    optional string string_field = 140;
+    repeated string string_field_repeated = 141;
+
+    optional bytes bytes_field = 150;
+    repeated bytes bytes_field_repeated = 151;
+
+    optional Outside outside_field = 160;
+    repeated Outside outside_field_repeated = 161;
+    repeated Outside outside_field_packed = 162 [packed=true];
+
+    optional Nested nested_field = 170;
+    repeated Nested nested_field_repeated = 171;
+
+    optional ImportedMessage imported_field = 180;
+    repeated ImportedMessage imported_field_repeated = 181;
+};
diff --git a/wifi/java/android/net/wifi/ParcelUtil.java b/wifi/java/android/net/wifi/ParcelUtil.java
new file mode 100644
index 0000000..a26877d
--- /dev/null
+++ b/wifi/java/android/net/wifi/ParcelUtil.java
@@ -0,0 +1,165 @@
+/**
+ * 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;
+
+import android.os.Parcel;
+
+import java.io.ByteArrayInputStream;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+/**
+ * Provides utilities for writing/reading a non-Parcelable objects to/from
+ * a Parcel object.
+ *
+ * @hide
+ */
+public class ParcelUtil {
+    /**
+     * Write a PrivateKey object |key| to the specified Parcel |dest|.
+     *
+     * Below is the data format:
+     * |algorithm|     -> String of algorithm name
+     * |endcodedKey|  -> byte[] of key data
+     *
+     * For a null PrivateKey object, a null string will be written to |algorithm| and
+     * |encodedKey| will be skipped. Since a PrivateKey can only be constructed with
+     * a valid algorithm String.
+     *
+     * @param dest Parcel object to write to
+     * @param key PrivateKey object to read from.
+     */
+    public static void writePrivateKey(Parcel dest, PrivateKey key) {
+        if (key == null) {
+            dest.writeString(null);
+            return;
+        }
+
+        dest.writeString(key.getAlgorithm());
+        dest.writeByteArray(key.getEncoded());
+    }
+
+    /**
+     * Read/create a PrivateKey object from a specified Parcel object |in|.
+     *
+     * Refer to the function above for the expected data format.
+     *
+     * @param in Parcel object to read from
+     * @return a PrivateKey object or null
+     */
+    public static PrivateKey readPrivateKey(Parcel in) {
+        String algorithm = in.readString();
+        if (algorithm == null) {
+            return null;
+        }
+
+        byte[] userKeyBytes = in.createByteArray();
+        try {
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+            return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(userKeyBytes));
+       } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+            return null;
+       }
+    }
+
+    /**
+     * Write a X509Certificate object |cert| to a Parcel object |dest|.
+     * The data being written to the Parcel is just a byte[] of the encoded certificate data.
+     *
+     * @param dest Parcel object to write to
+     * @param cert X509Certificate object to read from
+     */
+    public static void writeCertificate(Parcel dest, X509Certificate cert) {
+        byte[] certBytes = null;
+        if (cert != null) {
+            try {
+                certBytes = cert.getEncoded();
+            } catch (CertificateEncodingException e) {
+                /* empty, write null. */
+            }
+        }
+        dest.writeByteArray(certBytes);
+    }
+
+    /**
+     * Read/create a X509Certificate object from a specified Parcel object |in|.
+     *
+     * @param in Parcel object to read from
+     * @return a X509Certficate object or null
+     */
+    public static X509Certificate readCertificate(Parcel in) {
+        byte[] certBytes = in.createByteArray();
+        if (certBytes == null) {
+            return null;
+        }
+
+        try {
+            CertificateFactory cFactory = CertificateFactory.getInstance("X.509");
+            return (X509Certificate) cFactory
+                    .generateCertificate(new ByteArrayInputStream(certBytes));
+        } catch (CertificateException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Write an array of X509Certificate objects |certs| to a Parcel object |dest|.
+     * The data being written to the Parcel are consist of an integer indicating
+     * the size of the array and the certificates data.  Certificates data will be
+     * skipped for a null array or size of 0 array.
+     *
+     * @param dest Parcel object to write to
+     * @param certs array of X509Certificate objects to read from
+     */
+    public static void writeCertificates(Parcel dest, X509Certificate[] certs) {
+        if (certs == null || certs.length == 0) {
+            dest.writeInt(0);
+            return;
+        }
+
+        dest.writeInt(certs.length);
+        for (int i = 0; i < certs.length; i++) {
+            writeCertificate(dest, certs[i]);
+        }
+    }
+
+    /**
+     * Read/create an array of X509Certificate objects from a specified Parcel object |in|.
+     *
+     * @param in Parcel object to read from
+     * @return X509Certficate[] or null
+     */
+    public static X509Certificate[] readCertificates(Parcel in) {
+        int length = in.readInt();
+        if (length == 0) {
+            return null;
+        }
+
+        X509Certificate[] certs = new X509Certificate[length];
+        for (int i = 0; i < length; i++) {
+            certs[i] = readCertificate(in);
+        }
+        return certs;
+    }
+}
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index c0e8bc2..e410a9c 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -183,48 +183,14 @@
 
         dest.writeInt(mEapMethod);
         dest.writeInt(mPhase2Method);
-        writeCertificates(dest, mCaCerts);
-
-        if (mClientPrivateKey != null) {
-            String algorithm = mClientPrivateKey.getAlgorithm();
-            byte[] userKeyBytes = mClientPrivateKey.getEncoded();
-            dest.writeInt(userKeyBytes.length);
-            dest.writeByteArray(userKeyBytes);
-            dest.writeString(algorithm);
-        } else {
-            dest.writeInt(0);
-        }
-
-        writeCertificate(dest, mClientCertificate);
-    }
-
-    private void writeCertificates(Parcel dest, X509Certificate[] cert) {
-        if (cert != null && cert.length != 0) {
-            dest.writeInt(cert.length);
-            for (int i = 0; i < cert.length; i++) {
-                writeCertificate(dest, cert[i]);
-            }
-        } else {
-            dest.writeInt(0);
-        }
-    }
-
-    private void writeCertificate(Parcel dest, X509Certificate cert) {
-        if (cert != null) {
-            try {
-                byte[] certBytes = cert.getEncoded();
-                dest.writeInt(certBytes.length);
-                dest.writeByteArray(certBytes);
-            } catch (CertificateEncodingException e) {
-                dest.writeInt(0);
-            }
-        } else {
-            dest.writeInt(0);
-        }
+        ParcelUtil.writeCertificates(dest, mCaCerts);
+        ParcelUtil.writePrivateKey(dest, mClientPrivateKey);
+        ParcelUtil.writeCertificate(dest, mClientCertificate);
     }
 
     public static final Creator<WifiEnterpriseConfig> CREATOR =
             new Creator<WifiEnterpriseConfig>() {
+                @Override
                 public WifiEnterpriseConfig createFromParcel(Parcel in) {
                     WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
                     int count = in.readInt();
@@ -236,58 +202,13 @@
 
                     enterpriseConfig.mEapMethod = in.readInt();
                     enterpriseConfig.mPhase2Method = in.readInt();
-                    enterpriseConfig.mCaCerts = readCertificates(in);
-
-                    PrivateKey userKey = null;
-                    int len = in.readInt();
-                    if (len > 0) {
-                        try {
-                            byte[] bytes = new byte[len];
-                            in.readByteArray(bytes);
-                            String algorithm = in.readString();
-                            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
-                            userKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(bytes));
-                        } catch (NoSuchAlgorithmException e) {
-                            userKey = null;
-                        } catch (InvalidKeySpecException e) {
-                            userKey = null;
-                        }
-                    }
-
-                    enterpriseConfig.mClientPrivateKey = userKey;
-                    enterpriseConfig.mClientCertificate = readCertificate(in);
+                    enterpriseConfig.mCaCerts = ParcelUtil.readCertificates(in);
+                    enterpriseConfig.mClientPrivateKey = ParcelUtil.readPrivateKey(in);
+                    enterpriseConfig.mClientCertificate = ParcelUtil.readCertificate(in);
                     return enterpriseConfig;
                 }
 
-                private X509Certificate[] readCertificates(Parcel in) {
-                    X509Certificate[] certs = null;
-                    int len = in.readInt();
-                    if (len > 0) {
-                        certs = new X509Certificate[len];
-                        for (int i = 0; i < len; i++) {
-                            certs[i] = readCertificate(in);
-                        }
-                    }
-                    return certs;
-                }
-
-                private X509Certificate readCertificate(Parcel in) {
-                    X509Certificate cert = null;
-                    int len = in.readInt();
-                    if (len > 0) {
-                        try {
-                            byte[] bytes = new byte[len];
-                            in.readByteArray(bytes);
-                            CertificateFactory cFactory = CertificateFactory.getInstance("X.509");
-                            cert = (X509Certificate) cFactory
-                                    .generateCertificate(new ByteArrayInputStream(bytes));
-                        } catch (CertificateException e) {
-                            cert = null;
-                        }
-                    }
-                    return cert;
-                }
-
+                @Override
                 public WifiEnterpriseConfig[] newArray(int size) {
                     return new WifiEnterpriseConfig[size];
                 }
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
index 56baba9..5485824 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
+++ b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
@@ -23,6 +23,7 @@
 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.RttManager;
 
 /**
@@ -36,6 +37,7 @@
     void enableUsage();
     void disableUsage();
     boolean isUsageEnabled();
+    WifiNanCharacteristics getCharacteristics();
 
     // client API
     void connect(in IBinder binder, in String callingPackage, in IWifiNanEventCallback callback,
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.java b/wifi/java/android/net/wifi/nan/PublishConfig.java
index 4b67f9a..30c5bc0 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.java
+++ b/wifi/java/android/net/wifi/nan/PublishConfig.java
@@ -182,7 +182,7 @@
      *
      * @hide
      */
-    public void validate() throws IllegalArgumentException {
+    public void assertValid(WifiNanCharacteristics characteristics) throws IllegalArgumentException {
         WifiNanUtils.validateServiceName(mServiceName);
 
         if (!LvBufferUtils.isValid(mMatchFilter, 1)) {
@@ -198,6 +198,26 @@
         if (mTtlSec < 0) {
             throw new IllegalArgumentException("Invalid ttlSec - must be non-negative");
         }
+
+        if (characteristics != null) {
+            int maxServiceNameLength = characteristics.getMaxServiceNameLength();
+            if (maxServiceNameLength != 0 && mServiceName.length > maxServiceNameLength) {
+                throw new IllegalArgumentException(
+                        "Service name longer than supported by device characteristics");
+            }
+            int maxServiceSpecificInfoLength = characteristics.getMaxServiceSpecificInfoLength();
+            if (maxServiceSpecificInfoLength != 0 && mServiceSpecificInfo != null
+                    && mServiceSpecificInfo.length > maxServiceSpecificInfoLength) {
+                throw new IllegalArgumentException(
+                        "Service specific info longer than supported by device characteristics");
+            }
+            int maxMatchFilterLength = characteristics.getMaxMatchFilterLength();
+            if (maxMatchFilterLength != 0 && mMatchFilter != null
+                    && mMatchFilter.length > maxMatchFilterLength) {
+                throw new IllegalArgumentException(
+                        "Match filter longer than supported by device characteristics");
+            }
+        }
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/nan/SubscribeConfig.java b/wifi/java/android/net/wifi/nan/SubscribeConfig.java
index 4352fcf..ea7b8e4 100644
--- a/wifi/java/android/net/wifi/nan/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/nan/SubscribeConfig.java
@@ -209,7 +209,7 @@
      *
      * @hide
      */
-    public void validate() throws IllegalArgumentException {
+    public void assertValid(WifiNanCharacteristics characteristics) throws IllegalArgumentException {
         WifiNanUtils.validateServiceName(mServiceName);
 
         if (!LvBufferUtils.isValid(mMatchFilter, 1)) {
@@ -229,6 +229,26 @@
             throw new IllegalArgumentException(
                     "Invalid matchType - must be MATCH_FIRST_ONLY or MATCH_ALL");
         }
+
+        if (characteristics != null) {
+            int maxServiceNameLength = characteristics.getMaxServiceNameLength();
+            if (maxServiceNameLength != 0 && mServiceName.length > maxServiceNameLength) {
+                throw new IllegalArgumentException(
+                        "Service name longer than supported by device characteristics");
+            }
+            int maxServiceSpecificInfoLength = characteristics.getMaxServiceSpecificInfoLength();
+            if (maxServiceSpecificInfoLength != 0 && mServiceSpecificInfo != null
+                    && mServiceSpecificInfo.length > maxServiceSpecificInfoLength) {
+                throw new IllegalArgumentException(
+                        "Service specific info longer than supported by device characteristics");
+            }
+            int maxMatchFilterLength = characteristics.getMaxMatchFilterLength();
+            if (maxMatchFilterLength != 0 && mMatchFilter != null
+                    && mMatchFilter.length > maxMatchFilterLength) {
+                throw new IllegalArgumentException(
+                        "Match filter longer than supported by device characteristics");
+            }
+        }
     }
 
     /**
diff --git a/core/tests/coretests/src/android/print/mockservice/SettingsActivity.java b/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.aidl
similarity index 69%
copy from core/tests/coretests/src/android/print/mockservice/SettingsActivity.java
copy to wifi/java/android/net/wifi/nan/WifiNanCharacteristics.aidl
index fb76e67..e562a00 100644
--- a/core/tests/coretests/src/android/print/mockservice/SettingsActivity.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.aidl
@@ -14,15 +14,6 @@
  * limitations under the License.
  */
 
-package android.print.mockservice;
+package android.net.wifi.nan;
 
-import android.app.Activity;
-import android.os.Bundle;
-
-public class SettingsActivity extends Activity {
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
-}
+parcelable WifiNanCharacteristics;
diff --git a/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.java b/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.java
new file mode 100644
index 0000000..f43ed4d
--- /dev/null
+++ b/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.java
@@ -0,0 +1,103 @@
+/*
+ * 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;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The characteristics of the Wi-Fi NAN implementation.
+ *
+ * @hide PROPOSED_NAN_API
+ */
+public class WifiNanCharacteristics implements Parcelable {
+    /** @hide */
+    public static final String KEY_MAX_SERVICE_NAME_LENGTH = "key_max_service_name_length";
+    /** @hide */
+    public static final String KEY_MAX_SERVICE_SPECIFIC_INFO_LENGTH =
+            "key_max_service_specific_info_length";
+    /** @hide */
+    public static final String KEY_MAX_MATCH_FILTER_LENGTH = "key_max_match_filter_length";
+
+    private Bundle mCharacteristics = new Bundle();
+
+    /** @hide : should not be created by apps */
+    public WifiNanCharacteristics(Bundle characteristics) {
+        mCharacteristics = characteristics;
+    }
+
+    /**
+     * Returns the maximum string length that can be used to specify a NAN 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.
+     */
+    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
+     * 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.
+     *
+     * @return A positive integer, maximum length of byte array for NAN 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.
+     * 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.
+     */
+    public int getMaxMatchFilterLength() {
+        return mCharacteristics.getInt(KEY_MAX_MATCH_FILTER_LENGTH);
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeBundle(mCharacteristics);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<WifiNanCharacteristics> CREATOR =
+            new Creator<WifiNanCharacteristics>() {
+                @Override
+                public WifiNanCharacteristics createFromParcel(Parcel in) {
+                    WifiNanCharacteristics c = new WifiNanCharacteristics(in.readBundle());
+                    return c;
+                }
+
+                @Override
+                public WifiNanCharacteristics[] newArray(int size) {
+                    return new WifiNanCharacteristics[size];
+                }
+            };
+}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java
index bb15434..002b953 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanManager.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java
@@ -293,6 +293,20 @@
     }
 
     /**
+     * Returns the characteristics of the Wi-Fi NAN 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.
+     */
+    public WifiNanCharacteristics getCharacteristics() {
+        try {
+            return mService.getCharacteristics();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Attach to the Wi-Fi NAN 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
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSession.java b/wifi/java/android/net/wifi/nan/WifiNanSession.java
index 5fb2c06..df5e3c1 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSession.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSession.java
@@ -113,6 +113,8 @@
      *      An application must use the {@link WifiNanDiscoveryBaseSession#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}
+     * permission to start a publish discovery session.
      *
      * @param handler The Handler on whose thread to execute the callbacks of the {@code
      * callback} object. If a null is provided then the application's main thread will be used.
@@ -156,6 +158,8 @@
      *      An application must use the {@link WifiNanDiscoveryBaseSession#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}
+     * permission to start a subscribe discovery session.
      *
      * @param handler The Handler on whose thread to execute the callbacks of the {@code
      * callback} object. If a null is provided then the application's main thread will be used.
diff --git a/wifi/tests/src/android/net/wifi/FakeKeys.java b/wifi/tests/src/android/net/wifi/FakeKeys.java
index 0c73070..c0d60c3 100644
--- a/wifi/tests/src/android/net/wifi/FakeKeys.java
+++ b/wifi/tests/src/android/net/wifi/FakeKeys.java
@@ -19,11 +19,16 @@
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
 
 /**
- * A class containing test certificates.
+ * A class containing test certificates and private keys.
  */
 public class FakeKeys {
     private static final String CA_CERT0_STRING = "-----BEGIN CERTIFICATE-----\n" +
@@ -68,6 +73,146 @@
             "-----END CERTIFICATE-----\n";
     public static final X509Certificate CA_CERT1 = loadCertificate(CA_CERT1_STRING);
 
+    private static final String CLIENT_CERT_STR = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIE/DCCAuQCAQEwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxCzAJBgNV\n" +
+            "BAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdUZXN0aW5n\n" +
+            "MB4XDTE2MDkzMDIwNTQyOFoXDTE3MDkzMDIwNTQyOFowRDELMAkGA1UEBhMCVVMx\n" +
+            "CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdU\n" +
+            "ZXN0aW5nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnpmcbuaeHfnJ\n" +
+            "k+2QNvxmdVFTawyFMNk0USCq5sexscwmxbewG/Rb8YnixwJWS44v2XkSujB67z5C\n" +
+            "s2qudFEhRXKdEuC6idbAuA97KjipHh0AAniWMsyv61fvbgsUC0b0canx3LiDq81p\n" +
+            "y28NNGmAvoazLZUZ4AhBRiwYZY6FKk723gmZoGbEIeG7J1dlXPusc1662rIjz4eU\n" +
+            "zlmmlvqyHfNqnNk8L14Vug6Xh+lOEGN85xhu1YHAEKGrS89kZxs5rum/cZU8KH2V\n" +
+            "v6eKnY03kxjiVLQtnLpm/7VUEoCMGHyruRj+p3my4+DgqMsmsH52RZCBsjyGlpbU\n" +
+            "NOwOTIX6xh+Rqloduz4AnrMYYIiIw2s8g+2zJM7VbcVKx0fGS26BKdrxgrXWfmNE\n" +
+            "nR0/REQ5AxDGw0jfTUvtdTkXAf+K4MDjcNLEZ+MA4rHfAfQWZtUR5BkHCQYxNpJk\n" +
+            "pA0gyk+BpKdC4WdzI14NSWsu5sRCmBCFqH6BTOSEq/V1cNorBxNwLSSTwFFqUDqx\n" +
+            "Y5nQLXygkJf9WHZWtSKeSjtOYgilz7UKzC2s3CsjmIyGFe+SwpuHJnuE4Uc8Z5Cb\n" +
+            "bjNGHPzqL6XnmzZHJp7RF8kBdKdjGC7dCUltzOfICZeKlzOOq+Kw42T/nXjuXvpb\n" +
+            "nkXNxg741Nwd6RecykXJbseFwm3EYxkCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEA\n" +
+            "Ga1mGwI9aXkL2fTPXO9YkAPzoGeX8aeuVYSQaSkNq+5vnogYCyAt3YDHjRG+ewTT\n" +
+            "WbnPA991xRAPac+biJeXWmwvgGj0YuT7e79phAiGkTTnbAjFHGfYnBy/tI/v7btO\n" +
+            "hRNElA5yTJ1m2fVbBEKXzMR83jrT9iyI+YLRN86zUZIaC86xxSbqnrdWN2jOK6MX\n" +
+            "dS8Arp9tPQjC/4gW+2Ilxv68jiYh+5auWHQZVjppWVY//iu4mAbkq1pTwQEhZ8F8\n" +
+            "Zrmh9DHh60hLFcfSuhIAwf/NMzppwdkjy1ruKVrpijhGKGp4OWu8nvOUgHSzxc7F\n" +
+            "PwpVZ5N2Ku4L8MLO6BG2VasRJK7l17TzDXlfLZHJjkuryOFxVaQKt8ZNFgTOaCXS\n" +
+            "E+gpTLksKU7riYckoiP4+H1sn9qcis0e8s4o/uf1UVc8GSdDw61ReGM5oZEDm1u8\n" +
+            "H9x20QU6igLqzyBpqvCKv7JNgU1uB2PAODHH78zJiUfnKd1y+o+J1iWzaGj3EFji\n" +
+            "T8AXksbTP733FeFXfggXju2dyBH+Z1S5BBTEOd1brWgXlHSAZGm97MKZ94r6/tkX\n" +
+            "qfv3fCos0DKz0oV7qBxYS8wiYhzrRVxG6ITAoH8uuUVVQaZF+G4nJ2jEqNbfuKyX\n" +
+            "ATQsVNjNNlDA0J33GobPMjT326wa4YAWMx8PI5PJZ3g=\n" +
+            "-----END CERTIFICATE-----\n";
+    public static final X509Certificate CLIENT_CERT = loadCertificate(CLIENT_CERT_STR);
+
+    private static final byte[] FAKE_RSA_KEY_1 = new byte[] {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x02, (byte) 0x01,
+            (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+            (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+            (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82,
+            (byte) 0x02, (byte) 0x62, (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x5e,
+            (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81, (byte) 0x81,
+            (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6, (byte) 0x5b,
+            (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c, (byte) 0x66,
+            (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86, (byte) 0x8a,
+            (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3, (byte) 0x02,
+            (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08, (byte) 0xf3,
+            (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04, (byte) 0x6d,
+            (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f, (byte) 0x67,
+            (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c, (byte) 0xcb,
+            (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30, (byte) 0xe2,
+            (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5, (byte) 0x79,
+            (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b, (byte) 0xce,
+            (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb, (byte) 0x08,
+            (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff, (byte) 0x3b,
+            (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9, (byte) 0xc4,
+            (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29, (byte) 0x0d,
+            (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b, (byte) 0x23,
+            (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78, (byte) 0x08,
+            (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5, (byte) 0xf1,
+            (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19, (byte) 0xb4,
+            (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03, (byte) 0x16,
+            (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce, (byte) 0x9e,
+            (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03, (byte) 0x01,
+            (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80, (byte) 0x16,
+            (byte) 0x59, (byte) 0xc3, (byte) 0x24, (byte) 0x1d, (byte) 0x33, (byte) 0x98,
+            (byte) 0x9c, (byte) 0xc9, (byte) 0xc8, (byte) 0x2c, (byte) 0x88, (byte) 0xbf,
+            (byte) 0x0a, (byte) 0x01, (byte) 0xce, (byte) 0xfb, (byte) 0x34, (byte) 0x7a,
+            (byte) 0x58, (byte) 0x7a, (byte) 0xb0, (byte) 0xbf, (byte) 0xa6, (byte) 0xb2,
+            (byte) 0x60, (byte) 0xbe, (byte) 0x70, (byte) 0x21, (byte) 0xf5, (byte) 0xfc,
+            (byte) 0x85, (byte) 0x0d, (byte) 0x33, (byte) 0x58, (byte) 0xa1, (byte) 0xe5,
+            (byte) 0x09, (byte) 0x36, (byte) 0x84, (byte) 0xb2, (byte) 0x04, (byte) 0x0a,
+            (byte) 0x02, (byte) 0xd3, (byte) 0x88, (byte) 0x1f, (byte) 0x0c, (byte) 0x2b,
+            (byte) 0x1d, (byte) 0xe9, (byte) 0x3d, (byte) 0xe7, (byte) 0x79, (byte) 0xf9,
+            (byte) 0x32, (byte) 0x5c, (byte) 0x8a, (byte) 0x75, (byte) 0x49, (byte) 0x12,
+            (byte) 0xe4, (byte) 0x05, (byte) 0x26, (byte) 0xd4, (byte) 0x2e, (byte) 0x9e,
+            (byte) 0x1f, (byte) 0xcc, (byte) 0x54, (byte) 0xad, (byte) 0x33, (byte) 0x8d,
+            (byte) 0x99, (byte) 0x00, (byte) 0xdc, (byte) 0xf5, (byte) 0xb4, (byte) 0xa2,
+            (byte) 0x2f, (byte) 0xba, (byte) 0xe5, (byte) 0x62, (byte) 0x30, (byte) 0x6d,
+            (byte) 0xe6, (byte) 0x3d, (byte) 0xeb, (byte) 0x24, (byte) 0xc2, (byte) 0xdc,
+            (byte) 0x5f, (byte) 0xb7, (byte) 0x16, (byte) 0x35, (byte) 0xa3, (byte) 0x98,
+            (byte) 0x98, (byte) 0xa8, (byte) 0xef, (byte) 0xe8, (byte) 0xc4, (byte) 0x96,
+            (byte) 0x6d, (byte) 0x38, (byte) 0xab, (byte) 0x26, (byte) 0x6d, (byte) 0x30,
+            (byte) 0xc2, (byte) 0xa0, (byte) 0x44, (byte) 0xe4, (byte) 0xff, (byte) 0x7e,
+            (byte) 0xbe, (byte) 0x7c, (byte) 0x33, (byte) 0xa5, (byte) 0x10, (byte) 0xad,
+            (byte) 0xd7, (byte) 0x1e, (byte) 0x13, (byte) 0x20, (byte) 0xb3, (byte) 0x1f,
+            (byte) 0x41, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xf1, (byte) 0x89,
+            (byte) 0x07, (byte) 0x0f, (byte) 0xe8, (byte) 0xcf, (byte) 0xab, (byte) 0x13,
+            (byte) 0x2a, (byte) 0x8f, (byte) 0x88, (byte) 0x80, (byte) 0x11, (byte) 0x9a,
+            (byte) 0x79, (byte) 0xb6, (byte) 0x59, (byte) 0x3a, (byte) 0x50, (byte) 0x6e,
+            (byte) 0x57, (byte) 0x37, (byte) 0xab, (byte) 0x2a, (byte) 0xd2, (byte) 0xaa,
+            (byte) 0xd9, (byte) 0x72, (byte) 0x73, (byte) 0xff, (byte) 0x8b, (byte) 0x47,
+            (byte) 0x76, (byte) 0xdd, (byte) 0xdc, (byte) 0xf5, (byte) 0x97, (byte) 0x44,
+            (byte) 0x3a, (byte) 0x78, (byte) 0xbe, (byte) 0x17, (byte) 0xb4, (byte) 0x22,
+            (byte) 0x6f, (byte) 0xe5, (byte) 0x23, (byte) 0x70, (byte) 0x1d, (byte) 0x10,
+            (byte) 0x5d, (byte) 0xba, (byte) 0x16, (byte) 0x81, (byte) 0xf1, (byte) 0x45,
+            (byte) 0xce, (byte) 0x30, (byte) 0xb4, (byte) 0xab, (byte) 0x80, (byte) 0xe4,
+            (byte) 0x98, (byte) 0x31, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xda,
+            (byte) 0x82, (byte) 0x9d, (byte) 0x3f, (byte) 0xca, (byte) 0x2f, (byte) 0xe1,
+            (byte) 0xd4, (byte) 0x86, (byte) 0x77, (byte) 0x48, (byte) 0xa6, (byte) 0xab,
+            (byte) 0xab, (byte) 0x1c, (byte) 0x42, (byte) 0x5c, (byte) 0xd5, (byte) 0xc7,
+            (byte) 0x46, (byte) 0x59, (byte) 0x91, (byte) 0x3f, (byte) 0xfc, (byte) 0xcc,
+            (byte) 0xec, (byte) 0xc2, (byte) 0x40, (byte) 0x12, (byte) 0x2c, (byte) 0x8d,
+            (byte) 0x1f, (byte) 0xa2, (byte) 0x18, (byte) 0x88, (byte) 0xee, (byte) 0x82,
+            (byte) 0x4a, (byte) 0x5a, (byte) 0x5e, (byte) 0x88, (byte) 0x20, (byte) 0xe3,
+            (byte) 0x7b, (byte) 0xe0, (byte) 0xd8, (byte) 0x3a, (byte) 0x52, (byte) 0x9a,
+            (byte) 0x26, (byte) 0x6a, (byte) 0x04, (byte) 0xec, (byte) 0xe8, (byte) 0xb9,
+            (byte) 0x48, (byte) 0x40, (byte) 0xe1, (byte) 0xe1, (byte) 0x83, (byte) 0xa6,
+            (byte) 0x67, (byte) 0xa6, (byte) 0xfd, (byte) 0x02, (byte) 0x41, (byte) 0x00,
+            (byte) 0x89, (byte) 0x72, (byte) 0x3e, (byte) 0xb0, (byte) 0x90, (byte) 0xfd,
+            (byte) 0x4c, (byte) 0x0e, (byte) 0xd6, (byte) 0x13, (byte) 0x63, (byte) 0xcb,
+            (byte) 0xed, (byte) 0x38, (byte) 0x88, (byte) 0xb6, (byte) 0x79, (byte) 0xc4,
+            (byte) 0x33, (byte) 0x6c, (byte) 0xf6, (byte) 0xf8, (byte) 0xd8, (byte) 0xd0,
+            (byte) 0xbf, (byte) 0x9d, (byte) 0x35, (byte) 0xac, (byte) 0x69, (byte) 0xd2,
+            (byte) 0x2b, (byte) 0xc1, (byte) 0xf9, (byte) 0x24, (byte) 0x7b, (byte) 0xce,
+            (byte) 0xcd, (byte) 0xcb, (byte) 0xa7, (byte) 0xb2, (byte) 0x7a, (byte) 0x0a,
+            (byte) 0x27, (byte) 0x19, (byte) 0xc9, (byte) 0xaf, (byte) 0x0d, (byte) 0x21,
+            (byte) 0x89, (byte) 0x88, (byte) 0x7c, (byte) 0xad, (byte) 0x9e, (byte) 0x8d,
+            (byte) 0x47, (byte) 0x6d, (byte) 0x3f, (byte) 0xce, (byte) 0x7b, (byte) 0xa1,
+            (byte) 0x74, (byte) 0xf1, (byte) 0xa0, (byte) 0xa1, (byte) 0x02, (byte) 0x41,
+            (byte) 0x00, (byte) 0xd9, (byte) 0xa8, (byte) 0xf5, (byte) 0xfe, (byte) 0xce,
+            (byte) 0xe6, (byte) 0x77, (byte) 0x6b, (byte) 0xfe, (byte) 0x2d, (byte) 0xe0,
+            (byte) 0x1e, (byte) 0xb6, (byte) 0x2e, (byte) 0x12, (byte) 0x4e, (byte) 0x40,
+            (byte) 0xaf, (byte) 0x6a, (byte) 0x7b, (byte) 0x37, (byte) 0x49, (byte) 0x2a,
+            (byte) 0x96, (byte) 0x25, (byte) 0x83, (byte) 0x49, (byte) 0xd4, (byte) 0x0c,
+            (byte) 0xc6, (byte) 0x78, (byte) 0x25, (byte) 0x24, (byte) 0x90, (byte) 0x90,
+            (byte) 0x06, (byte) 0x15, (byte) 0x9e, (byte) 0xfe, (byte) 0xf9, (byte) 0xdf,
+            (byte) 0x5b, (byte) 0xf3, (byte) 0x7e, (byte) 0x38, (byte) 0x70, (byte) 0xeb,
+            (byte) 0x57, (byte) 0xd0, (byte) 0xd9, (byte) 0xa7, (byte) 0x0e, (byte) 0x14,
+            (byte) 0xf7, (byte) 0x95, (byte) 0x68, (byte) 0xd5, (byte) 0xc8, (byte) 0xab,
+            (byte) 0x9d, (byte) 0x3a, (byte) 0x2b, (byte) 0x51, (byte) 0xf9, (byte) 0x02,
+            (byte) 0x41, (byte) 0x00, (byte) 0x96, (byte) 0xdf, (byte) 0xe9, (byte) 0x67,
+            (byte) 0x6c, (byte) 0xdc, (byte) 0x90, (byte) 0x14, (byte) 0xb4, (byte) 0x1d,
+            (byte) 0x22, (byte) 0x33, (byte) 0x4a, (byte) 0x31, (byte) 0xc1, (byte) 0x9d,
+            (byte) 0x2e, (byte) 0xff, (byte) 0x9a, (byte) 0x2a, (byte) 0x95, (byte) 0x4b,
+            (byte) 0x27, (byte) 0x74, (byte) 0xcb, (byte) 0x21, (byte) 0xc3, (byte) 0xd2,
+            (byte) 0x0b, (byte) 0xb2, (byte) 0x46, (byte) 0x87, (byte) 0xf8, (byte) 0x28,
+            (byte) 0x01, (byte) 0x8b, (byte) 0xd8, (byte) 0xb9, (byte) 0x4b, (byte) 0xcd,
+            (byte) 0x9a, (byte) 0x96, (byte) 0x41, (byte) 0x0e, (byte) 0x36, (byte) 0x6d,
+            (byte) 0x40, (byte) 0x42, (byte) 0xbc, (byte) 0xd9, (byte) 0xd3, (byte) 0x7b,
+            (byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1,
+            (byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51
+    };
+    public static final PrivateKey RSA_KEY1 = loadPrivateRSAKey(FAKE_RSA_KEY_1);
 
     private static X509Certificate loadCertificate(String blob) {
         try {
@@ -80,4 +225,13 @@
             return null;
         }
     }
+
+    private static PrivateKey loadPrivateRSAKey(byte[] fakeKey) {
+        try {
+            KeyFactory kf = KeyFactory.getInstance("RSA");
+            return kf.generatePrivate(new PKCS8EncodedKeySpec(fakeKey));
+        } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
+            return null;
+        }
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/ParcelUtilTest.java b/wifi/tests/src/android/net/wifi/ParcelUtilTest.java
new file mode 100644
index 0000000..6787594
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/ParcelUtilTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+/**
+ * Unit tests for {@link android.net.wifi.ParcelUtil}.
+ */
+@SmallTest
+public class ParcelUtilTest {
+    private Parcel mParcel;
+
+    @Before
+    public void setUp() throws Exception {
+        mParcel = Parcel.obtain();
+    }
+
+    @Test
+    public void readWriteNullPrivateKey() throws Exception {
+        ParcelUtil.writePrivateKey(mParcel, null);
+
+        mParcel.setDataPosition(0);    // Rewind data position back to the beginning for read.
+        PrivateKey readKey = ParcelUtil.readPrivateKey(mParcel);
+        assertNull(readKey);
+    }
+
+    @Test
+    public void readWriteValidPrivateKey() throws Exception {
+        PrivateKey writeKey = FakeKeys.RSA_KEY1;
+        ParcelUtil.writePrivateKey(mParcel, writeKey);
+
+        mParcel.setDataPosition(0);    // Rewind data position back to the beginning for read.
+        PrivateKey readKey = ParcelUtil.readPrivateKey(mParcel);
+        assertNotNull(readKey);
+        assertEquals(writeKey.getAlgorithm(), readKey.getAlgorithm());
+        assertArrayEquals(writeKey.getEncoded(), readKey.getEncoded());
+    }
+
+    @Test
+    public void readWriteNullCertificate() throws Exception {
+        ParcelUtil.writeCertificate(mParcel, null);
+
+        mParcel.setDataPosition(0);    // Rewind data position back to the beginning for read.
+        X509Certificate readCert = ParcelUtil.readCertificate(mParcel);
+        assertNull(readCert);
+    }
+
+    @Test
+    public void readWriteValidCertificate() throws Exception {
+        X509Certificate writeCert = FakeKeys.CA_CERT1;
+        ParcelUtil.writeCertificate(mParcel, writeCert);
+
+        mParcel.setDataPosition(0);    // Rewind data position back to the beginning for read.
+        X509Certificate readCert = ParcelUtil.readCertificate(mParcel);
+        assertNotNull(readCert);
+        assertArrayEquals(writeCert.getEncoded(), readCert.getEncoded());
+    }
+
+    @Test
+    public void readWriteNullCertificates() throws Exception {
+        ParcelUtil.writeCertificates(mParcel, null);
+
+        mParcel.setDataPosition(0);    // Rewind data position back to the beginning for read.
+        X509Certificate[] readCerts = ParcelUtil.readCertificates(mParcel);
+        assertNull(readCerts);
+    }
+
+    @Test
+    public void readWriteValidCertificates() throws Exception {
+        X509Certificate[] writeCerts = new X509Certificate[2];
+        writeCerts[0] = FakeKeys.CA_CERT0;
+        writeCerts[1] = FakeKeys.CA_CERT1;
+        ParcelUtil.writeCertificates(mParcel, writeCerts);
+
+        mParcel.setDataPosition(0);    // Rewind data position back to the beginning for read.
+        X509Certificate[] readCerts = ParcelUtil.readCertificates(mParcel);
+        assertNotNull(readCerts);
+        assertEquals(writeCerts.length, readCerts.length);
+        for (int i = 0; i < writeCerts.length; i++) {
+            assertNotNull(readCerts[i]);
+            assertArrayEquals(writeCerts[i].getEncoded(), readCerts[i].getEncoded());
+        }
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
index 0d964b7..0e503d5 100644
--- a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -16,10 +16,12 @@
 
 package android.net.wifi;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import android.net.wifi.WifiEnterpriseConfig.Eap;
 import android.net.wifi.WifiEnterpriseConfig.Phase2;
@@ -30,6 +32,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import java.security.PrivateKey;
 import java.security.cert.X509Certificate;
 
 
@@ -259,6 +262,45 @@
         assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
     }
 
+    /**
+     * Verifies that parceling a WifiEnterpriseConfig preserves the key
+     * and certificates information.
+     */
+    @Test
+    public void parcelConfigWithKeyAndCerts() throws Exception {
+        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+        PrivateKey clientKey = FakeKeys.RSA_KEY1;
+        X509Certificate clientCert = FakeKeys.CLIENT_CERT;
+        X509Certificate[] caCerts = new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1};
+        enterpriseConfig.setClientKeyEntry(clientKey, clientCert);
+        enterpriseConfig.setCaCertificates(caCerts);
+        Parcel parcel = Parcel.obtain();
+        enterpriseConfig.writeToParcel(parcel, 0);
+
+        parcel.setDataPosition(0);  // Allow parcel to be read from the beginning.
+        mEnterpriseConfig = WifiEnterpriseConfig.CREATOR.createFromParcel(parcel);
+        PrivateKey actualClientKey = mEnterpriseConfig.getClientPrivateKey();
+        X509Certificate actualClientCert = mEnterpriseConfig.getClientCertificate();
+        X509Certificate[] actualCaCerts = mEnterpriseConfig.getCaCertificates();
+
+        /* Verify client private key. */
+        assertNotNull(actualClientKey);
+        assertEquals(clientKey.getAlgorithm(), actualClientKey.getAlgorithm());
+        assertArrayEquals(clientKey.getEncoded(), actualClientKey.getEncoded());
+
+        /* Verify client certificate. */
+        assertNotNull(actualClientCert);
+        assertArrayEquals(clientCert.getEncoded(), actualClientCert.getEncoded());
+
+        /* Verify CA certificates. */
+        assertNotNull(actualCaCerts);
+        assertEquals(caCerts.length, actualCaCerts.length);
+        for (int i = 0; i < caCerts.length; i++) {
+            assertNotNull(actualCaCerts[i]);
+            assertArrayEquals(caCerts[i].getEncoded(), actualCaCerts[i].getEncoded());
+        }
+    }
+
     /** Verifies proper operation of the getKeyId() method. */
     @Test
     public void getKeyId() {