Merge "Add atoms to log memory metrics."
diff --git a/Android.mk b/Android.mk
index 298b85d..866d2a7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -781,6 +781,7 @@
 LOCAL_SOURCE_FILES_ALL_GENERATED := true
 LOCAL_SRC_FILES := \
     cmds/am/proto/instrumentation_data.proto \
+    cmds/statsd/src/perfetto/perfetto_config.proto \
     $(call all-proto-files-under, core/proto) \
     $(call all-proto-files-under, libs/incident/proto) \
     $(call all-proto-files-under, cmds/statsd/src)
diff --git a/apct-tests/perftests/core/AndroidManifest.xml b/apct-tests/perftests/core/AndroidManifest.xml
index bd0b944..132a2f9 100644
--- a/apct-tests/perftests/core/AndroidManifest.xml
+++ b/apct-tests/perftests/core/AndroidManifest.xml
@@ -10,7 +10,11 @@
 
     <application>
         <uses-library android:name="android.test.runner" />
-        <activity android:name="android.perftests.utils.StubActivity" />
+        <activity android:name="android.perftests.utils.StubActivity">
+          <intent-filter>
+            <action android:name="com.android.perftests.core.PERFTEST" />
+          </intent-filter>
+        </activity>
         <service android:name="android.os.SomeService" android:exported="false" android:process=":some_service" />
     </application>
 
diff --git a/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java b/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
new file mode 100644
index 0000000..145fbcd
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2017 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 static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class PackageManagerPerfTest {
+    private static final String PERMISSION_NAME_EXISTS =
+            "com.android.perftests.core.TestPermission";
+    private static final String PERMISSION_NAME_DOESNT_EXIST =
+            "com.android.perftests.core.TestBadPermission";
+    private static final ComponentName TEST_ACTIVITY =
+            new ComponentName("com.android.perftests.core", "android.perftests.utils.StubActivity");
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void testCheckPermissionExists() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        final String packageName = TEST_ACTIVITY.getPackageName();
+
+        while (state.keepRunning()) {
+            int ret = pm.checkPermission(PERMISSION_NAME_EXISTS, packageName);
+        }
+    }
+
+    @Test
+    public void testCheckPermissionDoesntExist() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        final String packageName = TEST_ACTIVITY.getPackageName();
+
+        while (state.keepRunning()) {
+            int ret = pm.checkPermission(PERMISSION_NAME_DOESNT_EXIST, packageName);
+        }
+    }
+
+    @Test
+    public void testQueryIntentActivities() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        final Intent intent = new Intent("com.android.perftests.core.PERFTEST");
+
+        while (state.keepRunning()) {
+            pm.queryIntentActivities(intent, 0);
+        }
+    }
+
+    @Test
+    public void testGetPackageInfo() throws Exception {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        final String packageName = TEST_ACTIVITY.getPackageName();
+
+        while (state.keepRunning()) {
+            pm.getPackageInfo(packageName, 0);
+        }
+    }
+
+    @Test
+    public void testGetApplicationInfo() throws Exception {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        final String packageName = TEST_ACTIVITY.getPackageName();
+        
+        while (state.keepRunning()) {
+            pm.getApplicationInfo(packageName, 0);
+        }
+    }
+
+    @Test
+    public void testGetActivityInfo() throws Exception {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        
+        while (state.keepRunning()) {
+            pm.getActivityInfo(TEST_ACTIVITY, 0);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/os/PermissionTest.java b/apct-tests/perftests/core/src/android/os/PermissionTest.java
deleted file mode 100644
index d292e7d..0000000
--- a/apct-tests/perftests/core/src/android/os/PermissionTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2017 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 static android.content.pm.PackageManager.PERMISSION_DENIED;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
-import android.content.Context;
-import android.perftests.utils.BenchmarkState;
-import android.perftests.utils.PerfStatusReporter;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class PermissionTest {
-    private static final String PERMISSION_HAS_NAME = "com.android.perftests.core.TestPermission";
-    private static final String PERMISSION_DOESNT_HAVE_NAME =
-            "com.android.perftests.core.TestBadPermission";
-    private static final String THIS_PACKAGE_NAME = "com.android.perftests.core";
-
-    @Rule
-    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
-
-    @Test
-    public void testHasPermission() {
-        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        final Context context = InstrumentationRegistry.getTargetContext();
-        while (state.keepRunning()) {
-            int ret = context.getPackageManager().checkPermission(PERMISSION_HAS_NAME,
-                    THIS_PACKAGE_NAME);
-        }
-    }
-
-    @Test
-    public void testDoesntHavePermission() {
-        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        final Context context = InstrumentationRegistry.getTargetContext();
-
-        while (state.keepRunning()) {
-            int ret = context.getPackageManager().checkPermission(PERMISSION_DOESNT_HAVE_NAME,
-                    THIS_PACKAGE_NAME);
-        }
-    }
-
-}
diff --git a/api/current.txt b/api/current.txt
index 86f1a3b..65bcec7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2796,6 +2796,7 @@
     field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6
     field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5
     field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
+    field public static final int GLOBAL_ACTION_TAKE_SCREENSHOT = 9; // 0x9
     field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
     field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
     field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
diff --git a/api/system-current.txt b/api/system-current.txt
index f35984a..d33b030 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1777,9 +1777,9 @@
     method public android.hardware.radio.ProgramSelector.Identifier[] getAllIds(int);
     method public long getFirstId(int);
     method public android.hardware.radio.ProgramSelector.Identifier getPrimaryId();
-    method public int getProgramType();
+    method public deprecated int getProgramType();
     method public android.hardware.radio.ProgramSelector.Identifier[] getSecondaryIds();
-    method public long[] getVendorIds();
+    method public deprecated long[] getVendorIds();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.hardware.radio.ProgramSelector> CREATOR;
     field public static final int IDENTIFIER_TYPE_AMFM_FREQUENCY = 1; // 0x1
@@ -1787,27 +1787,31 @@
     field public static final int IDENTIFIER_TYPE_DAB_FREQUENCY = 8; // 0x8
     field public static final int IDENTIFIER_TYPE_DAB_SCID = 7; // 0x7
     field public static final int IDENTIFIER_TYPE_DAB_SIDECC = 5; // 0x5
+    field public static final int IDENTIFIER_TYPE_DAB_SID_EXT = 5; // 0x5
     field public static final int IDENTIFIER_TYPE_DRMO_FREQUENCY = 10; // 0xa
-    field public static final int IDENTIFIER_TYPE_DRMO_MODULATION = 11; // 0xb
+    field public static final deprecated int IDENTIFIER_TYPE_DRMO_MODULATION = 11; // 0xb
     field public static final int IDENTIFIER_TYPE_DRMO_SERVICE_ID = 9; // 0x9
     field public static final int IDENTIFIER_TYPE_HD_STATION_ID_EXT = 3; // 0x3
-    field public static final int IDENTIFIER_TYPE_HD_SUBCHANNEL = 4; // 0x4
+    field public static final int IDENTIFIER_TYPE_HD_STATION_NAME = 10004; // 0x2714
+    field public static final deprecated int IDENTIFIER_TYPE_HD_SUBCHANNEL = 4; // 0x4
     field public static final int IDENTIFIER_TYPE_INVALID = 0; // 0x0
     field public static final int IDENTIFIER_TYPE_RDS_PI = 2; // 0x2
     field public static final int IDENTIFIER_TYPE_SXM_CHANNEL = 13; // 0xd
     field public static final int IDENTIFIER_TYPE_SXM_SERVICE_ID = 12; // 0xc
-    field public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_END = 1999; // 0x7cf
-    field public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_START = 1000; // 0x3e8
-    field public static final int PROGRAM_TYPE_AM = 1; // 0x1
-    field public static final int PROGRAM_TYPE_AM_HD = 3; // 0x3
-    field public static final int PROGRAM_TYPE_DAB = 5; // 0x5
-    field public static final int PROGRAM_TYPE_DRMO = 6; // 0x6
-    field public static final int PROGRAM_TYPE_FM = 2; // 0x2
-    field public static final int PROGRAM_TYPE_FM_HD = 4; // 0x4
-    field public static final int PROGRAM_TYPE_INVALID = 0; // 0x0
-    field public static final int PROGRAM_TYPE_SXM = 7; // 0x7
-    field public static final int PROGRAM_TYPE_VENDOR_END = 1999; // 0x7cf
-    field public static final int PROGRAM_TYPE_VENDOR_START = 1000; // 0x3e8
+    field public static final int IDENTIFIER_TYPE_VENDOR_END = 1999; // 0x7cf
+    field public static final deprecated int IDENTIFIER_TYPE_VENDOR_PRIMARY_END = 1999; // 0x7cf
+    field public static final deprecated int IDENTIFIER_TYPE_VENDOR_PRIMARY_START = 1000; // 0x3e8
+    field public static final int IDENTIFIER_TYPE_VENDOR_START = 1000; // 0x3e8
+    field public static final deprecated int PROGRAM_TYPE_AM = 1; // 0x1
+    field public static final deprecated int PROGRAM_TYPE_AM_HD = 3; // 0x3
+    field public static final deprecated int PROGRAM_TYPE_DAB = 5; // 0x5
+    field public static final deprecated int PROGRAM_TYPE_DRMO = 6; // 0x6
+    field public static final deprecated int PROGRAM_TYPE_FM = 2; // 0x2
+    field public static final deprecated int PROGRAM_TYPE_FM_HD = 4; // 0x4
+    field public static final deprecated int PROGRAM_TYPE_INVALID = 0; // 0x0
+    field public static final deprecated int PROGRAM_TYPE_SXM = 7; // 0x7
+    field public static final deprecated int PROGRAM_TYPE_VENDOR_END = 1999; // 0x7cf
+    field public static final deprecated int PROGRAM_TYPE_VENDOR_START = 1000; // 0x3e8
   }
 
   public static final class ProgramSelector.Identifier implements android.os.Parcelable {
@@ -1822,7 +1826,7 @@
   public static abstract class ProgramSelector.IdentifierType implements java.lang.annotation.Annotation {
   }
 
-  public static abstract class ProgramSelector.ProgramType implements java.lang.annotation.Annotation {
+  public static abstract deprecated class ProgramSelector.ProgramType implements java.lang.annotation.Annotation {
   }
 
   public class RadioManager {
@@ -2860,9 +2864,18 @@
     method public void onTetheringStarted();
   }
 
+  public final class IpSecManager {
+    method public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(java.net.InetAddress, java.net.InetAddress, android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+  }
+
+  public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable {
+    method public void close();
+    method public java.lang.String getInterfaceName();
+  }
+
   public static class IpSecTransform.Builder {
+    method public android.net.IpSecTransform buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
     method public android.net.IpSecTransform.Builder setNattKeepalive(int);
-    method public android.net.IpSecTransform.Builder setUnderlyingNetwork(android.net.Network);
   }
 
   public class NetworkKey implements android.os.Parcelable {
diff --git a/cmds/incident_helper/src/TextParserBase.h b/cmds/incident_helper/src/TextParserBase.h
index c41612d..1667966 100644
--- a/cmds/incident_helper/src/TextParserBase.h
+++ b/cmds/incident_helper/src/TextParserBase.h
@@ -68,4 +68,4 @@
     virtual status_t Parse(const int in, const int out) const;
 };
 
-#endif // TEXT_PARSER_BASE_H
\ No newline at end of file
+#endif // TEXT_PARSER_BASE_H
diff --git a/cmds/incidentd/README.md b/cmds/incidentd/README.md
index ad0fa08..71c6deb 100644
--- a/cmds/incidentd/README.md
+++ b/cmds/incidentd/README.md
@@ -12,8 +12,8 @@
 
 ```
 root$ mmm -j frameworks/base/cmds/incidentd && \
-adb push $OUT/data/nativetest/incidentd_test/* /data/nativetest/incidentd_test/ && \
-adb shell /data/nativetest/incidentd_test/incidentd_test 2>/dev/null
+adb push $OUT/data/nativetest/incidentd_test/* /data/nativetest/ && \
+adb shell /data/nativetest/incidentd_test 2>/dev/null
 ```
 
 Run the test via AndroidTest.xml
diff --git a/cmds/incidentd/incidentd.rc b/cmds/incidentd/incidentd.rc
index 66667dc..1bd1468 100644
--- a/cmds/incidentd/incidentd.rc
+++ b/cmds/incidentd/incidentd.rc
@@ -19,4 +19,4 @@
 
 on post-fs-data
     # Create directory for incidentd
-    mkdir /data/misc/incidents 0770 root root
+    mkdir /data/misc/incidents 0770 incidentd incidentd
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index 30dd339..0fff4e6 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -63,12 +63,14 @@
 
         int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
         if (remainingTime <= 0) {
+            if (DEBUG) ALOGD("timed out due to long read");
             mTimedOut = true;
             break;
         }
 
         int count = poll(&pfds, 1, remainingTime);
         if (count == 0) {
+            if (DEBUG) ALOGD("timed out due to block calling poll");
             mTimedOut = true;
             break;
         } else if (count < 0) {
@@ -129,6 +131,7 @@
 
         int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
         if (remainingTime <= 0) {
+            if (DEBUG) ALOGD("timed out due to long read");
             mTimedOut = true;
             break;
         }
@@ -136,6 +139,7 @@
         // wait for any pfds to be ready to perform IO
         int count = poll(pfds, 3, remainingTime);
         if (count == 0) {
+            if (DEBUG) ALOGD("timed out due to block calling poll");
             mTimedOut = true;
             break;
         } else if (count < 0) {
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index c4b54bb..a97eb86 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -43,8 +43,9 @@
 String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
 
 static Status
-checkIncidentPermissions()
+checkIncidentPermissions(const IncidentReportArgs& args)
 {
+    // checking calling permission.
     if (!checkCallingPermission(DUMP_PERMISSION)) {
         ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
                 IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
@@ -57,10 +58,24 @@
         return Status::fromExceptionCode(Status::EX_SECURITY,
                 "Calling process does not have permission: android.permission.USAGE_STATS");
     }
+
+    // checking calling request uid permission.
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    switch (args.dest()) {
+        case DEST_LOCAL:
+            if (callingUid != AID_SHELL || callingUid != AID_ROOT) {
+                return Status::fromExceptionCode(Status::EX_SECURITY,
+                    "Calling process does not have permission to get local data.");
+            }
+        case DEST_EXPLICIT:
+            if (callingUid != AID_SHELL || callingUid != AID_ROOT ||
+                callingUid != AID_STATSD || callingUid != AID_SYSTEM) {
+                return Status::fromExceptionCode(Status::EX_SECURITY,
+                    "Calling process does not have permission to get explicit data.");
+            }
+    }
     return Status::ok();
 }
-
-
 // ================================================================================
 ReportRequestQueue::ReportRequestQueue()
 {
@@ -71,7 +86,7 @@
 }
 
 void
-ReportRequestQueue::addRequest(const sp<ReportRequest>& request) 
+ReportRequestQueue::addRequest(const sp<ReportRequest>& request)
 {
     unique_lock<mutex> lock(mLock);
     mQueue.push_back(request);
@@ -196,7 +211,7 @@
 {
     ALOGI("reportIncident");
 
-    Status status = checkIncidentPermissions();
+    Status status = checkIncidentPermissions(args);
     if (!status.isOk()) {
         return status;
     }
@@ -212,7 +227,7 @@
 {
     ALOGI("reportIncidentToStream");
 
-    Status status = checkIncidentPermissions();
+    Status status = checkIncidentPermissions(args);
     if (!status.isOk()) {
         return status;
     }
diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp
index 34930aa..bd559d6 100644
--- a/cmds/incidentd/src/Reporter.cpp
+++ b/cmds/incidentd/src/Reporter.cpp
@@ -251,7 +251,7 @@
     // Override umask. Not super critical. If it fails go on with life.
     chmod(filename, 0660);
 
-    if (chown(filename, AID_SYSTEM, AID_SYSTEM)) {
+    if (chown(filename, AID_INCIDENTD, AID_INCIDENTD)) {
         ALOGE("Unable to change ownership of incident file %s: %s\n", filename, strerror(errno));
         status_t err = -errno;
         unlink(mFilename.c_str());
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 61d16f8..0827785 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -19,6 +19,7 @@
 #include "Section.h"
 
 #include <errno.h>
+#include <sys/prctl.h>
 #include <unistd.h>
 #include <wait.h>
 
@@ -30,7 +31,6 @@
 #include <log/log_event_list.h>
 #include <log/logprint.h>
 #include <log/log_read.h>
-#include <private/android_filesystem_config.h> // for AID_NOBODY
 #include <private/android_logger.h>
 
 #include "FdBuffer.h"
@@ -55,26 +55,20 @@
 fork_execute_incident_helper(const int id, const char* name, Fpipe& p2cPipe, Fpipe& c2pPipe)
 {
     const char* ihArgs[] { INCIDENT_HELPER, "-s", String8::format("%d", id).string(), NULL };
-
     // fork used in multithreaded environment, avoid adding unnecessary code in child process
     pid_t pid = fork();
     if (pid == 0) {
-        // child process executes incident helper as nobody
-        if (setgid(AID_NOBODY) == -1) {
-            ALOGW("%s can't change gid: %s", name, strerror(errno));
-            _exit(EXIT_FAILURE);
-        }
-        if (setuid(AID_NOBODY) == -1) {
-            ALOGW("%s can't change uid: %s", name, strerror(errno));
-            _exit(EXIT_FAILURE);
-        }
-
-        if (dup2(p2cPipe.readFd(),  STDIN_FILENO)  != 0 || !p2cPipe.close() ||
-            dup2(c2pPipe.writeFd(), STDOUT_FILENO) != 1 || !c2pPipe.close()) {
+        if (TEMP_FAILURE_RETRY(dup2(p2cPipe.readFd(),  STDIN_FILENO))  != 0
+            || !p2cPipe.close()
+            || TEMP_FAILURE_RETRY(dup2(c2pPipe.writeFd(), STDOUT_FILENO)) != 1
+            || !c2pPipe.close()) {
             ALOGW("%s can't setup stdin and stdout for incident helper", name);
             _exit(EXIT_FAILURE);
         }
 
+        /* make sure the child dies when incidentd dies */
+        prctl(PR_SET_PDEATHSIG, SIGKILL);
+
         execv(INCIDENT_HELPER, const_cast<char**>(ihArgs));
 
         ALOGW("%s failed in incident helper process: %s", name, strerror(errno));
@@ -87,11 +81,23 @@
 }
 
 // ================================================================================
+static status_t statusCode(int status) {
+    if (WIFSIGNALED(status)) {
+      ALOGD("return by signal: %s", strerror(WTERMSIG(status)));
+      return -WTERMSIG(status);
+    } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
+      ALOGD("return by exit: %s", strerror(WEXITSTATUS(status)));
+      return -WEXITSTATUS(status);
+    }
+    return NO_ERROR;
+}
+
 static status_t kill_child(pid_t pid) {
     int status;
+    ALOGD("try to kill child process %d", pid);
     kill(pid, SIGKILL);
     if (waitpid(pid, &status, 0) == -1) return -1;
-    return WIFEXITED(status) == 0 ? NO_ERROR : -WEXITSTATUS(status);
+    return statusCode(status);
 }
 
 static status_t wait_child(pid_t pid) {
@@ -104,7 +110,7 @@
         nanosleep(&WAIT_INTERVAL_NS, NULL);
     }
     if (!died) return kill_child(pid);
-    return WIFEXITED(status) == 0 ? NO_ERROR : -WEXITSTATUS(status);
+    return statusCode(status);
 }
 // ================================================================================
 static const Privacy*
@@ -275,9 +281,9 @@
     status_t readStatus = buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(), c2pPipe.readFd(),
             this->timeoutMs, mIsSysfs);
     if (readStatus != NO_ERROR || buffer.timedOut()) {
-        ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s, kill: %s",
-            this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false",
-            strerror(-kill_child(pid)));
+        ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s",
+            this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
+        kill_child(pid);
         return readStatus;
     }
 
@@ -543,10 +549,10 @@
     close(cmdPipe.writeFd());
     status_t readStatus = buffer.read(ihPipe.readFd(), this->timeoutMs);
     if (readStatus != NO_ERROR || buffer.timedOut()) {
-        ALOGW("CommandSection '%s' failed to read data from incident helper: %s, "
-            "timedout: %s, kill command: %s, kill incident helper: %s",
-            this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false",
-            strerror(-kill_child(cmdPid)), strerror(-kill_child(ihPid)));
+        ALOGW("CommandSection '%s' failed to read data from incident helper: %s, timedout: %s",
+            this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
+        kill_child(cmdPid);
+        kill_child(ihPid);
         return readStatus;
     }
 
diff --git a/cmds/incidentd/src/io_util.cpp b/cmds/incidentd/src/io_util.cpp
index af4a35c..90f543e 100644
--- a/cmds/incidentd/src/io_util.cpp
+++ b/cmds/incidentd/src/io_util.cpp
@@ -23,7 +23,7 @@
 status_t write_all(int fd, uint8_t const* buf, size_t size)
 {
     while (size > 0) {
-        ssize_t amt = ::write(fd, buf, size);
+        ssize_t amt = TEMP_FAILURE_RETRY(::write(fd, buf, size));
         if (amt < 0) {
             return -errno;
         }
diff --git a/cmds/incidentd/src/report_directory.cpp b/cmds/incidentd/src/report_directory.cpp
index 65030b3..20111d8 100644
--- a/cmds/incidentd/src/report_directory.cpp
+++ b/cmds/incidentd/src/report_directory.cpp
@@ -58,26 +58,9 @@
                 goto done;
             }
         } else {
-            if (mkdir(dir, 0770)) {
-                ALOGE("No incident reports today. "
-                        "Unable to create incident report dir %s: %s", dir,
-                        strerror(errno));
-                err = -errno;
-                goto done;
-            }
-            if (chmod(dir, 0770)) {
-                ALOGE("No incident reports today. "
-                        "Unable to set permissions for incident report dir %s: %s", dir,
-                        strerror(errno));
-                err = -errno;
-                goto done;
-            }
-            if (chown(dir, AID_SYSTEM, AID_SYSTEM)) {
-                ALOGE("No incident reports today. Unable to change ownership of dir %s: %s\n",
-                        dir, strerror(errno));
-                err = -errno;
-                goto done;
-            }
+            ALOGE("No such directory %s, something wrong.", dir);
+            err = -1;
+            goto done;
         }
         if (!last) {
             *d++ = '/';
@@ -97,8 +80,7 @@
         err = BAD_VALUE;
         goto done;
     }
-    if ((st.st_uid != AID_SYSTEM && st.st_uid != AID_ROOT) ||
-        (st.st_gid != AID_SYSTEM && st.st_gid != AID_ROOT)) {
+    if (st.st_uid != AID_INCIDENTD || st.st_gid != AID_INCIDENTD) {
         ALOGE("No incident reports today. Owner is %d and group is %d on report directory %s",
                 st.st_uid, st.st_gid, directory);
         err = BAD_VALUE;
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 5eff548..01f4a84 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -34,6 +34,7 @@
     src/config/ConfigKey.cpp \
     src/config/ConfigListener.cpp \
     src/config/ConfigManager.cpp \
+    src/external/Perfetto.cpp \
     src/external/StatsPuller.cpp \
     src/external/StatsCompanionServicePuller.cpp \
     src/external/SubsystemSleepStatePuller.cpp \
@@ -57,6 +58,7 @@
     src/metrics/MetricsManager.cpp \
     src/metrics/metrics_manager_util.cpp \
     src/packages/UidMap.cpp \
+    src/perfetto/perfetto_config.proto \
     src/storage/StorageManager.cpp \
     src/StatsLogProcessor.cpp \
     src/StatsService.cpp \
@@ -209,6 +211,7 @@
 LOCAL_SRC_FILES := \
     src/stats_log.proto \
     src/statsd_config.proto \
+    src/perfetto/perfetto_config.proto \
     src/atoms.proto
 
 LOCAL_PROTOC_OPTIMIZE_TYPE := lite
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index f10b2cf..9b65acf 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -18,6 +18,7 @@
 #include "Log.h"
 
 #include "AnomalyTracker.h"
+#include "external/Perfetto.h"
 #include "guardrail/StatsdStats.h"
 
 #include <android/os/IIncidentManager.h>
@@ -239,7 +240,7 @@
                 }
                 break;
             case Subscription::SubscriberInformationCase::kPerfettoDetails:
-                ALOGW("Perfetto reports not implemented.");
+                CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details());
                 break;
             default:
                 break;
diff --git a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
index a61afb4..a751273 100644
--- a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
+++ b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
@@ -34,7 +34,7 @@
 namespace os {
 namespace statsd {
 
-static const string sProcFile = "/proc/uid_cputime/show_uid_stat";
+static const string sProcFile = "/proc/uid_time_in_state";
 static const int kLineBufferSize = 1024;
 
 /**
diff --git a/cmds/statsd/src/external/Perfetto.cpp b/cmds/statsd/src/external/Perfetto.cpp
new file mode 100644
index 0000000..f7b33e7
--- /dev/null
+++ b/cmds/statsd/src/external/Perfetto.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 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 "Log.h"
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"  // Alert
+
+#include <android-base/unique_fd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <string>
+
+namespace {
+const char kDropboxTag[] = "perfetto";
+}
+
+namespace android {
+namespace os {
+namespace statsd {
+
+bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config) {
+    ALOGD("Starting trace collection through perfetto");
+
+    if (!config.has_trace_config()) {
+        ALOGE("The perfetto trace config is empty, aborting");
+        return false;
+    }
+
+    android::base::unique_fd readPipe;
+    android::base::unique_fd writePipe;
+    if (!android::base::Pipe(&readPipe, &writePipe)) {
+        ALOGE("pipe() failed while calling the Perfetto client: %s", strerror(errno));
+        return false;
+    }
+
+    pid_t pid = fork();
+    if (pid < 0) {
+        ALOGE("fork() failed while calling the Perfetto client: %s", strerror(errno));
+        return false;
+    }
+
+    if (pid == 0) {
+        // Child process.
+
+        // No malloc calls or library calls after this point. Remember that even
+        // ALOGx (aka android_printLog()) can use dynamic memory for vsprintf().
+
+        writePipe.reset();  // Close the write end (owned by the main process).
+
+        // Replace stdin with |readPipe| so the main process can write into it.
+        if (dup2(readPipe.get(), STDIN_FILENO) < 0) _exit(1);
+        execl("/system/bin/perfetto", "perfetto", "--background", "--config", "-", "--dropbox",
+              kDropboxTag, nullptr);
+
+        // execl() doesn't return in case of success, if we get here something failed.
+        _exit(1);
+    }
+
+    // Main process.
+
+    readPipe.reset();  // Close the read end (owned by the child process).
+
+    // Using fopen() because fwrite() has the right logic to chunking write()
+    // over a pipe (see __sfvwrite()).
+    FILE* writePipeStream = fdopen(writePipe.get(), "wb");
+    if (!writePipeStream) {
+        ALOGE("fdopen() failed while calling the Perfetto client: %s", strerror(errno));
+        return false;
+    }
+
+    std::string cfgProto = config.trace_config().SerializeAsString();
+    size_t bytesWritten = fwrite(cfgProto.data(), 1, cfgProto.size(), writePipeStream);
+    fclose(writePipeStream);
+    if (bytesWritten != cfgProto.size() || cfgProto.size() == 0) {
+        ALOGE("fwrite() failed (ret: %zd) while calling the Perfetto client: %s", bytesWritten,
+              strerror(errno));
+        return false;
+    }
+
+    // This does NOT wait for the full duration of the trace. It just waits until the process
+    // has read the config from stdin and detached.
+    int childStatus = 0;
+    waitpid(pid, &childStatus, 0);
+    if (!WIFEXITED(childStatus) || WEXITSTATUS(childStatus) != 0) {
+        ALOGE("Child process failed (0x%x) while calling the Perfetto client", childStatus);
+        return false;
+    }
+
+    ALOGD("CollectPerfettoTraceAndUploadToDropbox() succeeded");
+    return true;
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/external/Perfetto.h b/cmds/statsd/src/external/Perfetto.h
new file mode 100644
index 0000000..e2e0253
--- /dev/null
+++ b/cmds/statsd/src/external/Perfetto.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 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
+
+using android::os::StatsLogEventWrapper;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class PerfettoDetails;  // Declared in statsd_config.pb.h
+
+// Starts the collection of a Perfetto trace with the given |config|.
+// The trace is uploaded to Dropbox by the perfetto cmdline util once done.
+// This method returns immediately after passing the config and does NOT wait
+// for the full duration of the trace.
+bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config);
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index c7550f7..e985873 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -285,8 +285,15 @@
             interval.start = value;
             interval.startUpdated = true;
         } else {
+            // Generally we expect value to be monotonically increasing.
+            // If not, there was a reset event. We take the absolute value as
+            // diff in this case.
             if (interval.startUpdated) {
-                interval.sum += (value - interval.start);
+                if (value > interval.start) {
+                    interval.sum += (value - interval.start);
+                } else {
+                    interval.sum += value;
+                }
                 interval.startUpdated = false;
             } else {
                 VLOG("No start for matching end %ld", value);
diff --git a/cmds/statsd/src/perfetto/perfetto_config.proto b/cmds/statsd/src/perfetto/perfetto_config.proto
new file mode 100644
index 0000000..dc868f9
--- /dev/null
+++ b/cmds/statsd/src/perfetto/perfetto_config.proto
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+message DataSourceConfig {
+  message FtraceConfig {
+    repeated string event_names = 1;
+  }
+
+  optional string name = 1;
+
+  optional uint32 target_buffer = 2;
+
+  optional FtraceConfig ftrace_config = 100;
+}
+
+message TraceConfig {
+  message BufferConfig {
+    optional uint32 size_kb = 1;
+
+    enum OptimizeFor {
+      DEFAULT = 0;
+      ONE_SHOT_READ = 1;
+
+    }
+    optional OptimizeFor optimize_for = 3;
+
+    enum FillPolicy {
+      UNSPECIFIED = 0;
+      RING_BUFFER = 1;
+    }
+    optional FillPolicy fill_policy = 4;
+  }
+  repeated BufferConfig buffers = 1;
+
+  message DataSource {
+    optional protos.DataSourceConfig config = 1;
+
+    repeated string producer_name_filter = 2;
+  }
+  repeated DataSource data_sources = 2;
+
+  optional uint32 duration_ms = 3;
+}
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 6247854..cd60ee7 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -22,6 +22,8 @@
 option java_package = "com.android.internal.os";
 option java_outer_classname = "StatsdConfigProto";
 
+import "frameworks/base/cmds/statsd/src/perfetto/perfetto_config.proto";
+
 enum Position {
     POSITION_UNKNOWN = 0;
     FIRST = 1;
@@ -272,7 +274,7 @@
 }
 
 message PerfettoDetails {
-    optional int32 perfetto_stuff = 1;
+    optional perfetto.protos.TraceConfig trace_config = 1;
 }
 
 message Subscription {
diff --git a/cmds/statsd/tools/dogfood/Android.mk b/cmds/statsd/tools/dogfood/Android.mk
index a4c0800..73fbaa4 100644
--- a/cmds/statsd/tools/dogfood/Android.mk
+++ b/cmds/statsd/tools/dogfood/Android.mk
@@ -21,9 +21,11 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_SRC_FILES += ../../src/stats_log.proto \
                    ../../src/atoms.proto \
+                   ../../src/perfetto/perfetto_config.proto \
                    ../../src/statsd_config.proto
 
 LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/../../src/
+
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite
 
diff --git a/cmds/statsd/tools/loadtest/Android.mk b/cmds/statsd/tools/loadtest/Android.mk
index 0a0fd66..f5722c2 100644
--- a/cmds/statsd/tools/loadtest/Android.mk
+++ b/cmds/statsd/tools/loadtest/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_SRC_FILES += ../../src/stats_log.proto \
                    ../../src/atoms.proto \
+                   ../../src/perfetto/perfetto_config.proto \
                    ../../src/statsd_config.proto
 LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/../../src/
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 97dcb90..0a4541b 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -363,6 +363,11 @@
      */
     public static final int GLOBAL_ACTION_LOCK_SCREEN = 8;
 
+    /**
+     * Action to take a screenshot
+     */
+    public static final int GLOBAL_ACTION_TAKE_SCREENSHOT = 9;
+
     private static final String LOG_TAG = "AccessibilityService";
 
     /**
diff --git a/core/java/android/hardware/radio/ProgramSelector.java b/core/java/android/hardware/radio/ProgramSelector.java
index 3556751..0cf7605 100644
--- a/core/java/android/hardware/radio/ProgramSelector.java
+++ b/core/java/android/hardware/radio/ProgramSelector.java
@@ -59,24 +59,56 @@
  */
 @SystemApi
 public final class ProgramSelector implements Parcelable {
+    /** Invalid program type.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_INVALID = 0;
-    /** Analogue AM radio (with or without RDS). */
+    /** Analogue AM radio (with or without RDS).
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_AM = 1;
-    /** analogue FM radio (with or without RDS). */
+    /** analogue FM radio (with or without RDS).
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_FM = 2;
-    /** AM HD Radio. */
+    /** AM HD Radio.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_AM_HD = 3;
-    /** FM HD Radio. */
+    /** FM HD Radio.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_FM_HD = 4;
-    /** Digital audio broadcasting. */
+    /** Digital audio broadcasting.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_DAB = 5;
-    /** Digital Radio Mondiale. */
+    /** Digital Radio Mondiale.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_DRMO = 6;
-    /** SiriusXM Satellite Radio. */
+    /** SiriusXM Satellite Radio.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_SXM = 7;
-    /** Vendor-specific, not synced across devices. */
+    /** Vendor-specific, not synced across devices.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_VENDOR_START = 1000;
+    /** @deprecated use {@link ProgramIdentifier} instead */
+    @Deprecated
     public static final int PROGRAM_TYPE_VENDOR_END = 1999;
+    /** @deprecated use {@link ProgramIdentifier} instead */
+    @Deprecated
     @IntDef(prefix = { "PROGRAM_TYPE_" }, value = {
         PROGRAM_TYPE_INVALID,
         PROGRAM_TYPE_AM,
@@ -112,18 +144,46 @@
      *
      * The subchannel index is 0-based (where 0 is MPS and 1..7 are SPS),
      * as opposed to HD Radio standard (where it's 1-based).
+     *
+     * @deprecated use IDENTIFIER_TYPE_HD_STATION_ID_EXT instead
      */
+    @Deprecated
     public static final int IDENTIFIER_TYPE_HD_SUBCHANNEL = 4;
     /**
-     * 24bit compound primary identifier for DAB.
+     * 64bit additional identifier for HD Radio.
+     *
+     * Due to Station ID abuse, some HD_STATION_ID_EXT identifiers may be not
+     * globally unique. To provide a best-effort solution, a short version of
+     * station name may be carried as additional identifier and may be used
+     * by the tuner hardware to double-check tuning.
+     *
+     * The name is limited to the first 8 A-Z0-9 characters (lowercase letters
+     * must be converted to uppercase). Encoded in little-endian ASCII:
+     * the first character of the name is the LSB.
+     *
+     * For example: "Abc" is encoded as 0x434241.
+     */
+    public static final int IDENTIFIER_TYPE_HD_STATION_NAME = 10004;
+    /**
+     * @see {@link IDENTIFIER_TYPE_DAB_SID_EXT}
+     */
+    public static final int IDENTIFIER_TYPE_DAB_SIDECC = 5;
+    /**
+     * 28bit compound primary identifier for Digital Audio Broadcasting.
      *
      * Consists of (from the LSB):
      * - 16bit: SId;
-     * - 8bit: ECC code.
+     * - 8bit: ECC code;
+     * - 4bit: SCIdS.
+     *
+     * SCIdS (Service Component Identifier within the Service) value
+     * of 0 represents the main service, while 1 and above represents
+     * secondary services.
+     *
      * The remaining bits should be set to zeros when writing on the chip side
      * and ignored when read.
      */
-    public static final int IDENTIFIER_TYPE_DAB_SIDECC = 5;
+    public static final int IDENTIFIER_TYPE_DAB_SID_EXT = IDENTIFIER_TYPE_DAB_SIDECC;
     /** 16bit */
     public static final int IDENTIFIER_TYPE_DAB_ENSEMBLE = 6;
     /** 12bit */
@@ -134,7 +194,11 @@
     public static final int IDENTIFIER_TYPE_DRMO_SERVICE_ID = 9;
     /** kHz */
     public static final int IDENTIFIER_TYPE_DRMO_FREQUENCY = 10;
-    /** 1: AM, 2:FM */
+    /**
+     * 1: AM, 2:FM
+     * @deprecated use {@link IDENTIFIER_TYPE_DRMO_FREQUENCY} instead
+     */
+    @Deprecated
     public static final int IDENTIFIER_TYPE_DRMO_MODULATION = 11;
     /** 32bit */
     public static final int IDENTIFIER_TYPE_SXM_SERVICE_ID = 12;
@@ -148,14 +212,29 @@
      * type between VENDOR_START and VENDOR_END (eg. identifier type 1015 must
      * not be used in any program type other than 1015).
      */
-    public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_START = PROGRAM_TYPE_VENDOR_START;
-    public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_END = PROGRAM_TYPE_VENDOR_END;
+    public static final int IDENTIFIER_TYPE_VENDOR_START = PROGRAM_TYPE_VENDOR_START;
+    /**
+     * @see {@link IDENTIFIER_TYPE_VENDOR_START}
+     */
+    public static final int IDENTIFIER_TYPE_VENDOR_END = PROGRAM_TYPE_VENDOR_END;
+    /**
+     * @deprecated use {@link IDENTIFIER_TYPE_VENDOR_START} instead
+     */
+    @Deprecated
+    public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_START = IDENTIFIER_TYPE_VENDOR_START;
+    /**
+     * @deprecated use {@link IDENTIFIER_TYPE_VENDOR_END} instead
+     */
+    @Deprecated
+    public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_END = IDENTIFIER_TYPE_VENDOR_END;
     @IntDef(prefix = { "IDENTIFIER_TYPE_" }, value = {
         IDENTIFIER_TYPE_INVALID,
         IDENTIFIER_TYPE_AMFM_FREQUENCY,
         IDENTIFIER_TYPE_RDS_PI,
         IDENTIFIER_TYPE_HD_STATION_ID_EXT,
         IDENTIFIER_TYPE_HD_SUBCHANNEL,
+        IDENTIFIER_TYPE_HD_STATION_NAME,
+        IDENTIFIER_TYPE_DAB_SID_EXT,
         IDENTIFIER_TYPE_DAB_SIDECC,
         IDENTIFIER_TYPE_DAB_ENSEMBLE,
         IDENTIFIER_TYPE_DAB_SCID,
@@ -166,7 +245,7 @@
         IDENTIFIER_TYPE_SXM_SERVICE_ID,
         IDENTIFIER_TYPE_SXM_CHANNEL,
     })
-    @IntRange(from = IDENTIFIER_TYPE_VENDOR_PRIMARY_START, to = IDENTIFIER_TYPE_VENDOR_PRIMARY_END)
+    @IntRange(from = IDENTIFIER_TYPE_VENDOR_START, to = IDENTIFIER_TYPE_VENDOR_END)
     @Retention(RetentionPolicy.SOURCE)
     public @interface IdentifierType {}
 
@@ -205,7 +284,9 @@
      * Type of a radio technology.
      *
      * @return program type.
+     * @deprecated use {@link getPrimaryId} instead
      */
+    @Deprecated
     public @ProgramType int getProgramType() {
         return mProgramType;
     }
@@ -273,7 +354,10 @@
      * preserving elements order.
      *
      * @return an array of vendor identifiers, must not be modified.
+     * @deprecated for HAL 1.x compatibility;
+     *             HAL 2.x uses standard primary/secondary lists for vendor IDs
      */
+    @Deprecated
     public @NonNull long[] getVendorIds() {
         return mVendorIds;
     }
@@ -427,6 +511,10 @@
         private final long mValue;
 
         public Identifier(@IdentifierType int type, long value) {
+            if (type == IDENTIFIER_TYPE_HD_STATION_NAME) {
+                // see getType
+                type = IDENTIFIER_TYPE_HD_SUBCHANNEL;
+            }
             mType = type;
             mValue = value;
         }
@@ -437,6 +525,13 @@
          * @return type of an identifier.
          */
         public @IdentifierType int getType() {
+            if (mType == IDENTIFIER_TYPE_HD_SUBCHANNEL && mValue > 10) {
+                /* HD_SUBCHANNEL and HD_STATION_NAME use the same identifier type, but they differ
+                 * in possible values: sub channel is 0-7, station name is greater than ASCII space
+                 * code (32).
+                 */
+                return IDENTIFIER_TYPE_HD_STATION_NAME;
+            }
             return mType;
         }
 
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 2cda58c..f04f03f6 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -19,6 +19,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
@@ -625,6 +626,133 @@
     }
 
     /**
+     * This class represents an IpSecTunnelInterface
+     *
+     * <p>IpSecTunnelInterface objects track tunnel interfaces that serve as
+     * local endpoints for IPsec tunnels.
+     *
+     * <p>Creating an IpSecTunnelInterface creates a device to which IpSecTransforms may be
+     * applied to provide IPsec security to packets sent through the tunnel. While a tunnel
+     * cannot be used in standalone mode within Android, the higher layers may use the tunnel
+     * to create Network objects which are accessible to the Android system.
+     * @hide
+     */
+    @SystemApi
+    public static final class IpSecTunnelInterface implements AutoCloseable {
+        private final IIpSecService mService;
+        private final InetAddress mRemoteAddress;
+        private final InetAddress mLocalAddress;
+        private final Network mUnderlyingNetwork;
+        private final CloseGuard mCloseGuard = CloseGuard.get();
+        private String mInterfaceName;
+        private int mResourceId = INVALID_RESOURCE_ID;
+
+        /** Get the underlying SPI held by this object. */
+        public String getInterfaceName() {
+            return mInterfaceName;
+        }
+
+        /**
+         * Add an address to the IpSecTunnelInterface
+         *
+         * <p>Add an address which may be used as the local inner address for
+         * tunneled traffic.
+         *
+         * @param address the local address for traffic inside the tunnel
+         * @throws IOException if the address could not be added
+         * @hide
+         */
+        public void addAddress(LinkAddress address) throws IOException {
+        }
+
+        /**
+         * Remove an address from the IpSecTunnelInterface
+         *
+         * <p>Remove an address which was previously added to the IpSecTunnelInterface
+         *
+         * @param address to be removed
+         * @throws IOException if the address could not be removed
+         * @hide
+         */
+        public void removeAddress(LinkAddress address) throws IOException {
+        }
+
+        private IpSecTunnelInterface(@NonNull IIpSecService service,
+                @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress,
+                @NonNull Network underlyingNetwork)
+                throws ResourceUnavailableException, IOException {
+            mService = service;
+            mLocalAddress = localAddress;
+            mRemoteAddress = remoteAddress;
+            mUnderlyingNetwork = underlyingNetwork;
+            // TODO: Call IpSecService
+        }
+
+        /**
+         * Delete an IpSecTunnelInterface
+         *
+         * <p>Calling close will deallocate the IpSecTunnelInterface and all of its system
+         * resources. Any packets bound for this interface either inbound or outbound will
+         * all be lost.
+         */
+        @Override
+        public void close() {
+            // try {
+            // TODO: Call IpSecService
+            mResourceId = INVALID_RESOURCE_ID;
+            // } catch (RemoteException e) {
+            //    throw e.rethrowFromSystemServer();
+            // }
+            mCloseGuard.close();
+        }
+
+        /** Check that the Interface was closed properly. */
+        @Override
+        protected void finalize() throws Throwable {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
+            }
+            close();
+        }
+    }
+
+    /**
+     * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic.
+     *
+     * @param localAddress The local addres of the tunnel
+     * @param remoteAddress The local addres of the tunnel
+     * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel.
+     *        This network should almost certainly be a network such as WiFi with an L2 address.
+     * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties
+     * @throws IOException indicating that the socket could not be opened or bound
+     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
+     * @hide
+     */
+    @SystemApi
+    public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
+            @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
+            throws ResourceUnavailableException, IOException {
+        return new IpSecTunnelInterface(mService, localAddress, remoteAddress, underlyingNetwork);
+    }
+
+    /**
+     * Apply a transform to the IpSecTunnelInterface
+     *
+     * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied
+     *        transform.
+     * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which
+     *        the transform will be used.
+     * @param transform an {@link IpSecTransform} created in tunnel mode
+     * @throws IOException indicating that the transform could not be applied due to a lower
+     *         layer failure.
+     * @hide
+     */
+    @SystemApi
+    void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction,
+            IpSecTransform transform) throws IOException {
+        // TODO: call IpSecService
+    }
+    /**
      * Construct an instance of IpSecManager within an application context.
      *
      * @param context the application context for this manager
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 7b9b483..be6026f 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -300,21 +300,6 @@
         }
 
         /**
-         * Set the {@link Network} which will carry tunneled traffic.
-         *
-         * <p>Restricts the transformed traffic to a particular {@link Network}. This is required
-         * for tunnel mode, otherwise tunneled traffic would be sent on the default network.
-         *
-         * @hide
-         */
-        @SystemApi
-        public IpSecTransform.Builder setUnderlyingNetwork(@NonNull Network net) {
-            Preconditions.checkNotNull(net);
-            mConfig.setNetwork(net);
-            return this;
-        }
-
-        /**
          * Add UDP encapsulation to an IPv4 transform.
          *
          * <p>This allows IPsec traffic to pass through a NAT.
@@ -415,6 +400,7 @@
          * @throws IOException indicating other errors
          * @hide
          */
+        @SystemApi
         public IpSecTransform buildTunnelModeTransform(
                 @NonNull InetAddress sourceAddress,
                 @NonNull IpSecManager.SecurityParameterIndex spi)
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index dc271d8..49879a8 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -35,6 +35,7 @@
 import android.view.Display;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.location.gnssmetrics.GnssMetrics;
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatteryStatsHelper;
 
@@ -683,6 +684,14 @@
 
         public abstract long[] getCpuFreqTimes(int which);
         public abstract long[] getScreenOffCpuFreqTimes(int which);
+        /**
+         * Returns cpu active time of an uid.
+         */
+        public abstract long getCpuActiveTime();
+        /**
+         * Returns cpu times of an uid on each cluster
+         */
+        public abstract long[] getCpuClusterTimes();
 
         /**
          * Returns cpu times of an uid at a particular process state.
@@ -1500,6 +1509,10 @@
         public static final int STATE2_WIFI_SIGNAL_STRENGTH_SHIFT = 4;
         public static final int STATE2_WIFI_SIGNAL_STRENGTH_MASK =
                 0x7 << STATE2_WIFI_SIGNAL_STRENGTH_SHIFT;
+        // Values for NUM_GPS_SIGNAL_QUALITY_LEVELS
+        public static final int STATE2_GPS_SIGNAL_QUALITY_SHIFT = 7;
+        public static final int STATE2_GPS_SIGNAL_QUALITY_MASK =
+            0x1 << STATE2_GPS_SIGNAL_QUALITY_SHIFT;
 
         public static final int STATE2_POWER_SAVE_FLAG = 1<<31;
         public static final int STATE2_VIDEO_ON_FLAG = 1<<30;
@@ -2088,6 +2101,23 @@
      */
     public abstract int getNumConnectivityChange(int which);
 
+
+    /**
+     * Returns the time in microseconds that the phone has been running with
+     * the given GPS signal quality level
+     *
+     * {@hide}
+     */
+    public abstract long getGpsSignalQualityTime(int strengthBin,
+        long elapsedRealtimeUs, int which);
+
+    /**
+     * Returns the GPS battery drain in mA-ms
+     *
+     * {@hide}
+     */
+    public abstract long getGpsBatteryDrainMaMs();
+
     /**
      * Returns the time in microseconds that the phone has been on while the device was
      * running on battery.
@@ -2312,6 +2342,9 @@
                 WIFI_SUPPL_STATE_NAMES, WIFI_SUPPL_STATE_SHORT_NAMES),
         new BitDescription(HistoryItem.STATE2_CAMERA_FLAG, "camera", "ca"),
         new BitDescription(HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG, "ble_scan", "bles"),
+        new BitDescription(HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK,
+            HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT, "gps_signal_quality", "Gss",
+            new String[] { "poor", "good"}, new String[] { "poor", "good"}),
     };
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
@@ -4732,6 +4765,43 @@
         pw.print(prefix);
         sb.setLength(0);
         sb.append(prefix);
+        sb.append("  GPS Statistics:");
+        pw.println(sb.toString());
+
+        sb.setLength(0);
+        sb.append(prefix);
+        sb.append("     GPS signal quality (Top 4 Average CN0):");
+        final String[] gpsSignalQualityDescription = new String[]{
+            "poor (less than 20 dBHz): ",
+            "good (greater than 20 dBHz): "};
+        final int numGpsSignalQualityBins = Math.min(GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS,
+            gpsSignalQualityDescription.length);
+        for (int i=0; i<numGpsSignalQualityBins; i++) {
+            final long time = getGpsSignalQualityTime(i, rawRealtime, which);
+            sb.append("\n    ");
+            sb.append(prefix);
+            sb.append("  ");
+            sb.append(gpsSignalQualityDescription[i]);
+            formatTimeMs(sb, time/1000);
+            sb.append("(");
+            sb.append(formatRatioLocked(time, whichBatteryRealtime));
+            sb.append(") ");
+        }
+        pw.println(sb.toString());
+
+        final long gpsBatteryDrainMaMs = getGpsBatteryDrainMaMs();
+        if (gpsBatteryDrainMaMs > 0) {
+            pw.print(prefix);
+            sb.setLength(0);
+            sb.append(prefix);
+            sb.append("     Battery Drain (mAh): ");
+            sb.append(Double.toString(((double) gpsBatteryDrainMaMs)/(3600 * 1000)));
+            pw.println(sb.toString());
+        }
+
+        pw.print(prefix);
+        sb.setLength(0);
+        sb.append(prefix);
         sb.append("  CONNECTIVITY POWER SUMMARY END");
         pw.println(sb.toString());
         pw.println("");
diff --git a/core/java/android/os/IPermissionController.aidl b/core/java/android/os/IPermissionController.aidl
index 5e8590a..3de953a 100644
--- a/core/java/android/os/IPermissionController.aidl
+++ b/core/java/android/os/IPermissionController.aidl
@@ -22,4 +22,5 @@
     boolean checkPermission(String permission, int pid, int uid);
     String[] getPackagesForUid(int uid);
     boolean isRuntimePermission(String permission);
+    int getPackageUid(String packageName, int flags);
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index e6cf5e6..7654e9b 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -151,6 +151,12 @@
      */
     public static final int OTA_UPDATE_UID = 1061;
 
+    /**
+     * Defines the UID used for incidentd.
+     * @hide
+     */
+    public static final int INCIDENTD_UID = 1067;
+
     /** {@hide} */
     public static final int NOBODY_UID = 9999;
 
diff --git a/core/java/android/os/connectivity/GpsBatteryStats.aidl b/core/java/android/os/connectivity/GpsBatteryStats.aidl
new file mode 100644
index 0000000..7b96d1a
--- /dev/null
+++ b/core/java/android/os/connectivity/GpsBatteryStats.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.connectivity;
+
+/** {@hide} */
+parcelable GpsBatteryStats;
\ No newline at end of file
diff --git a/core/java/android/os/connectivity/GpsBatteryStats.java b/core/java/android/os/connectivity/GpsBatteryStats.java
new file mode 100644
index 0000000..f2ac5ef
--- /dev/null
+++ b/core/java/android/os/connectivity/GpsBatteryStats.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os.connectivity;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.location.gnssmetrics.GnssMetrics;
+
+import java.util.Arrays;
+
+/**
+ * API for GPS power stats
+ *
+ * @hide
+ */
+public final class GpsBatteryStats implements Parcelable {
+
+  private long mLoggingDurationMs;
+  private long mEnergyConsumedMaMs;
+  private long[] mTimeInGpsSignalQualityLevel;
+
+  public static final Parcelable.Creator<GpsBatteryStats> CREATOR = new
+      Parcelable.Creator<GpsBatteryStats>() {
+        public GpsBatteryStats createFromParcel(Parcel in) {
+          return new GpsBatteryStats(in);
+        }
+
+        public GpsBatteryStats[] newArray(int size) {
+          return new GpsBatteryStats[size];
+        }
+      };
+
+  public GpsBatteryStats() {
+    initialize();
+  }
+
+  @Override
+  public void writeToParcel(Parcel out, int flags) {
+    out.writeLong(mLoggingDurationMs);
+    out.writeLong(mEnergyConsumedMaMs);
+    out.writeLongArray(mTimeInGpsSignalQualityLevel);
+  }
+
+  public void readFromParcel(Parcel in) {
+    mLoggingDurationMs = in.readLong();
+    mEnergyConsumedMaMs = in.readLong();
+    in.readLongArray(mTimeInGpsSignalQualityLevel);
+  }
+
+  public long getLoggingDurationMs() {
+    return mLoggingDurationMs;
+  }
+
+  public long getEnergyConsumedMaMs() {
+    return mEnergyConsumedMaMs;
+  }
+
+  public long[] getTimeInGpsSignalQualityLevel() {
+    return mTimeInGpsSignalQualityLevel;
+  }
+
+  public void setLoggingDurationMs(long t) {
+    mLoggingDurationMs = t;
+    return;
+  }
+
+  public void setEnergyConsumedMaMs(long e) {
+    mEnergyConsumedMaMs = e;
+    return;
+  }
+
+  public void setTimeInGpsSignalQualityLevel(long[] t) {
+    mTimeInGpsSignalQualityLevel = Arrays.copyOfRange(t, 0,
+        Math.min(t.length, GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS));
+    return;
+  }
+
+  @Override
+  public int describeContents() {
+    return 0;
+  }
+
+  private GpsBatteryStats(Parcel in) {
+    initialize();
+    readFromParcel(in);
+  }
+
+  private void initialize() {
+    mLoggingDurationMs = 0;
+    mEnergyConsumedMaMs = 0;
+    mTimeInGpsSignalQualityLevel = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+    return;
+  }
+}
\ No newline at end of file
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8c2a8ae..b2cc18b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16,10 +16,12 @@
 
 package android.provider;
 
+import static android.provider.SettingsValidators.ANY_INTEGER_VALIDATOR;
 import static android.provider.SettingsValidators.ANY_STRING_VALIDATOR;
 import static android.provider.SettingsValidators.BOOLEAN_VALIDATOR;
 import static android.provider.SettingsValidators.COMPONENT_NAME_VALIDATOR;
 import static android.provider.SettingsValidators.LENIENT_IP_ADDRESS_VALIDATOR;
+import static android.provider.SettingsValidators.LOCALE_VALIDATOR;
 import static android.provider.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
 import static android.provider.SettingsValidators.PACKAGE_NAME_VALIDATOR;
 import static android.provider.SettingsValidators.URI_VALIDATOR;
@@ -4008,6 +4010,9 @@
          * Keys we no longer back up under the current schema, but want to continue to
          * process when restoring historical backup datasets.
          *
+         * All settings in {@link LEGACY_RESTORE_SETTINGS} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
          * @hide
          */
         public static final String[] LEGACY_RESTORE_SETTINGS = {
@@ -4116,6 +4121,9 @@
         /**
          * These are all public system settings
          *
+         * All settings in {@link SETTINGS_TO_BACKUP} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
          * @hide
          */
         public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
@@ -4391,8 +4399,8 @@
         public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
                 Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
 
-       private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR =
-               BOOLEAN_VALIDATOR;
+        private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR =
+                BOOLEAN_VALIDATOR;
 
         /**
          * @deprecated Use
@@ -4402,6 +4410,9 @@
         public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
                 Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY;
 
+        private static final Validator WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_NUM_OPEN_NETWORKS_KEPT}
          * instead
@@ -4409,6 +4420,9 @@
         @Deprecated
         public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = Global.WIFI_NUM_OPEN_NETWORKS_KEPT;
 
+        private static final Validator WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_ON} instead
          */
@@ -5190,6 +5204,8 @@
         @Deprecated
         public static final String ALLOW_MOCK_LOCATION = "mock_location";
 
+        private static final Validator ALLOW_MOCK_LOCATION_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * On Android 8.0 (API level 26) and higher versions of the platform,
          * a 64-bit number (expressed as a hexadecimal string), unique to
@@ -5284,6 +5300,8 @@
         @TestApi
         public static final String AUTOFILL_SERVICE = "autofill_service";
 
+        private static final Validator AUTOFILL_SERVICE_VALIDATOR = COMPONENT_NAME_VALIDATOR;
+
         /**
          * Boolean indicating if Autofill supports field classification.
          *
@@ -5370,9 +5388,38 @@
          * List of input methods that are currently enabled.  This is a string
          * containing the IDs of all enabled input methods, each ID separated
          * by ':'.
+         *
+         * Format like "ime0;subtype0;subtype1;subtype2:ime1:ime2;subtype0"
+         * where imeId is ComponentName and subtype is int32.
          */
         public static final String ENABLED_INPUT_METHODS = "enabled_input_methods";
 
+        private static final Validator ENABLED_INPUT_METHODS_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                if (value == null) {
+                    return false;
+                }
+                String[] inputMethods = value.split(":");
+                boolean valid = true;
+                for (String inputMethod : inputMethods) {
+                    if (inputMethod.length() == 0) {
+                        return false;
+                    }
+                    String[] subparts = inputMethod.split(";");
+                    for (String subpart : subparts) {
+                        // allow either a non negative integer or a ComponentName
+                        valid |= (NON_NEGATIVE_INTEGER_VALIDATOR.validate(subpart)
+                                || COMPONENT_NAME_VALIDATOR.validate(subpart));
+                    }
+                    if (!valid) {
+                        return false;
+                    }
+                }
+                return valid;
+            }
+        };
+
         /**
          * List of system input methods that are currently disabled.  This is a string
          * containing the IDs of all disabled input methods, each ID separated
@@ -5388,6 +5435,8 @@
          */
         public static final String SHOW_IME_WITH_HARD_KEYBOARD = "show_ime_with_hard_keyboard";
 
+        private static final Validator SHOW_IME_WITH_HARD_KEYBOARD_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Host name and port for global http proxy. Uses ':' seperator for
          * between host and port.
@@ -5677,6 +5726,8 @@
          */
         public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled";
 
+        private static final Validator ACCESSIBILITY_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Setting specifying if the accessibility shortcut is enabled.
          * @hide
@@ -5684,6 +5735,8 @@
         public static final String ACCESSIBILITY_SHORTCUT_ENABLED =
                 "accessibility_shortcut_enabled";
 
+        private static final Validator ACCESSIBILITY_SHORTCUT_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Setting specifying if the accessibility shortcut is enabled.
          * @hide
@@ -5691,6 +5744,9 @@
         public static final String ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN =
                 "accessibility_shortcut_on_lock_screen";
 
+        private static final Validator ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting specifying if the accessibility shortcut dialog has been shown to this user.
          * @hide
@@ -5698,6 +5754,9 @@
         public static final String ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN =
                 "accessibility_shortcut_dialog_shown";
 
+        private static final Validator ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting specifying the accessibility service to be toggled via the accessibility
          * shortcut. Must be its flattened {@link ComponentName}.
@@ -5706,6 +5765,9 @@
         public static final String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE =
                 "accessibility_shortcut_target_service";
 
+        private static final Validator ACCESSIBILITY_SHORTCUT_TARGET_SERVICE_VALIDATOR =
+                COMPONENT_NAME_VALIDATOR;
+
         /**
          * Setting specifying the accessibility service or feature to be toggled via the
          * accessibility button in the navigation bar. This is either a flattened
@@ -5716,17 +5778,32 @@
         public static final String ACCESSIBILITY_BUTTON_TARGET_COMPONENT =
                 "accessibility_button_target_component";
 
+        private static final Validator ACCESSIBILITY_BUTTON_TARGET_COMPONENT_VALIDATOR =
+                new Validator() {
+                    @Override
+                    public boolean validate(String value) {
+                        // technically either ComponentName or class name, but there's proper value
+                        // validation at callsites, so allow any non-null string
+                        return value != null;
+                    }
+                };
+
         /**
          * If touch exploration is enabled.
          */
         public static final String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
 
+        private static final Validator TOUCH_EXPLORATION_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * List of the enabled accessibility providers.
          */
         public static final String ENABLED_ACCESSIBILITY_SERVICES =
             "enabled_accessibility_services";
 
+        private static final Validator ENABLED_ACCESSIBILITY_SERVICES_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(":");
+
         /**
          * List of the accessibility services to which the user has granted
          * permission to put the device into touch exploration mode.
@@ -5736,6 +5813,9 @@
         public static final String TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES =
             "touch_exploration_granted_accessibility_services";
 
+        private static final Validator TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(":");
+
         /**
          * Uri of the slice that's presented on the keyguard.
          * Defaults to a slice with the date and next alarm.
@@ -5754,6 +5834,8 @@
         @Deprecated
         public static final String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
 
+        private static final Validator ACCESSIBILITY_SPEAK_PASSWORD_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether to draw text with high contrast while in accessibility mode.
          *
@@ -5762,6 +5844,9 @@
         public static final String ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED =
                 "high_text_contrast_enabled";
 
+        private static final Validator ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting that specifies whether the display magnification is enabled via a system-wide
          * triple tap gesture. Display magnifications allows the user to zoom in the display content
@@ -5774,6 +5859,9 @@
         public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED =
                 "accessibility_display_magnification_enabled";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting that specifies whether the display magnification is enabled via a shortcut
          * affordance within the system's navigation area. Display magnifications allows the user to
@@ -5785,6 +5873,9 @@
         public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED =
                 "accessibility_display_magnification_navbar_enabled";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED_VALIDATOR
+                = BOOLEAN_VALIDATOR;
+
         /**
          * Setting that specifies what the display magnification scale is.
          * Display magnifications allows the user to zoom in the display
@@ -5798,6 +5889,9 @@
         public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE =
                 "accessibility_display_magnification_scale";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE_VALIDATOR =
+                new SettingsValidators.InclusiveFloatRangeValidator(1.0f, Float.MAX_VALUE);
+
         /**
          * Unused mangnification setting
          *
@@ -5850,6 +5944,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_ENABLED =
                 "accessibility_captioning_enabled";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting that specifies the language for captions as a locale string,
          * e.g. en_US.
@@ -5860,6 +5957,8 @@
         public static final String ACCESSIBILITY_CAPTIONING_LOCALE =
                 "accessibility_captioning_locale";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_LOCALE_VALIDATOR = LOCALE_VALIDATOR;
+
         /**
          * Integer property that specifies the preset style for captions, one
          * of:
@@ -5874,6 +5973,10 @@
         public static final String ACCESSIBILITY_CAPTIONING_PRESET =
                 "accessibility_captioning_preset";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_PRESET_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"-1", "0", "1", "2",
+                        "3", "4"});
+
         /**
          * Integer property that specifes the background color for captions as a
          * packed 32-bit color.
@@ -5884,6 +5987,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR =
                 "accessibility_captioning_background_color";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR_VALIDATOR =
+                ANY_INTEGER_VALIDATOR;
+
         /**
          * Integer property that specifes the foreground color for captions as a
          * packed 32-bit color.
@@ -5894,6 +6000,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR =
                 "accessibility_captioning_foreground_color";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR_VALIDATOR =
+                ANY_INTEGER_VALIDATOR;
+
         /**
          * Integer property that specifes the edge type for captions, one of:
          * <ul>
@@ -5908,6 +6017,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_EDGE_TYPE =
                 "accessibility_captioning_edge_type";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_EDGE_TYPE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"0", "1", "2"});
+
         /**
          * Integer property that specifes the edge color for captions as a
          * packed 32-bit color.
@@ -5919,6 +6031,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_EDGE_COLOR =
                 "accessibility_captioning_edge_color";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_EDGE_COLOR_VALIDATOR =
+                ANY_INTEGER_VALIDATOR;
+
         /**
          * Integer property that specifes the window color for captions as a
          * packed 32-bit color.
@@ -5929,6 +6044,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_WINDOW_COLOR =
                 "accessibility_captioning_window_color";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_WINDOW_COLOR_VALIDATOR =
+                ANY_INTEGER_VALIDATOR;
+
         /**
          * String property that specifies the typeface for captions, one of:
          * <ul>
@@ -5944,6 +6062,10 @@
         public static final String ACCESSIBILITY_CAPTIONING_TYPEFACE =
                 "accessibility_captioning_typeface";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_TYPEFACE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"DEFAULT",
+                        "MONOSPACE", "SANS_SERIF", "SERIF"});
+
         /**
          * Floating point property that specifies font scaling for captions.
          *
@@ -5952,12 +6074,18 @@
         public static final String ACCESSIBILITY_CAPTIONING_FONT_SCALE =
                 "accessibility_captioning_font_scale";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_FONT_SCALE_VALIDATOR =
+                new SettingsValidators.InclusiveFloatRangeValidator(0.5f, 2.0f);
+
         /**
          * Setting that specifies whether display color inversion is enabled.
          */
         public static final String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED =
                 "accessibility_display_inversion_enabled";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_INVERSION_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting that specifies whether display color space adjustment is
          * enabled.
@@ -5967,15 +6095,24 @@
         public static final String ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED =
                 "accessibility_display_daltonizer_enabled";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Integer property that specifies the type of color space adjustment to
-         * perform. Valid values are defined in AccessibilityManager.
+         * perform. Valid values are defined in AccessibilityManager:
+         * - AccessibilityManager.DALTONIZER_DISABLED = -1
+         * - AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY = 0
+         * - AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY = 12
          *
          * @hide
          */
         public static final String ACCESSIBILITY_DISPLAY_DALTONIZER =
                 "accessibility_display_daltonizer";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_DALTONIZER_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[] {"-1", "0", "12"});
+
         /**
          * Setting that specifies whether automatic click when the mouse pointer stops moving is
          * enabled.
@@ -5985,6 +6122,9 @@
         public static final String ACCESSIBILITY_AUTOCLICK_ENABLED =
                 "accessibility_autoclick_enabled";
 
+        private static final Validator ACCESSIBILITY_AUTOCLICK_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Integer setting specifying amount of time in ms the mouse pointer has to stay still
          * before performing click when {@link #ACCESSIBILITY_AUTOCLICK_ENABLED} is set.
@@ -5995,6 +6135,9 @@
         public static final String ACCESSIBILITY_AUTOCLICK_DELAY =
                 "accessibility_autoclick_delay";
 
+        private static final Validator ACCESSIBILITY_AUTOCLICK_DELAY_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Whether or not larger size icons are used for the pointer of mouse/trackpad for
          * accessibility.
@@ -6004,12 +6147,18 @@
         public static final String ACCESSIBILITY_LARGE_POINTER_ICON =
                 "accessibility_large_pointer_icon";
 
+        private static final Validator ACCESSIBILITY_LARGE_POINTER_ICON_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * The timeout for considering a press to be a long press in milliseconds.
          * @hide
          */
         public static final String LONG_PRESS_TIMEOUT = "long_press_timeout";
 
+        private static final Validator LONG_PRESS_TIMEOUT_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * The duration in milliseconds between the first tap's up event and the second tap's
          * down event for an interaction to be considered part of the same multi-press.
@@ -6063,16 +6212,22 @@
          */
         public static final String TTS_DEFAULT_RATE = "tts_default_rate";
 
+        private static final Validator TTS_DEFAULT_RATE_VALIDATOR = NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Default text-to-speech engine pitch. 100 = 1x
          */
         public static final String TTS_DEFAULT_PITCH = "tts_default_pitch";
 
+        private static final Validator TTS_DEFAULT_PITCH_VALIDATOR = NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Default text-to-speech engine.
          */
         public static final String TTS_DEFAULT_SYNTH = "tts_default_synth";
 
+        private static final Validator TTS_DEFAULT_SYNTH_VALIDATOR = PACKAGE_NAME_VALIDATOR;
+
         /**
          * Default text-to-speech language.
          *
@@ -6120,11 +6275,33 @@
          */
         public static final String TTS_DEFAULT_LOCALE = "tts_default_locale";
 
+        private static final Validator TTS_DEFAULT_LOCALE_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                if (value == null || value.length() == 0) {
+                    return false;
+                }
+                String[] ttsLocales = value.split(",");
+                boolean valid = true;
+                for (String ttsLocale : ttsLocales) {
+                    String[] parts = ttsLocale.split(":");
+                    valid |= ((parts.length == 2)
+                            && (parts[0].length() > 0)
+                            && ANY_STRING_VALIDATOR.validate(parts[0])
+                            && LOCALE_VALIDATOR.validate(parts[1]));
+                }
+                return valid;
+            }
+        };
+
         /**
          * Space delimited list of plugin packages that are enabled.
          */
         public static final String TTS_ENABLED_PLUGINS = "tts_enabled_plugins";
 
+        private static final Validator TTS_ENABLED_PLUGINS_VALIDATOR =
+                new SettingsValidators.PackageNameListValidator(" ");
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON}
          * instead.
@@ -6133,8 +6310,8 @@
         public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
                 Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
 
-       private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR =
-               BOOLEAN_VALIDATOR;
+        private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR =
+                BOOLEAN_VALIDATOR;
 
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY}
@@ -6144,6 +6321,9 @@
         public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
                 Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY;
 
+        private static final Validator WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_NUM_OPEN_NETWORKS_KEPT}
          * instead.
@@ -6152,6 +6332,9 @@
         public static final String WIFI_NUM_OPEN_NETWORKS_KEPT =
                 Global.WIFI_NUM_OPEN_NETWORKS_KEPT;
 
+        private static final Validator WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_ON}
          * instead.
@@ -6310,6 +6493,9 @@
         public static final String PREFERRED_TTY_MODE =
                 "preferred_tty_mode";
 
+        private static final Validator PREFERRED_TTY_MODE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"0", "1", "2", "3"});
+
         /**
          * Whether the enhanced voice privacy mode is enabled.
          * 0 = normal voice privacy
@@ -6318,6 +6504,8 @@
          */
         public static final String ENHANCED_VOICE_PRIVACY_ENABLED = "enhanced_voice_privacy_enabled";
 
+        private static final Validator ENHANCED_VOICE_PRIVACY_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether the TTY mode mode is enabled.
          * 0 = disabled
@@ -6326,6 +6514,8 @@
          */
         public static final String TTY_MODE_ENABLED = "tty_mode_enabled";
 
+        private static final Validator TTY_MODE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Controls whether settings backup is enabled.
          * Type: int ( 0 = disabled, 1 = enabled )
@@ -6496,24 +6686,32 @@
          */
         public static final String MOUNT_PLAY_NOTIFICATION_SND = "mount_play_not_snd";
 
+        private static final Validator MOUNT_PLAY_NOTIFICATION_SND_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether or not UMS auto-starts on UMS host detection. (0 = false, 1 = true)
          * @hide
          */
         public static final String MOUNT_UMS_AUTOSTART = "mount_ums_autostart";
 
+        private static final Validator MOUNT_UMS_AUTOSTART_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether or not a notification is displayed on UMS host detection. (0 = false, 1 = true)
          * @hide
          */
         public static final String MOUNT_UMS_PROMPT = "mount_ums_prompt";
 
+        private static final Validator MOUNT_UMS_PROMPT_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether or not a notification is displayed while UMS is enabled. (0 = false, 1 = true)
          * @hide
          */
         public static final String MOUNT_UMS_NOTIFY_ENABLED = "mount_ums_notify_enabled";
 
+        private static final Validator MOUNT_UMS_NOTIFY_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * If nonzero, ANRs in invisible background processes bring up a dialog.
          * Otherwise, the process will be silently killed.
@@ -6531,6 +6729,9 @@
         public static final String SHOW_FIRST_CRASH_DIALOG_DEV_OPTION =
                 "show_first_crash_dialog_dev_option";
 
+        private static final Validator SHOW_FIRST_CRASH_DIALOG_DEV_OPTION_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * The {@link ComponentName} string of the service to be used as the voice recognition
          * service.
@@ -6556,6 +6757,8 @@
          */
         public static final String SELECTED_SPELL_CHECKER = "selected_spell_checker";
 
+        private static final Validator SELECTED_SPELL_CHECKER_VALIDATOR = COMPONENT_NAME_VALIDATOR;
+
         /**
          * The {@link ComponentName} string of the selected subtype of the selected spell checker
          * service which is one of the services managed by the text service manager.
@@ -6565,13 +6768,18 @@
         public static final String SELECTED_SPELL_CHECKER_SUBTYPE =
                 "selected_spell_checker_subtype";
 
+        private static final Validator SELECTED_SPELL_CHECKER_SUBTYPE_VALIDATOR =
+                COMPONENT_NAME_VALIDATOR;
+
         /**
-         * The {@link ComponentName} string whether spell checker is enabled or not.
+         * Whether spell checker is enabled or not.
          *
          * @hide
          */
         public static final String SPELL_CHECKER_ENABLED = "spell_checker_enabled";
 
+        private static final Validator SPELL_CHECKER_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * What happens when the user presses the Power button while in-call
          * and the screen is on.<br/>
@@ -6583,6 +6791,9 @@
          */
         public static final String INCALL_POWER_BUTTON_BEHAVIOR = "incall_power_button_behavior";
 
+        private static final Validator INCALL_POWER_BUTTON_BEHAVIOR_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"1", "2"});
+
         /**
          * INCALL_POWER_BUTTON_BEHAVIOR value for "turn off screen".
          * @hide
@@ -6638,12 +6849,16 @@
          */
         public static final String WAKE_GESTURE_ENABLED = "wake_gesture_enabled";
 
+        private static final Validator WAKE_GESTURE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether the device should doze if configured.
          * @hide
          */
         public static final String DOZE_ENABLED = "doze_enabled";
 
+        private static final Validator DOZE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether doze should be always on.
          * @hide
@@ -6656,6 +6871,8 @@
          */
         public static final String DOZE_PULSE_ON_PICK_UP = "doze_pulse_on_pick_up";
 
+        private static final Validator DOZE_PULSE_ON_PICK_UP_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether the device should pulse on long press gesture.
          * @hide
@@ -6668,6 +6885,8 @@
          */
         public static final String DOZE_PULSE_ON_DOUBLE_TAP = "doze_pulse_on_double_tap";
 
+        private static final Validator DOZE_PULSE_ON_DOUBLE_TAP_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * The current night mode that has been selected by the user.  Owned
          * and controlled by UiModeManagerService.  Constants are as per
@@ -6682,6 +6901,8 @@
          */
         public static final String SCREENSAVER_ENABLED = "screensaver_enabled";
 
+        private static final Validator SCREENSAVER_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * The user's chosen screensaver components.
          *
@@ -6691,6 +6912,9 @@
          */
         public static final String SCREENSAVER_COMPONENTS = "screensaver_components";
 
+        private static final Validator SCREENSAVER_COMPONENTS_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(",");
+
         /**
          * If screensavers are enabled, whether the screensaver should be automatically launched
          * when the device is inserted into a (desk) dock.
@@ -6698,6 +6922,8 @@
          */
         public static final String SCREENSAVER_ACTIVATE_ON_DOCK = "screensaver_activate_on_dock";
 
+        private static final Validator SCREENSAVER_ACTIVATE_ON_DOCK_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * If screensavers are enabled, whether the screensaver should be automatically launched
          * when the screen times out when not on battery.
@@ -6705,6 +6931,8 @@
          */
         public static final String SCREENSAVER_ACTIVATE_ON_SLEEP = "screensaver_activate_on_sleep";
 
+        private static final Validator SCREENSAVER_ACTIVATE_ON_SLEEP_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * If screensavers are enabled, the default screensaver component.
          * @hide
@@ -6717,6 +6945,9 @@
          */
         public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
 
+        private static final Validator NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR =
+                COMPONENT_NAME_VALIDATOR;
+
         /**
          * Whether NFC payment is handled by the foreground application or a default.
          * @hide
@@ -6814,6 +7045,9 @@
         public static final String ENABLED_NOTIFICATION_ASSISTANT =
                 "enabled_notification_assistant";
 
+        private static final Validator ENABLED_NOTIFICATION_ASSISTANT_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(":");
+
         /**
          * Read only list of the service components that the current user has explicitly allowed to
          * see all of the user's notifications, separated by ':'.
@@ -6825,6 +7059,9 @@
         @Deprecated
         public static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
 
+        private static final Validator ENABLED_NOTIFICATION_LISTENERS_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(":");
+
         /**
          * Read only list of the packages that the current user has explicitly allowed to
          * manage do not disturb, separated by ':'.
@@ -6837,6 +7074,9 @@
         public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES =
                 "enabled_notification_policy_access_packages";
 
+        private static final Validator ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES_VALIDATOR =
+                new SettingsValidators.PackageNameListValidator(":");
+
         /**
          * Defines whether managed profile ringtones should be synced from it's parent profile
          * <p>
@@ -6850,6 +7090,8 @@
         @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
         public static final String SYNC_PARENT_SOUNDS = "sync_parent_sounds";
 
+        private static final Validator SYNC_PARENT_SOUNDS_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /** @hide */
         public static final String IMMERSIVE_MODE_CONFIRMATIONS = "immersive_mode_confirmations";
 
@@ -6936,12 +7178,17 @@
          */
         public static final String SLEEP_TIMEOUT = "sleep_timeout";
 
+        private static final Validator SLEEP_TIMEOUT_VALIDATOR =
+                new SettingsValidators.InclusiveIntegerRangeValidator(-1, Integer.MAX_VALUE);
+
         /**
          * Controls whether double tap to wake is enabled.
          * @hide
          */
         public static final String DOUBLE_TAP_TO_WAKE = "double_tap_to_wake";
 
+        private static final Validator DOUBLE_TAP_TO_WAKE_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * The current assistant component. It could be a voice interaction service,
          * or an activity that handles ACTION_ASSIST, or empty which means using the default
@@ -6958,6 +7205,8 @@
          */
         public static final String CAMERA_GESTURE_DISABLED = "camera_gesture_disabled";
 
+        private static final Validator CAMERA_GESTURE_DISABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether the camera launch gesture to double tap the power button when the screen is off
          * should be disabled.
@@ -6967,6 +7216,9 @@
         public static final String CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED =
                 "camera_double_tap_power_gesture_disabled";
 
+        private static final Validator CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Whether the camera double twist gesture to flip between front and back mode should be
          * enabled.
@@ -6976,6 +7228,9 @@
         public static final String CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED =
                 "camera_double_twist_to_flip_enabled";
 
+        private static final Validator CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Whether or not the smart camera lift trigger that launches the camera when the user moves
          * the phone into a position for taking photos should be enabled.
@@ -6998,6 +7253,9 @@
          */
         public static final String ASSIST_GESTURE_ENABLED = "assist_gesture_enabled";
 
+        private static final Validator ASSIST_GESTURE_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Sensitivity control for the assist gesture.
          *
@@ -7005,6 +7263,9 @@
          */
         public static final String ASSIST_GESTURE_SENSITIVITY = "assist_gesture_sensitivity";
 
+        private static final Validator ASSIST_GESTURE_SENSITIVITY_VALIDATOR =
+                new SettingsValidators.InclusiveFloatRangeValidator(0.0f, 1.0f);
+
         /**
          * Whether the assist gesture should silence alerts.
          *
@@ -7013,6 +7274,9 @@
         public static final String ASSIST_GESTURE_SILENCE_ALERTS_ENABLED =
                 "assist_gesture_silence_alerts_enabled";
 
+        private static final Validator ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Whether the assist gesture should wake the phone.
          *
@@ -7021,6 +7285,9 @@
         public static final String ASSIST_GESTURE_WAKE_ENABLED =
                 "assist_gesture_wake_enabled";
 
+        private static final Validator ASSIST_GESTURE_WAKE_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Whether Assist Gesture Deferred Setup has been completed
          *
@@ -7028,6 +7295,8 @@
          */
         public static final String ASSIST_GESTURE_SETUP_COMPLETE = "assist_gesture_setup_complete";
 
+        private static final Validator ASSIST_GESTURE_SETUP_COMPLETE_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Control whether Night display is currently activated.
          * @hide
@@ -7040,6 +7309,8 @@
          */
         public static final String NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode";
 
+        private static final Validator NIGHT_DISPLAY_AUTO_MODE_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Control the color temperature of Night Display, represented in Kelvin.
          * @hide
@@ -7047,6 +7318,9 @@
         public static final String NIGHT_DISPLAY_COLOR_TEMPERATURE =
                 "night_display_color_temperature";
 
+        private static final Validator NIGHT_DISPLAY_COLOR_TEMPERATURE_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Custom time when Night display is scheduled to activate.
          * Represented as milliseconds from midnight (e.g. 79200000 == 10pm).
@@ -7055,6 +7329,9 @@
         public static final String NIGHT_DISPLAY_CUSTOM_START_TIME =
                 "night_display_custom_start_time";
 
+        private static final Validator NIGHT_DISPLAY_CUSTOM_START_TIME_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Custom time when Night display is scheduled to deactivate.
          * Represented as milliseconds from midnight (e.g. 21600000 == 6am).
@@ -7062,6 +7339,9 @@
          */
         public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
 
+        private static final Validator NIGHT_DISPLAY_CUSTOM_END_TIME_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * A String representing the LocalDateTime when Night display was last activated. Use to
          * decide whether to apply the current activated state after a reboot or user change. In
@@ -7079,6 +7359,9 @@
          */
         public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
 
+        private static final Validator ENABLED_VR_LISTENERS_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(":");
+
         /**
          * Behavior of the display while in VR mode.
          *
@@ -7088,6 +7371,9 @@
          */
         public static final String VR_DISPLAY_MODE = "vr_display_mode";
 
+        private static final Validator VR_DISPLAY_MODE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"0", "1"});
+
         /**
          * Lower the display persistence while the system is in VR mode.
          *
@@ -7144,6 +7430,9 @@
         public static final String AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN =
                 "automatic_storage_manager_days_to_retain";
 
+        private static final Validator AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Default number of days of information for the automatic storage manager to retain.
          *
@@ -7185,12 +7474,30 @@
         public static final String SYSTEM_NAVIGATION_KEYS_ENABLED =
                 "system_navigation_keys_enabled";
 
+        private static final Validator SYSTEM_NAVIGATION_KEYS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Holds comma separated list of ordering of QS tiles.
          * @hide
          */
         public static final String QS_TILES = "sysui_qs_tiles";
 
+        private static final Validator QS_TILES_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                if (value == null) {
+                    return false;
+                }
+                String[] tiles = value.split(",");
+                boolean valid = true;
+                for (String tile : tiles) {
+                    // tile can be any non-empty string as specified by OEM
+                    valid |= ((tile.length() > 0) && ANY_STRING_VALIDATOR.validate(tile));
+                }
+                return valid;
+            }
+        };
+
         /**
          * Specifies whether the web action API is enabled.
          *
@@ -7226,18 +7533,38 @@
          */
         public static final String NOTIFICATION_BADGING = "notification_badging";
 
+        private static final Validator NOTIFICATION_BADGING_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Comma separated list of QS tiles that have been auto-added already.
          * @hide
          */
         public static final String QS_AUTO_ADDED_TILES = "qs_auto_tiles";
 
+        private static final Validator QS_AUTO_ADDED_TILES_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                if (value == null) {
+                    return false;
+                }
+                String[] tiles = value.split(",");
+                boolean valid = true;
+                for (String tile : tiles) {
+                    // tile can be any non-empty string as specified by OEM
+                    valid |= ((tile.length() > 0) && ANY_STRING_VALIDATOR.validate(tile));
+                }
+                return valid;
+            }
+        };
+
         /**
          * Whether the Lockdown button should be shown in the power menu.
          * @hide
          */
         public static final String LOCKDOWN_IN_POWER_MENU = "lockdown_in_power_menu";
 
+        private static final Validator LOCKDOWN_IN_POWER_MENU_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Backup manager behavioral parameters.
          * This is encoded as a key=value list, separated by commas. Ex:
@@ -7277,8 +7604,6 @@
         public static final String[] SETTINGS_TO_BACKUP = {
             BUGREPORT_IN_POWER_MENU,                            // moved to global
             ALLOW_MOCK_LOCATION,
-            PARENTAL_CONTROL_ENABLED,
-            PARENTAL_CONTROL_REDIRECT_URL,
             USB_MASS_STORAGE_ENABLED,                           // moved to global
             ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
             ACCESSIBILITY_DISPLAY_DALTONIZER,
@@ -7310,12 +7635,9 @@
             ACCESSIBILITY_CAPTIONING_TYPEFACE,
             ACCESSIBILITY_CAPTIONING_FONT_SCALE,
             ACCESSIBILITY_CAPTIONING_WINDOW_COLOR,
-            TTS_USE_DEFAULTS,
             TTS_DEFAULT_RATE,
             TTS_DEFAULT_PITCH,
             TTS_DEFAULT_SYNTH,
-            TTS_DEFAULT_LANG,
-            TTS_DEFAULT_COUNTRY,
             TTS_ENABLED_PLUGINS,
             TTS_DEFAULT_LOCALE,
             SHOW_IME_WITH_HARD_KEYBOARD,
@@ -7371,7 +7693,158 @@
             SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
         };
 
-        /** @hide */
+        /**
+         * All settings in {@link SETTINGS_TO_BACKUP} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
+         * @hide
+         */
+        public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
+        static {
+            VALIDATORS.put(BUGREPORT_IN_POWER_MENU, BUGREPORT_IN_POWER_MENU_VALIDATOR);
+            VALIDATORS.put(ALLOW_MOCK_LOCATION, ALLOW_MOCK_LOCATION_VALIDATOR);
+            VALIDATORS.put(USB_MASS_STORAGE_ENABLED, USB_MASS_STORAGE_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
+                    ACCESSIBILITY_DISPLAY_INVERSION_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_DALTONIZER,
+                    ACCESSIBILITY_DISPLAY_DALTONIZER_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
+                    ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+                    ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
+                    ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED_VALIDATOR);
+            VALIDATORS.put(AUTOFILL_SERVICE, AUTOFILL_SERVICE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+                    ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE_VALIDATOR);
+            VALIDATORS.put(ENABLED_ACCESSIBILITY_SERVICES,
+                    ENABLED_ACCESSIBILITY_SERVICES_VALIDATOR);
+            VALIDATORS.put(ENABLED_VR_LISTENERS, ENABLED_VR_LISTENERS_VALIDATOR);
+            VALIDATORS.put(ENABLED_INPUT_METHODS, ENABLED_INPUT_METHODS_VALIDATOR);
+            VALIDATORS.put(TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                    TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES_VALIDATOR);
+            VALIDATORS.put(TOUCH_EXPLORATION_ENABLED, TOUCH_EXPLORATION_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_ENABLED, ACCESSIBILITY_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+                    ACCESSIBILITY_SHORTCUT_TARGET_SERVICE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_BUTTON_TARGET_COMPONENT,
+                    ACCESSIBILITY_BUTTON_TARGET_COMPONENT_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
+                    ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_SHORTCUT_ENABLED,
+                    ACCESSIBILITY_SHORTCUT_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
+                    ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_SPEAK_PASSWORD, ACCESSIBILITY_SPEAK_PASSWORD_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED,
+                    ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_PRESET,
+                    ACCESSIBILITY_CAPTIONING_PRESET_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_ENABLED,
+                    ACCESSIBILITY_CAPTIONING_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_LOCALE,
+                    ACCESSIBILITY_CAPTIONING_LOCALE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR,
+                    ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR,
+                    ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_EDGE_TYPE,
+                    ACCESSIBILITY_CAPTIONING_EDGE_TYPE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_EDGE_COLOR,
+                    ACCESSIBILITY_CAPTIONING_EDGE_COLOR_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_TYPEFACE,
+                    ACCESSIBILITY_CAPTIONING_TYPEFACE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_FONT_SCALE,
+                    ACCESSIBILITY_CAPTIONING_FONT_SCALE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_WINDOW_COLOR,
+                    ACCESSIBILITY_CAPTIONING_WINDOW_COLOR_VALIDATOR);
+            VALIDATORS.put(TTS_DEFAULT_RATE, TTS_DEFAULT_RATE_VALIDATOR);
+            VALIDATORS.put(TTS_DEFAULT_PITCH, TTS_DEFAULT_PITCH_VALIDATOR);
+            VALIDATORS.put(TTS_DEFAULT_SYNTH, TTS_DEFAULT_SYNTH_VALIDATOR);
+            VALIDATORS.put(TTS_ENABLED_PLUGINS, TTS_ENABLED_PLUGINS_VALIDATOR);
+            VALIDATORS.put(TTS_DEFAULT_LOCALE, TTS_DEFAULT_LOCALE_VALIDATOR);
+            VALIDATORS.put(SHOW_IME_WITH_HARD_KEYBOARD, SHOW_IME_WITH_HARD_KEYBOARD_VALIDATOR);
+            VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+                    WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR);
+            VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
+                    WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR);
+            VALIDATORS.put(WIFI_NUM_OPEN_NETWORKS_KEPT, WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR);
+            VALIDATORS.put(SELECTED_SPELL_CHECKER, SELECTED_SPELL_CHECKER_VALIDATOR);
+            VALIDATORS.put(SELECTED_SPELL_CHECKER_SUBTYPE,
+                    SELECTED_SPELL_CHECKER_SUBTYPE_VALIDATOR);
+            VALIDATORS.put(SPELL_CHECKER_ENABLED, SPELL_CHECKER_ENABLED_VALIDATOR);
+            VALIDATORS.put(MOUNT_PLAY_NOTIFICATION_SND, MOUNT_PLAY_NOTIFICATION_SND_VALIDATOR);
+            VALIDATORS.put(MOUNT_UMS_AUTOSTART, MOUNT_UMS_AUTOSTART_VALIDATOR);
+            VALIDATORS.put(MOUNT_UMS_PROMPT, MOUNT_UMS_PROMPT_VALIDATOR);
+            VALIDATORS.put(MOUNT_UMS_NOTIFY_ENABLED, MOUNT_UMS_NOTIFY_ENABLED_VALIDATOR);
+            VALIDATORS.put(SLEEP_TIMEOUT, SLEEP_TIMEOUT_VALIDATOR);
+            VALIDATORS.put(DOUBLE_TAP_TO_WAKE, DOUBLE_TAP_TO_WAKE_VALIDATOR);
+            VALIDATORS.put(WAKE_GESTURE_ENABLED, WAKE_GESTURE_ENABLED_VALIDATOR);
+            VALIDATORS.put(LONG_PRESS_TIMEOUT, LONG_PRESS_TIMEOUT_VALIDATOR);
+            VALIDATORS.put(CAMERA_GESTURE_DISABLED, CAMERA_GESTURE_DISABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_AUTOCLICK_ENABLED,
+                    ACCESSIBILITY_AUTOCLICK_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_AUTOCLICK_DELAY, ACCESSIBILITY_AUTOCLICK_DELAY_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_LARGE_POINTER_ICON,
+                    ACCESSIBILITY_LARGE_POINTER_ICON_VALIDATOR);
+            VALIDATORS.put(PREFERRED_TTY_MODE, PREFERRED_TTY_MODE_VALIDATOR);
+            VALIDATORS.put(ENHANCED_VOICE_PRIVACY_ENABLED,
+                    ENHANCED_VOICE_PRIVACY_ENABLED_VALIDATOR);
+            VALIDATORS.put(TTY_MODE_ENABLED, TTY_MODE_ENABLED_VALIDATOR);
+            VALIDATORS.put(INCALL_POWER_BUTTON_BEHAVIOR, INCALL_POWER_BUTTON_BEHAVIOR_VALIDATOR);
+            VALIDATORS.put(NIGHT_DISPLAY_CUSTOM_START_TIME,
+                    NIGHT_DISPLAY_CUSTOM_START_TIME_VALIDATOR);
+            VALIDATORS.put(NIGHT_DISPLAY_CUSTOM_END_TIME, NIGHT_DISPLAY_CUSTOM_END_TIME_VALIDATOR);
+            VALIDATORS.put(NIGHT_DISPLAY_COLOR_TEMPERATURE,
+                    NIGHT_DISPLAY_COLOR_TEMPERATURE_VALIDATOR);
+            VALIDATORS.put(NIGHT_DISPLAY_AUTO_MODE, NIGHT_DISPLAY_AUTO_MODE_VALIDATOR);
+            VALIDATORS.put(SYNC_PARENT_SOUNDS, SYNC_PARENT_SOUNDS_VALIDATOR);
+            VALIDATORS.put(CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
+                    CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED_VALIDATOR);
+            VALIDATORS.put(CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
+                    CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED_VALIDATOR);
+            VALIDATORS.put(SYSTEM_NAVIGATION_KEYS_ENABLED,
+                    SYSTEM_NAVIGATION_KEYS_ENABLED_VALIDATOR);
+            VALIDATORS.put(QS_TILES, QS_TILES_VALIDATOR);
+            VALIDATORS.put(DOZE_ENABLED, DOZE_ENABLED_VALIDATOR);
+            VALIDATORS.put(DOZE_PULSE_ON_PICK_UP, DOZE_PULSE_ON_PICK_UP_VALIDATOR);
+            VALIDATORS.put(DOZE_PULSE_ON_DOUBLE_TAP, DOZE_PULSE_ON_DOUBLE_TAP_VALIDATOR);
+            VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR);
+            VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
+                    AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
+            VALIDATORS.put(ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_ENABLED_VALIDATOR);
+            VALIDATORS.put(ASSIST_GESTURE_SENSITIVITY, ASSIST_GESTURE_SENSITIVITY_VALIDATOR);
+            VALIDATORS.put(ASSIST_GESTURE_SETUP_COMPLETE, ASSIST_GESTURE_SETUP_COMPLETE_VALIDATOR);
+            VALIDATORS.put(ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
+                    ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR);
+            VALIDATORS.put(ASSIST_GESTURE_WAKE_ENABLED, ASSIST_GESTURE_WAKE_ENABLED_VALIDATOR);
+            VALIDATORS.put(VR_DISPLAY_MODE, VR_DISPLAY_MODE_VALIDATOR);
+            VALIDATORS.put(NOTIFICATION_BADGING, NOTIFICATION_BADGING_VALIDATOR);
+            VALIDATORS.put(QS_AUTO_ADDED_TILES, QS_AUTO_ADDED_TILES_VALIDATOR);
+            VALIDATORS.put(SCREENSAVER_ENABLED, SCREENSAVER_ENABLED_VALIDATOR);
+            VALIDATORS.put(SCREENSAVER_COMPONENTS, SCREENSAVER_COMPONENTS_VALIDATOR);
+            VALIDATORS.put(SCREENSAVER_ACTIVATE_ON_DOCK, SCREENSAVER_ACTIVATE_ON_DOCK_VALIDATOR);
+            VALIDATORS.put(SCREENSAVER_ACTIVATE_ON_SLEEP, SCREENSAVER_ACTIVATE_ON_SLEEP_VALIDATOR);
+            VALIDATORS.put(LOCKDOWN_IN_POWER_MENU, LOCKDOWN_IN_POWER_MENU_VALIDATOR);
+            VALIDATORS.put(SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
+                    SHOW_FIRST_CRASH_DIALOG_DEV_OPTION_VALIDATOR);
+            VALIDATORS.put(ENABLED_NOTIFICATION_LISTENERS,
+                    ENABLED_NOTIFICATION_LISTENERS_VALIDATOR); //legacy restore setting
+            VALIDATORS.put(ENABLED_NOTIFICATION_ASSISTANT,
+                    ENABLED_NOTIFICATION_ASSISTANT_VALIDATOR); //legacy restore setting
+            VALIDATORS.put(ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
+                    ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES_VALIDATOR); //legacy restore setting
+        }
+
+        /**
+         * Keys we no longer back up under the current schema, but want to continue to
+         * process when restoring historical backup datasets.
+         *
+         * All settings in {@link LEGACY_RESTORE_SETTINGS} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
+         * @hide
+         */
         public static final String[] LEGACY_RESTORE_SETTINGS = {
                 ENABLED_NOTIFICATION_LISTENERS,
                 ENABLED_NOTIFICATION_ASSISTANT,
@@ -8706,6 +9179,9 @@
        public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
                "wifi_networks_available_repeat_delay";
 
+       private static final Validator WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR =
+               NON_NEGATIVE_INTEGER_VALIDATOR;
+
        /**
         * 802.11 country code in ISO 3166 format
         * @hide
@@ -8735,6 +9211,9 @@
         */
        public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
 
+       private static final Validator WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR =
+               NON_NEGATIVE_INTEGER_VALIDATOR;
+
        /**
         * Whether the Wi-Fi should be on.  Only the Wi-Fi service should touch this.
         */
@@ -10780,7 +11259,15 @@
                 LOCATION_GLOBAL_KILL_SWITCH,
         };
 
-        /** @hide */
+        /**
+         * Keys we no longer back up under the current schema, but want to continue to
+         * process when restoring historical backup datasets.
+         *
+         * All settings in {@link LEGACY_RESTORE_SETTINGS} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
+         * @hide
+         */
         public static final String[] LEGACY_RESTORE_SETTINGS = {
         };
 
diff --git a/core/java/android/provider/SettingsValidators.java b/core/java/android/provider/SettingsValidators.java
index 22ef3b6..c384a2a 100644
--- a/core/java/android/provider/SettingsValidators.java
+++ b/core/java/android/provider/SettingsValidators.java
@@ -21,6 +21,8 @@
 
 import com.android.internal.util.ArrayUtils;
 
+import java.util.Locale;
+
 /**
  * This class provides both interface for validation and common validators
  * used to ensure Settings have meaningful values.
@@ -50,6 +52,18 @@
         }
     };
 
+    public static final Validator ANY_INTEGER_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(String value) {
+            try {
+                Integer.parseInt(value);
+                return true;
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+    };
+
     public static final Validator URI_VALIDATOR = new Validator() {
         @Override
         public boolean validate(String value) {
@@ -80,6 +94,9 @@
             // and underscores ('_'). However, individual package name parts may only
             // start with letters.
             // (https://developer.android.com/guide/topics/manifest/manifest-element.html#package)
+            if (value == null) {
+                return false;
+            }
             String[] subparts = value.split(".");
             boolean isValidPackageName = true;
             for (String subpart : subparts) {
@@ -106,10 +123,29 @@
 
         @Override
         public boolean validate(String value) {
+            if (value == null) {
+                return false;
+            }
             return value.length() <= MAX_IPV6_LENGTH;
         }
     };
 
+    public static final Validator LOCALE_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(String value) {
+            if (value == null) {
+                return false;
+            }
+            Locale[] validLocales = Locale.getAvailableLocales();
+            for (Locale locale : validLocales) {
+                if (value.equals(locale.toString())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    };
+
     public interface Validator {
         boolean validate(String value);
     }
@@ -166,4 +202,48 @@
             }
         }
     }
+
+    public static final class ComponentNameListValidator implements Validator {
+        private final String mSeparator;
+
+        public ComponentNameListValidator(String separator) {
+            mSeparator = separator;
+        }
+
+        @Override
+        public boolean validate(String value) {
+            if (value == null) {
+                return false;
+            }
+            String[] elements = value.split(mSeparator);
+            for (String element : elements) {
+                if (!COMPONENT_NAME_VALIDATOR.validate(element)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    public static final class PackageNameListValidator implements Validator {
+        private final String mSeparator;
+
+        public PackageNameListValidator(String separator) {
+            mSeparator = separator;
+        }
+
+        @Override
+        public boolean validate(String value) {
+            if (value == null) {
+                return false;
+            }
+            String[] elements = value.split(mSeparator);
+            for (String element : elements) {
+                if (!PACKAGE_NAME_VALIDATOR.validate(element)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
 }
diff --git a/core/java/android/text/style/BackgroundColorSpan.java b/core/java/android/text/style/BackgroundColorSpan.java
index de05f50..4f471a8 100644
--- a/core/java/android/text/style/BackgroundColorSpan.java
+++ b/core/java/android/text/style/BackgroundColorSpan.java
@@ -16,24 +16,48 @@
 
 package android.text.style;
 
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.text.ParcelableSpan;
 import android.text.TextPaint;
 import android.text.TextUtils;
 
+/**
+ * Changes the background color of the text to which the span is attached.
+ * <p>
+ * For example, to set a green background color for a text you would create a {@link
+ * android.text.SpannableStringBuilder} based on the text and set the span.
+ * <pre>{@code
+ * SpannableString string = new SpannableString("Text with a background color span");
+ *string.setSpan(new BackgroundColorSpan(color), 12, 28, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * }</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/backgroundcolorspan.png" />
+ * <figcaption>Set a background color for the text.</figcaption>
+ */
 public class BackgroundColorSpan extends CharacterStyle
         implements UpdateAppearance, ParcelableSpan {
 
     private final int mColor;
 
-    public BackgroundColorSpan(int color) {
+    /**
+     * Creates a {@link BackgroundColorSpan} from a color integer.
+     * <p>
+     *
+     * @param color color integer that defines the background color
+     * @see android.content.res.Resources#getColor(int, Resources.Theme)
+     */
+    public BackgroundColorSpan(@ColorInt int color) {
         mColor = color;
     }
 
-    public BackgroundColorSpan(Parcel src) {
+    /**
+     * Creates a {@link BackgroundColorSpan} from a parcel.
+     */
+    public BackgroundColorSpan(@NonNull Parcel src) {
         mColor = src.readInt();
     }
-    
+
     public int getSpanTypeId() {
         return getSpanTypeIdInternal();
     }
@@ -42,26 +66,40 @@
     public int getSpanTypeIdInternal() {
         return TextUtils.BACKGROUND_COLOR_SPAN;
     }
-    
+
     public int describeContents() {
         return 0;
     }
 
-    public void writeToParcel(Parcel dest, int flags) {
+    /**
+     * Flatten this object into a Parcel.
+     *
+     * @param dest The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written.
+     */
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         writeToParcelInternal(dest, flags);
     }
 
     /** @hide */
-    public void writeToParcelInternal(Parcel dest, int flags) {
+    public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
         dest.writeInt(mColor);
     }
 
+    /**
+     * @return the background color of this span.
+     * @see BackgroundColorSpan#BackgroundColorSpan(int)
+     */
+    @ColorInt
     public int getBackgroundColor() {
         return mColor;
     }
 
+    /**
+     * Updates the background color of the TextPaint.
+     */
     @Override
-    public void updateDrawState(TextPaint ds) {
-        ds.bgColor = mColor;
+    public void updateDrawState(@NonNull TextPaint textPaint) {
+        textPaint.bgColor = mColor;
     }
 }
diff --git a/core/java/android/text/style/ForegroundColorSpan.java b/core/java/android/text/style/ForegroundColorSpan.java
index 2bc6d54..08ab2a1 100644
--- a/core/java/android/text/style/ForegroundColorSpan.java
+++ b/core/java/android/text/style/ForegroundColorSpan.java
@@ -17,24 +17,48 @@
 package android.text.style;
 
 import android.annotation.ColorInt;
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.text.ParcelableSpan;
 import android.text.TextPaint;
 import android.text.TextUtils;
 
+/**
+ * Changes the color of the text to which the span is attached.
+ * <p>
+ * For example, to set a green text color you would create a {@link
+ * android.text.SpannableStringBuilder} based on the text and set the span.
+ * <pre>{@code
+ * SpannableString string = new SpannableString("Text with a foreground color span");
+ *string.setSpan(new ForegroundColorSpan(color), 12, 28, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * }</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/foregroundcolorspan.png" />
+ * <figcaption>Set a text color.</figcaption>
+ */
 public class ForegroundColorSpan extends CharacterStyle
         implements UpdateAppearance, ParcelableSpan {
 
     private final int mColor;
 
+    /**
+     * Creates a {@link ForegroundColorSpan} from a color integer.
+     * <p>
+     * To get the color integer associated with a particular color resource ID, use
+     * {@link android.content.res.Resources#getColor(int, Resources.Theme)}
+     *
+     * @param color color integer that defines the text color
+     */
     public ForegroundColorSpan(@ColorInt int color) {
         mColor = color;
     }
 
-    public ForegroundColorSpan(Parcel src) {
+    /**
+     * Creates a {@link ForegroundColorSpan} from a parcel.
+     */
+    public ForegroundColorSpan(@NonNull Parcel src) {
         mColor = src.readInt();
     }
-    
+
     public int getSpanTypeId() {
         return getSpanTypeIdInternal();
     }
@@ -48,22 +72,35 @@
         return 0;
     }
 
-    public void writeToParcel(Parcel dest, int flags) {
+    /**
+     * Flatten this object into a Parcel.
+     *
+     * @param dest  The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written.
+     */
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         writeToParcelInternal(dest, flags);
     }
 
     /** @hide */
-    public void writeToParcelInternal(Parcel dest, int flags) {
+    public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
         dest.writeInt(mColor);
     }
 
+    /**
+     * @return the foreground color of this span.
+     * @see ForegroundColorSpan#ForegroundColorSpan(int)
+     */
     @ColorInt
     public int getForegroundColor() {
         return mColor;
     }
 
+    /**
+     * Updates the color of the TextPaint to the foreground color.
+     */
     @Override
-    public void updateDrawState(TextPaint ds) {
-        ds.setColor(mColor);
+    public void updateDrawState(@NonNull TextPaint textPaint) {
+        textPaint.setColor(mColor);
     }
 }
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index ce8998f..5a09dab 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -16,6 +16,7 @@
 
 package android.util.apk;
 
+import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_VERITY_CHUNKED_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_DSA_WITH_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA512;
@@ -42,6 +43,7 @@
 import java.io.RandomAccessFile;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
+import java.security.DigestException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.KeyFactory;
@@ -105,7 +107,8 @@
      */
     public static X509Certificate[][] verify(String apkFile)
             throws SignatureNotFoundException, SecurityException, IOException {
-        return verify(apkFile, true);
+        VerifiedSigner vSigner = verify(apkFile, true);
+        return vSigner.certs;
     }
 
     /**
@@ -119,10 +122,11 @@
      */
     public static X509Certificate[][] plsCertsNoVerifyOnlyCerts(String apkFile)
             throws SignatureNotFoundException, SecurityException, IOException {
-        return verify(apkFile, false);
+        VerifiedSigner vSigner = verify(apkFile, false);
+        return vSigner.certs;
     }
 
-    private static X509Certificate[][] verify(String apkFile, boolean verifyIntegrity)
+    private static VerifiedSigner verify(String apkFile, boolean verifyIntegrity)
             throws SignatureNotFoundException, SecurityException, IOException {
         try (RandomAccessFile apk = new RandomAccessFile(apkFile, "r")) {
             return verify(apk, verifyIntegrity);
@@ -138,7 +142,7 @@
      *         verify.
      * @throws IOException if an I/O error occurs while reading the APK file.
      */
-    private static X509Certificate[][] verify(RandomAccessFile apk, boolean verifyIntegrity)
+    private static VerifiedSigner verify(RandomAccessFile apk, boolean verifyIntegrity)
             throws SignatureNotFoundException, SecurityException, IOException {
         SignatureInfo signatureInfo = findSignature(apk);
         return verify(apk, signatureInfo, verifyIntegrity);
@@ -163,7 +167,7 @@
      * @param signatureInfo APK Signature Scheme v2 Block and information relevant for verifying it
      *        against the APK file.
      */
-    private static X509Certificate[][] verify(
+    private static VerifiedSigner verify(
             RandomAccessFile apk,
             SignatureInfo signatureInfo,
             boolean doVerifyIntegrity) throws SecurityException, IOException {
@@ -207,7 +211,14 @@
             ApkSigningBlockUtils.verifyIntegrity(contentDigests, apk, signatureInfo);
         }
 
-        return signerCerts.toArray(new X509Certificate[signerCerts.size()][]);
+        byte[] verityRootHash = null;
+        if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
+            verityRootHash = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256);
+        }
+
+        return new VerifiedSigner(
+                signerCerts.toArray(new X509Certificate[signerCerts.size()][]),
+                verityRootHash);
     }
 
     private static X509Certificate[] verifySigner(
@@ -383,6 +394,24 @@
         return;
     }
 
+    static byte[] getVerityRootHash(String apkPath)
+            throws IOException, SignatureNotFoundException, SecurityException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            SignatureInfo signatureInfo = findSignature(apk);
+            VerifiedSigner vSigner = verify(apk, false);
+            return vSigner.verityRootHash;
+        }
+    }
+
+    static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory)
+            throws IOException, SignatureNotFoundException, SecurityException, DigestException,
+                   NoSuchAlgorithmException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            SignatureInfo signatureInfo = findSignature(apk);
+            return ApkSigningBlockUtils.generateApkVerity(apkPath, bufferFactory, signatureInfo);
+        }
+    }
+
     private static boolean isSupportedSignatureAlgorithm(int sigAlgorithm) {
         switch (sigAlgorithm) {
             case SIGNATURE_RSA_PSS_WITH_SHA256:
@@ -400,4 +429,20 @@
                 return false;
         }
     }
+
+    /**
+     * Verified APK Signature Scheme v2 signer.
+     *
+     * @hide for internal use only.
+     */
+    public static class VerifiedSigner {
+        public final X509Certificate[][] certs;
+        public final byte[] verityRootHash;
+
+        public VerifiedSigner(X509Certificate[][] certs, byte[] verityRootHash) {
+            this.certs = certs;
+            this.verityRootHash = verityRootHash;
+        }
+
+    }
 }
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index c9e67fe..1b04eb2 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -16,6 +16,7 @@
 
 package android.util.apk;
 
+import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_VERITY_CHUNKED_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_DSA_WITH_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA512;
@@ -43,6 +44,7 @@
 import java.io.RandomAccessFile;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
+import java.security.DigestException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.KeyFactory;
@@ -211,6 +213,10 @@
             ApkSigningBlockUtils.verifyIntegrity(contentDigests, apk, signatureInfo);
         }
 
+        if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
+            result.verityRootHash = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256);
+        }
+
         return result;
     }
 
@@ -499,6 +505,24 @@
         return new VerifiedProofOfRotation(certs, flagsList);
     }
 
+    static byte[] getVerityRootHash(String apkPath)
+            throws IOException, SignatureNotFoundException, SecurityException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            SignatureInfo signatureInfo = findSignature(apk);
+            VerifiedSigner vSigner = verify(apk, false);
+            return vSigner.verityRootHash;
+        }
+    }
+
+    static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory)
+            throws IOException, SignatureNotFoundException, SecurityException, DigestException,
+                   NoSuchAlgorithmException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            SignatureInfo signatureInfo = findSignature(apk);
+            return ApkSigningBlockUtils.generateApkVerity(apkPath, bufferFactory, signatureInfo);
+        }
+    }
+
     private static boolean isSupportedSignatureAlgorithm(int sigAlgorithm) {
         switch (sigAlgorithm) {
             case SIGNATURE_RSA_PSS_WITH_SHA256:
@@ -541,6 +565,8 @@
         public final X509Certificate[] certs;
         public final VerifiedProofOfRotation por;
 
+        public byte[] verityRootHash;
+
         public VerifiedSigner(X509Certificate[] certs, VerifiedProofOfRotation por) {
             this.certs = certs;
             this.por = por;
diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java
index 555c474..a2a7616 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -36,7 +36,9 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.security.DigestException;
 import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.util.ArrayList;
@@ -367,4 +369,51 @@
         // v2 didn't work, try jarsigner
         return verifyV1Signature(apkPath, false);
     }
+
+    /**
+     * @return the verity root hash in the Signing Block.
+     */
+    public static byte[] getVerityRootHash(String apkPath)
+            throws IOException, SignatureNotFoundException, SecurityException {
+        // first try v3
+        try {
+            return ApkSignatureSchemeV3Verifier.getVerityRootHash(apkPath);
+        } catch (SignatureNotFoundException e) {
+            // try older version
+        }
+        return ApkSignatureSchemeV2Verifier.getVerityRootHash(apkPath);
+    }
+
+    /**
+     * Generates the Merkle tree and verity metadata to the buffer allocated by the {@code
+     * ByteBufferFactory}.
+     *
+     * @return the verity root hash of the generated Merkle tree.
+     */
+    public static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory)
+            throws IOException, SignatureNotFoundException, SecurityException, DigestException,
+                   NoSuchAlgorithmException {
+        // first try v3
+        try {
+            return ApkSignatureSchemeV3Verifier.generateApkVerity(apkPath, bufferFactory);
+        } catch (SignatureNotFoundException e) {
+            // try older version
+        }
+        return ApkSignatureSchemeV2Verifier.generateApkVerity(apkPath, bufferFactory);
+    }
+
+    /**
+     * Result of a successful APK verification operation.
+     */
+    public static class Result {
+        public final Certificate[][] certs;
+        public final Signature[] sigs;
+        public final int signatureSchemeVersion;
+
+        public Result(Certificate[][] certs, Signature[] sigs, int signingVersion) {
+            this.certs = certs;
+            this.sigs = sigs;
+            this.signatureSchemeVersion = signingVersion;
+        }
+    }
 }
diff --git a/core/java/android/util/apk/ApkSigningBlockUtils.java b/core/java/android/util/apk/ApkSigningBlockUtils.java
index 9d53847..4146f6f 100644
--- a/core/java/android/util/apk/ApkSigningBlockUtils.java
+++ b/core/java/android/util/apk/ApkSigningBlockUtils.java
@@ -306,6 +306,26 @@
     }
 
     /**
+     * Generates the fsverity header and hash tree to be used by kernel for the given apk. This
+     * method does not check whether the root hash exists in the Signing Block or not.
+     *
+     * <p>The output is stored in the {@link ByteBuffer} created by the given {@link
+     * ByteBufferFactory}.
+     *
+     * @return the root hash of the generated hash tree.
+     */
+    public static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory,
+            SignatureInfo signatureInfo)
+            throws IOException, SignatureNotFoundException, SecurityException, DigestException,
+                   NoSuchAlgorithmException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            ApkVerityBuilder.ApkVerityResult result = ApkVerityBuilder.generateApkVerity(apk,
+                    signatureInfo, bufferFactory);
+            return result.rootHash;
+        }
+    }
+
+    /**
      * Returns the ZIP End of Central Directory (EoCD) and its offset in the file.
      *
      * @throws IOException if an I/O error occurs while reading the file.
diff --git a/core/java/android/util/apk/ApkVerityBuilder.java b/core/java/android/util/apk/ApkVerityBuilder.java
index 7412ef4..a0d5e4c 100644
--- a/core/java/android/util/apk/ApkVerityBuilder.java
+++ b/core/java/android/util/apk/ApkVerityBuilder.java
@@ -164,11 +164,11 @@
         }
 
         private void fillUpLastOutputChunk() {
-            int extra = (int) (BUFFER_SIZE - mOutput.position() % BUFFER_SIZE);
-            if (extra == 0) {
+            int lastBlockSize = (int) (mOutput.position() % BUFFER_SIZE);
+            if (lastBlockSize == 0) {
                 return;
             }
-            mOutput.put(ByteBuffer.allocate(extra));
+            mOutput.put(ByteBuffer.allocate(BUFFER_SIZE - lastBlockSize));
         }
     }
 
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 388180d..e2d1ad5 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -23,6 +23,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.WorkSource;
 import android.os.connectivity.CellularBatteryStats;
+import android.os.connectivity.GpsBatteryStats;
 import android.os.health.HealthStatsParceler;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ModemActivityInfo;
@@ -91,6 +92,7 @@
     void noteVibratorOff(int uid);
     void noteStartGps(int uid);
     void noteStopGps(int uid);
+    void noteGpsSignalQuality(int signalLevel);
     void noteScreenState(int state);
     void noteScreenBrightness(int brightness);
     void noteUserActivity(int uid, int event);
@@ -140,6 +142,9 @@
     /** {@hide} */
     CellularBatteryStats getCellularBatteryStats();
 
+    /** {@hide} */
+    GpsBatteryStats getGpsBatteryStats();
+
     HealthStatsParceler takeUidSnapshot(int uid);
     HealthStatsParceler[] takeUidSnapshots(in int[] uid);
 
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 15dc6f5..5a59e70 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -665,14 +665,14 @@
 
     /**
      * Calculate the baseline power usage for the device when it is in suspend and idle.
-     * The device is drawing POWER_CPU_IDLE power at its lowest power state.
-     * The device is drawing POWER_CPU_IDLE + POWER_CPU_AWAKE power when a wakelock is held.
+     * The device is drawing POWER_CPU_SUSPEND power at its lowest power state.
+     * The device is drawing POWER_CPU_SUSPEND + POWER_CPU_IDLE power when a wakelock is held.
      */
     private void addIdleUsage() {
         final double suspendPowerMaMs = (mTypeBatteryRealtimeUs / 1000) *
-                mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE);
+                mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_SUSPEND);
         final double idlePowerMaMs = (mTypeBatteryUptimeUs / 1000) *
-                mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE);
+                mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE);
         final double totalPowerMah = (suspendPowerMaMs + idlePowerMaMs) / (60 * 60 * 1000);
         if (DEBUG && totalPowerMah != 0) {
             Log.d(TAG, "Suspend: time=" + (mTypeBatteryRealtimeUs / 1000)
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index ac5dbc4..799e3e8 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -34,6 +34,7 @@
 import android.os.BatteryStats;
 import android.os.Build;
 import android.os.connectivity.CellularBatteryStats;
+import android.os.connectivity.GpsBatteryStats;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBatteryPropertiesRegistrar;
@@ -78,6 +79,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.location.gnssmetrics.GnssMetrics;
 import com.android.internal.net.NetworkStatsFactory;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
@@ -153,11 +155,11 @@
             MAX_HISTORY_BUFFER = 96*1024;  // 96KB
             MAX_MAX_HISTORY_BUFFER = 128*1024; // 128KB
         } else {
-            MAX_HISTORY_ITEMS = 2000;
-            MAX_MAX_HISTORY_ITEMS = 3000;
-            MAX_WAKELOCKS_PER_UID = 100;
-            MAX_HISTORY_BUFFER = 256*1024;  // 256KB
-            MAX_MAX_HISTORY_BUFFER = 320*1024;  // 256KB
+            MAX_HISTORY_ITEMS = 4000;
+            MAX_MAX_HISTORY_ITEMS = 6000;
+            MAX_WAKELOCKS_PER_UID = 200;
+            MAX_HISTORY_BUFFER = 512*1024;  // 512KB
+            MAX_MAX_HISTORY_BUFFER = 640*1024;  // 640KB
         }
     }
 
@@ -198,6 +200,12 @@
     protected KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
             new KernelUidCpuFreqTimeReader();
     @VisibleForTesting
+    protected KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader =
+            new KernelUidCpuActiveTimeReader();
+    @VisibleForTesting
+    protected KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
+            new KernelUidCpuClusterTimeReader();
+    @VisibleForTesting
     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
 
     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
@@ -666,6 +674,10 @@
     int mCameraOnNesting;
     StopwatchTimer mCameraOnTimer;
 
+    int mGpsSignalQualityBin = -1;
+    final StopwatchTimer[] mGpsSignalQualityTimer =
+        new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+
     int mPhoneSignalStrengthBin = -1;
     int mPhoneSignalStrengthBinRaw = -1;
     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
@@ -3880,6 +3892,8 @@
         }
         mKernelUidCpuTimeReader.removeUid(isolatedUid);
         mKernelUidCpuFreqTimeReader.removeUid(isolatedUid);
+        mKernelUidCpuActiveTimeReader.removeUid(isolatedUid);
+        mKernelUidCpuClusterTimeReader.removeUid(isolatedUid);
     }
 
     public int mapUid(int uid) {
@@ -4575,10 +4589,37 @@
             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime, uptime);
+            stopAllGpsSignalQualityTimersLocked(-1);
+            mGpsSignalQualityBin = -1;
         }
         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
     }
 
+    public void noteGpsSignalQualityLocked(int signalLevel) {
+        if (mGpsNesting == 0) {
+            return;
+        }
+        if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+            stopAllGpsSignalQualityTimersLocked(-1);
+            return;
+        }
+        final long elapsedRealtime = mClocks.elapsedRealtime();
+        final long uptime = mClocks.uptimeMillis();
+        if (mGpsSignalQualityBin != signalLevel) {
+            if (mGpsSignalQualityBin >= 0) {
+                mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
+            }
+            if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
+                mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
+            }
+            mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
+                    | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
+            addHistoryRecordLocked(elapsedRealtime, uptime);
+            mGpsSignalQualityBin = signalLevel;
+        }
+        return;
+    }
+
     public void noteScreenStateLocked(int state) {
         state = mPretendScreenOff ? Display.STATE_OFF : state;
 
@@ -4912,6 +4953,18 @@
         mDailyPackageChanges.add(pc);
     }
 
+    void stopAllGpsSignalQualityTimersLocked(int except) {
+        final long elapsedRealtime = mClocks.elapsedRealtime();
+        for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            if (i == except) {
+                continue;
+            }
+            while (mGpsSignalQualityTimer[i].isRunningLocked()) {
+                mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
+            }
+        }
+    }
+
     public void notePhoneOnLocked() {
         if (!mPhoneOn) {
             final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -6123,6 +6176,20 @@
         return val;
     }
 
+    @Override public long getGpsSignalQualityTime(int strengthBin,
+        long elapsedRealtimeUs, int which) {
+        if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+            return 0;
+        }
+        return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
+            elapsedRealtimeUs, which);
+    }
+
+    @Override public long getGpsBatteryDrainMaMs() {
+        //TODO: Add GPS power computation (b/67213967)
+        return 0;
+    }
+
     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
@@ -6479,9 +6546,11 @@
         LongSamplingCounter mUserCpuTime;
         LongSamplingCounter mSystemCpuTime;
         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
+        LongSamplingCounter mCpuActiveTimeMs;
 
         LongSamplingCounterArray mCpuFreqTimeMs;
         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
+        LongSamplingCounterArray mCpuClusterTimesMs;
 
         LongSamplingCounterArray[] mProcStateTimeMs;
         LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
@@ -6551,6 +6620,8 @@
 
             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
+            mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
+            mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
 
             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
                 @Override public Wakelock instantiateObject() {
@@ -6598,6 +6669,17 @@
         }
 
         @Override
+        public long getCpuActiveTime() {
+            return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
+        }
+
+        @Override
+        public long[] getCpuClusterTimes() {
+            return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
+        }
+
+
+        @Override
         public long[] getCpuFreqTimes(int which, int procState) {
             if (which < 0 || which >= NUM_PROCESS_STATE) {
                 return null;
@@ -7660,6 +7742,9 @@
                 mScreenOffCpuFreqTimeMs.reset(false);
             }
 
+            mCpuActiveTimeMs.reset(false);
+            mCpuClusterTimesMs.reset(false);
+
             if (mProcStateTimeMs != null) {
                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
                     if (counters != null) {
@@ -7864,6 +7949,8 @@
                 if (mScreenOffCpuFreqTimeMs != null) {
                     mScreenOffCpuFreqTimeMs.detach();
                 }
+                mCpuActiveTimeMs.detach();
+                mCpuClusterTimesMs.detach();
 
                 if (mProcStateTimeMs != null) {
                     for (LongSamplingCounterArray counters : mProcStateTimeMs) {
@@ -8139,6 +8226,10 @@
 
             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
+
+            mCpuActiveTimeMs.writeToParcel(out);
+            mCpuClusterTimesMs.writeToParcel(out);
+
             if (mProcStateTimeMs != null) {
                 out.writeInt(mProcStateTimeMs.length);
                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
@@ -8456,6 +8547,9 @@
             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
                     in, mBsi.mOnBatteryScreenOffTimeBase);
 
+            mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
+            mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
+
             int length = in.readInt();
             if (length == NUM_PROCESS_STATE) {
                 mProcStateTimeMs = new LongSamplingCounterArray[length];
@@ -9822,6 +9916,10 @@
             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
                     mOnBatteryTimeBase);
         }
+        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
+                mOnBatteryTimeBase);
+        }
         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
@@ -10511,6 +10609,9 @@
             mWifiSignalStrengthsTimer[i].reset(false);
         }
         mWifiMulticastWakelockTimer.reset(false);
+        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i].reset(false);
+        }
         mWifiActivity.reset(false);
         mBluetoothActivity.reset(false);
         mModemActivity.reset(false);
@@ -11437,6 +11538,8 @@
         if (!mOnBatteryInternal) {
             mKernelUidCpuTimeReader.readDelta(null);
             mKernelUidCpuFreqTimeReader.readDelta(null);
+            mKernelUidCpuActiveTimeReader.readDelta(null);
+            mKernelUidCpuClusterTimeReader.readDelta(null);
             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
                 mKernelCpuSpeedReaders[cluster].readDelta();
             }
@@ -11453,6 +11556,8 @@
             updateClusterSpeedTimes(updatedUids);
         }
         readKernelUidCpuFreqTimesLocked(partialTimersToConsider);
+        readKernelUidCpuActiveTimesLocked();
+        readKernelUidCpuClusterTimesLocked();
     }
 
     /**
@@ -11764,6 +11869,64 @@
         }
     }
 
+    /**
+     * Take a snapshot of the cpu active times spent by each uid and update the corresponding
+     * counters.
+     */
+    @VisibleForTesting
+    public void readKernelUidCpuActiveTimesLocked() {
+        final long startTimeMs = mClocks.uptimeMillis();
+        mKernelUidCpuActiveTimeReader.readDelta((uid, cpuActiveTimesUs) -> {
+            uid = mapUid(uid);
+            if (Process.isIsolated(uid)) {
+                mKernelUidCpuActiveTimeReader.removeUid(uid);
+                Slog.w(TAG, "Got active times for an isolated uid with no mapping: " + uid);
+                return;
+            }
+            if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
+                Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
+                mKernelUidCpuActiveTimeReader.removeUid(uid);
+                return;
+            }
+            final Uid u = getUidStatsLocked(uid);
+            u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesUs);
+        });
+
+        final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
+        if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
+            Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
+        }
+    }
+
+    /**
+     * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
+     * counters.
+     */
+    @VisibleForTesting
+    public void readKernelUidCpuClusterTimesLocked() {
+        final long startTimeMs = mClocks.uptimeMillis();
+        mKernelUidCpuClusterTimeReader.readDelta((uid, cpuClusterTimesUs) -> {
+            uid = mapUid(uid);
+            if (Process.isIsolated(uid)) {
+                mKernelUidCpuClusterTimeReader.removeUid(uid);
+                Slog.w(TAG, "Got cluster times for an isolated uid with no mapping: " + uid);
+                return;
+            }
+            if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
+                Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
+                mKernelUidCpuClusterTimeReader.removeUid(uid);
+                return;
+            }
+            final Uid u = getUidStatsLocked(uid);
+            u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesUs);
+        });
+
+        final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
+        if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
+            Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
+        }
+    }
+
     boolean setChargingLocked(boolean charging) {
         if (mCharging != charging) {
             mCharging = charging;
@@ -12367,6 +12530,21 @@
         return s;
     }
 
+    /*@hide */
+    public GpsBatteryStats getGpsBatteryStats() {
+        GpsBatteryStats s = new GpsBatteryStats();
+        final int which = STATS_SINCE_CHARGED;
+        final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
+        s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
+        s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
+        long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+        for (int i=0; i<time.length; i++) {
+            time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
+        }
+        s.setTimeInGpsSignalQualityLevel(time);
+        return s;
+    }
+
     @Override
     public LevelStepTracker getChargeLevelStepTracker() {
         return mChargeStepTracker;
@@ -13044,6 +13222,9 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
         }
+        for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
+        }
         mWifiActivity.readSummaryFromParcel(in);
         mBluetoothActivity.readSummaryFromParcel(in);
         mModemActivity.readSummaryFromParcel(in);
@@ -13249,6 +13430,10 @@
                     in, mOnBatteryTimeBase);
             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
                     in, mOnBatteryScreenOffTimeBase);
+
+            u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
+            u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
+
             int length = in.readInt();
             if (length == Uid.NUM_PROCESS_STATE) {
                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
@@ -13482,6 +13667,9 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
+        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+        }
         mWifiActivity.writeSummaryToParcel(out);
         mBluetoothActivity.writeSummaryToParcel(out);
         mModemActivity.writeSummaryToParcel(out);
@@ -13725,6 +13913,9 @@
             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
 
+            u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
+            u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
+
             if (u.mProcStateTimeMs != null) {
                 out.writeInt(u.mProcStateTimeMs.length);
                 for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
@@ -13954,7 +14145,10 @@
             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
                     null, mOnBatteryTimeBase, in);
         }
-
+        for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
+                null, mOnBatteryTimeBase, in);
+        }
         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
                 NUM_WIFI_TX_LEVELS, in);
         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
@@ -14154,6 +14348,9 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
         }
+        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
+        }
         mWifiActivity.writeToParcel(out, 0);
         mBluetoothActivity.writeToParcel(out, 0);
         mModemActivity.writeToParcel(out, 0);
@@ -14348,6 +14545,10 @@
                 pr.println("*** Wifi signal strength #" + i + ":");
                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
             }
+            for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+                pr.println("*** GPS signal quality #" + i + ":");
+                mGpsSignalQualityTimer[i].logState(pr, "  ");
+            }
             pr.println("*** Flashlight timer:");
             mFlashlightOnTimer.logState(pr, "  ");
             pr.println("*** Camera timer:");
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index bb743c1..a34e7f5 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -31,8 +31,7 @@
 
     @Override
     public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
-                             long rawUptimeUs, int statsType) {
-
+            long rawUptimeUs, int statsType) {
         app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
         final int numClusters = mProfile.getNumCpuClusters();
 
@@ -42,7 +41,7 @@
             for (int speed = 0; speed < speedsForCluster; speed++) {
                 final long timeUs = u.getTimeAtCpuSpeed(cluster, speed, statsType);
                 final double cpuSpeedStepPower = timeUs *
-                        mProfile.getAveragePowerForCpu(cluster, speed);
+                        mProfile.getAveragePowerForCpuCore(cluster, speed);
                 if (DEBUG) {
                     Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
                             + speed + " timeUs=" + timeUs + " power="
@@ -51,6 +50,25 @@
                 cpuPowerMaUs += cpuSpeedStepPower;
             }
         }
+        cpuPowerMaUs += u.getCpuActiveTime() * mProfile.getAveragePower(
+                PowerProfile.POWER_CPU_ACTIVE);
+        long[] cpuClusterTimes = u.getCpuClusterTimes();
+        if (cpuClusterTimes != null) {
+            if (cpuClusterTimes.length == numClusters) {
+                for (int i = 0; i < numClusters; i++) {
+                    double power = cpuClusterTimes[i] * mProfile.getAveragePowerForCpuCluster(i);
+                    cpuPowerMaUs += power;
+                    if (DEBUG) {
+                        Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + i + " clusterTimeUs="
+                                + cpuClusterTimes[i] + " power="
+                                + BatteryStatsHelper.makemAh(power / MICROSEC_IN_HR));
+                    }
+                }
+            } else {
+                Log.w(TAG, "UID " + u.getUid() + " CPU cluster # mismatch: Power Profile # "
+                        + numClusters + " actual # " + cpuClusterTimes.length);
+            }
+        }
         app.cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR;
 
         if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) {
diff --git a/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java
new file mode 100644
index 0000000..cb96c5c
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+import android.annotation.Nullable;
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+
+/**
+ * Reads /proc/uid_concurrent_active_time which has the format:
+ * active: X (X is # cores)
+ * [uid0]: [time-0] [time-1] [time-2] ... (# entries = # cores)
+ * [uid1]: [time-0] [time-1] [time-2] ... ...
+ * ...
+ * Time-N means the CPU time a UID spent running concurrently with N other processes.
+ * The file contains a monotonically increasing count of time for a single boot. This class
+ * maintains the previous results of a call to {@link #readDelta} in order to provide a
+ * proper delta.
+ */
+public class KernelUidCpuActiveTimeReader {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "KernelUidCpuActiveTimeReader";
+    private static final String UID_TIMES_PROC_FILE = "/proc/uid_concurrent_active_time";
+
+    private int mCoreCount;
+    private long mLastTimeReadMs;
+    private long mNowTimeMs;
+    private SparseArray<long[]> mLastUidCpuActiveTimeMs = new SparseArray<>();
+
+    public interface Callback {
+        void onUidCpuActiveTime(int uid, long cpuActiveTimeMs);
+    }
+
+    public void readDelta(@Nullable Callback cb) {
+        final int oldMask = StrictMode.allowThreadDiskReadsMask();
+        try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
+            mNowTimeMs = SystemClock.elapsedRealtime();
+            readDeltaInternal(reader, cb);
+            mLastTimeReadMs = mNowTimeMs;
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
+        } finally {
+            StrictMode.setThreadPolicyMask(oldMask);
+        }
+    }
+
+    public void removeUid(int uid) {
+        mLastUidCpuActiveTimeMs.delete(uid);
+    }
+
+    public void removeUidsInRange(int startUid, int endUid) {
+        if (endUid < startUid) {
+            Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
+            return;
+        }
+        mLastUidCpuActiveTimeMs.put(startUid, null);
+        mLastUidCpuActiveTimeMs.put(endUid, null);
+        final int firstIndex = mLastUidCpuActiveTimeMs.indexOfKey(startUid);
+        final int lastIndex = mLastUidCpuActiveTimeMs.indexOfKey(endUid);
+        mLastUidCpuActiveTimeMs.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
+    }
+
+    @VisibleForTesting
+    public void readDeltaInternal(BufferedReader reader, @Nullable Callback cb) throws IOException {
+        String line = reader.readLine();
+        if (line == null || !line.startsWith("active:")) {
+            Slog.e(TAG, String.format("Malformed proc file: %s ", UID_TIMES_PROC_FILE));
+            return;
+        }
+        if (mCoreCount == 0) {
+            mCoreCount = Integer.parseInt(line.substring(line.indexOf(' ')+1));
+        }
+        while ((line = reader.readLine()) != null) {
+            final int index = line.indexOf(' ');
+            final int uid = Integer.parseInt(line.substring(0, index - 1), 10);
+            readTimesForUid(uid, line.substring(index + 1), cb);
+        }
+    }
+
+    private void readTimesForUid(int uid, String line, @Nullable Callback cb) {
+        long[] lastActiveTime = mLastUidCpuActiveTimeMs.get(uid);
+        if (lastActiveTime == null) {
+            lastActiveTime = new long[mCoreCount];
+            mLastUidCpuActiveTimeMs.put(uid, lastActiveTime);
+        }
+        final String[] timesStr = line.split(" ");
+        if (timesStr.length != mCoreCount) {
+            Slog.e(TAG, String.format("# readings don't match # cores, readings: %d, CPU cores: %d",
+                    timesStr.length, mCoreCount));
+            return;
+        }
+        long sumDeltas = 0;
+        final long[] curActiveTime = new long[mCoreCount];
+        boolean notify = false;
+        for (int i = 0; i < mCoreCount; i++) {
+            // Times read will be in units of 10ms
+            curActiveTime[i] = Long.parseLong(timesStr[i], 10) * 10;
+            long delta = curActiveTime[i] - lastActiveTime[i];
+            if (delta < 0 || curActiveTime[i] < 0) {
+                if (DEBUG) {
+                    final StringBuilder sb = new StringBuilder();
+                    sb.append(String.format("Malformed cpu active time for UID=%d\n", uid));
+                    sb.append(String.format("data=(%d,%d)\n", lastActiveTime[i], curActiveTime[i]));
+                    sb.append("times=(");
+                    TimeUtils.formatDuration(mLastTimeReadMs, sb);
+                    sb.append(",");
+                    TimeUtils.formatDuration(mNowTimeMs, sb);
+                    sb.append(")");
+                    Slog.e(TAG, sb.toString());
+                }
+                return;
+            }
+            notify |= delta > 0;
+            sumDeltas += delta / (i + 1);
+        }
+        if (notify) {
+            System.arraycopy(curActiveTime, 0, lastActiveTime, 0, mCoreCount);
+            if (cb != null) {
+                cb.onUidCpuActiveTime(uid, sumDeltas);
+            }
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java
new file mode 100644
index 0000000..85153bc
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+import android.annotation.Nullable;
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Reads /proc/uid_concurrent_policy_time which has the format:
+ * policy0: X policy4: Y (there are X cores on policy0, Y cores on policy4)
+ * [uid0]: [time-0-0] [time-0-1] ... [time-1-0] [time-1-1] ...
+ * [uid1]: [time-0-0] [time-0-1] ... [time-1-0] [time-1-1] ...
+ * ...
+ * Time-X-Y means the time a UID spent on clusterX running concurrently with Y other processes.
+ * The file contains a monotonically increasing count of time for a single boot. This class
+ * maintains the previous results of a call to {@link #readDelta} in order to provide a proper
+ * delta.
+ */
+public class KernelUidCpuClusterTimeReader {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "KernelUidCpuClusterTimeReader";
+    private static final String UID_TIMES_PROC_FILE = "/proc/uid_concurrent_policy_time";
+
+    // mCoreOnCluster[i] is the # of cores on cluster i
+    private int[] mCoreOnCluster;
+    private int mCores;
+    private long mLastTimeReadMs;
+    private long mNowTimeMs;
+    private SparseArray<long[]> mLastUidPolicyTimeMs = new SparseArray<>();
+
+    public interface Callback {
+        /**
+         * @param uid
+         * @param cpuActiveTimeMs the first dimension is cluster, the second dimension is the # of
+         *                        processes running concurrently with this uid.
+         */
+        void onUidCpuPolicyTime(int uid, long[] cpuActiveTimeMs);
+    }
+
+    public void readDelta(@Nullable Callback cb) {
+        final int oldMask = StrictMode.allowThreadDiskReadsMask();
+        try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
+            mNowTimeMs = SystemClock.elapsedRealtime();
+            readDeltaInternal(reader, cb);
+            mLastTimeReadMs = mNowTimeMs;
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
+        } finally {
+            StrictMode.setThreadPolicyMask(oldMask);
+        }
+    }
+
+    public void removeUid(int uid) {
+        mLastUidPolicyTimeMs.delete(uid);
+    }
+
+    public void removeUidsInRange(int startUid, int endUid) {
+        if (endUid < startUid) {
+            Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
+            return;
+        }
+        mLastUidPolicyTimeMs.put(startUid, null);
+        mLastUidPolicyTimeMs.put(endUid, null);
+        final int firstIndex = mLastUidPolicyTimeMs.indexOfKey(startUid);
+        final int lastIndex = mLastUidPolicyTimeMs.indexOfKey(endUid);
+        mLastUidPolicyTimeMs.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
+    }
+
+    @VisibleForTesting
+    public void readDeltaInternal(BufferedReader reader, @Nullable Callback cb) throws IOException {
+        String line = reader.readLine();
+        if (line == null || !line.startsWith("policy")) {
+            Slog.e(TAG, String.format("Malformed proc file: %s ", UID_TIMES_PROC_FILE));
+            return;
+        }
+        if (mCoreOnCluster == null) {
+            List<Integer> list = new ArrayList<>();
+            String[] policies = line.split(" ");
+
+            if (policies.length == 0 || policies.length % 2 != 0) {
+                Slog.e(TAG, String.format("Malformed proc file: %s ", UID_TIMES_PROC_FILE));
+                return;
+            }
+
+            for (int i = 0; i < policies.length; i+=2) {
+                list.add(Integer.parseInt(policies[i+1]));
+            }
+
+            mCoreOnCluster = new int[list.size()];
+            for(int i=0;i<list.size();i++){
+                mCoreOnCluster[i] = list.get(i);
+                mCores += mCoreOnCluster[i];
+            }
+        }
+        while ((line = reader.readLine()) != null) {
+            final int index = line.indexOf(' ');
+            final int uid = Integer.parseInt(line.substring(0, index - 1), 10);
+            readTimesForUid(uid, line.substring(index + 1), cb);
+        }
+    }
+
+    private void readTimesForUid(int uid, String line, @Nullable Callback cb) {
+        long[] lastPolicyTime = mLastUidPolicyTimeMs.get(uid);
+        if (lastPolicyTime == null) {
+            lastPolicyTime = new long[mCores];
+            mLastUidPolicyTimeMs.put(uid, lastPolicyTime);
+        }
+        final String[] timeStr = line.split(" ");
+        if (timeStr.length != mCores) {
+            Slog.e(TAG, String.format("# readings don't match # cores, readings: %d, # CPU cores: %d",
+                    timeStr.length, mCores));
+            return;
+        }
+        final long[] deltaPolicyTime = new long[mCores];
+        final long[] currPolicyTime = new long[mCores];
+        boolean notify = false;
+        for (int i = 0; i < mCores; i++) {
+            // Times read will be in units of 10ms
+            currPolicyTime[i] = Long.parseLong(timeStr[i], 10) * 10;
+            deltaPolicyTime[i] = currPolicyTime[i] - lastPolicyTime[i];
+            if (deltaPolicyTime[i] < 0 || currPolicyTime[i] < 0) {
+                if (DEBUG) {
+                    final StringBuilder sb = new StringBuilder();
+                    sb.append(String.format("Malformed cpu policy time for UID=%d\n", uid));
+                    sb.append(String.format("data=(%d,%d)\n", lastPolicyTime[i], currPolicyTime[i]));
+                    sb.append("times=(");
+                    TimeUtils.formatDuration(mLastTimeReadMs, sb);
+                    sb.append(",");
+                    TimeUtils.formatDuration(mNowTimeMs, sb);
+                    sb.append(")");
+                    Slog.e(TAG, sb.toString());
+                }
+                return;
+            }
+            notify |= deltaPolicyTime[i] > 0;
+        }
+        if (notify) {
+            System.arraycopy(currPolicyTime, 0, lastPolicyTime, 0, mCores);
+            if (cb != null) {
+                final long[] times = new long[mCoreOnCluster.length];
+                int core = 0;
+                for (int i = 0; i < mCoreOnCluster.length; i++) {
+                    for (int j = 0; j < mCoreOnCluster[i]; j++) {
+                        times[i] += deltaPolicyTime[core++] / (j+1);
+                    }
+                }
+                cb.onUidCpuPolicyTime(uid, times);
+            }
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 872b465..fcbbcd0 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -21,6 +21,7 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -43,23 +44,25 @@
     public static final String POWER_NONE = "none";
 
     /**
-     * Power consumption when CPU is in power collapse mode.
+     * POWER_CPU_SUSPEND: Power consumption when CPU is in power collapse mode.
+     * POWER_CPU_IDLE: Power consumption when CPU is awake (when a wake lock is held). This should
+     *                 be zero on devices that can go into full CPU power collapse even when a wake
+     *                 lock is held. Otherwise, this is the power consumption in addition to
+     *                 POWER_CPU_SUSPEND due to a wake lock being held but with no CPU activity.
+     * POWER_CPU_ACTIVE: Power consumption when CPU is running, excluding power consumed by clusters
+     *                   and cores.
+     *
+     * CPU Power Equation (assume two clusters):
+     * Total power = POWER_CPU_SUSPEND  (always added)
+     *               + POWER_CPU_IDLE   (skip this and below if in power collapse mode)
+     *               + POWER_CPU_ACTIVE (skip this and below if CPU is not running, but a wakelock
+     *                                   is held)
+     *               + cluster_power.cluster0 + cluster_power.cluster1 (skip cluster not running)
+     *               + core_power.cluster0 * num running cores in cluster 0
+     *               + core_power.cluster1 * num running cores in cluster 1
      */
+    public static final String POWER_CPU_SUSPEND = "cpu.suspend";
     public static final String POWER_CPU_IDLE = "cpu.idle";
-
-    /**
-     * Power consumption when CPU is awake (when a wake lock is held).  This
-     * should be 0 on devices that can go into full CPU power collapse even
-     * when a wake lock is held.  Otherwise, this is the power consumption in
-     * addition to POWER_CPU_IDLE due to a wake lock being held but with no
-     * CPU activity.
-     */
-    public static final String POWER_CPU_AWAKE = "cpu.awake";
-
-    /**
-     * Power consumption when CPU is in power collapse mode.
-     */
-    @Deprecated
     public static final String POWER_CPU_ACTIVE = "cpu.active";
 
     /**
@@ -182,9 +185,6 @@
      */
     public static final String POWER_CAMERA = "camera.avg";
 
-    @Deprecated
-    public static final String POWER_CPU_SPEEDS = "cpu.speeds";
-
     /**
      * Power consumed by wif batched scaning.  Broken down into bins by
      * Channels Scanned per Hour.  May do 1-720 scans per hour of 1-100 channels
@@ -197,7 +197,15 @@
      */
     public static final String POWER_BATTERY_CAPACITY = "battery.capacity";
 
-    static final HashMap<String, Object> sPowerMap = new HashMap<>();
+    /**
+     * A map from Power Use Item to its power consumption.
+     */
+    static final HashMap<String, Double> sPowerItemMap = new HashMap<>();
+    /**
+     * A map from Power Use Item to an array of its power consumption
+     * (for items with variable power e.g. CPU).
+     */
+    static final HashMap<String, Double[]> sPowerArrayMap = new HashMap<>();
 
     private static final String TAG_DEVICE = "device";
     private static final String TAG_ITEM = "item";
@@ -207,23 +215,32 @@
 
     private static final Object sLock = new Object();
 
+    @VisibleForTesting
     public PowerProfile(Context context) {
-        // Read the XML file for the given profile (normally only one per
-        // device)
+        this(context, false);
+    }
+
+    /**
+     * For PowerProfileTest
+     */
+    @VisibleForTesting
+    public PowerProfile(Context context, boolean forTest) {
+        // Read the XML file for the given profile (normally only one per device)
         synchronized (sLock) {
-            if (sPowerMap.size() == 0) {
-                readPowerValuesFromXml(context);
+            if (sPowerItemMap.size() == 0 && sPowerArrayMap.size() == 0) {
+                readPowerValuesFromXml(context, forTest);
             }
             initCpuClusters();
         }
     }
 
-    private void readPowerValuesFromXml(Context context) {
-        int id = com.android.internal.R.xml.power_profile;
+    private void readPowerValuesFromXml(Context context, boolean forTest) {
+        final int id = forTest ? com.android.internal.R.xml.power_profile_test :
+                com.android.internal.R.xml.power_profile;
         final Resources resources = context.getResources();
         XmlResourceParser parser = resources.getXml(id);
         boolean parsingArray = false;
-        ArrayList<Double> array = new ArrayList<Double>();
+        ArrayList<Double> array = new ArrayList<>();
         String arrayName = null;
 
         try {
@@ -237,7 +254,7 @@
 
                 if (parsingArray && !element.equals(TAG_ARRAYITEM)) {
                     // Finish array
-                    sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
+                    sPowerArrayMap.put(arrayName, array.toArray(new Double[array.size()]));
                     parsingArray = false;
                 }
                 if (element.equals(TAG_ARRAY)) {
@@ -255,7 +272,7 @@
                         } catch (NumberFormatException nfe) {
                         }
                         if (element.equals(TAG_ITEM)) {
-                            sPowerMap.put(name, value);
+                            sPowerItemMap.put(name, value);
                         } else if (parsingArray) {
                             array.add(value);
                         }
@@ -263,7 +280,7 @@
                 }
             }
             if (parsingArray) {
-                sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
+                sPowerArrayMap.put(arrayName, array.toArray(new Double[array.size()]));
             }
         } catch (XmlPullParserException e) {
             throw new RuntimeException(e);
@@ -300,52 +317,56 @@
             String key = configResIdKeys[i];
             // if we already have some of these parameters in power_profile.xml, ignore the
             // value in config.xml
-            if ((sPowerMap.containsKey(key) && (Double) sPowerMap.get(key) > 0)) {
+            if ((sPowerItemMap.containsKey(key) && sPowerItemMap.get(key) > 0)) {
                 continue;
             }
             int value = resources.getInteger(configResIds[i]);
             if (value > 0) {
-                sPowerMap.put(key, (double) value);
+                sPowerItemMap.put(key, (double) value);
             }
         }
     }
 
     private CpuClusterKey[] mCpuClusters;
 
-    private static final String POWER_CPU_CLUSTER_CORE_COUNT = "cpu.clusters.cores";
-    private static final String POWER_CPU_CLUSTER_SPEED_PREFIX = "cpu.speeds.cluster";
-    private static final String POWER_CPU_CLUSTER_ACTIVE_PREFIX = "cpu.active.cluster";
+    private static final String CPU_PER_CLUSTER_CORE_COUNT = "cpu.clusters.cores";
+    private static final String CPU_CLUSTER_POWER_COUNT = "cpu.cluster_power.cluster";
+    private static final String CPU_CORE_SPEED_PREFIX = "cpu.core_speeds.cluster";
+    private static final String CPU_CORE_POWER_PREFIX = "cpu.core_power.cluster";
 
-    @SuppressWarnings("deprecation")
     private void initCpuClusters() {
-        // Figure out how many CPU clusters we're dealing with
-        final Object obj = sPowerMap.get(POWER_CPU_CLUSTER_CORE_COUNT);
-        if (obj == null || !(obj instanceof Double[])) {
+        if (sPowerArrayMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) {
+            final Double[] data = sPowerArrayMap.get(CPU_PER_CLUSTER_CORE_COUNT);
+            mCpuClusters = new CpuClusterKey[data.length];
+            for (int cluster = 0; cluster < data.length; cluster++) {
+                int numCpusInCluster = (int) Math.round(data[cluster]);
+                mCpuClusters[cluster] = new CpuClusterKey(
+                        CPU_CORE_SPEED_PREFIX + cluster, CPU_CLUSTER_POWER_COUNT + cluster,
+                        CPU_CORE_POWER_PREFIX + cluster, numCpusInCluster);
+            }
+        } else {
             // Default to single.
             mCpuClusters = new CpuClusterKey[1];
-            mCpuClusters[0] = new CpuClusterKey(POWER_CPU_SPEEDS, POWER_CPU_ACTIVE, 1);
-
-        } else {
-            final Double[] array = (Double[]) obj;
-            mCpuClusters = new CpuClusterKey[array.length];
-            for (int cluster = 0; cluster < array.length; cluster++) {
-                int numCpusInCluster = (int) Math.round(array[cluster]);
-                mCpuClusters[cluster] = new CpuClusterKey(
-                        POWER_CPU_CLUSTER_SPEED_PREFIX + cluster,
-                        POWER_CPU_CLUSTER_ACTIVE_PREFIX + cluster,
-                        numCpusInCluster);
+            int numCpus = 1;
+            if (sPowerItemMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) {
+                numCpus = (int) Math.round(sPowerItemMap.get(CPU_PER_CLUSTER_CORE_COUNT));
             }
+            mCpuClusters[0] = new CpuClusterKey(CPU_CORE_SPEED_PREFIX + 0,
+                    CPU_CLUSTER_POWER_COUNT + 0, CPU_CORE_POWER_PREFIX + 0, numCpus);
         }
     }
 
     public static class CpuClusterKey {
-        private final String timeKey;
-        private final String powerKey;
+        private final String freqKey;
+        private final String clusterPowerKey;
+        private final String corePowerKey;
         private final int numCpus;
 
-        private CpuClusterKey(String timeKey, String powerKey, int numCpus) {
-            this.timeKey = timeKey;
-            this.powerKey = powerKey;
+        private CpuClusterKey(String freqKey, String clusterPowerKey,
+                String corePowerKey, int numCpus) {
+            this.freqKey = freqKey;
+            this.clusterPowerKey = clusterPowerKey;
+            this.corePowerKey = corePowerKey;
             this.numCpus = numCpus;
         }
     }
@@ -354,21 +375,30 @@
         return mCpuClusters.length;
     }
 
-    public int getNumCoresInCpuCluster(int index) {
-        return mCpuClusters[index].numCpus;
+    public int getNumCoresInCpuCluster(int cluster) {
+        return mCpuClusters[cluster].numCpus;
     }
 
-    public int getNumSpeedStepsInCpuCluster(int index) {
-        Object value = sPowerMap.get(mCpuClusters[index].timeKey);
-        if (value != null && value instanceof Double[]) {
-            return ((Double[])value).length;
+    public int getNumSpeedStepsInCpuCluster(int cluster) {
+        if (cluster < 0 || cluster >= mCpuClusters.length) {
+            return 0; // index out of bound
+        }
+        if (sPowerArrayMap.containsKey(mCpuClusters[cluster].freqKey)) {
+            return sPowerArrayMap.get(mCpuClusters[cluster].freqKey).length;
         }
         return 1; // Only one speed
     }
 
-    public double getAveragePowerForCpu(int cluster, int step) {
+    public double getAveragePowerForCpuCluster(int cluster) {
         if (cluster >= 0 && cluster < mCpuClusters.length) {
-            return getAveragePower(mCpuClusters[cluster].powerKey, step);
+            return getAveragePower(mCpuClusters[cluster].clusterPowerKey);
+        }
+        return 0;
+    }
+
+    public double getAveragePowerForCpuCore(int cluster, int step) {
+        if (cluster >= 0 && cluster < mCpuClusters.length) {
+            return getAveragePower(mCpuClusters[cluster].corePowerKey, step);
         }
         return 0;
     }
@@ -379,14 +409,10 @@
      * @return the number of memory bandwidth buckets.
      */
     public int getNumElements(String key) {
-        if (sPowerMap.containsKey(key)) {
-            Object data = sPowerMap.get(key);
-            if (data instanceof Double[]) {
-                final Double[] values = (Double[]) data;
-                return values.length;
-            } else {
-                return 1;
-            }
+        if (sPowerItemMap.containsKey(key)) {
+            return 1;
+        } else if (sPowerArrayMap.containsKey(key)) {
+            return sPowerArrayMap.get(key).length;
         }
         return 0;
     }
@@ -399,13 +425,10 @@
      * @return the average current in milliAmps.
      */
     public double getAveragePowerOrDefault(String type, double defaultValue) {
-        if (sPowerMap.containsKey(type)) {
-            Object data = sPowerMap.get(type);
-            if (data instanceof Double[]) {
-                return ((Double[])data)[0];
-            } else {
-                return (Double) sPowerMap.get(type);
-            }
+        if (sPowerItemMap.containsKey(type)) {
+            return sPowerItemMap.get(type);
+        } else if (sPowerArrayMap.containsKey(type)) {
+            return sPowerArrayMap.get(type)[0];
         } else {
             return defaultValue;
         }
@@ -429,19 +452,16 @@
      * @return the average current in milliAmps.
      */
     public double getAveragePower(String type, int level) {
-        if (sPowerMap.containsKey(type)) {
-            Object data = sPowerMap.get(type);
-            if (data instanceof Double[]) {
-                final Double[] values = (Double[]) data;
-                if (values.length > level && level >= 0) {
-                    return values[level];
-                } else if (level < 0 || values.length == 0) {
-                    return 0;
-                } else {
-                    return values[values.length - 1];
-                }
+        if (sPowerItemMap.containsKey(type)) {
+            return sPowerItemMap.get(type);
+        } else if (sPowerArrayMap.containsKey(type)) {
+            final Double[] values = sPowerArrayMap.get(type);
+            if (values.length > level && level >= 0) {
+                return values[level];
+            } else if (level < 0 || values.length == 0) {
+                return 0;
             } else {
-                return (Double) data;
+                return values[values.length - 1];
             }
         } else {
             return 0;
diff --git a/core/java/com/android/internal/os/WakelockPowerCalculator.java b/core/java/com/android/internal/os/WakelockPowerCalculator.java
index c7897b2..486b584 100644
--- a/core/java/com/android/internal/os/WakelockPowerCalculator.java
+++ b/core/java/com/android/internal/os/WakelockPowerCalculator.java
@@ -26,7 +26,7 @@
     private long mTotalAppWakelockTimeMs = 0;
 
     public WakelockPowerCalculator(PowerProfile profile) {
-        mPowerWakelock = profile.getAveragePower(PowerProfile.POWER_CPU_AWAKE);
+        mPowerWakelock = profile.getAveragePower(PowerProfile.POWER_CPU_IDLE);
     }
 
     @Override
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 66b777e..2b51033 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -102,6 +102,7 @@
             case android.os.Process.ROOT_UID:
             case android.os.Process.SYSTEM_UID:
             case android.os.Process.SHELL_UID:
+            case android.os.Process.INCIDENTD_UID:
                 return true;
         }
 
diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java
index f7ea787..7fd94c6 100644
--- a/core/java/com/android/internal/util/ScreenshotHelper.java
+++ b/core/java/com/android/internal/util/ScreenshotHelper.java
@@ -1,5 +1,6 @@
 package com.android.internal.util;
 
+import android.annotation.NonNull;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -32,8 +33,18 @@
         mContext = context;
     }
 
+    /**
+     * Request a screenshot be taken.
+     *
+     * @param screenshotType The type of screenshot, for example either
+     *                       {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN}
+     *                       or {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION}
+     * @param hasStatus {@code true} if the status bar is currently showing. {@code false} if not.
+     * @param hasNav {@code true} if the navigation bar is currently showing. {@code false} if not.
+     * @param handler A handler used in case the screenshot times out
+     */
     public void takeScreenshot(final int screenshotType, final boolean hasStatus,
-            final boolean hasNav, Handler handler) {
+            final boolean hasNav, @NonNull Handler handler) {
         synchronized (mScreenshotLock) {
             if (mScreenshotConnection != null) {
                 return;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 547e83c..e4e46f6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1747,6 +1747,12 @@
     <permission android:name="android.permission.SEND_EMBMS_INTENTS"
         android:protectionLevel="signature|privileged" />
 
+
+    <!-- Allows internal management of the sensor framework
+         @hide -->
+    <permission android:name="android.permission.MANAGE_SENSORS"
+        android:protectionLevel="signature" />
+
     <!-- Must be required by an ImsService to ensure that only the
          system can bind to it.
          <p>Protection level: signature|privileged
@@ -3692,6 +3698,10 @@
     <permission android:name="android.permission.READ_RUNTIME_PROFILES"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- @hide Allows audio policy management. -->
+    <permission android:name="android.permission.MANAGE_AUDIO_POLICY"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows an application to turn on / off quiet mode.
          @hide <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MODIFY_QUIET_MODE"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f084159..7005e28 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -640,6 +640,12 @@
     <!-- Wifi driver supports batched scan -->
     <bool translatable="false" name="config_wifi_batched_scan_supported">false</bool>
 
+    <!-- Wifi driver supports Automatic channel selection (ACS) for softap -->
+    <bool translatable="false" name="config_wifi_softap_acs_supported">false</bool>
+
+    <!-- Wifi driver supports IEEE80211AC for softap -->
+    <bool translatable="false" name="config_wifi_softap_ieee80211ac_supported">false</bool>
+
     <!-- Idle Receive current for wifi radio. 0 by default-->
     <integer translatable="false" name="config_wifi_idle_receive_cur_ma">0</integer>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1993ab4..5309115 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -309,6 +309,8 @@
   <java-symbol type="bool" name="config_useFixedVolume" />
   <java-symbol type="bool" name="config_forceDefaultOrientation" />
   <java-symbol type="bool" name="config_wifi_batched_scan_supported" />
+  <java-symbol type="bool" name="config_wifi_softap_acs_supported" />
+  <java-symbol type="bool" name="config_wifi_softap_ieee80211ac_supported" />
   <java-symbol type="bool" name="config_enableMultiUserUI"/>
   <java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
   <java-symbol type="bool" name="config_hasRecents" />
@@ -1508,6 +1510,7 @@
   <java-symbol type="xml" name="password_kbd_symbols" />
   <java-symbol type="xml" name="password_kbd_symbols_shift" />
   <java-symbol type="xml" name="power_profile" />
+  <java-symbol type="xml" name="power_profile_test" />
   <java-symbol type="xml" name="sms_short_codes" />
   <java-symbol type="xml" name="audio_assets" />
   <java-symbol type="xml" name="global_keys" />
diff --git a/core/res/res/xml/power_profile_test.xml b/core/res/res/xml/power_profile_test.xml
new file mode 100644
index 0000000..cdb7134
--- /dev/null
+++ b/core/res/res/xml/power_profile_test.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2017, 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.
+*/
+-->
+<device name="Android">
+    <!-- All values are in mAh except as noted.
+         This file is for PowerProfileTest.java. Changes must be synced between these two. Since
+         power_profile.xml may be overridden by actual device's power_profile.xml at compile time,
+         this test config ensures we have something constant to test against. Values below are
+         sample values, not meant to reflect any real device.
+    -->
+
+    <!-- Nothing -->
+    <item name="none">0</item>
+
+    <!-- This is the battery capacity in mAh -->
+    <item name="battery.capacity">3000</item>
+
+    <!-- Number of cores each CPU cluster contains -->
+    <array name="cpu.clusters.cores">
+        <value>4</value> <!-- Cluster 0 has 4 cores (cpu0, cpu1, cpu2, cpu3) -->
+        <value>4</value> <!-- Cluster 1 has 4 cores (cpu4, cpu5, cpu5, cpu7) -->
+    </array>
+
+    <!-- Power consumption when CPU is suspended -->
+    <item name="cpu.suspend">5</item>
+    <!-- Additional power consumption when CPU is in a kernel idle loop -->
+    <item name="cpu.idle">1.11</item>
+    <!-- Additional power consumption by CPU excluding cluster and core when  running -->
+    <item name="cpu.active">2.55</item>
+
+    <!-- Additional power consumption by CPU cluster0 itself when running excluding cores in it -->
+    <item name="cpu.cluster_power.cluster0">2.11</item>
+    <!-- Additional power consumption by CPU cluster1 itself when running excluding cores in it -->
+    <item name="cpu.cluster_power.cluster1">2.22</item>
+
+    <!-- Different CPU speeds as reported in
+         /sys/devices/system/cpu/cpu0/cpufreq/stats/scaling_available_frequencies -->
+    <array name="cpu.core_speeds.cluster0">
+        <value>300000</value> <!-- 300 MHz CPU speed -->
+        <value>1000000</value> <!-- 1000 MHz CPU speed -->
+        <value>2000000</value> <!-- 2000 MHz CPU speed -->
+    </array>
+    <!-- Different CPU speeds as reported in
+         /sys/devices/system/cpu/cpu4/cpufreq/stats/scaling_available_frequencies -->
+    <array name="cpu.core_speeds.cluster1">
+        <value>300000</value> <!-- 300 MHz CPU speed -->
+        <value>1000000</value> <!-- 1000 MHz CPU speed -->
+        <value>2500000</value> <!-- 2500 MHz CPU speed -->
+        <value>3000000</value> <!-- 3000 MHz CPU speed -->
+    </array>
+
+    <!-- Additional power used by a CPU from cluster 0 when running at different
+         speeds. Currently this measurement also includes cluster cost. -->
+    <array name="cpu.core_power.cluster0">
+        <value>10</value> <!-- 300 MHz CPU speed -->
+        <value>20</value> <!-- 1000 MHz CPU speed -->
+        <value>30</value> <!-- 1900 MHz CPU speed -->
+    </array>
+    <!-- Additional power used by a CPU from cluster 1 when running at different
+         speeds. Currently this measurement also includes cluster cost. -->
+    <array name="cpu.core_power.cluster1">
+        <value>25</value> <!-- 300 MHz CPU speed -->
+        <value>35</value> <!-- 1000 MHz CPU speed -->
+        <value>50</value> <!-- 2500 MHz CPU speed -->
+        <value>60</value> <!-- 3000 MHz CPU speed -->
+    </array>
+
+    <!-- Additional power used when screen is turned on at minimum brightness -->
+    <item name="screen.on">100</item>
+    <!-- Additional power used when screen is at maximum brightness, compared to
+         screen at minimum brightness -->
+    <item name="screen.full">800</item>
+
+    <!-- Average power used by the camera flash module when on -->
+    <item name="camera.flashlight">500</item>
+    <!-- Average power use by the camera subsystem for a typical camera
+         application. Intended as a rough estimate for an application running a
+         preview and capturing approximately 10 full-resolution pictures per
+         minute. -->
+    <item name="camera.avg">600</item>
+
+    <!-- Additional power used when audio decoding/encoding via DSP -->
+    <item name="dsp.audio">100</item>
+
+    <!-- Additional power used when GPS is acquiring a signal -->
+    <item name="gps.on">10</item>
+
+    <!-- Additional power used when cellular radio is transmitting/receiving -->
+    <item name="radio.active">60</item>
+    <!-- Additional power used when cellular radio is paging the tower -->
+    <item name="radio.scanning">3</item>
+    <!-- Additional power used when the cellular radio is on. Multi-value entry,
+         one per signal strength (no signal, weak, moderate, strong) -->
+    <array name="radio.on"> <!-- Strength 0 to BINS-1 -->
+        <value>6</value>       <!-- none -->
+        <value>5</value>       <!-- poor -->
+        <value>4</value>       <!-- moderate -->
+        <value>3</value>       <!-- good -->
+        <value>3</value>       <!-- great -->
+    </array>
+</device>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 37b3180..ec3a6ce 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -534,7 +534,9 @@
                  Settings.Secure.VOICE_RECOGNITION_SERVICE,
                  Settings.Secure.INSTANT_APPS_ENABLED,
                  Settings.Secure.BACKUP_MANAGER_CONSTANTS,
-                 Settings.Secure.KEYGUARD_SLICE_URI);
+                 Settings.Secure.KEYGUARD_SLICE_URI,
+                 Settings.Secure.PARENTAL_CONTROL_ENABLED,
+                 Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL);
 
     @Test
     public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
index 00732b0..4c4aeaf 100644
--- a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
@@ -36,20 +36,28 @@
 
     @Test
     public void ensureAllBackedUpSystemSettingsHaveValidators() {
-        String offenders = getOffenders(Settings.System.SETTINGS_TO_BACKUP,
-                Settings.System.VALIDATORS);
+        String offenders = getOffenders(concat(Settings.System.SETTINGS_TO_BACKUP,
+                Settings.System.LEGACY_RESTORE_SETTINGS), Settings.System.VALIDATORS);
 
         failIfOffendersPresent(offenders, "Settings.System");
     }
 
     @Test
     public void ensureAllBackedUpGlobalSettingsHaveValidators() {
-        String offenders = getOffenders(Settings.Global.SETTINGS_TO_BACKUP,
-                Settings.Global.VALIDATORS);
+        String offenders = getOffenders(concat(Settings.Global.SETTINGS_TO_BACKUP,
+                Settings.Global.LEGACY_RESTORE_SETTINGS), Settings.Global.VALIDATORS);
 
         failIfOffendersPresent(offenders, "Settings.Global");
     }
 
+    @Test
+    public void ensureAllBackedUpSecureSettingsHaveValidators() {
+        String offenders = getOffenders(concat(Settings.Secure.SETTINGS_TO_BACKUP,
+                Settings.Secure.LEGACY_RESTORE_SETTINGS), Settings.Secure.VALIDATORS);
+
+        failIfOffendersPresent(offenders, "Settings.Secure");
+    }
+
     private void failIfOffendersPresent(String offenders, String settingsType) {
         if (offenders.length() > 0) {
             fail("All " + settingsType + " settings that are backed up have to have a non-null"
@@ -66,4 +74,16 @@
         }
         return offenders.toString();
     }
+
+    private String[] concat(String[] first, String[] second) {
+        if (second == null || second.length == 0) {
+            return first;
+        }
+        final int firstLen = first.length;
+        final int secondLen = second.length;
+        String[] both = new String[firstLen + secondLen];
+        System.arraycopy(first, 0, both, 0, firstLen);
+        System.arraycopy(second, 0, both, firstLen, secondLen);
+        return both;
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
index b5a7bec..32053e3 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
@@ -62,9 +62,9 @@
  *
  * Build: m FrameworksCoreTests
  * Install: adb install -r \
- *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
+ * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
  * Run: adb shell am instrument -e class com.android.internal.os.BatteryStatsCpuTimesTest -w \
- *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ * com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
  *
  * or
  *
@@ -73,10 +73,18 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class BatteryStatsCpuTimesTest {
-    @Mock KernelUidCpuTimeReader mKernelUidCpuTimeReader;
-    @Mock KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader;
-    @Mock BatteryStatsImpl.UserInfoProvider mUserInfoProvider;
-    @Mock PowerProfile mPowerProfile;
+    @Mock
+    KernelUidCpuTimeReader mKernelUidCpuTimeReader;
+    @Mock
+    KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader;
+    @Mock
+    KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader;
+    @Mock
+    KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader;
+    @Mock
+    BatteryStatsImpl.UserInfoProvider mUserInfoProvider;
+    @Mock
+    PowerProfile mPowerProfile;
 
     private MockClocks mClocks;
     private MockBatteryStatsImpl mBatteryStatsImpl;
@@ -90,6 +98,8 @@
         mBatteryStatsImpl = new MockBatteryStatsImpl(mClocks)
                 .setKernelUidCpuTimeReader(mKernelUidCpuTimeReader)
                 .setKernelUidCpuFreqTimeReader(mKernelUidCpuFreqTimeReader)
+                .setKernelUidCpuActiveTimeReader(mKernelUidCpuActiveTimeReader)
+                .setKernelUidCpuClusterTimeReader(mKernelUidCpuClusterTimeReader)
                 .setUserInfoProvider(mUserInfoProvider);
     }
 
@@ -134,6 +144,10 @@
         verify(mKernelUidCpuFreqTimeReader, times(2)).perClusterTimesAvailable();
         verify(mKernelUidCpuFreqTimeReader).readDelta(
                 any(KernelUidCpuFreqTimeReader.Callback.class));
+        verify(mKernelUidCpuActiveTimeReader).readDelta(
+                any(KernelUidCpuActiveTimeReader.Callback.class));
+        verify(mKernelUidCpuClusterTimeReader).readDelta(
+                any(KernelUidCpuClusterTimeReader.Callback.class));
         verifyNoMoreInteractions(mKernelUidCpuFreqTimeReader);
         for (int i = 0; i < numClusters; ++i) {
             verify(mKernelCpuSpeedReaders[i]).readDelta();
@@ -228,7 +242,7 @@
         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -301,7 +315,7 @@
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
         final int isolatedAppId = FIRST_ISOLATED_UID + 27;
         final int isolatedUid = UserHandle.getUid(testUserId, isolatedAppId);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 isolatedAppId,
                 FIRST_APPLICATION_UID + 33
@@ -389,7 +403,7 @@
         final int invalidUid = UserHandle.getUid(invalidUserId, FIRST_APPLICATION_UID + 99);
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
         when(mUserInfoProvider.exists(invalidUserId)).thenReturn(false);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -431,7 +445,7 @@
         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -514,10 +528,10 @@
 
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
-            FIRST_APPLICATION_UID + 22,
-            FIRST_APPLICATION_UID + 27,
-            FIRST_APPLICATION_UID + 33
+        final int[] testUids = getUids(testUserId, new int[]{
+                FIRST_APPLICATION_UID + 22,
+                FIRST_APPLICATION_UID + 27,
+                FIRST_APPLICATION_UID + 33
         });
         final long[][] uidTimesMs = {
                 {4, 10, 5, 9, 4},
@@ -589,7 +603,7 @@
 
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -693,7 +707,7 @@
 
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -782,7 +796,7 @@
             }
         }
         for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
-            for (int speed = 0 ; speed < clusterFreqs[cluster]; ++speed) {
+            for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
                 assertEquals("There shouldn't be any left-overs: "
                                 + Arrays.deepToString(expectedWakeLockUidTimesUs),
                         0, expectedWakeLockUidTimesUs[cluster][speed]);
@@ -797,7 +811,7 @@
 
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -874,7 +888,7 @@
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
         final int isolatedAppId = FIRST_ISOLATED_UID + 27;
         final int isolatedUid = UserHandle.getUid(testUserId, isolatedAppId);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 isolatedAppId,
                 FIRST_APPLICATION_UID + 33
@@ -969,7 +983,7 @@
         final int invalidUid = UserHandle.getUid(invalidUserId, FIRST_APPLICATION_UID + 99);
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
         when(mUserInfoProvider.exists(invalidUserId)).thenReturn(false);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -986,7 +1000,7 @@
                 callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
             }
             // And one for the invalid uid
-            callback.onUidCpuFreqTime(invalidUid, new long[] {12, 839, 32, 34, 21});
+            callback.onUidCpuFreqTime(invalidUid, new long[]{12, 839, 32, 34, 21});
             return null;
         }).when(mKernelUidCpuFreqTimeReader).readDelta(
                 any(KernelUidCpuFreqTimeReader.Callback.class));
@@ -1009,6 +1023,136 @@
         verify(mKernelUidCpuFreqTimeReader).removeUid(invalidUid);
     }
 
+    @Test
+    public void testReadKernelUidCpuActiveTimesLocked() {
+        // PRECONDITIONS
+        updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
+
+        final int testUserId = 11;
+        when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
+        final int[] testUids = getUids(testUserId, new int[]{
+                FIRST_APPLICATION_UID + 22,
+                FIRST_APPLICATION_UID + 27,
+                FIRST_APPLICATION_UID + 33
+        });
+        final long[] uidTimesMs = {8000, 25000, 3000, 0, 42000};
+        doAnswer(invocation -> {
+            final KernelUidCpuActiveTimeReader.Callback callback =
+                    (KernelUidCpuActiveTimeReader.Callback) invocation.getArguments()[0];
+            for (int i = 0; i < testUids.length; ++i) {
+                callback.onUidCpuActiveTime(testUids[i], uidTimesMs[i]);
+            }
+            return null;
+        }).when(mKernelUidCpuActiveTimeReader).readDelta(
+                any(KernelUidCpuActiveTimeReader.Callback.class));
+
+        // RUN
+        mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked();
+
+        // VERIFY
+        for (int i = 0; i < testUids.length; ++i) {
+            final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
+            assertNotNull("No entry for uid=" + testUids[i], u);
+            assertEquals("Unexpected cpu active time for uid=" + testUids[i], uidTimesMs[i],
+                    u.getCpuActiveTime());
+        }
+
+        // Repeat the test when the screen is off.
+
+        // PRECONDITIONS
+        updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
+        final long[] deltasMs = {43000, 3345000, 2143000, 123000, 4554000};
+        doAnswer(invocation -> {
+            final KernelUidCpuActiveTimeReader.Callback callback =
+                    (KernelUidCpuActiveTimeReader.Callback) invocation.getArguments()[0];
+            for (int i = 0; i < testUids.length; ++i) {
+                callback.onUidCpuActiveTime(testUids[i], deltasMs[i]);
+            }
+            return null;
+        }).when(mKernelUidCpuActiveTimeReader).readDelta(
+                any(KernelUidCpuActiveTimeReader.Callback.class));
+
+        // RUN
+        mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked();
+
+        // VERIFY
+        for (int i = 0; i < testUids.length; ++i) {
+            final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
+            assertNotNull("No entry for uid=" + testUids[i], u);
+            assertEquals("Unexpected cpu active time for uid=" + testUids[i],
+                    uidTimesMs[i] + deltasMs[i], u.getCpuActiveTime());
+        }
+    }
+
+    @Test
+    public void testReadKernelUidCpuClusterTimesLocked() {
+        // PRECONDITIONS
+        updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
+
+        final int testUserId = 11;
+        when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
+        final int[] testUids = getUids(testUserId, new int[]{
+                FIRST_APPLICATION_UID + 22,
+                FIRST_APPLICATION_UID + 27,
+                FIRST_APPLICATION_UID + 33
+        });
+        final long[][] uidTimesMs = {
+                {4000, 10000},
+                {5000, 1000},
+                {8000, 0}
+        };
+        doAnswer(invocation -> {
+            final KernelUidCpuClusterTimeReader.Callback callback =
+                    (KernelUidCpuClusterTimeReader.Callback) invocation.getArguments()[0];
+            for (int i = 0; i < testUids.length; ++i) {
+                callback.onUidCpuPolicyTime(testUids[i], uidTimesMs[i]);
+            }
+            return null;
+        }).when(mKernelUidCpuClusterTimeReader).readDelta(
+                any(KernelUidCpuClusterTimeReader.Callback.class));
+
+        // RUN
+        mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked();
+
+        // VERIFY
+        for (int i = 0; i < testUids.length; ++i) {
+            final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
+            assertNotNull("No entry for uid=" + testUids[i], u);
+            assertArrayEquals("Unexpected cpu cluster time for uid=" + testUids[i], uidTimesMs[i],
+                    u.getCpuClusterTimes());
+        }
+
+        // Repeat the test when the screen is off.
+
+        // PRECONDITIONS
+        updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
+        final long[][] deltasMs = {
+                {3000, 12000},
+                {3248327490475L, 0},
+                {43000, 3345000}
+        };
+        doAnswer(invocation -> {
+            final KernelUidCpuClusterTimeReader.Callback callback =
+                    (KernelUidCpuClusterTimeReader.Callback) invocation.getArguments()[0];
+            for (int i = 0; i < testUids.length; ++i) {
+                callback.onUidCpuPolicyTime(testUids[i], deltasMs[i]);
+            }
+            return null;
+        }).when(mKernelUidCpuClusterTimeReader).readDelta(
+                any(KernelUidCpuClusterTimeReader.Callback.class));
+
+        // RUN
+        mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked();
+
+        // VERIFY
+        for (int i = 0; i < testUids.length; ++i) {
+            final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
+            assertNotNull("No entry for uid=" + testUids[i], u);
+            assertArrayEquals("Unexpected cpu cluster time for uid=" + testUids[i], sum(uidTimesMs[i], deltasMs[i]),
+                    u.getCpuClusterTimes());
+        }
+    }
+
     private void updateTimeBasesLocked(boolean unplugged, int screenState,
             long upTime, long realTime) {
         // Set PowerProfile=null before calling updateTimeBasesLocked to avoid execution of
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index e8f2456..702f4b8 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -39,8 +39,11 @@
         KernelMemoryBandwidthStatsTest.class,
         KernelSingleUidTimeReaderTest.class,
         KernelUidCpuFreqTimeReaderTest.class,
+        KernelUidCpuActiveTimeReaderTest.class,
+        KernelUidCpuClusterTimeReaderTest.class,
         KernelWakelockReaderTest.class,
-        LongSamplingCounterArrayTest.class
+        LongSamplingCounterArrayTest.class,
+        PowerProfileTest.class
     })
 public class BatteryStatsTests {
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
new file mode 100644
index 0000000..1ac82bd
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.BufferedReader;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Test class for {@link KernelUidCpuActiveTimeReader}.
+ *
+ * To run it:
+ * bit FrameworksCoreTests:com.android.internal.os.KernelUidCpuActiveTimeReaderTest
+ *
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KernelUidCpuActiveTimeReaderTest {
+    @Mock private BufferedReader mBufferedReader;
+    @Mock private KernelUidCpuActiveTimeReader.Callback mCallback;
+
+    private KernelUidCpuActiveTimeReader mReader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mReader = new KernelUidCpuActiveTimeReader();
+    }
+
+    public class Temp {
+
+        public void method() {
+            method1(new long[][]{{1,2,3}, {2,3,4}});
+            method1(new long[][]{{2,2,3}, {2,3,4}});
+        }
+        public int method1(long[][] array) {
+            return array.length * array[0].length;
+        }
+    }
+
+    @Test
+    public void testReadDelta() throws Exception {
+        final int cores = 8;
+        final String info = "active: 8";
+        final int[] uids = {1, 22, 333, 4444, 5555};
+
+        final long[][] times = increaseTime(new long[uids.length][cores]);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for(int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(times[i]));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that a second call will only return deltas.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times1 = increaseTime(times);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for(int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times1[i], times[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that there won't be a callback if the proc file values didn't change.
+        Mockito.reset(mCallback, mBufferedReader);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that calling with a null callback doesn't result in any crashes
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times2 = increaseTime(times1);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times2));
+        mReader.readDeltaInternal(mBufferedReader, null);
+
+        // Verify that the readDelta call will only return deltas when
+        // the previous call had null callback.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times3 = increaseTime(times2);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i = 0; i < uids.length; ++i) {
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times3[i], times2[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+    }
+
+    @Test
+    public void testReadDelta_malformedData() throws Exception {
+        final int cores = 8;
+        final String info = "active: 8";
+        final int[] uids = {1, 22, 333, 4444, 5555};
+        final long[][] times = increaseTime(new long[uids.length][cores]);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for(int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(times[i]));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that there is no callback if subsequent call provides wrong # of entries.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] temp = increaseTime(times);
+        final long[][] times1 = new long[uids.length][];
+        for(int i=0;i<temp.length;i++){
+            times1[i] = Arrays.copyOfRange(temp[i], 0, 6);
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified if the given core count does not match
+        // the following # of entries.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times2 = increaseTime(times);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times2));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for(int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times2[i], times[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that there is no callback if any value in the proc file is -ve.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times3 = increaseTime(times2);
+        times3[uids.length - 1][cores - 1] *= -1;
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i = 0; i < uids.length - 1; ++i) {
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times3[i], times2[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified when the proc file had -ve value.
+        Mockito.reset(mCallback, mBufferedReader);
+        for (int i = 0; i < cores; i++) {
+            times3[uids.length - 1][i] = times2[uids.length - 1][i] + uids[uids.length - 1] * 1000;
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verify(mCallback).onUidCpuActiveTime(uids[uids.length - 1], getTotal(subtract(times3[uids.length - 1], times2[uids.length - 1])));
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that there is no callback if the values in the proc file are decreased.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times4 = increaseTime(times3);
+        times4[uids.length - 1][cores - 1] = times3[uids.length - 1][cores - 1] - 1;
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times4));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i = 0; i < uids.length - 1; ++i) {
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times4[i], times3[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified when the proc file had decreased values.
+        Mockito.reset(mCallback, mBufferedReader);
+        for (int i = 0; i < cores; i++) {
+            times4[uids.length - 1][i] = times3[uids.length - 1][i] + uids[uids.length - 1] * 1000;
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times4));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verify(mCallback).onUidCpuActiveTime(uids[uids.length - 1], getTotal(subtract(times4[uids.length - 1], times3[uids.length - 1])));
+        verifyNoMoreInteractions(mCallback);
+    }
+
+    private long[] subtract(long[] a1, long[] a2) {
+        long[] val = new long[a1.length];
+        for (int i = 0; i < val.length; ++i) {
+            val[i] = a1[i] - a2[i];
+        }
+        return val;
+    }
+
+    private String[] formatTime(int[] uids, long[][] times) {
+        String[] lines = new String[uids.length + 1];
+        for (int i=0;i<uids.length;i++){
+            StringBuilder sb = new StringBuilder();
+            sb.append(uids[i]).append(':');
+            for(int j=0;j<times[i].length;j++){
+                sb.append(' ').append(times[i][j]);
+            }
+            lines[i] = sb.toString();
+        }
+        lines[uids.length] = null;
+        return lines;
+    }
+
+    private long[][] increaseTime(long[][] original) {
+        long[][] newTime = new long[original.length][original[0].length];
+        Random rand = new Random();
+        for(int i = 0;i<original.length;i++){
+            for(int j=0;j<original[0].length;j++){
+                newTime[i][j] = original[i][j] + rand.nextInt(1000_000) + 10000;
+            }
+        }
+        return newTime;
+    }
+
+    private long getTotal(long[] times) {
+        long sum = 0;
+        for(int i=0;i<times.length;i++){
+            sum+=times[i] * 10 / (i+1);
+        }
+        return sum;
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
new file mode 100644
index 0000000..0d1f852
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.BufferedReader;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Test class for {@link KernelUidCpuClusterTimeReader}.
+ *
+ * To run it:
+ * bit FrameworksCoreTests:com.android.internal.os.KernelUidCpuClusterTimeReaderTest
+ *
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KernelUidCpuClusterTimeReaderTest {
+    @Mock private BufferedReader mBufferedReader;
+    @Mock private KernelUidCpuClusterTimeReader.Callback mCallback;
+
+    private KernelUidCpuClusterTimeReader mReader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mReader = new KernelUidCpuClusterTimeReader();
+    }
+
+    @Test
+    public void testReadDelta() throws Exception {
+        final String info = "policy0: 2 policy4: 4";
+        final int cores = 6;
+        final int[] cluster = {2, 4};
+        final int[] uids = {1, 22, 333, 4444, 5555};
+
+        // Verify initial call
+        final long[][] times = increaseTime(new long[uids.length][cores]);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, times[i]));
+        }
+
+        // Verify that a second call will only return deltas.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times1 = increaseTime(times);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, subtract(times1[i], times[i])));
+        }
+
+        // Verify that there won't be a callback if the proc file values didn't change.
+        Mockito.reset(mCallback, mBufferedReader);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that calling with a null callback doesn't result in any crashes
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times2 = increaseTime(times1);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times2));
+        mReader.readDeltaInternal(mBufferedReader, null);
+
+        // Verify that the readDelta call will only return deltas when
+        // the previous call had null callback.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times3 = increaseTime(times2);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, subtract(times3[i], times2[i])));
+        }
+
+    }
+
+    @Test
+    public void testReadDelta_malformedData() throws Exception {
+        final String info = "policy0: 2 policy4: 4";
+        final int cores = 6;
+        final int[] cluster = {2, 4};
+        final int[] uids = {1, 22, 333, 4444, 5555};
+
+        // Verify initial call
+        final long[][] times = increaseTime(new long[uids.length][cores]);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, times[i]));
+        }
+
+        // Verify that there is no callback if subsequent call provides wrong # of entries.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] temp = increaseTime(times);
+        final long[][] times1 = new long[uids.length][];
+        for(int i=0;i<temp.length;i++){
+            times1[i] = Arrays.copyOfRange(temp[i], 0, 4);
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified if the given core count does not match
+        // the following # of entries.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times2 = increaseTime(times);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times2));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, subtract(times2[i], times[i])));
+        }
+
+        // Verify that there is no callback if any value in the proc file is -ve.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times3 = increaseTime(times2);
+        times3[uids.length - 1][cores - 1] *= -1;
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length-1;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, subtract(times3[i], times2[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified when the proc file had -ve value.
+        Mockito.reset(mCallback, mBufferedReader);
+        for(int i=0;i<cores;i++){
+            times3[uids.length -1][i] = times2[uids.length -1][i] + uids[uids.length -1]*1000;
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verify(mCallback, times(1)).onUidCpuPolicyTime(uids[uids.length-1], getTotal(cluster, subtract(times3[uids.length -1], times2[uids.length -1])));
+
+        // // Verify that there is no callback if the values in the proc file are decreased.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times4 = increaseTime(times3);
+        times4[uids.length - 1][cores - 1] = times3[uids.length - 1][cores - 1] - 1;
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times4));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length-1;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, subtract(times4[i], times3[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified when the proc file had decreased values.
+        Mockito.reset(mCallback, mBufferedReader);
+        for(int i=0;i<cores;i++){
+            times4[uids.length -1][i] = times3[uids.length -1][i] + uids[uids.length -1]*1000;
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times4));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verify(mCallback, times(1))
+                .onUidCpuPolicyTime(uids[uids.length-1], getTotal(cluster, subtract(times3[uids.length -1], times2[uids.length -1])));
+
+    }
+
+
+    private long[] subtract(long[] a1, long[] a2) {
+        long[] val = new long[a1.length];
+        for (int i = 0; i < val.length; ++i) {
+            val[i] = a1[i] - a2[i];
+        }
+        return val;
+    }
+
+    private String[] formatTime(int[] uids, long[][] times) {
+        String[] lines = new String[uids.length + 1];
+        for (int i=0;i<uids.length;i++){
+            StringBuilder sb = new StringBuilder();
+            sb.append(uids[i]).append(':');
+            for(int j=0;j<times[i].length;j++){
+                sb.append(' ').append(times[i][j]);
+            }
+            lines[i] = sb.toString();
+        }
+        lines[uids.length] = null;
+        return lines;
+    }
+
+    private long[][] increaseTime(long[][] original) {
+        long[][] newTime = new long[original.length][original[0].length];
+        Random rand = new Random();
+        for(int i = 0;i<original.length;i++){
+            for(int j=0;j<original[0].length;j++){
+                newTime[i][j] = original[i][j] + rand.nextInt(1000_000) + 10000;
+            }
+        }
+        return newTime;
+    }
+
+    // Format an array of cluster times according to the algorithm in KernelUidCpuClusterTimeReader
+    private long[] getTotal(int[] cluster, long[] times) {
+        int core = 0;
+        long[] sum = new long[cluster.length];
+        for(int i=0;i<cluster.length;i++){
+            for(int j=0;j<cluster[i];j++){
+                sum[i] += times[core++] * 10 / (j+1);
+            }
+        }
+        return sum;
+    }
+
+    // Compare array1 against flattened 2d array array2 element by element
+    private boolean testEqual(long[] array1, long[][] array2) {
+        int k=0;
+        for(int i=0;i<array2.length;i++){
+            for(int j=0;j<array2[i].length;j++){
+                if (k >= array1.length || array1[k++]!=array2[i][j])return false;
+            }
+        }
+        return k == array1.length;
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index 6c5a2aa..660c744 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -88,6 +88,16 @@
         return this;
     }
 
+    public MockBatteryStatsImpl setKernelUidCpuActiveTimeReader(KernelUidCpuActiveTimeReader reader) {
+        mKernelUidCpuActiveTimeReader = reader;
+        return this;
+    }
+
+    public MockBatteryStatsImpl setKernelUidCpuClusterTimeReader(KernelUidCpuClusterTimeReader reader) {
+        mKernelUidCpuClusterTimeReader = reader;
+        return this;
+    }
+
     public MockBatteryStatsImpl setKernelUidCpuTimeReader(KernelUidCpuTimeReader reader) {
         mKernelUidCpuTimeReader = reader;
         return this;
diff --git a/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java b/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
new file mode 100644
index 0000000..eb7da9c
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+
+import junit.framework.TestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/*
+ * Keep this file in sync with frameworks/base/core/res/res/xml/power_profile_test.xml
+ */
+@SmallTest
+public class PowerProfileTest extends TestCase {
+
+    private PowerProfile mProfile;
+
+    @Before
+    public void setUp() {
+        mProfile = new PowerProfile(InstrumentationRegistry.getContext(), true);
+    }
+
+    @Test
+    public void testPowerProfile() {
+        assertEquals(2, mProfile.getNumCpuClusters());
+        assertEquals(4, mProfile.getNumCoresInCpuCluster(0));
+        assertEquals(4, mProfile.getNumCoresInCpuCluster(1));
+        assertEquals(5.0, mProfile.getAveragePower(PowerProfile.POWER_CPU_SUSPEND));
+        assertEquals(1.11, mProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE));
+        assertEquals(2.55, mProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE));
+        assertEquals(2.11, mProfile.getAveragePowerForCpuCluster(0));
+        assertEquals(2.22, mProfile.getAveragePowerForCpuCluster(1));
+        assertEquals(3, mProfile.getNumSpeedStepsInCpuCluster(0));
+        assertEquals(30.0, mProfile.getAveragePowerForCpuCore(0, 2));
+        assertEquals(4, mProfile.getNumSpeedStepsInCpuCluster(1));
+        assertEquals(60.0, mProfile.getAveragePowerForCpuCore(1, 3));
+        assertEquals(3000.0, mProfile.getBatteryCapacity());
+    }
+
+}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 993bae1..c0633cb 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -165,6 +165,9 @@
 
     <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
 
+    <assign-permission name="android.permission.DUMP" uid="incidentd" />
+    <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="incidentd" />
+
     <assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" />
     <assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" />
 
diff --git a/docs/html/reference/images/text/style/backgroundcolorspan.png b/docs/html/reference/images/text/style/backgroundcolorspan.png
new file mode 100644
index 0000000..e7e7271
--- /dev/null
+++ b/docs/html/reference/images/text/style/backgroundcolorspan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/foregroundcolorspan.png b/docs/html/reference/images/text/style/foregroundcolorspan.png
new file mode 100644
index 0000000..f60db6c
--- /dev/null
+++ b/docs/html/reference/images/text/style/foregroundcolorspan.png
Binary files differ
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 05dadc9..4d715d1 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -33,6 +33,8 @@
 import android.net.Uri;
 import android.system.ErrnoException;
 import android.system.Os;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
 
 import libcore.io.IoUtils;
 import dalvik.system.CloseGuard;
@@ -64,6 +66,19 @@
         Resources getResources() { return null; }
 
         /* @hide */
+        int getDensity() { return Bitmap.DENSITY_NONE; }
+
+        /* @hide */
+        int computeDstDensity() {
+            Resources res = getResources();
+            if (res == null) {
+                return Bitmap.getDefaultDensity();
+            }
+
+            return res.getDisplayMetrics().densityDpi;
+        }
+
+        /* @hide */
         abstract ImageDecoder createImageDecoder() throws IOException;
     };
 
@@ -170,26 +185,73 @@
         return decoder;
     }
 
+    private static class InputStreamSource extends Source {
+        InputStreamSource(Resources res, InputStream is, int inputDensity) {
+            if (is == null) {
+                throw new IllegalArgumentException("The InputStream cannot be null");
+            }
+            mResources = res;
+            mInputStream = is;
+            mInputDensity = res != null ? inputDensity : Bitmap.DENSITY_NONE;
+        }
+
+        final Resources mResources;
+        InputStream mInputStream;
+        final int mInputDensity;
+
+        @Override
+        public Resources getResources() { return mResources; }
+
+        @Override
+        public int getDensity() { return mInputDensity; }
+
+        @Override
+        public ImageDecoder createImageDecoder() throws IOException {
+
+            synchronized (this) {
+                if (mInputStream == null) {
+                    throw new IOException("Cannot reuse InputStreamSource");
+                }
+                InputStream is = mInputStream;
+                mInputStream = null;
+                return createFromStream(is);
+            }
+        }
+    }
+
     private static class ResourceSource extends Source {
         ResourceSource(Resources res, int resId) {
             mResources = res;
             mResId = resId;
+            mResDensity = Bitmap.DENSITY_NONE;
         }
 
         final Resources mResources;
         final int       mResId;
+        int             mResDensity;
 
         @Override
         public Resources getResources() { return mResources; }
 
         @Override
+        public int getDensity() { return mResDensity; }
+
+        @Override
         public ImageDecoder createImageDecoder() throws IOException {
             // This is just used in order to access the underlying Asset and
             // keep it alive. FIXME: Can we skip creating this object?
             InputStream is = null;
             ImageDecoder decoder = null;
+            TypedValue value = new TypedValue();
             try {
-                is = mResources.openRawResource(mResId);
+                is = mResources.openRawResource(mResId, value);
+
+                if (value.density == TypedValue.DENSITY_DEFAULT) {
+                    mResDensity = DisplayMetrics.DENSITY_DEFAULT;
+                } else if (value.density != TypedValue.DENSITY_NONE) {
+                    mResDensity = value.density;
+                }
+
                 if (!(is instanceof AssetManager.AssetInputStream)) {
                     // This should never happen.
                     throw new RuntimeException("Resource is not an asset?");
@@ -421,6 +483,22 @@
     }
 
     /**
+     * Internal API used to generate bitmaps for use by Drawables (i.e. BitmapDrawable)
+     * @hide
+     */
+    public static Source createSource(Resources res, InputStream is) {
+        return new InputStreamSource(res, is, Bitmap.getDefaultDensity());
+    }
+
+    /**
+     * Internal API used to generate bitmaps for use by Drawables (i.e. BitmapDrawable)
+     * @hide
+     */
+    public static Source createSource(Resources res, InputStream is, int density) {
+        return new InputStreamSource(res, is, density);
+    }
+
+    /**
      *  Return the width and height of a given sample size.
      *
      *  This takes an input that functions like
@@ -476,6 +554,10 @@
         this.resize(dimensions.x, dimensions.y);
     }
 
+    private boolean requestedResize() {
+        return mWidth != mDesiredWidth || mHeight != mDesiredHeight;
+    }
+
     // These need to stay in sync with ImageDecoder.cpp's Allocator enum.
     /**
      *  Use the default allocation for the pixel memory.
@@ -730,6 +812,9 @@
                                                 "Drawable!");
             }
 
+            // this call potentially manipulates the decoder so it must be performed prior to
+            // decoding the bitmap and after decode set the density on the resulting bitmap
+            final int srcDensity = computeDensity(src, decoder);
             if (decoder.mAnimated) {
                 // AnimatedImageDrawable calls postProcessAndRelease only if
                 // mPostProcess exists.
@@ -737,7 +822,8 @@
                         null : decoder;
                 Drawable d = new AnimatedImageDrawable(decoder.mNativePtr,
                         postProcessPtr, decoder.mDesiredWidth,
-                        decoder.mDesiredHeight, decoder.mCropRect,
+                        decoder.mDesiredHeight, srcDensity,
+                        src.computeDstDensity(), decoder.mCropRect,
                         decoder.mInputStream, decoder.mAssetFd);
                 // d has taken ownership of these objects.
                 decoder.mInputStream = null;
@@ -746,13 +832,15 @@
             }
 
             Bitmap bm = decoder.decodeBitmap();
-            Resources res = src.getResources();
-            if (res == null) {
-                bm.setDensity(Bitmap.DENSITY_NONE);
-            }
+            bm.setDensity(srcDensity);
 
+            Resources res = src.getResources();
             byte[] np = bm.getNinePatchChunk();
             if (np != null && NinePatch.isNinePatchChunk(np)) {
+                if (res != null) {
+                    bm.setDensity(res.getDisplayMetrics().densityDpi);
+                }
+
                 Rect opticalInsets = new Rect();
                 bm.getOpticalInsets(opticalInsets);
                 Rect padding = new Rect();
@@ -799,10 +887,48 @@
                 }
             }
 
-            return decoder.decodeBitmap();
+            // this call potentially manipulates the decoder so it must be performed prior to
+            // decoding the bitmap
+            final int srcDensity = computeDensity(src, decoder);
+            Bitmap bm = decoder.decodeBitmap();
+            bm.setDensity(srcDensity);
+            return bm;
         }
     }
 
+    // This method may modify the decoder so it must be called prior to performing the decode
+    private static int computeDensity(@NonNull Source src, @NonNull ImageDecoder decoder) {
+        // if the caller changed the size then we treat the density as unknown
+        if (decoder.requestedResize()) {
+            return Bitmap.DENSITY_NONE;
+        }
+
+        // Special stuff for compatibility mode: if the target density is not
+        // the same as the display density, but the resource -is- the same as
+        // the display density, then don't scale it down to the target density.
+        // This allows us to load the system's density-correct resources into
+        // an application in compatibility mode, without scaling those down
+        // to the compatibility density only to have them scaled back up when
+        // drawn to the screen.
+        Resources res = src.getResources();
+        final int srcDensity = src.getDensity();
+        if (res != null && res.getDisplayMetrics().noncompatDensityDpi == srcDensity) {
+            return srcDensity;
+        }
+
+        // downscale the bitmap if the asset has a higher density than the default
+        final int dstDensity = src.computeDstDensity();
+        if (srcDensity != Bitmap.DENSITY_NONE && srcDensity > dstDensity) {
+            float scale = (float) dstDensity / srcDensity;
+            int scaledWidth = (int) (decoder.mWidth * scale + 0.5f);
+            int scaledHeight = (int) (decoder.mHeight * scale + 0.5f);
+            decoder.resize(scaledWidth, scaledHeight);
+            return dstDensity;
+        }
+
+        return srcDensity;
+    }
+
     private String getMimeType() {
         return nGetMimeType(mNativePtr);
     }
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index ce3bd9a..da170c0 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -20,12 +20,14 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.res.AssetFileDescriptor;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.ImageDecoder;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.SystemClock;
+import android.util.DisplayMetrics;
 
 import libcore.io.IoUtils;
 import libcore.util.NativeAllocationRegistry;
@@ -59,22 +61,31 @@
      * decoder is only non-null if it has a PostProcess
      */
     public AnimatedImageDrawable(long nativeImageDecoder,
-            @Nullable ImageDecoder decoder, int width, int height, Rect cropRect,
+            @Nullable ImageDecoder decoder, int width, int height,
+            int srcDensity, int dstDensity, Rect cropRect,
             InputStream inputStream, AssetFileDescriptor afd)
             throws IOException {
-        mNativePtr = nCreate(nativeImageDecoder, decoder, width, height, cropRect);
-        mInputStream = inputStream;
-        mAssetFd = afd;
+        width = Bitmap.scaleFromDensity(width, srcDensity, dstDensity);
+        height = Bitmap.scaleFromDensity(height, srcDensity, dstDensity);
 
         if (cropRect == null) {
             mIntrinsicWidth  = width;
             mIntrinsicHeight = height;
         } else {
+            cropRect.set(Bitmap.scaleFromDensity(cropRect.left, srcDensity, dstDensity),
+                    Bitmap.scaleFromDensity(cropRect.top, srcDensity, dstDensity),
+                    Bitmap.scaleFromDensity(cropRect.right, srcDensity, dstDensity),
+                    Bitmap.scaleFromDensity(cropRect.bottom, srcDensity, dstDensity));
             mIntrinsicWidth  = cropRect.width();
             mIntrinsicHeight = cropRect.height();
         }
 
-        long nativeSize = nNativeByteSize(mNativePtr);
+        mNativePtr = nCreate(nativeImageDecoder, decoder, width, height, cropRect);
+        mInputStream = inputStream;
+        mAssetFd = afd;
+
+        // FIXME: Use the right size for the native allocation.
+        long nativeSize = 200;
         NativeAllocationRegistry registry = new NativeAllocationRegistry(
                 AnimatedImageDrawable.class.getClassLoader(), nGetNativeFinalizer(), nativeSize);
         registry.registerNativeAllocation(this, mNativePtr);
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index e3740e3..f74c39d 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -27,6 +27,7 @@
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
+import android.graphics.ImageDecoder;
 import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.Outline;
@@ -49,6 +50,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
@@ -111,7 +113,7 @@
      */
     @Deprecated
     public BitmapDrawable() {
-        mBitmapState = new BitmapState((Bitmap) null);
+        init(new BitmapState((Bitmap) null), null);
     }
 
     /**
@@ -124,8 +126,7 @@
     @SuppressWarnings("unused")
     @Deprecated
     public BitmapDrawable(Resources res) {
-        mBitmapState = new BitmapState((Bitmap) null);
-        mBitmapState.mTargetDensity = mTargetDensity;
+        init(new BitmapState((Bitmap) null), res);
     }
 
     /**
@@ -135,7 +136,7 @@
      */
     @Deprecated
     public BitmapDrawable(Bitmap bitmap) {
-        this(new BitmapState(bitmap), null);
+        init(new BitmapState(bitmap), null);
     }
 
     /**
@@ -143,8 +144,7 @@
      * the display metrics of the resources.
      */
     public BitmapDrawable(Resources res, Bitmap bitmap) {
-        this(new BitmapState(bitmap), res);
-        mBitmapState.mTargetDensity = mTargetDensity;
+        init(new BitmapState(bitmap), res);
     }
 
     /**
@@ -154,10 +154,7 @@
      */
     @Deprecated
     public BitmapDrawable(String filepath) {
-        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
-        if (mBitmapState.mBitmap == null) {
-            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
-        }
+        this(null, filepath);
     }
 
     /**
@@ -165,10 +162,21 @@
      */
     @SuppressWarnings("unused")
     public BitmapDrawable(Resources res, String filepath) {
-        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
-        mBitmapState.mTargetDensity = mTargetDensity;
-        if (mBitmapState.mBitmap == null) {
-            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
+        Bitmap bitmap = null;
+        try (FileInputStream stream = new FileInputStream(filepath)) {
+            bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, stream),
+                    (info, decoder) -> {
+                decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR);
+            });
+        } catch (Exception e) {
+            /*  do nothing. This matches the behavior of BitmapFactory.decodeFile()
+                If the exception happened on decode, mBitmapState.mBitmap will be null.
+            */
+        } finally {
+            init(new BitmapState(bitmap), res);
+            if (mBitmapState.mBitmap == null) {
+                android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
+            }
         }
     }
 
@@ -179,10 +187,7 @@
      */
     @Deprecated
     public BitmapDrawable(java.io.InputStream is) {
-        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
-        if (mBitmapState.mBitmap == null) {
-            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
-        }
+        this(null, is);
     }
 
     /**
@@ -190,10 +195,21 @@
      */
     @SuppressWarnings("unused")
     public BitmapDrawable(Resources res, java.io.InputStream is) {
-        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
-        mBitmapState.mTargetDensity = mTargetDensity;
-        if (mBitmapState.mBitmap == null) {
-            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
+        Bitmap bitmap = null;
+        try {
+            bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, is),
+                    (info, decoder) -> {
+                decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR);
+            });
+        } catch (Exception e) {
+            /*  do nothing. This matches the behavior of BitmapFactory.decodeStream()
+                If the exception happened on decode, mBitmapState.mBitmap will be null.
+            */
+        } finally {
+            init(new BitmapState(bitmap), res);
+            if (mBitmapState.mBitmap == null) {
+                android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
+            }
         }
     }
 
@@ -812,9 +828,19 @@
                 }
             }
 
+            int density = Bitmap.DENSITY_NONE;
+            if (value.density == TypedValue.DENSITY_DEFAULT) {
+                density = DisplayMetrics.DENSITY_DEFAULT;
+            } else if (value.density != TypedValue.DENSITY_NONE) {
+                density = value.density;
+            }
+
             Bitmap bitmap = null;
             try (InputStream is = r.openRawResource(srcResId, value)) {
-                bitmap = BitmapFactory.decodeResourceStream(r, value, is, null, null);
+                ImageDecoder.Source source = ImageDecoder.createSource(r, is, density);
+                bitmap = ImageDecoder.decodeBitmap(source, (info, decoder) -> {
+                    decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR);
+                });
             } catch (Exception e) {
                 // Do nothing and pick up the error below.
             }
@@ -1013,14 +1039,21 @@
         }
     }
 
+    private BitmapDrawable(BitmapState state, Resources res) {
+        init(state, res);
+    }
+
     /**
-     * The one constructor to rule them all. This is called by all public
+     * The one helper to rule them all. This is called by all public & private
      * constructors to set the state and initialize local properties.
      */
-    private BitmapDrawable(BitmapState state, Resources res) {
+    private void init(BitmapState state, Resources res) {
         mBitmapState = state;
-
         updateLocalState(res);
+
+        if (mBitmapState != null && res != null) {
+            mBitmapState.mTargetDensity = mTargetDensity;
+        }
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index f17cd76..291b0a0 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -37,6 +37,7 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
+import android.graphics.ImageDecoder;
 import android.graphics.Insets;
 import android.graphics.NinePatch;
 import android.graphics.Outline;
@@ -50,11 +51,13 @@
 import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.util.StateSet;
 import android.util.TypedValue;
 import android.util.Xml;
 import android.view.View;
 
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
@@ -1175,6 +1178,10 @@
             return null;
         }
 
+        if (opts == null) {
+            return getBitmapDrawable(res, value, is);
+        }
+
         /*  ugh. The decodeStream contract is that we have already allocated
             the pad rect, but if the bitmap does not had a ninepatch chunk,
             then the pad will be ignored. If we could change this to lazily
@@ -1207,6 +1214,33 @@
         return null;
     }
 
+    private static Drawable getBitmapDrawable(Resources res, TypedValue value, InputStream is) {
+        try {
+            ImageDecoder.Source source = null;
+            if (value != null) {
+                int density = Bitmap.DENSITY_NONE;
+                if (value.density == TypedValue.DENSITY_DEFAULT) {
+                    density = DisplayMetrics.DENSITY_DEFAULT;
+                } else if (value.density != TypedValue.DENSITY_NONE) {
+                    density = value.density;
+                }
+                source = ImageDecoder.createSource(res, is, density);
+            } else {
+                source = ImageDecoder.createSource(res, is);
+            }
+
+            return ImageDecoder.decodeDrawable(source, (info, decoder) -> {
+                decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR);
+            });
+        } catch (IOException e) {
+            /*  do nothing.
+                If the exception happened on decode, the drawable will be null.
+            */
+            Log.e("Drawable", "Unable to decode stream: " + e);
+        }
+        return null;
+    }
+
     /**
      * Create a drawable from an XML document. For more information on how to
      * create resources in XML, see
@@ -1306,11 +1340,10 @@
         }
 
         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, pathName);
-        try {
-            Bitmap bm = BitmapFactory.decodeFile(pathName);
-            if (bm != null) {
-                return drawableFromBitmap(null, bm, null, null, null, pathName);
-            }
+        try (FileInputStream stream = new FileInputStream(pathName)) {
+            return getBitmapDrawable(null, null, stream);
+        } catch(IOException e) {
+            // Do nothing; we will just return null if the FileInputStream had an error
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
         }
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 833376c..603926f 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -19,10 +19,12 @@
 import android.os.SystemClock;
 
 import android.util.Base64;
+import android.util.Log;
 import android.util.TimeUtils;
 
 import java.util.Arrays;
 
+import com.android.internal.app.IBatteryStats;
 import com.android.internal.location.nano.GnssLogsProto.GnssLog;
 
 /**
@@ -31,14 +33,29 @@
  */
 public class GnssMetrics {
 
+  private static final String TAG = GnssMetrics.class.getSimpleName();
+
+  /* Constant which indicates GPS signal quality is poor */
+  public static final int GPS_SIGNAL_QUALITY_POOR = 0;
+
+  /* Constant which indicates GPS signal quality is good */
+  public static final int GPS_SIGNAL_QUALITY_GOOD = 1;
+
+  /* Number of GPS signal quality levels */
+  public static final int NUM_GPS_SIGNAL_QUALITY_LEVELS = GPS_SIGNAL_QUALITY_GOOD + 1;
+
   /** Default time between location fixes (in millisecs) */
   private static final int DEFAULT_TIME_BETWEEN_FIXES_MILLISECS = 1000;
 
   /* The time since boot when logging started */
   private String logStartInElapsedRealTime;
 
+  /* GNSS power metrics */
+  private GnssPowerMetrics mGnssPowerMetrics;
+
   /** Constructor */
-  public GnssMetrics() {
+  public GnssMetrics(IBatteryStats stats) {
+    mGnssPowerMetrics = new GnssPowerMetrics(stats);
     locationFailureStatistics = new Statistics();
     timeToFirstFixSecStatistics = new Statistics();
     positionAccuracyMeterStatistics = new Statistics();
@@ -103,11 +120,18 @@
   *
   */
   public void logCn0(float[] cn0s, int numSv) {
-    if (numSv < 4) {
+    if (numSv == 0 || cn0s == null || cn0s.length == 0 || cn0s.length < numSv) {
+      if (numSv == 0) {
+         mGnssPowerMetrics.reportSignalQuality(null, 0);
+      }
       return;
     }
     float[] cn0Array = Arrays.copyOf(cn0s, numSv);
     Arrays.sort(cn0Array);
+    mGnssPowerMetrics.reportSignalQuality(cn0Array, numSv);
+    if (numSv < 4) {
+      return;
+    }
     if (cn0Array[numSv - 4] > 0.0) {
       double top4AvgCn0 = 0.0;
       for (int i = numSv - 4; i < numSv; i++) {
@@ -265,4 +289,62 @@
     topFourAverageCn0Statistics.reset();
     return;
   }
+
+  /* Class for handling GNSS power related metrics */
+  private class GnssPowerMetrics {
+
+    /* Threshold for Top Four Average CN0 below which GNSS signal quality is declared poor */
+    private static final double POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ = 20.0;
+
+    /* Minimum change in Top Four Average CN0 needed to trigger a report */
+    private static final double REPORTING_THRESHOLD_DB_HZ = 1.0;
+
+    /* BatteryStats API */
+    private final IBatteryStats mBatteryStats;
+
+    /* Last reported Top Four Average CN0 */
+    private double mLastAverageCn0;
+
+    public GnssPowerMetrics(IBatteryStats stats) {
+      mBatteryStats = stats;
+      // Used to initialize the variable to a very small value (unachievable in practice) so that
+      // the first CNO report will trigger an update to BatteryStats
+      mLastAverageCn0 = -100.0;
+    }
+
+    /**
+     * Reports signal quality to BatteryStats. Signal quality is based on Top four average CN0. If
+     * the number of SVs seen is less than 4, then signal quality is the average CN0.
+     * Changes are reported only if the average CN0 changes by more than REPORTING_THRESHOLD_DB_HZ.
+     */
+    public void reportSignalQuality(float[] ascendingCN0Array, int numSv) {
+      double avgCn0 = 0.0;
+      if (numSv > 0) {
+        for (int i = Math.max(0, numSv - 4); i < numSv; i++) {
+          avgCn0 += (double) ascendingCN0Array[i];
+        }
+        avgCn0 /= Math.min(numSv, 4);
+      }
+      if (Math.abs(avgCn0 - mLastAverageCn0) < REPORTING_THRESHOLD_DB_HZ) {
+        return;
+      }
+      try {
+        mBatteryStats.noteGpsSignalQuality(getSignalLevel(avgCn0));
+        mLastAverageCn0 = avgCn0;
+      } catch (Exception e) {
+        Log.w(TAG, "Exception", e);
+      }
+      return;
+    }
+
+    /**
+     * Obtains signal level based on CN0
+     */
+    private int getSignalLevel(double cn0) {
+      if (cn0 > POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) {
+        return GnssMetrics.GPS_SIGNAL_QUALITY_GOOD;
+      }
+      return GnssMetrics.GPS_SIGNAL_QUALITY_POOR;
+    }
+  }
 }
\ No newline at end of file
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index e56944d..2cd764d 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -914,7 +914,8 @@
             (1 << STREAM_MUSIC) |
             (1 << STREAM_RING) |
             (1 << STREAM_NOTIFICATION) |
-            (1 << STREAM_SYSTEM);
+            (1 << STREAM_SYSTEM) |
+            (1 << STREAM_VOICE_CALL);
 
     /**
      * Event posted by AudioTrack and AudioRecord JNI (JNIDeviceCallback) when routing changes.
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 9ee205f..2a697b8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -302,6 +302,7 @@
         // fail to boot if there're any backed up settings that don't have a non-null validator
         ensureAllBackedUpSystemSettingsHaveValidators();
         ensureAllBackedUpGlobalSettingsHaveValidators();
+        ensureAllBackedUpSecureSettingsHaveValidators();
 
         synchronized (mLock) {
             mUserManager = UserManager.get(getContext());
@@ -321,19 +322,26 @@
     }
 
     private void ensureAllBackedUpSystemSettingsHaveValidators() {
-        String offenders = getOffenders(Settings.System.SETTINGS_TO_BACKUP,
-                Settings.System.VALIDATORS);
+        String offenders = getOffenders(concat(Settings.System.SETTINGS_TO_BACKUP,
+                Settings.System.LEGACY_RESTORE_SETTINGS), Settings.System.VALIDATORS);
 
         failToBootIfOffendersPresent(offenders, "Settings.System");
     }
 
     private void ensureAllBackedUpGlobalSettingsHaveValidators() {
-        String offenders = getOffenders(Settings.Global.SETTINGS_TO_BACKUP,
-                Settings.Global.VALIDATORS);
+        String offenders = getOffenders(concat(Settings.Global.SETTINGS_TO_BACKUP,
+                Settings.Global.LEGACY_RESTORE_SETTINGS), Settings.Global.VALIDATORS);
 
         failToBootIfOffendersPresent(offenders, "Settings.Global");
     }
 
+    private void ensureAllBackedUpSecureSettingsHaveValidators() {
+        String offenders = getOffenders(concat(Settings.Secure.SETTINGS_TO_BACKUP,
+                Settings.Secure.LEGACY_RESTORE_SETTINGS), Settings.Secure.VALIDATORS);
+
+        failToBootIfOffendersPresent(offenders, "Settings.Secure");
+    }
+
     private void failToBootIfOffendersPresent(String offenders, String settingsType) {
         if (offenders.length() > 0) {
             throw new RuntimeException("All " + settingsType + " settings that are backed up"
@@ -352,6 +360,18 @@
         return offenders.toString();
     }
 
+    private final String[] concat(String[] first, String[] second) {
+        if (second == null || second.length == 0) {
+            return first;
+        }
+        final int firstLen = first.length;
+        final int secondLen = second.length;
+        String[] both = new String[firstLen + secondLen];
+        System.arraycopy(first, 0, both, 0, firstLen);
+        System.arraycopy(second, 0, both, firstLen, secondLen);
+        return both;
+    }
+
     @Override
     public Bundle call(String method, String name, Bundle args) {
         final int requestingUserId = getRequestingUserId(args);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 0f43db0..2a6d55c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -135,6 +135,9 @@
     <uses-permission android:name="android.permission.RESTRICTED_VR_ACCESS" />
     <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE" />
     <uses-permission android:name="android.permission.SET_HARMFUL_APP_WARNINGS" />
+    <uses-permission android:name="android.permission.MANAGE_SENSORS" />
+
+    <uses-permission android:name="android.permission.MANAGE_AUDIO_POLICY" />
 
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
index 931a994..69e347c9 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
@@ -463,4 +463,8 @@
     public boolean isReportingEnabled() {
         return mAllowReportRejectedTouch;
     }
+
+    public void onFalsingSessionStarted() {
+        sessionEntrypoint();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index e4b405f..ed659e2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -167,6 +167,9 @@
         if (mDataCollector.isEnabledFull()) {
             registerSensors(COLLECTOR_SENSORS);
         }
+        if (mDataCollector.isEnabled()) {
+            mDataCollector.onFalsingSessionStarted();
+        }
     }
 
     private void registerSensors(int [] sensors) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 5e08ec3..c9dc253 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1704,7 +1704,7 @@
         if (mReportRejectedTouch == null) {
             return;
         }
-        mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD
+        mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD && !mDozing
                 && mFalsingManager.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE);
     }
 
@@ -4506,6 +4506,7 @@
             ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing);
         }
         updateDozingState();
+        updateReportRejectedTouchVisibility();
         Trace.endSection();
     }
 
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index f99ac5c..9b67f8f 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5144,6 +5144,11 @@
     // OS: P
     APPLICATIONS_DIRECTORY_ACCESS_DETAIL = 1284;
 
+    // OPEN: Settings > Battery > Smart Battery > Restricted apps
+    // CATEGORY: SETTINGS
+    // OS: P
+    FUELGAUGE_RESTRICTED_APP_DETAILS = 1285;
+
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java
index 3b8d4bc..672518c 100644
--- a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java
@@ -21,6 +21,8 @@
 import android.content.Context;
 import android.hardware.input.InputManager;
 import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -30,20 +32,34 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ScreenshotHelper;
 import com.android.server.LocalServices;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
+import java.util.function.Supplier;
+
 /**
  * Handle the back-end of AccessibilityService#performGlobalAction
  */
 public class GlobalActionPerformer {
     private final WindowManagerInternal mWindowManagerService;
     private final Context mContext;
+    private Supplier<ScreenshotHelper> mScreenshotHelperSupplier;
 
     public GlobalActionPerformer(Context context, WindowManagerInternal windowManagerInternal) {
         mContext = context;
         mWindowManagerService = windowManagerInternal;
+        mScreenshotHelperSupplier = null;
+    }
+
+    // Used to mock ScreenshotHelper
+    @VisibleForTesting
+    public GlobalActionPerformer(Context context, WindowManagerInternal windowManagerInternal,
+            Supplier<ScreenshotHelper> screenshotHelperSupplier) {
+        this(context, windowManagerInternal);
+        mScreenshotHelperSupplier = screenshotHelperSupplier;
     }
 
     public boolean performGlobalAction(int action) {
@@ -79,6 +95,9 @@
                 case AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN: {
                     return lockScreen();
                 }
+                case AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT: {
+                    return takeScreenshot();
+                }
             }
             return false;
         } finally {
@@ -167,4 +186,12 @@
         mWindowManagerService.lockNow();
         return true;
     }
+
+    private boolean takeScreenshot() {
+        ScreenshotHelper screenshotHelper = (mScreenshotHelperSupplier != null)
+                ? mScreenshotHelperSupplier.get() : new ScreenshotHelper(mContext);
+        screenshotHelper.takeScreenshot(android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
+                true, true, new Handler(Looper.getMainLooper()));
+        return true;
+    }
 }
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index 5188910..465bb09 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -3464,16 +3464,21 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BACKUP, "isAppEligibleForBackup");
 
-        String callerLogString = "BMS.isAppEligibleForBackup";
-        TransportClient transportClient =
-                mTransportManager.getCurrentTransportClient(callerLogString);
-        boolean eligible =
-                AppBackupUtils.appIsRunningAndEligibleForBackupWithTransport(
-                        transportClient, packageName, mPackageManager);
-        if (transportClient != null) {
-            mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
+        long oldToken = Binder.clearCallingIdentity();
+        try {
+            String callerLogString = "BMS.isAppEligibleForBackup";
+            TransportClient transportClient =
+                    mTransportManager.getCurrentTransportClient(callerLogString);
+            boolean eligible =
+                    AppBackupUtils.appIsRunningAndEligibleForBackupWithTransport(
+                            transportClient, packageName, mPackageManager);
+            if (transportClient != null) {
+                mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
+            }
+            return eligible;
+        } finally {
+            Binder.restoreCallingIdentity(oldToken);
         }
-        return eligible;
     }
 
     @Override
@@ -3481,21 +3486,26 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BACKUP, "filterAppsEligibleForBackup");
 
-        String callerLogString = "BMS.filterAppsEligibleForBackup";
-        TransportClient transportClient =
-                mTransportManager.getCurrentTransportClient(callerLogString);
-        List<String> eligibleApps = new LinkedList<>();
-        for (String packageName : packages) {
-            if (AppBackupUtils
-                    .appIsRunningAndEligibleForBackupWithTransport(
-                            transportClient, packageName, mPackageManager)) {
-                eligibleApps.add(packageName);
+        long oldToken = Binder.clearCallingIdentity();
+        try {
+            String callerLogString = "BMS.filterAppsEligibleForBackup";
+            TransportClient transportClient =
+                    mTransportManager.getCurrentTransportClient(callerLogString);
+            List<String> eligibleApps = new LinkedList<>();
+            for (String packageName : packages) {
+                if (AppBackupUtils
+                        .appIsRunningAndEligibleForBackupWithTransport(
+                                transportClient, packageName, mPackageManager)) {
+                    eligibleApps.add(packageName);
+                }
             }
+            if (transportClient != null) {
+                mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
+            }
+            return eligibleApps.toArray(new String[eligibleApps.size()]);
+        } finally {
+            Binder.restoreCallingIdentity(oldToken);
         }
-        if (transportClient != null) {
-            mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
-        }
-        return eligibleApps.toArray(new String[eligibleApps.size()]);
     }
 
     @Override
@@ -3514,6 +3524,9 @@
                     } else if ("agents".startsWith(arg)) {
                         dumpAgents(pw);
                         return;
+                    } else if ("transportclients".equals(arg.toLowerCase())) {
+                        mTransportManager.dump(pw);
+                        return;
                     }
                 }
             }
@@ -3576,6 +3589,8 @@
                 }
             }
 
+            mTransportManager.dump(pw);
+
             pw.println("Pending init: " + mPendingInits.size());
             for (String s : mPendingInits) {
                 pw.println("    " + s);
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index 6d9231d..7e179e5 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -43,6 +43,7 @@
 import com.android.server.backup.transport.TransportNotAvailableException;
 import com.android.server.backup.transport.TransportNotRegisteredException;
 
+import java.io.PrintWriter;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -633,6 +634,10 @@
                 !Thread.holdsLock(mTransportLock), "Can't call transport with transport lock held");
     }
 
+    public void dump(PrintWriter pw) {
+        mTransportClientManager.dump(pw);
+    }
+
     private static Predicate<ComponentName> fromPackageFilter(String packageName) {
         return transportComponent -> packageName.equals(transportComponent.getPackageName());
     }
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClient.java b/services/backup/java/com/android/server/backup/transport/TransportClient.java
index 399f338..7b2e3df 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClient.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClient.java
@@ -16,6 +16,8 @@
 
 package com.android.server.backup.transport;
 
+import static com.android.server.backup.transport.TransportUtils.formatMessage;
+
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.WorkerThread;
@@ -28,6 +30,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.UserHandle;
+import android.text.format.DateFormat;
 import android.util.ArrayMap;
 import android.util.EventLog;
 import android.util.Log;
@@ -41,6 +44,9 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -65,6 +71,7 @@
  */
 public class TransportClient {
     private static final String TAG = "TransportClient";
+    private static final int LOG_BUFFER_SIZE = 5;
 
     private final Context mContext;
     private final Intent mBindIntent;
@@ -73,6 +80,10 @@
     private final Handler mListenerHandler;
     private final String mPrefixForLog;
     private final Object mStateLock = new Object();
+    private final Object mLogBufferLock = new Object();
+
+    @GuardedBy("mLogBufferLock")
+    private final List<String> mLogBuffer = new LinkedList<>();
 
     @GuardedBy("mStateLock")
     private final Map<TransportConnectionListener, String> mListeners = new ArrayMap<>();
@@ -112,7 +123,7 @@
 
         // For logging
         String classNameForLog = mTransportComponent.getShortClassName().replaceFirst(".*\\.", "");
-        mPrefixForLog = classNameForLog + "#" + mIdentifier + ": ";
+        mPrefixForLog = classNameForLog + "#" + mIdentifier + ":";
     }
 
     public ComponentName getTransportComponent() {
@@ -229,7 +240,7 @@
 
             switch (mState) {
                 case State.UNUSABLE:
-                    log(Log.DEBUG, caller, "Async connect: UNUSABLE client");
+                    log(Log.WARN, caller, "Async connect: UNUSABLE client");
                     notifyListener(listener, null, caller);
                     break;
                 case State.IDLE:
@@ -324,14 +335,14 @@
 
         IBackupTransport transport = mTransport;
         if (transport != null) {
-            log(Log.DEBUG, caller, "Sync connect: reusing transport");
+            log(Log.INFO, caller, "Sync connect: reusing transport");
             return transport;
         }
 
         // If it's already UNUSABLE we return straight away, no need to go to main-thread
         synchronized (mStateLock) {
             if (mState == State.UNUSABLE) {
-                log(Log.DEBUG, caller, "Sync connect: UNUSABLE client");
+                log(Log.WARN, caller, "Sync connect: UNUSABLE client");
                 return null;
             }
         }
@@ -403,13 +414,16 @@
     }
 
     private void notifyListener(
-            TransportConnectionListener listener, IBackupTransport transport, String caller) {
-        log(Log.VERBOSE, caller, "Notifying listener of transport = " + transport);
+            TransportConnectionListener listener,
+            @Nullable IBackupTransport transport,
+            String caller) {
+        String transportString = (transport != null) ? "IBackupTransport" : "null";
+        log(Log.INFO, "Notifying [" + caller + "] transport = " + transportString);
         mListenerHandler.post(() -> listener.onTransportConnectionResult(transport, this));
     }
 
     @GuardedBy("mStateLock")
-    private void notifyListenersAndClearLocked(IBackupTransport transport) {
+    private void notifyListenersAndClearLocked(@Nullable IBackupTransport transport) {
         for (Map.Entry<TransportConnectionListener, String> entry : mListeners.entrySet()) {
             TransportConnectionListener listener = entry.getKey();
             String caller = entry.getValue();
@@ -509,13 +523,30 @@
     }
 
     private void log(int priority, String message) {
-        TransportUtils.log(priority, TAG, message);
+        TransportUtils.log(priority, TAG, formatMessage(mPrefixForLog, null, message));
+        saveLogEntry(formatMessage(null, null, message));
     }
 
-    private void log(int priority, String caller, String msg) {
-        TransportUtils.log(priority, TAG, mPrefixForLog, caller, msg);
-        // TODO(brufino): Log in internal list for dump
-        // CharSequence time = DateFormat.format("yyyy-MM-dd HH:mm:ss", System.currentTimeMillis());
+    private void log(int priority, String caller, String message) {
+        TransportUtils.log(priority, TAG, formatMessage(mPrefixForLog, caller, message));
+        saveLogEntry(formatMessage(null, caller, message));
+    }
+
+    private void saveLogEntry(String message) {
+        CharSequence time = DateFormat.format("yyyy-MM-dd HH:mm:ss", System.currentTimeMillis());
+        message = time + " " + message;
+        synchronized (mLogBufferLock) {
+            if (mLogBuffer.size() == LOG_BUFFER_SIZE) {
+                mLogBuffer.remove(mLogBuffer.size() - 1);
+            }
+            mLogBuffer.add(0, message);
+        }
+    }
+
+    List<String> getLogBuffer() {
+        synchronized (mLogBufferLock) {
+            return Collections.unmodifiableList(mLogBuffer);
+        }
     }
 
     @IntDef({Transition.DOWN, Transition.NO_TRANSITION, Transition.UP})
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
index 1cbe7471..1132bce 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
@@ -17,19 +17,20 @@
 package com.android.server.backup.transport;
 
 import static com.android.server.backup.TransportManager.SERVICE_ACTION_TRANSPORT_HOST;
+import static com.android.server.backup.transport.TransportUtils.formatMessage;
 
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.util.Log;
-
 import com.android.server.backup.TransportManager;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.WeakHashMap;
 
 /**
  * Manages the creation and disposal of {@link TransportClient}s. The only class that should use
  * this is {@link TransportManager}, all the other usages should go to {@link TransportManager}.
- *
- * <p>TODO(brufino): Implement pool of TransportClients
  */
 public class TransportClientManager {
     private static final String TAG = "TransportClientManager";
@@ -37,6 +38,7 @@
     private final Context mContext;
     private final Object mTransportClientsLock = new Object();
     private int mTransportClientsCreated = 0;
+    private Map<TransportClient, String> mTransportClientsCallerMap = new WeakHashMap<>();
 
     public TransportClientManager(Context context) {
         mContext = context;
@@ -62,8 +64,10 @@
                             bindIntent,
                             transportComponent,
                             Integer.toString(mTransportClientsCreated));
+            mTransportClientsCallerMap.put(transportClient, caller);
             mTransportClientsCreated++;
-            TransportUtils.log(Log.DEBUG, TAG, caller, "Retrieving " + transportClient);
+            TransportUtils.log(
+                    Log.DEBUG, TAG, formatMessage(null, caller, "Retrieving " + transportClient));
             return transportClient;
         }
     }
@@ -77,7 +81,25 @@
      *     details.
      */
     public void disposeOfTransportClient(TransportClient transportClient, String caller) {
-        TransportUtils.log(Log.DEBUG, TAG, caller, "Disposing of " + transportClient);
         transportClient.unbind(caller);
+        synchronized (mTransportClientsLock) {
+            TransportUtils.log(
+                    Log.DEBUG, TAG, formatMessage(null, caller, "Disposing of " + transportClient));
+            mTransportClientsCallerMap.remove(transportClient);
+        }
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println("Transport clients created: " + mTransportClientsCreated);
+        synchronized (mTransportClientsLock) {
+            pw.println("Current transport clients: " + mTransportClientsCallerMap.size());
+            for (TransportClient transportClient : mTransportClientsCallerMap.keySet()) {
+                String caller = mTransportClientsCallerMap.get(transportClient);
+                pw.println("    " + transportClient + " [" + caller + "]");
+                for (String logEntry : transportClient.getLogBuffer()) {
+                    pw.println("        " + logEntry);
+                }
+            }
+        }
     }
 }
diff --git a/services/backup/java/com/android/server/backup/transport/TransportUtils.java b/services/backup/java/com/android/server/backup/transport/TransportUtils.java
index 92bba9b..56b2d44 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportUtils.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportUtils.java
@@ -41,22 +41,21 @@
     }
 
     static void log(int priority, String tag, String message) {
-        log(priority, tag, null, message);
-    }
-
-    static void log(int priority, String tag, @Nullable String caller, String message) {
-        log(priority, tag, "", caller, message);
-    }
-
-    static void log(
-            int priority, String tag, String prefix, @Nullable String caller, String message) {
         if (Log.isLoggable(tag, priority)) {
-            if (caller != null) {
-                prefix += "[" + caller + "] ";
-            }
-            Slog.println(priority, tag, prefix + message);
+            Slog.println(priority, tag, message);
         }
     }
 
+    static String formatMessage(@Nullable String prefix, @Nullable String caller, String message) {
+        StringBuilder string = new StringBuilder();
+        if (prefix != null) {
+            string.append(prefix).append(" ");
+        }
+        if (caller != null) {
+            string.append("[").append(caller).append("] ");
+        }
+        return string.append(message).toString();
+    }
+
     private TransportUtils() {}
 }
diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/ForceAppStandbyTracker.java
index a75a367..a538bde 100644
--- a/services/core/java/com/android/server/ForceAppStandbyTracker.java
+++ b/services/core/java/com/android/server/ForceAppStandbyTracker.java
@@ -737,21 +737,23 @@
      * @return whether alarms should be restricted for a UID package-name.
      */
     public boolean areAlarmsRestricted(int uid, @NonNull String packageName) {
-        return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false);
+        return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false,
+                /* exemptOnBatterySaver =*/ false);
     }
 
     /**
      * @return whether jobs should be restricted for a UID package-name.
      */
     public boolean areJobsRestricted(int uid, @NonNull String packageName) {
-        return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true);
+        return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true,
+                /* exemptOnBatterySaver =*/ false);
     }
 
     /**
      * @return whether force-app-standby is effective for a UID package-name.
      */
     private boolean isRestricted(int uid, @NonNull String packageName,
-            boolean useTempWhitelistToo) {
+            boolean useTempWhitelistToo, boolean exemptOnBatterySaver) {
         if (isInForeground(uid)) {
             return false;
         }
@@ -765,12 +767,13 @@
                     ArrayUtils.contains(mTempWhitelistedAppIds, appId)) {
                 return false;
             }
-
-            if (mForceAllAppsStandby) {
+            if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) {
                 return true;
             }
-
-            return mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName);
+            if (exemptOnBatterySaver) {
+                return false;
+            }
+            return mForceAllAppsStandby;
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 29d33ce..c0c684c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8601,6 +8601,16 @@
             }
             return false;
         }
+
+        @Override
+        public int getPackageUid(String packageName, int flags) {
+            try {
+                return mActivityManagerService.mContext.getPackageManager()
+                        .getPackageUid(packageName, flags);
+            } catch (NameNotFoundException nnfe) {
+                return -1;
+            }
+        }
     }
 
     class IntentFirewallInterface implements IntentFirewall.AMSInterface {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 81e8eb0..207aaa7 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -40,6 +40,7 @@
 import android.os.WorkSource;
 import android.os.WorkSource.WorkChain;
 import android.os.connectivity.CellularBatteryStats;
+import android.os.connectivity.GpsBatteryStats;
 import android.os.health.HealthStatsParceler;
 import android.os.health.HealthStatsWriter;
 import android.os.health.UidHealthStats;
@@ -594,6 +595,12 @@
         }
     }
 
+    public void noteGpsSignalQuality(int signalLevel) {
+        synchronized (mStats) {
+            mStats.noteGpsSignalQualityLocked(signalLevel);
+        }
+    }
+
     public void noteScreenState(int state) {
         enforceCallingPermission();
         if (DBG) Slog.d(TAG, "begin noteScreenState");
@@ -1448,6 +1455,16 @@
     }
 
     /**
+     * Gets a snapshot of Gps stats
+     * @hide
+     */
+    public GpsBatteryStats getGpsBatteryStats() {
+        synchronized (mStats) {
+            return mStats.getGpsBatteryStats();
+        }
+    }
+
+    /**
      * Gets a snapshot of the system health for a particular uid.
      */
     @Override
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 799f2a9..f721049 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1047,9 +1047,11 @@
 
     private void checkMuteAffectedStreams() {
         // any stream with a min level > 0 is not muteable by definition
+        // STREAM_VOICE_CALL can be muted by applications that has the the MODIFY_PHONE_STATE permission.
         for (int i = 0; i < mStreamStates.length; i++) {
             final VolumeStreamState vss = mStreamStates[i];
-            if (vss.mIndexMin > 0) {
+            if (vss.mIndexMin > 0 &&
+                vss.mStreamType != AudioSystem.STREAM_VOICE_CALL) {
                 mMuteAffectedStreams &= ~(1 << vss.mStreamType);
             }
         }
@@ -1412,6 +1414,18 @@
             return;
         }
 
+        // If adjust is mute and the stream is STREAM_VOICE_CALL, make sure
+        // that the calling app have the MODIFY_PHONE_STATE permission.
+        if (isMuteAdjust &&
+            streamType == AudioSystem.STREAM_VOICE_CALL &&
+            mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.MODIFY_PHONE_STATE)
+                    != PackageManager.PERMISSION_GRANTED) {
+            Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
         // use stream type alias here so that streams with same alias have the same behavior,
         // including with regard to silent mode control (e.g the use of STREAM_RING below and in
         // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
@@ -1712,6 +1726,15 @@
                     + " CHANGE_ACCESSIBILITY_VOLUME  callingPackage=" + callingPackage);
             return;
         }
+        if ((streamType == AudioManager.STREAM_VOICE_CALL) &&
+                (index == 0) &&
+                (mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.MODIFY_PHONE_STATE)
+                    != PackageManager.PERMISSION_GRANTED)) {
+            Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL and index 0 without"
+                    + " MODIFY_PHONE_STATE  callingPackage=" + callingPackage);
+            return;
+        }
         mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
                 index/*val1*/, flags/*val2*/, callingPackage));
         setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
@@ -4503,27 +4526,30 @@
             if (mStreamType == srcStream.mStreamType) {
                 return;
             }
-            synchronized (VolumeStreamState.class) {
-                int srcStreamType = srcStream.getStreamType();
-                // apply default device volume from source stream to all devices first in case
-                // some devices are present in this stream state but not in source stream state
-                int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
-                index = rescaleIndex(index, srcStreamType, mStreamType);
-                for (int i = 0; i < mIndexMap.size(); i++) {
-                    mIndexMap.put(mIndexMap.keyAt(i), index);
-                }
-                // Now apply actual volume for devices in source stream state
-                SparseIntArray srcMap = srcStream.mIndexMap;
-                for (int i = 0; i < srcMap.size(); i++) {
-                    int device = srcMap.keyAt(i);
-                    index = srcMap.valueAt(i);
+            synchronized (mSettingsLock) {
+                synchronized (VolumeStreamState.class) {
+                    int srcStreamType = srcStream.getStreamType();
+                    // apply default device volume from source stream to all devices first in case
+                    // some devices are present in this stream state but not in source stream state
+                    int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
                     index = rescaleIndex(index, srcStreamType, mStreamType);
+                    for (int i = 0; i < mIndexMap.size(); i++) {
+                        mIndexMap.put(mIndexMap.keyAt(i), index);
+                    }
+                    // Now apply actual volume for devices in source stream state
+                    SparseIntArray srcMap = srcStream.mIndexMap;
+                    for (int i = 0; i < srcMap.size(); i++) {
+                        int device = srcMap.keyAt(i);
+                        index = srcMap.valueAt(i);
+                        index = rescaleIndex(index, srcStreamType, mStreamType);
 
-                    setIndex(index, device, caller);
+                        setIndex(index, device, caller);
+                    }
                 }
             }
         }
 
+        @GuardedBy("mSettingsLock")
         public void setAllIndexesToMax() {
             synchronized (VolumeStreamState.class) {
                 for (int i = 0; i < mIndexMap.size(); i++) {
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index e093c9d..1ae7d20 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -222,7 +222,7 @@
             MutableInt halResult = new MutableInt(Result.UNKNOWN_ERROR);
             MutableBoolean flagState = new MutableBoolean(false);
             try {
-                mHwSession.getConfigFlag(flag, (int result, boolean value) -> {
+                mHwSession.isConfigFlagSet(flag, (int result, boolean value) -> {
                     halResult.value = result;
                     flagState.value = value;
                 });
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 6dc5403..48d275c 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -827,7 +827,7 @@
                 return isEnabled();
             }
         };
-        mGnssMetrics = new GnssMetrics();
+        mGnssMetrics = new GnssMetrics(mBatteryStats);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fba404e..6dc384a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -49,6 +49,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -3180,6 +3181,21 @@
          */
         SurfaceControl mAppAnimationLayer = null;
 
+        /**
+         * Given that the split-screen divider does not have an AppWindowToken, it
+         * will have to live inside of a "NonAppWindowContainer", in particular
+         * {@link DisplayContent#mAboveAppWindowsContainers}. However, in visual Z order
+         * it will need to be interleaved with some of our children, appearing on top of
+         * both docked stacks but underneath any assistant stacks.
+         *
+         * To solve this problem we have this anchor control, which will always exist so
+         * we can always assign it the correct value in our {@link #assignChildLayers}.
+         * Likewise since it always exists, {@link AboveAppWindowContainers} can always
+         * assign the divider a layer relative to it. This way we prevent linking lifecycle
+         * events between the two containers.
+         */
+        SurfaceControl mSplitScreenDividerAnchor = null;
+
         // Cached reference to some special stacks we tend to get a lot so we don't need to loop
         // through the list to find them.
         private TaskStack mHomeStack = null;
@@ -3496,37 +3512,39 @@
 
         @Override
         void assignChildLayers(SurfaceControl.Transaction t) {
+
+            final int HOME_STACK_STATE = 0;
+            final int NORMAL_STACK_STATE = 1;
+            final int ALWAYS_ON_TOP_STATE = 2;
+
             int layer = 0;
-
-            // We allow stacks to change visual order from the AM specified order due to
-            // Z-boosting during animations. However we must take care to ensure TaskStacks
-            // which are marked as alwaysOnTop remain that way.
-            for (int i = 0; i < mChildren.size(); i++) {
-                final TaskStack s = mChildren.get(i);
-                s.assignChildLayers();
-                if (!s.needsZBoost() && !s.isAlwaysOnTop()) {
-                    s.assignLayer(t, layer++);
+            for (int state = 0; state <= ALWAYS_ON_TOP_STATE; state++) {
+                for (int i = 0; i < mChildren.size(); i++) {
+                    final TaskStack s = mChildren.get(i);
+                    if (state == HOME_STACK_STATE && s.isActivityTypeHome()) {
+                        s.assignLayer(t, layer++);
+                    } else if (state == NORMAL_STACK_STATE && !s.isActivityTypeHome()
+                            && !s.isAlwaysOnTop()) {
+                        s.assignLayer(t, layer++);
+                        if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) {
+                            t.setLayer(mSplitScreenDividerAnchor, layer++);
+                        }
+                    } else if (state == ALWAYS_ON_TOP_STATE && s.isAlwaysOnTop()) {
+                        s.assignLayer(t, layer++);
+                    }
+                }
+                // The appropriate place for App-Transitions to occur is right
+                // above all other animations but still below things in the Picture-and-Picture
+                // windowing mode.
+                if (state == NORMAL_STACK_STATE && mAppAnimationLayer != null) {
+                    t.setLayer(mAppAnimationLayer, layer++);
                 }
             }
             for (int i = 0; i < mChildren.size(); i++) {
                 final TaskStack s = mChildren.get(i);
-                if (s.needsZBoost() && !s.isAlwaysOnTop()) {
-                    s.assignLayer(t, layer++);
-                }
-            }
-            for (int i = 0; i < mChildren.size(); i++) {
-                final TaskStack s = mChildren.get(i);
-                if (s.isAlwaysOnTop()) {
-                    s.assignLayer(t, layer++);
-                }
+                s.assignChildLayers(t);
             }
 
-            // The appropriate place for App-Transitions to occur is right
-            // above all other animations but still below things in the Picture-and-Picture
-            // windowing mode.
-            if (mAppAnimationLayer != null) {
-                t.setLayer(mAppAnimationLayer, layer++);
-            }
         }
 
         @Override
@@ -3534,6 +3552,10 @@
             return mAppAnimationLayer;
         }
 
+        SurfaceControl getSplitScreenDividerAnchor() {
+            return mSplitScreenDividerAnchor;
+        }
+
         @Override
         void onParentSet() {
             super.onParentSet();
@@ -3541,11 +3563,18 @@
                 mAppAnimationLayer = makeChildSurface(null)
                         .setName("animationLayer")
                         .build();
-                getPendingTransaction().show(mAppAnimationLayer);
+                mSplitScreenDividerAnchor = makeChildSurface(null)
+                        .setName("splitScreenDividerAnchor")
+                        .build();
+                getPendingTransaction()
+                        .show(mAppAnimationLayer)
+                        .show(mSplitScreenDividerAnchor);
                 scheduleAnimation();
             } else {
                 mAppAnimationLayer.destroy();
                 mAppAnimationLayer = null;
+                mSplitScreenDividerAnchor.destroy();
+                mSplitScreenDividerAnchor = null;
             }
         }
     }
@@ -3560,6 +3589,12 @@
                     && imeContainer.getSurfaceControl() != null;
             for (int j = 0; j < mChildren.size(); ++j) {
                 final WindowToken wt = mChildren.get(j);
+
+                // See {@link mSplitScreenDividerAnchor}
+                if (wt.windowType == TYPE_DOCK_DIVIDER) {
+                    wt.assignRelativeLayer(t, mTaskStackContainers.getSplitScreenDividerAnchor(), 1);
+                    continue;
+                }
                 wt.assignLayer(t, j);
                 wt.assignChildLayers(t);
 
diff --git a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
index 66d0da1..429dd8f 100644
--- a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
@@ -50,13 +50,16 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.test.mock.MockContentResolver;
 import android.util.ArraySet;
 import android.util.Pair;
 
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
+import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.ForceAppStandbyTracker.Listener;
 
 import org.junit.Before;
@@ -137,6 +140,9 @@
     private Consumer<PowerSaveState> mPowerSaveObserver;
     private BroadcastReceiver mReceiver;
 
+    private MockContentResolver mMockContentResolver;
+    private FakeSettingsProvider mFakeSettingsProvider;
+
     private boolean mPowerSaveMode;
 
     private final ArraySet<Pair<Integer, String>> mRestrictedPackages = new ArraySet();
@@ -182,6 +188,11 @@
                 any(int[].class)
                 )).thenAnswer(inv -> new ArrayList<AppOpsManager.PackageOps>());
 
+        mMockContentResolver = new MockContentResolver();
+        mFakeSettingsProvider = new FakeSettingsProvider();
+        when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
+        mMockContentResolver.addProvider(Settings.AUTHORITY, mFakeSettingsProvider);
+
         // Call start.
         instance.start();
 
@@ -495,8 +506,8 @@
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
-        // Power save on.
-        mPowerSaveMode = true;
+        // Updating to the same state should not fire listener
+        mPowerSaveMode = false;
         mPowerSaveObserver.accept(getPowerSaveState());
 
         assertNoCallbacks(l);
@@ -534,14 +545,14 @@
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
         verify(l, times(0)).unblockAlarmsForUid(anyInt());
-        verify(l, times(0)).unblockAlarmsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
+        verify(l, times(1)).unblockAlarmsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
         reset(l);
 
         setAppOps(UID_10_2, PACKAGE_2, false);
 
         verify(l, times(0)).updateAllJobs();
         verify(l, times(0)).updateJobsForUid(anyInt());
-        verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
+        verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
         verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -634,10 +645,20 @@
         mPowerSaveMode = true;
         mPowerSaveObserver.accept(getPowerSaveState());
 
+        verify(l, times(1)).updateAllJobs();
+        verify(l, times(0)).updateJobsForUid(anyInt());
+        verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+
+        verify(l, times(0)).unblockAllUnrestrictedAlarms();
+        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
+        reset(l);
+
         instance.setPowerSaveWhitelistAppIds(new int[] {UID_1, UID_2}, new int[] {});
 
         waitUntilMainHandlerDrain();
-        verify(l, times(1)).updateAllJobs();
+        // Called once for updating all whitelist and once for updating temp whitelist
+        verify(l, times(2)).updateAllJobs();
         verify(l, times(0)).updateJobsForUid(anyInt());
         verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
@@ -699,7 +720,7 @@
         verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
-        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
@@ -723,7 +744,7 @@
         verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
-        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
@@ -743,6 +764,15 @@
         mPowerSaveMode = false;
         mPowerSaveObserver.accept(getPowerSaveState());
 
+        verify(l, times(1)).updateAllJobs();
+        verify(l, times(0)).updateJobsForUid(eq(UID_10_1));
+        verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+
+        verify(l, times(1)).unblockAllUnrestrictedAlarms();
+        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
+        reset(l);
+
         mIUidObserver.onUidActive(UID_10_1);
 
         waitUntilMainHandlerDrain();
@@ -751,7 +781,7 @@
         verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
-        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
@@ -775,7 +805,7 @@
         verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
-        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java
index 1213e81..e72e460 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java
@@ -16,13 +16,18 @@
 
 package com.android.server.accessibility;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.accessibilityservice.AccessibilityService;
 import android.app.StatusBarManager;
 import android.content.Context;
+import android.os.Handler;
 
+import com.android.internal.util.ScreenshotHelper;
 import com.android.server.wm.WindowManagerInternal;
 
 import org.junit.Before;
@@ -39,6 +44,7 @@
     @Mock Context mMockContext;
     @Mock WindowManagerInternal mMockWindowManagerInternal;
     @Mock StatusBarManager mMockStatusBarManager;
+    @Mock ScreenshotHelper mMockScreenshotHelper;
 
     @Before
     public void setup() {
@@ -48,7 +54,8 @@
                 .thenReturn(mMockStatusBarManager);
 
         mGlobalActionPerformer =
-                new GlobalActionPerformer(mMockContext, mMockWindowManagerInternal);
+                new GlobalActionPerformer(mMockContext, mMockWindowManagerInternal,
+                        () -> mMockScreenshotHelper);
     }
 
     @Test
@@ -70,4 +77,13 @@
         mGlobalActionPerformer.performGlobalAction(AccessibilityService.GLOBAL_ACTION_POWER_DIALOG);
         verify(mMockWindowManagerInternal).showGlobalActions();
     }
+
+    @Test
+    public void testScreenshot_requestsFromScreenshotHelper() {
+        mGlobalActionPerformer.performGlobalAction(
+                AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT);
+        verify(mMockScreenshotHelper).takeScreenshot(
+                eq(android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN), anyBoolean(),
+                anyBoolean(), any(Handler.class));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
index 6468763..5f44fb6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
@@ -17,14 +17,17 @@
 package com.android.server.wm;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
@@ -74,11 +77,11 @@
             return super.setRelativeLayer(sc, relativeTo, layer);
         }
 
-        int getLayer(SurfaceControl sc) {
+        private int getLayer(SurfaceControl sc) {
             return mLayersForControl.getOrDefault(sc, 0);
         }
 
-        SurfaceControl getRelativeLayer(SurfaceControl sc) {
+        private SurfaceControl getRelativeLayer(SurfaceControl sc) {
             return mRelativeLayersForControl.get(sc);
         }
     };
@@ -146,8 +149,9 @@
         return p;
     }
 
-    void assertZOrderGreaterThan(LayerRecordingTransaction t,
-            SurfaceControl left, SurfaceControl right) throws Exception {
+
+    void assertZOrderGreaterThan(LayerRecordingTransaction t, SurfaceControl left,
+            SurfaceControl right) throws Exception {
         final LinkedList<SurfaceControl> leftParentChain = getAncestors(t, left);
         final LinkedList<SurfaceControl> rightParentChain = getAncestors(t, right);
 
@@ -171,9 +175,12 @@
         }
     }
 
-    void assertWindowLayerGreaterThan(LayerRecordingTransaction t,
-            WindowState left, WindowState right) throws Exception {
-        assertZOrderGreaterThan(t, left.getSurfaceControl(), right.getSurfaceControl());
+    void assertWindowHigher(WindowState left, WindowState right) throws Exception {
+        assertZOrderGreaterThan(mTransaction, left.getSurfaceControl(), right.getSurfaceControl());
+    }
+
+    WindowState createWindow(String name) {
+        return createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, name);
     }
 
     @Test
@@ -184,38 +191,37 @@
         // The Ime has an higher base layer than app windows and lower base layer than system
         // windows, so it should be above app windows and below system windows if there isn't an IME
         // target.
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mNavBarWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mStatusBarWindow, mImeWindow);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mNavBarWindow, mImeWindow);
+        assertWindowHigher(mStatusBarWindow, mImeWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
     public void testAssignWindowLayers_ForImeWithAppTarget() throws Exception {
-        final WindowState imeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
+        final WindowState imeAppTarget = createWindow("imeAppTarget");
         sWm.mInputMethodTarget = imeAppTarget;
+
         mDisplayContent.assignChildLayers(mTransaction);
 
         // Ime should be above all app windows and below system windows if it is targeting an app
         // window.
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, imeAppTarget);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mNavBarWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mStatusBarWindow, mImeWindow);
+        assertWindowHigher(mImeWindow, imeAppTarget);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mNavBarWindow, mImeWindow);
+        assertWindowHigher(mStatusBarWindow, mImeWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
     public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() throws Exception {
-        final WindowState imeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
+        final WindowState imeAppTarget = createWindow("imeAppTarget");
         final WindowState imeAppTargetChildAboveWindow = createWindow(imeAppTarget,
                 TYPE_APPLICATION_ATTACHED_DIALOG, imeAppTarget.mToken,
                 "imeAppTargetChildAboveWindow");
@@ -228,41 +234,38 @@
 
         // Ime should be above all app windows except for child windows that are z-ordered above it
         // and below system windows if it is targeting an app window.
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, imeAppTarget);
-        assertWindowLayerGreaterThan(mTransaction, imeAppTargetChildAboveWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mNavBarWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mStatusBarWindow, mImeWindow);
+        assertWindowHigher(mImeWindow, imeAppTarget);
+        assertWindowHigher(imeAppTargetChildAboveWindow, mImeWindow);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mNavBarWindow, mImeWindow);
+        assertWindowHigher(mStatusBarWindow, mImeWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
     public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() throws Exception {
-        final WindowState appBelowImeTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "appBelowImeTarget");
-        final WindowState imeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
-        final WindowState appAboveImeTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "appAboveImeTarget");
+        final WindowState appBelowImeTarget = createWindow("appBelowImeTarget");
+        final WindowState imeAppTarget = createWindow("imeAppTarget");
+        final WindowState appAboveImeTarget = createWindow("appAboveImeTarget");
 
         sWm.mInputMethodTarget = imeAppTarget;
         mDisplayContent.assignChildLayers(mTransaction);
 
         // Ime should be above all app windows except for non-fullscreen app window above it and
         // below system windows if it is targeting an app window.
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, imeAppTarget);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, appBelowImeTarget);
-        assertWindowLayerGreaterThan(mTransaction, appAboveImeTarget, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mNavBarWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mStatusBarWindow, mImeWindow);
+        assertWindowHigher(mImeWindow, imeAppTarget);
+        assertWindowHigher(mImeWindow, appBelowImeTarget);
+        assertWindowHigher(appAboveImeTarget, mImeWindow);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mNavBarWindow, mImeWindow);
+        assertWindowHigher(mStatusBarWindow, mImeWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
@@ -276,20 +279,20 @@
 
         // The IME target base layer is higher than all window except for the nav bar window, so the
         // IME should be above all windows except for the nav bar.
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, imeSystemOverlayTarget);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mDockedDividerWindow);
+        assertWindowHigher(mImeWindow, imeSystemOverlayTarget);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mImeWindow, mDockedDividerWindow);
 
         // The IME has a higher base layer than the status bar so we may expect it to go
         // above the status bar once they are both in the Non-App layer, as past versions of this
         // test enforced. However this seems like the wrong behavior unless the status bar is the
         // IME target.
-        assertWindowLayerGreaterThan(mTransaction, mNavBarWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mStatusBarWindow, mImeWindow);
+        assertWindowHigher(mNavBarWindow, mImeWindow);
+        assertWindowHigher(mStatusBarWindow, mImeWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
@@ -297,17 +300,18 @@
         sWm.mInputMethodTarget = mStatusBarWindow;
         mDisplayContent.assignChildLayers(mTransaction);
 
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mDockedDividerWindow);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mStatusBarWindow);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mImeWindow, mDockedDividerWindow);
+        assertWindowHigher(mImeWindow, mStatusBarWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
     public void testStackLayers() throws Exception {
+        final WindowState anyWindow1 = createWindow("anyWindow");
         final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
                 ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
                 "pinnedStackWindow");
@@ -317,12 +321,22 @@
         final WindowState assistantStackWindow = createWindowOnStack(null, WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
                 mDisplayContent, "assistantStackWindow");
+        final WindowState homeActivityWindow = createWindowOnStack(null, WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_HOME, TYPE_BASE_APPLICATION,
+                mDisplayContent, "homeActivityWindow");
+        final WindowState anyWindow2 = createWindow("anyWindow2");
 
         mDisplayContent.assignChildLayers(mTransaction);
 
-        assertWindowLayerGreaterThan(mTransaction, dockedStackWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, assistantStackWindow, dockedStackWindow);
-        assertWindowLayerGreaterThan(mTransaction, pinnedStackWindow, assistantStackWindow);
+        assertWindowHigher(dockedStackWindow, homeActivityWindow);
+        assertWindowHigher(assistantStackWindow, homeActivityWindow);
+        assertWindowHigher(pinnedStackWindow, homeActivityWindow);
+        assertWindowHigher(anyWindow1, homeActivityWindow);
+        assertWindowHigher(anyWindow2, homeActivityWindow);
+        assertWindowHigher(pinnedStackWindow, anyWindow1);
+        assertWindowHigher(pinnedStackWindow, anyWindow2);
+        assertWindowHigher(pinnedStackWindow, dockedStackWindow);
+        assertWindowHigher(pinnedStackWindow, assistantStackWindow);
     }
 
     @Test
@@ -337,9 +351,9 @@
 
         // Ime should be above all app windows and below system windows if it is targeting an app
         // window.
-        assertWindowLayerGreaterThan(mTransaction, navBarPanel, mNavBarWindow);
-        assertWindowLayerGreaterThan(mTransaction, statusBarPanel, mStatusBarWindow);
-        assertWindowLayerGreaterThan(mTransaction, statusBarSubPanel, statusBarPanel);
+        assertWindowHigher(navBarPanel, mNavBarWindow);
+        assertWindowHigher(statusBarPanel, mStatusBarWindow);
+        assertWindowHigher(statusBarSubPanel, statusBarPanel);
     }
 
     @Test
@@ -347,8 +361,7 @@
         // TODO(b/70040778): We should aim to eliminate the last user of TYPE_APPLICATION_MEDIA
         // then we can drop all negative layering on the windowing side.
 
-        final WindowState anyWindow =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "anyWindow");
+        final WindowState anyWindow = createWindow("anyWindow");
         final WindowState child = createWindow(anyWindow, TYPE_APPLICATION_MEDIA, mDisplayContent,
                 "TypeApplicationMediaChild");
         final WindowState mediaOverlayChild = createWindow(anyWindow, TYPE_APPLICATION_MEDIA_OVERLAY,
@@ -356,7 +369,29 @@
 
         mDisplayContent.assignChildLayers(mTransaction);
 
-        assertWindowLayerGreaterThan(mTransaction, anyWindow, mediaOverlayChild);
-        assertWindowLayerGreaterThan(mTransaction, mediaOverlayChild, child);
+        assertWindowHigher(anyWindow, mediaOverlayChild);
+        assertWindowHigher(mediaOverlayChild, child);
+    }
+
+    @Test
+    public void testDockedDividerPosition() throws Exception {
+        final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
+                ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
+                "pinnedStackWindow");
+        final WindowState splitScreenWindow = createWindowOnStack(null,
+                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
+                mDisplayContent, "splitScreenWindow");
+        final WindowState splitScreenSecondaryWindow = createWindowOnStack(null,
+                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
+                TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
+        final WindowState assistantStackWindow = createWindowOnStack(null, WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
+                mDisplayContent, "assistantStackWindow");
+
+        mDisplayContent.assignChildLayers(mTransaction);
+
+        assertWindowHigher(mDockedDividerWindow, splitScreenWindow);
+        assertWindowHigher(mDockedDividerWindow, splitScreenSecondaryWindow);
+        assertWindowHigher(pinnedStackWindow, mDockedDividerWindow);
     }
 }
diff --git a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
index 4098b98..0504c79 100644
--- a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
@@ -62,6 +62,11 @@
                 public boolean isRuntimePermission(String permission) {
                     return false;
                 }
+
+                @Override
+                public int getPackageUid(String packageName, int flags) {
+                    return -1;
+                }
             };
             ServiceManagerNative.asInterface(BinderInternal.getContextObject())
                     .setPermissionController(pc);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 6438631..2c60118 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -267,8 +267,15 @@
     public static final int AP_BAND_5GHZ = 1;
 
     /**
+     * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
+     * operating country code and current radio conditions.
+     * @hide
+     */
+    public static final int AP_BAND_ANY = -1;
+
+    /**
      * The band which AP resides on
-     * 0-2G  1-5G
+     * -1:Any 0:2G 1:5G
      * By default, 2G is chosen
      * @hide
      */