Merge "Remove unnecessary static libraries in libmedia2_jni" into pi-dev
diff --git a/api/current.txt b/api/current.txt
index 30b413a..59e7c46 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6331,6 +6331,7 @@
     method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException;
     method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
     method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public boolean supportsTransferOwnership();
     method public boolean usesPolicy(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.admin.DeviceAdminInfo> CREATOR;
@@ -6395,7 +6396,6 @@
     field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
     field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
     field public static final java.lang.String EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE = "android.app.extra.TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE";
-    field public static final java.lang.String SUPPORT_TRANSFER_OWNERSHIP_META_DATA = "android.app.support_transfer_ownership";
   }
 
   public class DeviceAdminService extends android.app.Service {
@@ -21249,9 +21249,10 @@
     method public final boolean switchToPreviousInputMethod();
     method public void updateFullscreenMode();
     method public void updateInputViewShown();
+    field public static final int BACK_DISPOSITION_ADJUST_NOTHING = 3; // 0x3
     field public static final int BACK_DISPOSITION_DEFAULT = 0; // 0x0
-    field public static final int BACK_DISPOSITION_WILL_DISMISS = 2; // 0x2
-    field public static final int BACK_DISPOSITION_WILL_NOT_DISMISS = 1; // 0x1
+    field public static final deprecated int BACK_DISPOSITION_WILL_DISMISS = 2; // 0x2
+    field public static final deprecated int BACK_DISPOSITION_WILL_NOT_DISMISS = 1; // 0x1
   }
 
   public class InputMethodService.InputMethodImpl extends android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl {
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index 3570144..2b85ec0 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -34,11 +34,11 @@
 
 FdBuffer::~FdBuffer() {}
 
-status_t FdBuffer::read(int fd, int64_t timeout) {
-    struct pollfd pfds = {.fd = fd, .events = POLLIN};
+status_t FdBuffer::read(unique_fd* fd, int64_t timeout) {
+    struct pollfd pfds = {.fd = fd->get(), .events = POLLIN};
     mStartTime = uptimeMillis();
 
-    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
+    fcntl(fd->get(), F_SETFL, fcntl(fd->get(), F_GETFL, 0) | O_NONBLOCK);
 
     while (true) {
         if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
@@ -67,16 +67,16 @@
                 VLOG("return event has error %s", strerror(errno));
                 return errno != 0 ? -errno : UNKNOWN_ERROR;
             } else {
-                ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
+                ssize_t amt = ::read(fd->get(), mBuffer.writeBuffer(), mBuffer.currentToWrite());
                 if (amt < 0) {
                     if (errno == EAGAIN || errno == EWOULDBLOCK) {
                         continue;
                     } else {
-                        VLOG("Fail to read %d: %s", fd, strerror(errno));
+                        VLOG("Fail to read %d: %s", fd->get(), strerror(errno));
                         return -errno;
                     }
                 } else if (amt == 0) {
-                    VLOG("Reached EOF of fd=%d", fd);
+                    VLOG("Reached EOF of fd=%d", fd->get());
                     break;
                 }
                 mBuffer.wp()->move(amt);
@@ -87,7 +87,7 @@
     return NO_ERROR;
 }
 
-status_t FdBuffer::readFully(int fd) {
+status_t FdBuffer::readFully(unique_fd* fd) {
     mStartTime = uptimeMillis();
 
     while (true) {
@@ -99,10 +99,10 @@
         }
         if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
 
-        ssize_t amt =
-                TEMP_FAILURE_RETRY(::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite()));
+        ssize_t amt = TEMP_FAILURE_RETRY(
+                ::read(fd->get(), mBuffer.writeBuffer(), mBuffer.currentToWrite()));
         if (amt < 0) {
-            VLOG("Fail to read %d: %s", fd, strerror(errno));
+            VLOG("Fail to read %d: %s", fd->get(), strerror(errno));
             return -errno;
         } else if (amt == 0) {
             VLOG("Done reading %zu bytes", mBuffer.size());
@@ -116,20 +116,20 @@
     return NO_ERROR;
 }
 
-status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
-                                             const bool isSysfs) {
+status_t FdBuffer::readProcessedDataInStream(unique_fd* fd, unique_fd* toFd, unique_fd* fromFd,
+                                             int64_t timeoutMs, const bool isSysfs) {
     struct pollfd pfds[] = {
-            {.fd = fd, .events = POLLIN},
-            {.fd = toFd, .events = POLLOUT},
-            {.fd = fromFd, .events = POLLIN},
+            {.fd = fd->get(), .events = POLLIN},
+            {.fd = toFd->get(), .events = POLLOUT},
+            {.fd = fromFd->get(), .events = POLLIN},
     };
 
     mStartTime = uptimeMillis();
 
     // mark all fds non blocking
-    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
-    fcntl(toFd, F_SETFL, fcntl(toFd, F_GETFL, 0) | O_NONBLOCK);
-    fcntl(fromFd, F_SETFL, fcntl(fromFd, F_GETFL, 0) | O_NONBLOCK);
+    fcntl(fd->get(), F_SETFL, fcntl(fd->get(), F_GETFL, 0) | O_NONBLOCK);
+    fcntl(toFd->get(), F_SETFL, fcntl(toFd->get(), F_GETFL, 0) | O_NONBLOCK);
+    fcntl(fromFd->get(), F_SETFL, fcntl(fromFd->get(), F_GETFL, 0) | O_NONBLOCK);
 
     // A circular buffer holds data read from fd and writes to parsing process
     uint8_t cirBuf[BUFFER_SIZE];
@@ -166,10 +166,10 @@
         for (int i = 0; i < 3; ++i) {
             if ((pfds[i].revents & POLLERR) != 0) {
                 if (i == 0 && isSysfs) {
-                    VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
+                    VLOG("fd %d is sysfs, ignore its POLLERR return value", fd->get());
                     continue;
                 }
-                VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
+                VLOG("fd[%d]=%d returns error events: %s", i, fd->get(), strerror(errno));
                 return errno != 0 ? -errno : UNKNOWN_ERROR;
             }
         }
@@ -178,17 +178,17 @@
         if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
             ssize_t amt;
             if (rpos >= wpos) {
-                amt = ::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos);
+                amt = ::read(fd->get(), cirBuf + rpos, BUFFER_SIZE - rpos);
             } else {
-                amt = ::read(fd, cirBuf + rpos, wpos - rpos);
+                amt = ::read(fd->get(), cirBuf + rpos, wpos - rpos);
             }
             if (amt < 0) {
                 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
-                    VLOG("Fail to read fd %d: %s", fd, strerror(errno));
+                    VLOG("Fail to read fd %d: %s", fd->get(), strerror(errno));
                     return -errno;
                 }  // otherwise just continue
             } else if (amt == 0) {
-                VLOG("Reached EOF of input file %d", fd);
+                VLOG("Reached EOF of input file %d", fd->get());
                 pfds[0].fd = -1;  // reach EOF so don't have to poll pfds[0].
             } else {
                 rpos += amt;
@@ -200,13 +200,13 @@
         if (cirSize > 0 && pfds[1].fd != -1) {
             ssize_t amt;
             if (rpos > wpos) {
-                amt = ::write(toFd, cirBuf + wpos, rpos - wpos);
+                amt = ::write(toFd->get(), cirBuf + wpos, rpos - wpos);
             } else {
-                amt = ::write(toFd, cirBuf + wpos, BUFFER_SIZE - wpos);
+                amt = ::write(toFd->get(), cirBuf + wpos, BUFFER_SIZE - wpos);
             }
             if (amt < 0) {
                 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
-                    VLOG("Fail to write toFd %d: %s", toFd, strerror(errno));
+                    VLOG("Fail to write toFd %d: %s", toFd->get(), strerror(errno));
                     return -errno;
                 }  // otherwise just continue
             } else {
@@ -217,8 +217,8 @@
 
         // if buffer is empty and fd is closed, close write fd.
         if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
-            VLOG("Close write pipe %d", toFd);
-            ::close(pfds[1].fd);
+            VLOG("Close write pipe %d", toFd->get());
+            toFd->reset();
             pfds[1].fd = -1;
         }
 
@@ -231,14 +231,14 @@
         }
 
         // read from parsing process
-        ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
+        ssize_t amt = ::read(fromFd->get(), mBuffer.writeBuffer(), mBuffer.currentToWrite());
         if (amt < 0) {
             if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
-                VLOG("Fail to read fromFd %d: %s", fromFd, strerror(errno));
+                VLOG("Fail to read fromFd %d: %s", fromFd->get(), strerror(errno));
                 return -errno;
             }  // otherwise just continue
         } else if (amt == 0) {
-            VLOG("Reached EOF of fromFd %d", fromFd);
+            VLOG("Reached EOF of fromFd %d", fromFd->get());
             break;
         } else {
             mBuffer.wp()->move(amt);
diff --git a/cmds/incidentd/src/FdBuffer.h b/cmds/incidentd/src/FdBuffer.h
index 34ebcf5..db3a74b 100644
--- a/cmds/incidentd/src/FdBuffer.h
+++ b/cmds/incidentd/src/FdBuffer.h
@@ -18,10 +18,12 @@
 #ifndef FD_BUFFER_H
 #define FD_BUFFER_H
 
+#include <android-base/unique_fd.h>
 #include <android/util/EncodedBuffer.h>
 #include <utils/Errors.h>
 
 using namespace android;
+using namespace android::base;
 using namespace android::util;
 using namespace std;
 
@@ -38,13 +40,13 @@
      * Returns NO_ERROR if there were no errors or if we timed out.
      * Will mark the file O_NONBLOCK.
      */
-    status_t read(int fd, int64_t timeoutMs);
+    status_t read(unique_fd* fd, int64_t timeoutMs);
 
     /**
      * Read the data until we hit eof.
      * Returns NO_ERROR if there were no errors.
      */
-    status_t readFully(int fd);
+    status_t readFully(unique_fd* fd);
 
     /**
      * Read processed results by streaming data to a parsing process, e.g. incident helper.
@@ -56,8 +58,8 @@
      *
      * Poll will return POLLERR if fd is from sysfs, handle this edge case.
      */
-    status_t readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
-                                       const bool isSysfs = false);
+    status_t readProcessedDataInStream(unique_fd* fd, unique_fd* toFd, unique_fd* fromFd,
+                                       int64_t timeoutMs, const bool isSysfs = false);
 
     /**
      * Whether we timed out.
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index d02b4dd..aeccefd 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -352,7 +352,8 @@
             printPrivacy(p, out, String8(""));
         } else if (opt == "parse") {
             FdBuffer buf;
-            status_t error = buf.read(fileno(in), 60000);
+            unique_fd infd(fileno(in));
+            status_t error = buf.read(&infd, 60000);
             if (error != NO_ERROR) {
                 fprintf(err, "Error reading from stdin\n");
                 return error;
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 5cde5a9..ab4e764 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -277,8 +277,8 @@
 status_t FileSection::Execute(ReportRequestSet* requests) const {
     // read from mFilename first, make sure the file is available
     // add O_CLOEXEC to make sure it is closed when exec incident helper
-    int fd = open(mFilename, O_RDONLY | O_CLOEXEC);
-    if (fd == -1) {
+    unique_fd fd(open(mFilename, O_RDONLY | O_CLOEXEC));
+    if (fd.get() == -1) {
         ALOGW("FileSection '%s' failed to open file", this->name.string());
         return -errno;
     }
@@ -299,9 +299,8 @@
     }
 
     // parent process
-    status_t readStatus = buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(), c2pPipe.readFd(),
-                                                           this->timeoutMs, mIsSysfs);
-    close(fd);  // close the fd anyway.
+    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",
@@ -342,17 +341,17 @@
 status_t GZipSection::Execute(ReportRequestSet* requests) const {
     // Reads the files in order, use the first available one.
     int index = 0;
-    int fd = -1;
+    unique_fd fd;
     while (mFilenames[index] != NULL) {
-        fd = open(mFilenames[index], O_RDONLY | O_CLOEXEC);
-        if (fd != -1) {
+        fd.reset(open(mFilenames[index], O_RDONLY | O_CLOEXEC));
+        if (fd.get() != -1) {
             break;
         }
         ALOGW("GZipSection failed to open file %s", mFilenames[index]);
         index++;  // look at the next file.
     }
-    VLOG("GZipSection is using file %s, fd=%d", mFilenames[index], fd);
-    if (fd == -1) return -1;
+    VLOG("GZipSection is using file %s, fd=%d", mFilenames[index], fd.get());
+    if (fd.get() == -1) return -1;
 
     FdBuffer buffer;
     Fpipe p2cPipe;
@@ -388,9 +387,9 @@
     VLOG("GZipSection '%s' editPos=%zd, dataBeginAt=%zd", this->name.string(), editPos,
          dataBeginAt);
 
-    status_t readStatus = buffer.readProcessedDataInStream(
-            fd, p2cPipe.writeFd(), c2pPipe.readFd(), this->timeoutMs, isSysfs(mFilenames[index]));
-    close(fd);  // close the fd anyway.
+    status_t readStatus =
+            buffer.readProcessedDataInStream(&fd, &p2cPipe.writeFd(), &c2pPipe.readFd(),
+                                             this->timeoutMs, isSysfs(mFilenames[index]));
 
     if (readStatus != NO_ERROR || buffer.timedOut()) {
         ALOGW("GZipSection '%s' failed to read data from gzip: %s, timedout: %s",
@@ -424,7 +423,7 @@
 // ================================================================================
 struct WorkerThreadData : public virtual RefBase {
     const WorkerThreadSection* section;
-    int fds[2];
+    Fpipe pipe;
 
     // Lock protects these fields
     mutex lock;
@@ -433,16 +432,10 @@
 
     WorkerThreadData(const WorkerThreadSection* section);
     virtual ~WorkerThreadData();
-
-    int readFd() { return fds[0]; }
-    int writeFd() { return fds[1]; }
 };
 
 WorkerThreadData::WorkerThreadData(const WorkerThreadSection* sec)
-    : section(sec), workerDone(false), workerError(NO_ERROR) {
-    fds[0] = -1;
-    fds[1] = -1;
-}
+    : section(sec), workerDone(false), workerError(NO_ERROR) {}
 
 WorkerThreadData::~WorkerThreadData() {}
 
@@ -454,7 +447,7 @@
 
 static void* worker_thread_func(void* cookie) {
     WorkerThreadData* data = (WorkerThreadData*)cookie;
-    status_t err = data->section->BlockingCall(data->writeFd());
+    status_t err = data->section->BlockingCall(data->pipe.writeFd().get());
 
     {
         unique_lock<mutex> lock(data->lock);
@@ -462,7 +455,7 @@
         data->workerError = err;
     }
 
-    close(data->writeFd());
+    data->pipe.writeFd().reset();
     data->decStrong(data->section);
     // data might be gone now. don't use it after this point in this thread.
     return NULL;
@@ -479,8 +472,7 @@
     sp<WorkerThreadData> data = new WorkerThreadData(this);
 
     // Create the pipe
-    err = pipe(data->fds);
-    if (err != 0) {
+    if (!data->pipe.init()) {
         return -errno;
     }
 
@@ -507,7 +499,7 @@
     pthread_attr_destroy(&attr);
 
     // Loop reading until either the timeout or the worker side is done (i.e. eof).
-    err = buffer.read(data->readFd(), this->timeoutMs);
+    err = buffer.read(&data->pipe.readFd(), this->timeoutMs);
     if (err != NO_ERROR) {
         // TODO: Log this error into the incident report.
         ALOGW("WorkerThreadSection '%s' reader failed with error '%s'", this->name.string(),
@@ -516,7 +508,7 @@
 
     // Done with the read fd. The worker thread closes the write one so
     // we never race and get here first.
-    close(data->readFd());
+    data->pipe.readFd().reset();
 
     // If the worker side is finished, then return its error (which may overwrite
     // our possible error -- but it's more interesting anyway).  If not, then we timed out.
@@ -602,7 +594,8 @@
     // child process to execute the command as root
     if (cmdPid == 0) {
         // replace command's stdout with ihPipe's write Fd
-        if (dup2(cmdPipe.writeFd(), STDOUT_FILENO) != 1 || !ihPipe.close() || !cmdPipe.close()) {
+        if (dup2(cmdPipe.writeFd().get(), STDOUT_FILENO) != 1 || !ihPipe.close() ||
+            !cmdPipe.close()) {
             ALOGW("CommandSection '%s' failed to set up stdout: %s", this->name.string(),
                   strerror(errno));
             _exit(EXIT_FAILURE);
@@ -619,8 +612,8 @@
         return -errno;
     }
 
-    close(cmdPipe.writeFd());
-    status_t readStatus = buffer.read(ihPipe.readFd(), this->timeoutMs);
+    cmdPipe.writeFd().reset();
+    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",
               this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
@@ -921,10 +914,10 @@
             break;
         } else if (child == 0) {
             // This is the child process.
-            close(dumpPipe.readFd());
+            dumpPipe.readFd().reset();
             const int ret = dump_backtrace_to_file_timeout(
                     pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
-                    is_java_process ? 5 : 20, dumpPipe.writeFd());
+                    is_java_process ? 5 : 20, dumpPipe.writeFd().get());
             if (ret == -1) {
                 if (errno == 0) {
                     ALOGW("Dumping failed for pid '%d', likely due to a timeout\n", pid);
@@ -932,25 +925,17 @@
                     ALOGE("Dumping failed for pid '%d': %s\n", pid, strerror(errno));
                 }
             }
-            if (close(dumpPipe.writeFd()) != 0) {
-                ALOGW("TombstoneSection '%s' failed to close dump pipe writeFd: %d",
-                      this->name.string(), errno);
-                _exit(EXIT_FAILURE);
-            }
-
+            dumpPipe.writeFd().reset();
             _exit(EXIT_SUCCESS);
         }
-        close(dumpPipe.writeFd());
+        dumpPipe.writeFd().reset();
         // Parent process.
         // Read from the pipe concurrently to avoid blocking the child.
         FdBuffer buffer;
-        err = buffer.readFully(dumpPipe.readFd());
+        err = buffer.readFully(&dumpPipe.readFd());
         if (err != NO_ERROR) {
             ALOGW("TombstoneSection '%s' failed to read stack dump: %d", this->name.string(), err);
-            if (close(dumpPipe.readFd()) != 0) {
-                ALOGW("TombstoneSection '%s' failed to close dump pipe readFd: %s",
-                      this->name.string(), strerror(errno));
-            }
+            dumpPipe.readFd().reset();
             break;
         }
 
@@ -967,13 +952,7 @@
         proto.write(android::os::BackTraceProto::Stack::DUMP_DURATION_NS,
                     static_cast<long long>(Nanotime() - start));
         proto.end(token);
-
-        if (close(dumpPipe.readFd()) != 0) {
-            ALOGW("TombstoneSection '%s' failed to close dump pipe readFd: %d", this->name.string(),
-                  errno);
-            err = -errno;
-            break;
-        }
+        dumpPipe.readFd().reset();
     }
 
     proto.flush(pipeWriteFd);
diff --git a/cmds/incidentd/src/incidentd_util.cpp b/cmds/incidentd/src/incidentd_util.cpp
index c869c7a..d799513 100644
--- a/cmds/incidentd/src/incidentd_util.cpp
+++ b/cmds/incidentd/src/incidentd_util.cpp
@@ -53,16 +53,17 @@
 
 bool Fpipe::init() { return Pipe(&mRead, &mWrite); }
 
-int Fpipe::readFd() const { return mRead.get(); }
+unique_fd& Fpipe::readFd() { return mRead; }
 
-int Fpipe::writeFd() const { return mWrite.get(); }
+unique_fd& Fpipe::writeFd() { return mWrite; }
 
 pid_t fork_execute_cmd(const char* cmd, char* const argv[], Fpipe* input, Fpipe* output) {
     // fork used in multithreaded environment, avoid adding unnecessary code in child process
     pid_t pid = fork();
     if (pid == 0) {
-        if (TEMP_FAILURE_RETRY(dup2(input->readFd(), STDIN_FILENO)) < 0 || !input->close() ||
-            TEMP_FAILURE_RETRY(dup2(output->writeFd(), STDOUT_FILENO)) < 0 || !output->close()) {
+        if (TEMP_FAILURE_RETRY(dup2(input->readFd().get(), STDIN_FILENO)) < 0 || !input->close() ||
+            TEMP_FAILURE_RETRY(dup2(output->writeFd().get(), STDOUT_FILENO)) < 0 ||
+            !output->close()) {
             ALOGW("Can't setup stdin and stdout for command %s", cmd);
             _exit(EXIT_FAILURE);
         }
@@ -76,8 +77,8 @@
         _exit(EXIT_FAILURE);  // always exits with failure if any
     }
     // close the fds used in child process.
-    close(input->readFd());
-    close(output->writeFd());
+    input->readFd().reset();
+    output->writeFd().reset();
     return pid;
 }
 
diff --git a/cmds/incidentd/src/incidentd_util.h b/cmds/incidentd/src/incidentd_util.h
index 3f7df91..228d776 100644
--- a/cmds/incidentd/src/incidentd_util.h
+++ b/cmds/incidentd/src/incidentd_util.h
@@ -41,8 +41,8 @@
 
     bool init();
     bool close();
-    int readFd() const;
-    int writeFd() const;
+    unique_fd& readFd();
+    unique_fd& writeFd();
 
 private:
     unique_fd mRead;
diff --git a/cmds/incidentd/tests/FdBuffer_test.cpp b/cmds/incidentd/tests/FdBuffer_test.cpp
index 0e5eec6..bf77017 100644
--- a/cmds/incidentd/tests/FdBuffer_test.cpp
+++ b/cmds/incidentd/tests/FdBuffer_test.cpp
@@ -37,6 +37,7 @@
 public:
     virtual void SetUp() override {
         ASSERT_NE(tf.fd, -1);
+        tffd.reset(tf.fd);
         ASSERT_NE(p2cPipe.init(), -1);
         ASSERT_NE(c2pPipe.init(), -1);
     }
@@ -56,13 +57,13 @@
         EXPECT_EQ(expected[i], '\0');
     }
 
-    bool DoDataStream(int rFd, int wFd) {
+    bool DoDataStream(unique_fd* rFd, unique_fd* wFd) {
         char buf[BUFFER_SIZE];
         ssize_t nRead;
-        while ((nRead = read(rFd, buf, BUFFER_SIZE)) > 0) {
+        while ((nRead = read(rFd->get(), buf, BUFFER_SIZE)) > 0) {
             ssize_t nWritten = 0;
             while (nWritten < nRead) {
-                ssize_t amt = write(wFd, buf + nWritten, nRead - nWritten);
+                ssize_t amt = write(wFd->get(), buf + nWritten, nRead - nWritten);
                 if (amt < 0) {
                     return false;
                 }
@@ -75,6 +76,7 @@
 protected:
     FdBuffer buffer;
     TemporaryFile tf;
+    unique_fd tffd;
     Fpipe p2cPipe;
     Fpipe c2pPipe;
 
@@ -85,7 +87,7 @@
 TEST_F(FdBufferTest, ReadAndWrite) {
     std::string testdata = "FdBuffer test string";
     ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
-    ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, READ_TIMEOUT));
+    ASSERT_EQ(NO_ERROR, buffer.read(&tffd, READ_TIMEOUT));
     AssertBufferReadSuccessful(testdata.size());
     AssertBufferContent(testdata.c_str());
 }
@@ -98,7 +100,7 @@
 TEST_F(FdBufferTest, ReadAndIterate) {
     std::string testdata = "FdBuffer test string";
     ASSERT_TRUE(WriteStringToFile(testdata, tf.path));
-    ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, READ_TIMEOUT));
+    ASSERT_EQ(NO_ERROR, buffer.read(&tffd, READ_TIMEOUT));
 
     int i = 0;
     EncodedBuffer::iterator it = buffer.data();
@@ -117,16 +119,16 @@
     ASSERT_TRUE(pid != -1);
 
     if (pid == 0) {
-        close(c2pPipe.readFd());
+        c2pPipe.readFd().reset();
         while (true) {
             write(c2pPipe.writeFd(), "poo", 3);
             sleep(1);
         }
         _exit(EXIT_FAILURE);
     } else {
-        close(c2pPipe.writeFd());
+        c2pPipe.writeFd().reset();
 
-        status_t status = buffer.read(c2pPipe.readFd(), QUICK_TIMEOUT_MS);
+        status_t status = buffer.read(&c2pPipe.readFd(), QUICK_TIMEOUT_MS);
         ASSERT_EQ(NO_ERROR, status);
         EXPECT_TRUE(buffer.timedOut());
 
@@ -143,20 +145,20 @@
     ASSERT_TRUE(pid != -1);
 
     if (pid == 0) {
-        close(p2cPipe.writeFd());
-        close(c2pPipe.readFd());
+        p2cPipe.writeFd().reset();
+        c2pPipe.readFd().reset();
         ASSERT_TRUE(WriteStringToFd(HEAD, c2pPipe.writeFd()));
-        ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
-        close(p2cPipe.readFd());
-        close(c2pPipe.writeFd());
+        ASSERT_TRUE(DoDataStream(&p2cPipe.readFd(), &c2pPipe.writeFd()));
+        p2cPipe.readFd().reset();
+        c2pPipe.writeFd().reset();
         // Must exit here otherwise the child process will continue executing the test binary.
         _exit(EXIT_SUCCESS);
     } else {
-        close(p2cPipe.readFd());
-        close(c2pPipe.writeFd());
+        p2cPipe.readFd().reset();
+        c2pPipe.writeFd().reset();
 
-        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
-                                                             c2pPipe.readFd(), READ_TIMEOUT));
+        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(&tffd, &p2cPipe.writeFd(),
+                                                             &c2pPipe.readFd(), READ_TIMEOUT));
         AssertBufferReadSuccessful(HEAD.size() + testdata.size());
         AssertBufferContent(expected.c_str());
         wait(&pid);
@@ -172,23 +174,23 @@
     ASSERT_TRUE(pid != -1);
 
     if (pid == 0) {
-        close(p2cPipe.writeFd());
-        close(c2pPipe.readFd());
+        p2cPipe.writeFd().reset();
+        c2pPipe.readFd().reset();
         std::string data;
         // wait for read finishes then write.
         ASSERT_TRUE(ReadFdToString(p2cPipe.readFd(), &data));
         data = HEAD + data;
         ASSERT_TRUE(WriteStringToFd(data, c2pPipe.writeFd()));
-        close(p2cPipe.readFd());
-        close(c2pPipe.writeFd());
+        p2cPipe.readFd().reset();
+        c2pPipe.writeFd().reset();
         // Must exit here otherwise the child process will continue executing the test binary.
         _exit(EXIT_SUCCESS);
     } else {
-        close(p2cPipe.readFd());
-        close(c2pPipe.writeFd());
+        p2cPipe.readFd().reset();
+        c2pPipe.writeFd().reset();
 
-        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
-                                                             c2pPipe.readFd(), READ_TIMEOUT));
+        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(&tffd, &p2cPipe.writeFd(),
+                                                             &c2pPipe.readFd(), READ_TIMEOUT));
         AssertBufferReadSuccessful(HEAD.size() + testdata.size());
         AssertBufferContent(expected.c_str());
         wait(&pid);
@@ -202,18 +204,18 @@
     ASSERT_TRUE(pid != -1);
 
     if (pid == 0) {
-        close(p2cPipe.writeFd());
-        close(c2pPipe.readFd());
-        ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
-        close(p2cPipe.readFd());
-        close(c2pPipe.writeFd());
+        p2cPipe.writeFd().reset();
+        c2pPipe.readFd().reset();
+        ASSERT_TRUE(DoDataStream(&p2cPipe.readFd(), &c2pPipe.writeFd()));
+        p2cPipe.readFd().reset();
+        c2pPipe.writeFd().reset();
         _exit(EXIT_SUCCESS);
     } else {
-        close(p2cPipe.readFd());
-        close(c2pPipe.writeFd());
+        p2cPipe.readFd().reset();
+        c2pPipe.writeFd().reset();
 
-        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
-                                                             c2pPipe.readFd(), READ_TIMEOUT));
+        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(&tffd, &p2cPipe.writeFd(),
+                                                             &c2pPipe.readFd(), READ_TIMEOUT));
         AssertBufferReadSuccessful(0);
         AssertBufferContent("");
         wait(&pid);
@@ -223,24 +225,24 @@
 TEST_F(FdBufferTest, ReadInStreamMoreThan4MB) {
     const std::string testFile = kTestDataPath + "morethan4MB.txt";
     size_t fourMB = (size_t)4 * 1024 * 1024;
-    int fd = open(testFile.c_str(), O_RDONLY | O_CLOEXEC);
-    ASSERT_NE(fd, -1);
+    unique_fd fd(open(testFile.c_str(), O_RDONLY | O_CLOEXEC));
+    ASSERT_NE(fd.get(), -1);
     int pid = fork();
     ASSERT_TRUE(pid != -1);
 
     if (pid == 0) {
-        close(p2cPipe.writeFd());
-        close(c2pPipe.readFd());
-        ASSERT_TRUE(DoDataStream(p2cPipe.readFd(), c2pPipe.writeFd()));
-        close(p2cPipe.readFd());
-        close(c2pPipe.writeFd());
+        p2cPipe.writeFd().reset();
+        c2pPipe.readFd().reset();
+        ASSERT_TRUE(DoDataStream(&p2cPipe.readFd(), &c2pPipe.writeFd()));
+        p2cPipe.readFd().reset();
+        c2pPipe.writeFd().reset();
         _exit(EXIT_SUCCESS);
     } else {
-        close(p2cPipe.readFd());
-        close(c2pPipe.writeFd());
+        p2cPipe.readFd().reset();
+        c2pPipe.writeFd().reset();
 
-        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(),
-                                                             c2pPipe.readFd(), READ_TIMEOUT));
+        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(&fd, &p2cPipe.writeFd(),
+                                                             &c2pPipe.readFd(), READ_TIMEOUT));
         EXPECT_EQ(buffer.size(), fourMB);
         EXPECT_FALSE(buffer.timedOut());
         EXPECT_TRUE(buffer.truncated());
@@ -266,18 +268,18 @@
     ASSERT_TRUE(pid != -1);
 
     if (pid == 0) {
-        close(p2cPipe.writeFd());
-        close(c2pPipe.readFd());
+        p2cPipe.writeFd().reset();
+        c2pPipe.readFd().reset();
         while (true) {
             sleep(1);
         }
         _exit(EXIT_FAILURE);
     } else {
-        close(p2cPipe.readFd());
-        close(c2pPipe.writeFd());
+        p2cPipe.readFd().reset();
+        c2pPipe.writeFd().reset();
 
-        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(tf.fd, p2cPipe.writeFd(),
-                                                             c2pPipe.readFd(), QUICK_TIMEOUT_MS));
+        ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(&tffd, &p2cPipe.writeFd(),
+                                                             &c2pPipe.readFd(), QUICK_TIMEOUT_MS));
         EXPECT_TRUE(buffer.timedOut());
         kill(pid, SIGKILL);  // reap the child process
     }
diff --git a/cmds/incidentd/tests/PrivacyBuffer_test.cpp b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
index c7c69a7..5edc0c7 100644
--- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp
+++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
@@ -58,7 +58,8 @@
 
     void writeToFdBuffer(string str) {
         ASSERT_TRUE(WriteStringToFile(str, tf.path));
-        ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, 10000));
+        unique_fd tffd(tf.fd);
+        ASSERT_EQ(NO_ERROR, buffer.read(&tffd, 10000));
         ASSERT_EQ(str.size(), buffer.size());
     }
 
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 50a5ddd..5d6a1d1a 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -17,7 +17,6 @@
 statsd_common_src := \
     ../../core/java/android/os/IStatsCompanionService.aidl \
     ../../core/java/android/os/IStatsManager.aidl \
-    src/stats_log_common.proto \
     src/statsd_config.proto \
     src/FieldValue.cpp \
     src/stats_log_util.cpp \
@@ -224,7 +223,6 @@
 
 LOCAL_SRC_FILES := \
     src/stats_log.proto \
-    src/stats_log_common.proto \
     src/statsd_config.proto \
     src/perfetto/perfetto_config.proto \
     src/atoms.proto
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 8f72a8f..652ec9d 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -270,11 +270,9 @@
     it->second->onDumpReport(dumpTimeStampNs, &proto);
 
     // Fill in UidMap.
-    auto uidMap = mUidMap->getOutput(key);
-    const int uidMapSize = uidMap.ByteSize();
-    char uidMapBuffer[uidMapSize];
-    uidMap.SerializeToArray(&uidMapBuffer[0], uidMapSize);
-    proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP, uidMapBuffer, uidMapSize);
+    vector<uint8_t> uidMap;
+    mUidMap->getOutput(key, &uidMap);
+    proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP, uidMap.data());
 
     // Fill in the timestamps.
     proto.write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_ELAPSED_NANOS,
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index d05c91b..c42514a 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -16,7 +16,6 @@
 #pragma once
 
 #include "config/ConfigKey.h"
-#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h"
 #include "statslog.h"
 
 #include <gtest/gtest_prod.h>
diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h
index ae946d1..15b4a97 100644
--- a/cmds/statsd/src/matchers/matcher_util.h
+++ b/cmds/statsd/src/matchers/matcher_util.h
@@ -24,7 +24,6 @@
 #include <string>
 #include <unordered_map>
 #include <vector>
-#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "packages/UidMap.h"
 #include "stats_util.h"
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index e322ca4..efbe96e 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define DEBUG true  // STOPSHIP if true
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "stats_log_util.h"
@@ -28,10 +28,33 @@
 
 using namespace android;
 
+using android::base::StringPrintf;
+using android::util::FIELD_COUNT_REPEATED;
+using android::util::FIELD_TYPE_BOOL;
+using android::util::FIELD_TYPE_FLOAT;
+using android::util::FIELD_TYPE_INT32;
+using android::util::FIELD_TYPE_INT64;
+using android::util::FIELD_TYPE_MESSAGE;
+using android::util::FIELD_TYPE_STRING;
+using android::util::ProtoOutputStream;
+
 namespace android {
 namespace os {
 namespace statsd {
 
+const int FIELD_ID_SNAPSHOT_PACKAGE_NAME = 1;
+const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION = 2;
+const int FIELD_ID_SNAPSHOT_PACKAGE_UID = 3;
+const int FIELD_ID_SNAPSHOT_TIMESTAMP = 1;
+const int FIELD_ID_SNAPSHOT_PACKAGE_INFO = 2;
+const int FIELD_ID_SNAPSHOTS = 1;
+const int FIELD_ID_CHANGES = 2;
+const int FIELD_ID_CHANGE_DELETION = 1;
+const int FIELD_ID_CHANGE_TIMESTAMP = 2;
+const int FIELD_ID_CHANGE_PACKAGE = 3;
+const int FIELD_ID_CHANGE_UID = 4;
+const int FIELD_ID_CHANGE_VERSION = 5;
+
 UidMap::UidMap() : mBytesUsed(0) {}
 
 UidMap::~UidMap() {}
@@ -93,23 +116,35 @@
         lock_guard<mutex> lock(mMutex);  // Exclusively lock for updates.
 
         mMap.clear();
+        ProtoOutputStream proto;
+        uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+                                      FIELD_ID_SNAPSHOT_PACKAGE_INFO);
         for (size_t j = 0; j < uid.size(); j++) {
-            mMap.insert(make_pair(
-                    uid[j], AppData(string(String8(packageName[j]).string()), versionCode[j])));
+            string package = string(String8(packageName[j]).string());
+            mMap.insert(make_pair(uid[j], AppData(package, versionCode[j])));
+            proto.write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, package);
+            proto.write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION, (int)versionCode[j]);
+            proto.write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, (int)uid[j]);
         }
+        proto.end(token);
 
-        auto snapshot = mOutput.add_snapshots();
-        snapshot->set_elapsed_timestamp_nanos(timestamp);
-        for (size_t j = 0; j < uid.size(); j++) {
-            auto t = snapshot->add_package_info();
-            t->set_name(string(String8(packageName[j]).string()));
-            t->set_version(int(versionCode[j]));
-            t->set_uid(uid[j]);
+        // Copy ProtoOutputStream output to
+        auto iter = proto.data();
+        size_t pos = 0;
+        vector<char> outData(proto.size());
+        while (iter.readBuffer() != NULL) {
+            size_t toRead = iter.currentToRead();
+            std::memcpy(&(outData[pos]), iter.readBuffer(), toRead);
+            pos += toRead;
+            iter.rp()->move(toRead);
         }
-        mBytesUsed += snapshot->ByteSize();
+        SnapshotRecord record(timestamp, outData);
+        mSnapshots.push_back(record);
+
+        mBytesUsed += proto.size() + kBytesTimestampField;
         ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
-        StatsdStats::getInstance().setUidMapSnapshots(mOutput.snapshots_size());
+        StatsdStats::getInstance().setUidMapSnapshots(mSnapshots.size());
         getListenerListCopyLocked(&broadcastList);
     }
     // To avoid invoking callback while holding the internal lock. we get a copy of the listener
@@ -136,16 +171,11 @@
     {
         lock_guard<mutex> lock(mMutex);
 
-        auto log = mOutput.add_changes();
-        log->set_deletion(false);
-        log->set_elapsed_timestamp_nanos(timestamp);
-        log->set_app(appName);
-        log->set_uid(uid);
-        log->set_version(versionCode);
-        mBytesUsed += log->ByteSize();
+        mChanges.emplace_back(false, timestamp, appName, uid, versionCode);
+        mBytesUsed += kBytesChangeRecord;
         ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
-        StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
+        StatsdStats::getInstance().setUidMapChanges(mChanges.size());
 
         auto range = mMap.equal_range(int(uid));
         bool found = false;
@@ -180,17 +210,16 @@
         limit = maxBytesOverride;
     }
     while (mBytesUsed > limit) {
-        VLOG("Bytes used %zu is above limit %zu, need to delete something", mBytesUsed, limit);
-        if (mOutput.snapshots_size() > 0) {
-            auto snapshots = mOutput.mutable_snapshots();
-            snapshots->erase(snapshots->begin());  // Remove first snapshot.
+        ALOGI("Bytes used %zu is above limit %zu, need to delete something", mBytesUsed, limit);
+        if (mSnapshots.size() > 0) {
+            mBytesUsed -= mSnapshots.front().bytes.size() + kBytesTimestampField;
+            mSnapshots.pop_front();
             StatsdStats::getInstance().noteUidMapDropped(1, 0);
-        } else if (mOutput.changes_size() > 0) {
-            auto changes = mOutput.mutable_changes();
-            changes->DeleteSubrange(0, 1);
+        } else if (mChanges.size() > 0) {
+            mBytesUsed -= kBytesChangeRecord;
+            mChanges.pop_front();
             StatsdStats::getInstance().noteUidMapDropped(0, 1);
         }
-        mBytesUsed = mOutput.ByteSize();
     }
 }
 
@@ -217,15 +246,11 @@
     {
         lock_guard<mutex> lock(mMutex);
 
-        auto log = mOutput.add_changes();
-        log->set_deletion(true);
-        log->set_elapsed_timestamp_nanos(timestamp);
-        log->set_app(app);
-        log->set_uid(uid);
-        mBytesUsed += log->ByteSize();
+        mChanges.emplace_back(true, timestamp, app, uid, 0);
+        mBytesUsed += kBytesChangeRecord;
         ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
-        StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
+        StatsdStats::getInstance().setUidMapChanges(mChanges.size());
 
         auto range = mMap.equal_range(int(uid));
         for (auto it = range.first; it != range.second; ++it) {
@@ -281,7 +306,8 @@
 }
 
 void UidMap::clearOutput() {
-    mOutput.Clear();
+    mSnapshots.clear();
+    mChanges.clear();
     // Also update the guardrail trackers.
     StatsdStats::getInstance().setUidMapChanges(0);
     StatsdStats::getInstance().setUidMapSnapshots(1);
@@ -305,59 +331,111 @@
     return mBytesUsed;
 }
 
-UidMapping UidMap::getOutput(const ConfigKey& key) {
-    return getOutput(getElapsedRealtimeNs(), key);
+void UidMap::getOutput(const ConfigKey& key, vector<uint8_t>* outData) {
+    getOutput(getElapsedRealtimeNs(), key, outData);
 }
 
-UidMapping UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key) {
+void UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key, vector<uint8_t>* outData) {
     lock_guard<mutex> lock(mMutex);  // Lock for updates
 
-    auto ret = UidMapping(mOutput);  // Copy that will be returned.
+    ProtoOutputStream proto;
+    for (const ChangeRecord& record : mChanges) {
+        if (record.timestampNs > mLastUpdatePerConfigKey[key]) {
+            uint64_t changesToken =
+                    proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_CHANGES);
+            proto.write(FIELD_TYPE_BOOL | FIELD_ID_CHANGE_DELETION, (bool)record.deletion);
+            proto.write(FIELD_TYPE_INT64 | FIELD_ID_CHANGE_TIMESTAMP,
+                        (long long)record.timestampNs);
+            proto.write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PACKAGE, record.package);
+            proto.write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_UID, (int)record.uid);
+            proto.write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_VERSION, (int)record.version);
+            proto.end(changesToken);
+        }
+    }
+
+    bool atLeastOneSnapshot = false;
+    unsigned int count = 0;
+    for (const SnapshotRecord& record : mSnapshots) {
+        // Ensure that we include at least the latest snapshot.
+        if ((count == mSnapshots.size() - 1 && !atLeastOneSnapshot) ||
+            record.timestampNs > mLastUpdatePerConfigKey[key]) {
+            uint64_t snapshotsToken =
+                    proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SNAPSHOTS);
+            atLeastOneSnapshot = true;
+            count++;
+            proto.write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP,
+                        (long long)record.timestampNs);
+            proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_SNAPSHOT_PACKAGE_INFO, record.bytes.data());
+            proto.end(snapshotsToken);
+        }
+    }
+
     int64_t prevMin = getMinimumTimestampNs();
     mLastUpdatePerConfigKey[key] = timestamp;
     int64_t newMin = getMinimumTimestampNs();
 
-    if (newMin > prevMin) {  // Delete anything possible now that the minimum has moved forward.
+    if (newMin > prevMin) {  // Delete anything possible now that the minimum has
+                             // moved forward.
         int64_t cutoff_nanos = newMin;
-        auto snapshots = mOutput.mutable_snapshots();
-        auto it_snapshots = snapshots->cbegin();
-        while (it_snapshots != snapshots->cend()) {
-            if (it_snapshots->elapsed_timestamp_nanos() < cutoff_nanos) {
-                // it_snapshots points to the following element after erasing.
-                it_snapshots = snapshots->erase(it_snapshots);
-            } else {
-                ++it_snapshots;
+        for (auto it_snapshots = mSnapshots.begin(); it_snapshots != mSnapshots.end();
+             ++it_snapshots) {
+            if (it_snapshots->timestampNs < cutoff_nanos) {
+                mBytesUsed -= it_snapshots->bytes.size() + kBytesTimestampField;
+                mSnapshots.erase(it_snapshots);
             }
         }
-        auto deltas = mOutput.mutable_changes();
-        auto it_deltas = deltas->cbegin();
-        while (it_deltas != deltas->cend()) {
-            if (it_deltas->elapsed_timestamp_nanos() < cutoff_nanos) {
-                // it_snapshots points to the following element after erasing.
-                it_deltas = deltas->erase(it_deltas);
-            } else {
-                ++it_deltas;
+        for (auto it_changes = mChanges.begin(); it_changes != mChanges.end(); ++it_changes) {
+            if (it_changes->timestampNs < cutoff_nanos) {
+                mBytesUsed -= kBytesChangeRecord;
+                mChanges.erase(it_changes);
             }
         }
 
-        if (mOutput.snapshots_size() == 0) {
-            // Produce another snapshot. This results in extra data being uploaded but helps
-            // ensure we can re-construct the UID->app name, versionCode mapping in server.
-            auto snapshot = mOutput.add_snapshots();
-            snapshot->set_elapsed_timestamp_nanos(timestamp);
-            for (auto it : mMap) {
-                auto t = snapshot->add_package_info();
-                t->set_name(it.second.packageName);
-                t->set_version(it.second.versionCode);
-                t->set_uid(it.first);
+        if (mSnapshots.size() == 0) {
+            // Produce another snapshot. This results in extra data being uploaded but
+            // helps ensure we can re-construct the UID->app name, versionCode mapping
+            // in server.
+            ProtoOutputStream proto;
+            uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+                                          FIELD_ID_SNAPSHOT_PACKAGE_INFO);
+            for (const auto& it : mMap) {
+                proto.write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME,
+                            it.second.packageName);
+                proto.write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
+                            (int)it.second.versionCode);
+                proto.write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, (int)it.first);
             }
+            proto.end(token);
+
+            // Copy ProtoOutputStream output to
+            auto iter = proto.data();
+            vector<char> outData(proto.size());
+            size_t pos = 0;
+            while (iter.readBuffer() != NULL) {
+                size_t toRead = iter.currentToRead();
+                std::memcpy(&(outData[pos]), iter.readBuffer(), toRead);
+                pos += toRead;
+                iter.rp()->move(toRead);
+            }
+            mSnapshots.emplace_back(timestamp, outData);
+            mBytesUsed += kBytesTimestampField + outData.size();
         }
     }
-    mBytesUsed = mOutput.ByteSize();  // Compute actual size after potential deletions.
     StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
-    StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
-    StatsdStats::getInstance().setUidMapSnapshots(mOutput.snapshots_size());
-    return ret;
+    StatsdStats::getInstance().setUidMapChanges(mChanges.size());
+    StatsdStats::getInstance().setUidMapSnapshots(mSnapshots.size());
+    if (outData != nullptr) {
+        outData->clear();
+        outData->resize(proto.size());
+        size_t pos = 0;
+        auto iter = proto.data();
+        while (iter.readBuffer() != NULL) {
+            size_t toRead = iter.currentToRead();
+            std::memcpy(&((*outData)[pos]), iter.readBuffer(), toRead);
+            pos += toRead;
+            iter.rp()->move(toRead);
+        }
+    }
 }
 
 void UidMap::printUidMap(FILE* out) const {
@@ -374,7 +452,7 @@
 
     // Ensure there is at least one snapshot available since this configuration also needs to know
     // what all the uid's represent.
-    if (mOutput.snapshots_size() == 0) {
+    if (mSnapshots.size() == 0) {
         sp<IStatsCompanionService> statsCompanion = nullptr;
         // Get statscompanion service from service manager
         const sp<IServiceManager> sm(defaultServiceManager());
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index c41e0aa..b0181f7 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -18,7 +18,6 @@
 
 #include "config/ConfigKey.h"
 #include "config/ConfigListener.h"
-#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h"
 #include "packages/PackageInfoListener.h"
 
 #include <binder/IResultReceiver.h>
@@ -27,6 +26,7 @@
 #include <log/logprint.h>
 #include <stdio.h>
 #include <utils/RefBase.h>
+#include <list>
 #include <mutex>
 #include <set>
 #include <string>
@@ -45,6 +45,45 @@
     AppData(const string& a, const int64_t v) : packageName(a), versionCode(v){};
 };
 
+// When calling getOutput, we retrieve all the ChangeRecords since the last
+// timestamp we called getOutput for this configuration key.
+struct ChangeRecord {
+    const bool deletion;
+    const int64_t timestampNs;
+    const string package;
+    const int32_t uid;
+    const int32_t version;
+
+    ChangeRecord(const bool isDeletion, const int64_t timestampNs, const string& package,
+                 const int32_t uid, const int32_t version)
+        : deletion(isDeletion),
+          timestampNs(timestampNs),
+          package(package),
+          uid(uid),
+          version(version) {
+    }
+};
+
+const unsigned int kBytesChangeRecord = sizeof(struct ChangeRecord);
+
+// Storing the int64 for a timestamp is expected to take 10 bytes (could take
+// less because of varint encoding).
+const unsigned int kBytesTimestampField = 10;
+
+// When calling getOutput, we retrieve all the snapshots since the last
+// timestamp we called getOutput for this configuration key.
+struct SnapshotRecord {
+    const int64_t timestampNs;
+
+    // For performance reasons, we convert the package_info field (which is a
+    // repeated field of PackageInfo messages).
+    vector<char> bytes;
+
+    SnapshotRecord(const int64_t timestampNs, vector<char> bytes)
+        : timestampNs(timestampNs), bytes(bytes) {
+    }
+};
+
 // UidMap keeps track of what the corresponding app name (APK name) and version code for every uid
 // at any given moment. This map must be updated by StatsCompanionService.
 class UidMap : public virtual android::RefBase {
@@ -93,8 +132,10 @@
     // Returns the host uid if it exists. Otherwise, returns the same uid that was passed-in.
     virtual int getHostUidOrSelf(int uid) const;
 
-    // Gets the output. If every config key has received the output, then the output is cleared.
-    UidMapping getOutput(const ConfigKey& key);
+    // Gets all snapshots and changes that have occurred since the last output.
+    // If every config key has received a change or snapshot record, then this
+    // record is deleted.
+    void getOutput(const ConfigKey& key, vector<uint8_t>* outData);
 
     // Forces the output to be cleared. We still generate a snapshot based on the current state.
     // This results in extra data uploaded but helps us reconstruct the uid mapping on the server
@@ -117,7 +158,7 @@
                    const int64_t& versionCode);
     void removeApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid);
 
-    UidMapping getOutput(const int64_t& timestamp, const ConfigKey& key);
+    void getOutput(const int64_t& timestamp, const ConfigKey& key, vector<uint8_t>* outData);
 
     void getListenerListCopyLocked(std::vector<wp<PackageInfoListener>>* output);
 
@@ -133,8 +174,11 @@
     // to the parent uid.
     std::unordered_map<int, int> mIsolatedUidMap;
 
-    // We prepare the output proto as apps are updated, so that we can grab the current output.
-    UidMapping mOutput;
+    // Record the changes that can be provided with the uploads.
+    std::list<ChangeRecord> mChanges;
+
+    // Record the snapshots that can be provided with the uploads.
+    std::list<SnapshotRecord> mSnapshots;
 
     // Metric producers that should be notified if there's an upgrade in any app.
     set<wp<PackageInfoListener>> mSubscribers;
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 0412538..dd3b37c 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -22,7 +22,6 @@
 option java_outer_classname = "StatsLog";
 
 import "frameworks/base/cmds/statsd/src/atoms.proto";
-import "frameworks/base/cmds/statsd/src/stats_log_common.proto";
 
 message DimensionsValue {
   optional int32 field = 1;
@@ -148,6 +147,33 @@
   }
 }
 
+message UidMapping {
+    message PackageInfoSnapshot {
+        message PackageInfo {
+            optional string name = 1;
+
+            optional int64 version = 2;
+
+            optional int32 uid = 3;
+        }
+        optional int64 elapsed_timestamp_nanos = 1;
+
+        repeated PackageInfo package_info = 2;
+    }
+    repeated PackageInfoSnapshot snapshots = 1;
+
+    message Change {
+        optional bool deletion = 1;
+
+        optional int64 elapsed_timestamp_nanos = 2;
+        optional string app = 3;
+        optional int32 uid = 4;
+
+        optional int64 version = 5;
+    }
+    repeated Change changes = 2;
+}
+
 message ConfigMetricsReport {
   repeated StatsLogReport metrics = 1;
 
diff --git a/cmds/statsd/src/stats_log_common.proto b/cmds/statsd/src/stats_log_common.proto
deleted file mode 100644
index c41f31e..0000000
--- a/cmds/statsd/src/stats_log_common.proto
+++ /dev/null
@@ -1,49 +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.
- */
-
-syntax = "proto2";
-
-package android.os.statsd;
-
-option java_package = "com.android.os";
-option java_outer_classname = "StatsLogCommon";
-
-message UidMapping {
-    message PackageInfoSnapshot {
-        message PackageInfo {
-            optional string name = 1;
-
-            optional int64 version = 2;
-
-            optional int32 uid = 3;
-        }
-        optional int64 elapsed_timestamp_nanos = 1;
-
-        repeated PackageInfo package_info = 2;
-    }
-    repeated PackageInfoSnapshot snapshots = 1;
-
-    message Change {
-        optional bool deletion = 1;
-
-        optional int64 elapsed_timestamp_nanos = 2;
-        optional string app = 3;
-        optional int32 uid = 4;
-
-        optional int64 version = 5;
-    }
-    repeated Change changes = 2;
-}
\ No newline at end of file
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index c512e3c..9722050 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -19,7 +19,6 @@
 #include <android/util/ProtoOutputStream.h>
 #include "FieldValue.h"
 #include "HashableDimensionKey.h"
-#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "guardrail/StatsdStats.h"
 
diff --git a/cmds/statsd/src/stats_util.h b/cmds/statsd/src/stats_util.h
index 80e46d6..e0206d1 100644
--- a/cmds/statsd/src/stats_util.h
+++ b/cmds/statsd/src/stats_util.h
@@ -17,7 +17,6 @@
 #pragma once
 
 #include "HashableDimensionKey.h"
-#include "frameworks/base/cmds/statsd/src/stats_log_common.pb.h"
 #include "logd/LogReader.h"
 
 #include <unordered_map>
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index ca656ed..ee7d770 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -174,41 +174,52 @@
     versions.push_back(4);
     versions.push_back(5);
     m.updateMap(1, uids, versions, apps);
-    EXPECT_EQ(1, m.mOutput.snapshots_size());
+    EXPECT_EQ(1U, m.mSnapshots.size());
 
-    UidMapping results = m.getOutput(2, config1);
+    vector<uint8_t> bytes;
+    m.getOutput(2, config1, &bytes);
+    UidMapping results;
+    results.ParseFromArray(bytes.data(), bytes.size());
     EXPECT_EQ(1, results.snapshots_size());
 
     // It should be cleared now
-    EXPECT_EQ(1, m.mOutput.snapshots_size());
-    results = m.getOutput(3, config1);
+    EXPECT_EQ(1U, m.mSnapshots.size());
+    bytes.clear();
+    m.getOutput(2, config1, &bytes);
+    results.ParseFromArray(bytes.data(), bytes.size());
     EXPECT_EQ(1, results.snapshots_size());
 
     // Now add another configuration.
     m.OnConfigUpdated(config2);
     m.updateApp(5, String16(kApp1.c_str()), 1000, 40);
-    EXPECT_EQ(1, m.mOutput.changes_size());
-    results = m.getOutput(6, config1);
+    EXPECT_EQ(1U, m.mChanges.size());
+    bytes.clear();
+    m.getOutput(6, config1, &bytes);
+    results.ParseFromArray(bytes.data(), bytes.size());
     EXPECT_EQ(1, results.snapshots_size());
     EXPECT_EQ(1, results.changes_size());
-    EXPECT_EQ(1, m.mOutput.changes_size());
+    EXPECT_EQ(1U, m.mChanges.size());
 
     // Add another delta update.
     m.updateApp(7, String16(kApp2.c_str()), 1001, 41);
-    EXPECT_EQ(2, m.mOutput.changes_size());
+    EXPECT_EQ(2U, m.mChanges.size());
 
     // We still can't remove anything.
-    results = m.getOutput(8, config1);
+    bytes.clear();
+    m.getOutput(8, config1, &bytes);
+    results.ParseFromArray(bytes.data(), bytes.size());
     EXPECT_EQ(1, results.snapshots_size());
-    EXPECT_EQ(2, results.changes_size());
-    EXPECT_EQ(2, m.mOutput.changes_size());
+    EXPECT_EQ(1, results.changes_size());
+    EXPECT_EQ(2U, m.mChanges.size());
 
-    results = m.getOutput(9, config2);
+    bytes.clear();
+    m.getOutput(9, config2, &bytes);
+    results.ParseFromArray(bytes.data(), bytes.size());
     EXPECT_EQ(1, results.snapshots_size());
     EXPECT_EQ(2, results.changes_size());
     // At this point both should be cleared.
-    EXPECT_EQ(1, m.mOutput.snapshots_size());
-    EXPECT_EQ(0, m.mOutput.changes_size());
+    EXPECT_EQ(1U, m.mSnapshots.size());
+    EXPECT_EQ(0U, m.mChanges.size());
 }
 
 TEST(UidMapTest, TestMemoryComputed) {
@@ -231,10 +242,11 @@
     m.updateApp(3, String16(kApp1.c_str()), 1000, 40);
     EXPECT_TRUE(m.mBytesUsed > snapshot_bytes);
 
-    m.getOutput(2, config1);
+    vector<uint8_t> bytes;
+    m.getOutput(2, config1, &bytes);
     size_t prevBytes = m.mBytesUsed;
 
-    m.getOutput(4, config1);
+    m.getOutput(4, config1, &bytes);
     EXPECT_TRUE(m.mBytesUsed < prevBytes);
 }
 
@@ -256,17 +268,17 @@
         versions.push_back(1);
     }
     m.updateMap(1, uids, versions, apps);
-    EXPECT_EQ(1, m.mOutput.snapshots_size());
+    EXPECT_EQ(1U, m.mSnapshots.size());
 
     m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2);
-    EXPECT_EQ(1, m.mOutput.snapshots_size());
-    EXPECT_EQ(1, m.mOutput.changes_size());
+    EXPECT_EQ(1U, m.mSnapshots.size());
+    EXPECT_EQ(1U, m.mChanges.size());
 
     // Now force deletion by limiting the memory to hold one delta change.
     m.maxBytesOverride = 80; // Since the app string alone requires >45 characters.
     m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4);
-    EXPECT_EQ(0, m.mOutput.snapshots_size());
-    EXPECT_EQ(1, m.mOutput.changes_size());
+    EXPECT_EQ(0U, m.mSnapshots.size());
+    EXPECT_EQ(1U, m.mChanges.size());
 }
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 9f71f26..99d871e 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -11,6 +11,7 @@
 Landroid/app/ActivityManager;->getMaxRecentTasksStatic()I
 Landroid/app/ActivityManager;->getService()Landroid/app/IActivityManager;
 Landroid/app/ActivityManager;->IActivityManagerSingleton:Landroid/util/Singleton;
+Landroid/app/ActivityManager;->isHighEndGfx()Z
 Landroid/app/ActivityManager;->isLowRamDeviceStatic()Z
 Landroid/app/ActivityManager;->isUserRunning(I)Z
 Landroid/app/ActivityManager;->mContext:Landroid/content/Context;
@@ -96,6 +97,7 @@
 Landroid/app/ActivityThread;->mNumVisibleActivities:I
 Landroid/app/ActivityThread;->mPackages:Landroid/util/ArrayMap;
 Landroid/app/ActivityThread;->mProviderMap:Landroid/util/ArrayMap;
+Landroid/app/ActivityThread;->mResourcePackages:Landroid/util/ArrayMap;
 Landroid/app/ActivityThread;->mServices:Landroid/util/ArrayMap;
 Landroid/app/ActivityThread;->performNewIntents(Landroid/os/IBinder;Ljava/util/List;Z)V
 Landroid/app/ActivityThread;->performStopActivity(Landroid/os/IBinder;ZLjava/lang/String;)V
@@ -116,6 +118,7 @@
 Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;ZI)V
 Landroid/app/admin/DevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;Z)V
 Landroid/app/admin/DevicePolicyManager;->throwIfParentInstance(Ljava/lang/String;)V
+Landroid/app/admin/DevicePolicyManager;->setDefaultSmsApplication(Landroid/content/ComponentName;Ljava/lang/String;)V
 Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I
 Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I
 Landroid/app/admin/SecurityLog$SecurityEvent;-><init>([B)V
@@ -230,6 +233,7 @@
 Landroid/app/IApplicationThread;->scheduleTrimMemory(I)V
 Landroid/app/INotificationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/INotificationManager;
 Landroid/app/INotificationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/app/Instrumentation;->execStartActivities(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Landroid/app/Activity;[Landroid/content/Intent;Landroid/os/Bundle;)V
 Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Landroid/app/Activity;Landroid/content/Intent;ILandroid/os/Bundle;)Landroid/app/Instrumentation$ActivityResult;
 Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Ljava/lang/String;Landroid/content/Intent;ILandroid/os/Bundle;)Landroid/app/Instrumentation$ActivityResult;
 Landroid/app/Instrumentation;->execStartActivity(Landroid/content/Context;Landroid/os/IBinder;Landroid/os/IBinder;Ljava/lang/String;Landroid/content/Intent;ILandroid/os/Bundle;Landroid/os/UserHandle;)Landroid/app/Instrumentation$ActivityResult;
@@ -309,6 +313,7 @@
 Landroid/app/trust/ITrustManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/usage/UsageStatsManager;->mService:Landroid/app/usage/IUsageStatsManager;
 Landroid/app/usage/UsageStats;->mLastEvent:I
+Landroid/app/usage/UsageStats;->mTotalTimeInForeground:J
 Landroid/app/WallpaperColors;->getColorHints()I
 Landroid/app/WallpaperManager;->getBitmap()Landroid/graphics/Bitmap;
 Landroid/app/WallpaperManager;->getBitmap(Z)Landroid/graphics/Bitmap;
@@ -345,6 +350,7 @@
 Landroid/content/BroadcastReceiver;->setPendingResult(Landroid/content/BroadcastReceiver$PendingResult;)V
 Landroid/content/ContentProviderClient;->mContentProvider:Landroid/content/IContentProvider;
 Landroid/content/ContentProviderClient;->mPackageName:Ljava/lang/String;
+Landroid/content/ContentProvider;->coerceToLocalContentProvider(Landroid/content/IContentProvider;)Landroid/content/ContentProvider;
 Landroid/content/ContentProvider;->mContext:Landroid/content/Context;
 Landroid/content/ContentProvider;->mPathPermissions:[Landroid/content/pm/PathPermission;
 Landroid/content/ContentProvider;->mReadPermission:Ljava/lang/String;
@@ -354,11 +360,19 @@
 Landroid/content/ContentProviderOperation;->TYPE_DELETE:I
 Landroid/content/ContentProviderOperation;->TYPE_INSERT:I
 Landroid/content/ContentProviderOperation;->TYPE_UPDATE:I
+Landroid/content/ContentProvider;->setAppOps(II)V
+Landroid/content/ContentResolver;->acquireExistingProvider(Landroid/content/Context;Ljava/lang/String;)Landroid/content/IContentProvider;
+Landroid/content/ContentResolver;->acquireProvider(Landroid/content/Context;Ljava/lang/String;)Landroid/content/IContentProvider;
 Landroid/content/ContentResolver;->acquireProvider(Landroid/net/Uri;)Landroid/content/IContentProvider;
+Landroid/content/ContentResolver;->acquireProvider(Ljava/lang/String;)Landroid/content/IContentProvider;
+Landroid/content/ContentResolver;->acquireUnstableProvider(Landroid/content/Context;Ljava/lang/String;)Landroid/content/IContentProvider;
 Landroid/content/ContentResolver;->getContentService()Landroid/content/IContentService;
 Landroid/content/ContentResolver;->getSyncStatus(Landroid/accounts/Account;Ljava/lang/String;)Landroid/content/SyncStatusInfo;
 Landroid/content/ContentResolver;->mContext:Landroid/content/Context;
 Landroid/content/ContentResolver;->mPackageName:Ljava/lang/String;
+Landroid/content/ContentResolver;->releaseProvider(Landroid/content/IContentProvider;)Z
+Landroid/content/ContentResolver;->releaseUnstableProvider(Landroid/content/IContentProvider;)Z
+Landroid/content/ContentResolver;->unstableProviderDied(Landroid/content/IContentProvider;)V
 Landroid/content/ContentValues;-><init>(Ljava/util/HashMap;)V
 Landroid/content/ContentValues;->mValues:Ljava/util/HashMap;
 Landroid/content/Context;->getSharedPrefsFile(Ljava/lang/String;)Ljava/io/File;
@@ -391,6 +405,7 @@
 Landroid/content/pm/ApplicationInfo;->scanPublicSourceDir:Ljava/lang/String;
 Landroid/content/pm/ApplicationInfo;->scanSourceDir:Ljava/lang/String;
 Landroid/content/pm/ApplicationInfo;->secondaryNativeLibraryDir:Ljava/lang/String;
+Landroid/content/pm/ComponentInfo;->getComponentName()Landroid/content/ComponentName;
 Landroid/content/pm/IPackageManager;->getInstallLocation()I
 Landroid/content/pm/IPackageManager;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo;
 Landroid/content/pm/IPackageManager;->setApplicationEnabledSetting(Ljava/lang/String;IIILjava/lang/String;)V
@@ -404,6 +419,7 @@
 Landroid/content/pm/LauncherActivityInfo;->mActivityInfo:Landroid/content/pm/ActivityInfo;
 Landroid/content/pm/LauncherApps;->mPm:Landroid/content/pm/PackageManager;
 Landroid/content/pm/LauncherApps;->startShortcut(Ljava/lang/String;Ljava/lang/String;Landroid/graphics/Rect;Landroid/os/Bundle;I)V
+Landroid/content/pm/PackageItemInfo;->setForceSafeLabels(Z)V
 Landroid/content/pm/PackageManager;->buildRequestPermissionsIntent([Ljava/lang/String;)Landroid/content/Intent;
 Landroid/content/pm/PackageManager;->freeStorageAndNotify(JLandroid/content/pm/IPackageDataObserver;)V
 Landroid/content/pm/PackageManager;->freeStorageAndNotify(Ljava/lang/String;JLandroid/content/pm/IPackageDataObserver;)V
@@ -502,6 +518,7 @@
 Landroid/content/res/Resources;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V
 Landroid/content/res/Resources;->updateSystemConfiguration(Landroid/content/res/Configuration;Landroid/util/DisplayMetrics;Landroid/content/res/CompatibilityInfo;)V
 Landroid/content/res/StringBlock;-><init>(JZ)V
+Landroid/content/res/TypedArray;->extractThemeAttrs()[I
 Landroid/content/res/TypedArray;->getNonConfigurationString(II)Ljava/lang/String;
 Landroid/content/res/TypedArray;->getValueAt(ILandroid/util/TypedValue;)Z
 Landroid/content/res/TypedArray;->mAssets:Landroid/content/res/AssetManager;
@@ -518,6 +535,7 @@
 Landroid/content/res/XmlBlock;->newParser()Landroid/content/res/XmlResourceParser;
 Landroid/content/res/XmlBlock$Parser;->mBlock:Landroid/content/res/XmlBlock;
 Landroid/content/res/XmlBlock$Parser;->mParseState:J
+Landroid/content/SearchRecentSuggestionsProvider;->mSuggestionProjection:[Ljava/lang/String;
 Landroid/content/SyncStatusInfo;->lastSuccessTime:J
 Landroid/database/AbstractCursor;->mExtras:Landroid/os/Bundle;
 Landroid/database/AbstractCursor;->mNotifyUri:Landroid/net/Uri;
@@ -556,6 +574,7 @@
 Landroid/graphics/Camera;->native_instance:J
 Landroid/graphics/Canvas;-><init>(J)V
 Landroid/graphics/Canvas;->release()V
+Landroid/graphics/ColorMatrixColorFilter;->setColorMatrix(Landroid/graphics/ColorMatrix;)V
 Landroid/graphics/drawable/AnimatedImageDrawable;->onAnimationEnd()V
 Landroid/graphics/drawable/AnimatedStateListDrawable$AnimatedStateListState;->mStateIds:Landroid/util/SparseIntArray;
 Landroid/graphics/drawable/AnimatedStateListDrawable$AnimatedStateListState;->mTransitions:Landroid/util/LongSparseLongArray;
@@ -622,6 +641,8 @@
 Landroid/graphics/NinePatch$InsetStruct;-><init>(IIIIIIIIFIF)V
 Landroid/graphics/NinePatch;->mBitmap:Landroid/graphics/Bitmap;
 Landroid/graphics/Picture;->mNativePicture:J
+Landroid/graphics/PorterDuffColorFilter;->setColor(I)V
+Landroid/graphics/PorterDuffColorFilter;->setMode(Landroid/graphics/PorterDuff$Mode;)V
 Landroid/graphics/Region;-><init>(JI)V
 Landroid/graphics/Region;->mNativeRegion:J
 Landroid/graphics/SurfaceTexture;->mFrameAvailableListener:J
@@ -629,6 +650,7 @@
 Landroid/graphics/SurfaceTexture;->mSurfaceTexture:J
 Landroid/graphics/SurfaceTexture;->nativeDetachFromGLContext()I
 Landroid/graphics/SurfaceTexture;->postEventFromNative(Ljava/lang/ref/WeakReference;)V
+Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;II)Landroid/graphics/Typeface;
 Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;Ljava/lang/String;II)Landroid/graphics/Typeface;
 Landroid/graphics/Typeface;->mStyle:I
 Landroid/graphics/Typeface;->sDefaults:[Landroid/graphics/Typeface;
@@ -694,8 +716,13 @@
 Landroid/hardware/usb/UsbManager;->setCurrentFunction(Ljava/lang/String;Z)V
 Landroid/hardware/usb/UsbManager;->setPortRoles(Landroid/hardware/usb/UsbPort;II)V
 Landroid/hardware/usb/UsbPortStatus;->getCurrentDataRole()I
+Landroid/hardware/usb/UsbPortStatus;->getCurrentMode()I
+Landroid/hardware/usb/UsbPortStatus;->getCurrentPowerRole()I
+Landroid/hardware/usb/UsbPortStatus;->getSupportedRoleCombinations()I
 Landroid/hardware/usb/UsbPortStatus;->isConnected()Z
 Landroid/hardware/usb/UsbPortStatus;->isRoleCombinationSupported(II)Z
+Landroid/hardware/usb/UsbRequest;->mBuffer:Ljava/nio/ByteBuffer;
+Landroid/hardware/usb/UsbRequest;->mLength:I
 Landroid/hardware/usb/UsbRequest;->mNativeContext:J
 Landroid/icu/impl/CurrencyData;-><init>()V
 Landroid/icu/impl/number/DecimalFormatProperties;->readObject(Ljava/io/ObjectInputStream;)V
@@ -773,7 +800,9 @@
 Landroid/media/AudioFormat;->mSampleRate:I
 Landroid/media/audiofx/AudioEffect;->command(I[B[B)I
 Landroid/media/audiofx/AudioEffect;->getParameter([I[B)I
+Landroid/media/audiofx/AudioEffect;->getParameter([I[I)I
 Landroid/media/audiofx/AudioEffect;-><init>(Ljava/util/UUID;Ljava/util/UUID;II)V
+Landroid/media/audiofx/AudioEffect;->setParameter([I[S)I
 Landroid/media/AudioGainConfig;-><init>(ILandroid/media/AudioGain;II[II)V
 Landroid/media/AudioGainConfig;->mChannelMask:I
 Landroid/media/AudioGainConfig;->mIndex:I
@@ -833,6 +862,7 @@
 Landroid/media/AudioSystem;->getPrimaryOutputSamplingRate()I
 Landroid/media/AudioSystem;->recordingCallbackFromNative(IIII[I)V
 Landroid/media/AudioSystem;->setDeviceConnectionState(IILjava/lang/String;Ljava/lang/String;)I
+Landroid/media/AudioSystem;->setErrorCallback(Landroid/media/AudioSystem$ErrorCallback;)V
 Landroid/media/AudioTrack;->deferred_connect(J)V
 Landroid/media/AudioTrack;->getLatency()I
 Landroid/media/AudioTrack;->mJniData:J
@@ -840,6 +870,9 @@
 Landroid/media/AudioTrack;->mStreamType:I
 Landroid/media/AudioTrack;->native_release()V
 Landroid/media/AudioTrack;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
+Landroid/media/IAudioService;->getStreamMaxVolume(I)I
+Landroid/media/IAudioService;->getStreamVolume(I)I
+Landroid/media/IAudioService;->setStreamVolume(IIILjava/lang/String;)V
 Landroid/media/IAudioService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IAudioService;
 Landroid/media/IAudioService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/media/JetPlayer;->mNativePlayerInJavaObj:J
@@ -894,6 +927,7 @@
 Landroid/media/RemoteDisplay;->notifyDisplayError(I)V
 Landroid/media/RingtoneManager;->getRingtone(Landroid/content/Context;Landroid/net/Uri;I)Landroid/media/Ringtone;
 Landroid/media/session/MediaSessionLegacyHelper;->getHelper(Landroid/content/Context;)Landroid/media/session/MediaSessionLegacyHelper;
+Landroid/media/session/MediaSession;->mCallback:Landroid/media/session/MediaSession$CallbackMessageHandler;
 Landroid/media/soundtrigger/SoundTriggerDetector$EventPayload;->getCaptureSession()Ljava/lang/Integer;
 Landroid/media/soundtrigger/SoundTriggerDetector$EventPayload;->getData()[B
 Landroid/media/soundtrigger/SoundTriggerManager;->loadSoundModel(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;)I
@@ -954,6 +988,7 @@
 Landroid/net/NetworkPolicyManager;->mService:Landroid/net/INetworkPolicyManager;
 Landroid/net/NetworkStats;->capacity:I
 Landroid/net/NetworkStats;->defaultNetwork:[I
+Landroid/net/NetworkStatsHistory$Entry;->rxBytes:J
 Landroid/net/NetworkStats;->iface:[Ljava/lang/String;
 Landroid/net/NetworkStats;->metered:[I
 Landroid/net/NetworkStats;->operations:[J
@@ -966,7 +1001,9 @@
 Landroid/net/NetworkStats;->txBytes:[J
 Landroid/net/NetworkStats;->txPackets:[J
 Landroid/net/NetworkStats;->uid:[I
+Landroid/net/NetworkTemplate;->buildTemplateWifi()Landroid/net/NetworkTemplate;
 Landroid/net/ProxyInfo;-><init>(Ljava/lang/String;ILjava/lang/String;)V
+Landroid/net/SntpClient;-><init>()V
 Landroid/net/SSLCertificateSocketFactory;->castToOpenSSLSocket(Ljava/net/Socket;)Lcom/android/org/conscrypt/OpenSSLSocketImpl;
 Landroid/net/SSLCertificateSocketFactory;->getAlpnSelectedProtocol(Ljava/net/Socket;)[B
 Landroid/net/SSLCertificateSocketFactory;->getDelegate()Ljavax/net/ssl/SSLSocketFactory;
@@ -1043,6 +1080,7 @@
 Landroid/os/BatteryStats;->getUidStats()Landroid/util/SparseArray;
 Landroid/os/BatteryStats$HistoryItem;->states2:I
 Landroid/os/BatteryStats;->NUM_DATA_CONNECTION_TYPES:I
+Landroid/os/BatteryStats;->startIteratingHistoryLocked()Z
 Landroid/os/BatteryStats$Timer;->getTotalTimeLocked(JI)J
 Landroid/os/BatteryStats$Uid;->getFullWifiLockTime(JI)J
 Landroid/os/BatteryStats$Uid;->getProcessStats()Landroid/util/ArrayMap;
@@ -1107,6 +1145,7 @@
 Landroid/os/FileUtils;->stringToFile(Ljava/lang/String;Ljava/lang/String;)V
 Landroid/os/Handler;->getIMessenger()Landroid/os/IMessenger;
 Landroid/os/Handler;->hasCallbacks(Ljava/lang/Runnable;)Z
+Landroid/os/Handler;-><init>(Z)V
 Landroid/os/Handler;->mCallback:Landroid/os/Handler$Callback;
 Landroid/os/Handler;->mMessenger:Landroid/os/IMessenger;
 Landroid/os/HwParcel;-><init>(Z)V
@@ -1220,14 +1259,31 @@
 Landroid/os/UpdateLock;->release()V
 Landroid/os/UpdateLock;->TIMESTAMP:Ljava/lang/String;
 Landroid/os/UpdateLock;->UPDATE_LOCK_CHANGED:Ljava/lang/String;
+Landroid/os/UserHandle;->AID_APP_END:I
+Landroid/os/UserHandle;->AID_APP_START:I
+Landroid/os/UserHandle;->AID_CACHE_GID_START:I
+Landroid/os/UserHandle;->AID_ROOT:I
+Landroid/os/UserHandle;->AID_SHARED_GID_START:I
 Landroid/os/UserHandle;->ALL:Landroid/os/UserHandle;
+Landroid/os/UserHandle;->CURRENT:Landroid/os/UserHandle;
+Landroid/os/UserHandle;->CURRENT_OR_SELF:Landroid/os/UserHandle;
+Landroid/os/UserHandle;->ERR_GID:I
 Landroid/os/UserHandle;->getAppIdFromSharedAppGid(I)I
 Landroid/os/UserHandle;->getCallingUserId()I
 Landroid/os/UserHandle;->getUid(II)I
 Landroid/os/UserHandle;->getUserId(I)I
 Landroid/os/UserHandle;-><init>(I)V
+Landroid/os/UserHandle;->MU_ENABLED:Z
+Landroid/os/UserHandle;->OWNER:Landroid/os/UserHandle;
 Landroid/os/UserHandle;->PER_USER_RANGE:I
+Landroid/os/UserHandle;->SYSTEM:Landroid/os/UserHandle;
+Landroid/os/UserHandle;->USER_ALL:I
+Landroid/os/UserHandle;->USER_CURRENT:I
+Landroid/os/UserHandle;->USER_CURRENT_OR_SELF:I
+Landroid/os/UserHandle;->USER_NULL:I
 Landroid/os/UserHandle;->USER_OWNER:I
+Landroid/os/UserHandle;->USER_SERIAL_SYSTEM:I
+Landroid/os/UserHandle;->USER_SYSTEM:I
 Landroid/os/UserManager;->getBadgedLabelForUser(Ljava/lang/CharSequence;Landroid/os/UserHandle;)Ljava/lang/CharSequence;
 Landroid/os/UserManager;->get(Landroid/content/Context;)Landroid/os/UserManager;
 Landroid/os/UserManager;->getMaxSupportedUsers()I
@@ -1238,10 +1294,23 @@
 Landroid/os/UserManager;->getUserInfo(I)Landroid/content/pm/UserInfo;
 Landroid/os/UserManager;->getUserSerialNumber(I)I
 Landroid/os/UserManager;->getUsers()Ljava/util/List;
+Landroid/os/UserManager;->getUserStartRealtime()J
+Landroid/os/UserManager;->getUserUnlockRealtime()J
 Landroid/os/UserManager;->hasBaseUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
 Landroid/os/UserManager;->isLinkedUser()Z
 Landroid/os/UserManager;->isUserUnlocked(I)Z
+Landroid/os/VintfObject;->getHalNamesAndVersions()[Ljava/lang/String;
+Landroid/os/VintfObject;->getSepolicyVersion()Ljava/lang/String;
+Landroid/os/VintfObject;->getTargetFrameworkCompatibilityMatrixVersion()Ljava/lang/Long;
+Landroid/os/VintfObject;->getVndkSnapshots()Ljava/util/Map;
 Landroid/os/VintfObject;->report()[Ljava/lang/String;
+Landroid/os/VintfRuntimeInfo;->getCpuInfo()Ljava/lang/String;
+Landroid/os/VintfRuntimeInfo;->getHardwareId()Ljava/lang/String;
+Landroid/os/VintfRuntimeInfo;->getKernelVersion()Ljava/lang/String;
+Landroid/os/VintfRuntimeInfo;->getNodeName()Ljava/lang/String;
+Landroid/os/VintfRuntimeInfo;->getOsName()Ljava/lang/String;
+Landroid/os/VintfRuntimeInfo;->getOsRelease()Ljava/lang/String;
+Landroid/os/VintfRuntimeInfo;->getOsVersion()Ljava/lang/String;
 Landroid/os/WorkSource;->add(ILjava/lang/String;)Z
 Landroid/os/WorkSource;->add(I)Z
 Landroid/os/WorkSource;->addReturningNewbs(Landroid/os/WorkSource;)Landroid/os/WorkSource;
@@ -1296,6 +1365,8 @@
 Landroid/provider/Browser;->deleteFromHistory(Landroid/content/ContentResolver;Ljava/lang/String;)V
 Landroid/provider/Browser;->getVisitedHistory(Landroid/content/ContentResolver;)[Ljava/lang/String;
 Landroid/provider/Browser;->sendString(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V
+Landroid/provider/CalendarContract$CalendarAlerts;->findNextAlarmTime(Landroid/content/ContentResolver;J)J
+Landroid/provider/CalendarContract$CalendarAlerts;->rescheduleMissedAlarms(Landroid/content/ContentResolver;Landroid/content/Context;Landroid/app/AlarmManager;)V
 Landroid/provider/Settings$ContentProviderHolder;->mContentProvider:Landroid/content/IContentProvider;
 Landroid/provider/Settings$Global;->ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED:Ljava/lang/String;
 Landroid/provider/Settings$Global;->PACKAGE_VERIFIER_ENABLE:Ljava/lang/String;
@@ -1569,6 +1640,60 @@
 Landroid/service/wallpaper/WallpaperService$Engine;->setFixedSizeAllowed(Z)V
 Landroid/speech/tts/TextToSpeech;->getCurrentEngine()Ljava/lang/String;
 Landroid/system/Int32Ref;->value:I
+Landroid/system/OsConstants;->AF_NETLINK:I
+Landroid/system/OsConstants;->AF_PACKET:I
+Landroid/system/OsConstants;->ARPHRD_ETHER:I
+Landroid/system/OsConstants;->ARPHRD_LOOPBACK:I
+Landroid/system/OsConstants;->CAP_TO_INDEX(I)I
+Landroid/system/OsConstants;->CAP_TO_MASK(I)I
+Landroid/system/OsConstants;->ENONET:I
+Landroid/system/OsConstants;->ETH_P_ALL:I
+Landroid/system/OsConstants;->ETH_P_ARP:I
+Landroid/system/OsConstants;->ETH_P_IP:I
+Landroid/system/OsConstants;->ETH_P_IPV6:I
+Landroid/system/OsConstants;->EUSERS:I
+Landroid/system/OsConstants;->ICMP6_ECHO_REPLY:I
+Landroid/system/OsConstants;->ICMP6_ECHO_REQUEST:I
+Landroid/system/OsConstants;->ICMP_ECHO:I
+Landroid/system/OsConstants;->ICMP_ECHOREPLY:I
+Landroid/system/OsConstants;->initConstants()V
+Landroid/system/OsConstants;-><init>()V
+Landroid/system/OsConstants;->IP_MULTICAST_ALL:I
+Landroid/system/OsConstants;->IP_RECVTOS:I
+Landroid/system/OsConstants;->_LINUX_CAPABILITY_VERSION_3:I
+Landroid/system/OsConstants;->MAP_POPULATE:I
+Landroid/system/OsConstants;->NETLINK_NETFILTER:I
+Landroid/system/OsConstants;->NETLINK_ROUTE:I
+Landroid/system/OsConstants;->O_DIRECT:I
+Landroid/system/OsConstants;->placeholder()I
+Landroid/system/OsConstants;->PR_CAP_AMBIENT:I
+Landroid/system/OsConstants;->PR_CAP_AMBIENT_RAISE:I
+Landroid/system/OsConstants;->RLIMIT_NOFILE:I
+Landroid/system/OsConstants;->RTMGRP_IPV4_IFADDR:I
+Landroid/system/OsConstants;->RTMGRP_IPV4_MROUTE:I
+Landroid/system/OsConstants;->RTMGRP_IPV4_ROUTE:I
+Landroid/system/OsConstants;->RTMGRP_IPV4_RULE:I
+Landroid/system/OsConstants;->RTMGRP_IPV6_IFADDR:I
+Landroid/system/OsConstants;->RTMGRP_IPV6_IFINFO:I
+Landroid/system/OsConstants;->RTMGRP_IPV6_MROUTE:I
+Landroid/system/OsConstants;->RTMGRP_IPV6_PREFIX:I
+Landroid/system/OsConstants;->RTMGRP_IPV6_ROUTE:I
+Landroid/system/OsConstants;->RTMGRP_LINK:I
+Landroid/system/OsConstants;->RTMGRP_NEIGH:I
+Landroid/system/OsConstants;->RTMGRP_NOTIFY:I
+Landroid/system/OsConstants;->RTMGRP_TC:I
+Landroid/system/OsConstants;->SO_DOMAIN:I
+Landroid/system/OsConstants;->SO_PROTOCOL:I
+Landroid/system/OsConstants;->SPLICE_F_MORE:I
+Landroid/system/OsConstants;->SPLICE_F_MOVE:I
+Landroid/system/OsConstants;->SPLICE_F_NONBLOCK:I
+Landroid/system/OsConstants;->TIOCOUTQ:I
+Landroid/system/OsConstants;->UDP_ENCAP_ESPINUDP:I
+Landroid/system/OsConstants;->UDP_ENCAP_ESPINUDP_NON_IKE:I
+Landroid/system/OsConstants;->UDP_ENCAP:I
+Landroid/system/OsConstants;->UNIX_PATH_MAX:I
+Landroid/system/OsConstants;->XATTR_CREATE:I
+Landroid/system/OsConstants;->XATTR_REPLACE:I
 Landroid/system/StructTimeval;->fromMillis(J)Landroid/system/StructTimeval;
 Landroid/telecom/TelecomManager;->EXTRA_IS_HANDOVER:Ljava/lang/String;
 Landroid/telecom/TelecomManager;->getUserSelectedOutgoingPhoneAccount()Landroid/telecom/PhoneAccountHandle;
@@ -1591,6 +1716,7 @@
 Landroid/telephony/SignalStrength;->getLteRsrq()I
 Landroid/telephony/SignalStrength;->getLteRssnr()I
 Landroid/telephony/SignalStrength;->getLteSignalStrength()I
+Landroid/telephony/SignalStrength;-><init>()V
 Landroid/telephony/SignalStrength;->mGsmBitErrorRate:I
 Landroid/telephony/SignalStrength;->mGsmSignalStrength:I
 Landroid/telephony/SignalStrength;->mLteCqi:I
@@ -1726,7 +1852,9 @@
 Landroid/util/NtpTrustedTime;->getCachedNtpTimeReference()J
 Landroid/util/NtpTrustedTime;->getInstance(Landroid/content/Context;)Landroid/util/NtpTrustedTime;
 Landroid/util/NtpTrustedTime;->hasCache()Z
+Landroid/util/Pools$SimplePool;->mPool:[Ljava/lang/Object;
 Landroid/util/Pools$SynchronizedPool;->acquire()Ljava/lang/Object;
+Landroid/util/Pools$SynchronizedPool;-><init>(I)V
 Landroid/util/Rational;->mDenominator:I
 Landroid/util/Rational;->mNumerator:I
 Landroid/util/Rational;->readObject(Ljava/io/ObjectInputStream;)V
@@ -1909,6 +2037,7 @@
 Landroid/view/View;->fitsSystemWindows()Z
 Landroid/view/View;->getAccessibilityDelegate()Landroid/view/View$AccessibilityDelegate;
 Landroid/view/View;->getListenerInfo()Landroid/view/View$ListenerInfo;
+Landroid/view/View;->getLocationOnScreen()[I
 Landroid/view/View;->getTransitionAlpha()F
 Landroid/view/View;->getViewRootImpl()Landroid/view/ViewRootImpl;
 Landroid/view/ViewGroup;->dispatchViewAdded(Landroid/view/View;)V
@@ -2293,6 +2422,7 @@
 Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setContactUri(Ljava/lang/String;)V
 Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setFeatureTag(Ljava/lang/String;)V
 Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setTimestamp(Ljava/lang/String;)V
+Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V
 Lcom/android/internal/app/AlertController$RecycleListView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
 Lcom/android/internal/app/IAppOpsService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IAppOpsService;
 Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
@@ -2300,6 +2430,7 @@
 Lcom/android/internal/app/IBatteryStats;->getStatistics()[B
 Lcom/android/internal/app/IBatteryStats$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IBatteryStats;
 Lcom/android/internal/app/IBatteryStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Lcom/android/internal/app/IVoiceInteractionManagerService;->getKeyphraseSoundModel(ILjava/lang/String;)Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;
 Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService;
 Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z
 Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
@@ -2592,6 +2723,7 @@
 Ldalvik/system/DexFile;->loadClassBinaryName(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/util/List;)Ljava/lang/Class;
 Ldalvik/system/DexFile;->mCookie:Ljava/lang/Object;
 Ldalvik/system/DexFile;->mFileName:Ljava/lang/String;
+Ldalvik/system/DexFile;->mInternalCookie:Ljava/lang/Object;
 Ldalvik/system/DexFile;->openDexFile(Ljava/lang/String;Ljava/lang/String;ILjava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ljava/lang/Object;
 Ldalvik/system/DexPathList;->addDexPath(Ljava/lang/String;Ljava/io/File;)V
 Ldalvik/system/DexPathList;->dexElements:[Ldalvik/system/DexPathList$Element;
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index ed2aaf9..5fbe5b3 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -16,31 +16,31 @@
 
 package android.app.admin;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
 import android.annotation.NonNull;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
-import android.content.res.Resources.NotFoundException;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Printer;
 import android.util.SparseArray;
 import android.util.Xml;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -266,6 +266,12 @@
      */
     int mUsesPolicies;
 
+    /**
+     * Whether this administrator can be a target in an ownership transfer.
+     *
+     * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
+     */
+    boolean mSupportsTransferOwnership;
 
     /**
      * Constructor.
@@ -347,6 +353,12 @@
                                     + getComponent() + ": " + policyName);
                         }
                     }
+                } else if (tagName.equals("support-transfer-ownership")) {
+                    if (parser.next() != XmlPullParser.END_TAG) {
+                        throw new XmlPullParserException(
+                                "support-transfer-ownership tag must be empty.");
+                    }
+                    mSupportsTransferOwnership = true;
                 }
             }
         } catch (NameNotFoundException e) {
@@ -360,6 +372,7 @@
     DeviceAdminInfo(Parcel source) {
         mActivityInfo = ActivityInfo.CREATOR.createFromParcel(source);
         mUsesPolicies = source.readInt();
+        mSupportsTransferOwnership = source.readBoolean();
     }
 
     /**
@@ -458,6 +471,13 @@
         return sRevKnownPolicies.get(policyIdent).tag;
     }
 
+    /**
+     * Return true if this administrator can be a target in an ownership transfer.
+     */
+    public boolean supportsTransferOwnership() {
+        return mSupportsTransferOwnership;
+    }
+
     /** @hide */
     public ArrayList<PolicyInfo> getUsedPolicies() {
         ArrayList<PolicyInfo> res = new ArrayList<PolicyInfo>();
@@ -502,6 +522,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         mActivityInfo.writeToParcel(dest, flags);
         dest.writeInt(mUsesPolicies);
+        dest.writeBoolean(mSupportsTransferOwnership);
     }
 
     /**
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 8c30fc4..1c9477d 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -505,31 +505,6 @@
     public static final String EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE =
             "android.app.extra.TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE";
 
-    /**
-     * Name under which a device administration component indicates whether it supports transfer of
-     * ownership. This meta-data is of type <code>boolean</code>. A value of <code>true</code>
-     * allows this administrator to be used as a target administrator for a transfer. If the value
-     * is <code>false</code>, ownership cannot be transferred to this administrator. The default
-     * value is <code>false</code>.
-     * <p>This metadata is used to avoid ownership transfer migration to an administrator with a
-     * version which does not yet support it.
-     * <p>Usage:
-     * <pre>
-     * &lt;receiver name="..." android:permission="android.permission.BIND_DEVICE_ADMIN"&gt;
-     *     &lt;meta-data
-     *         android:name="android.app.device_admin"
-     *         android:resource="@xml/..." /&gt;
-     *     &lt;meta-data
-     *         android:name="android.app.support_transfer_ownership"
-     *         android:value="true" /&gt;
-     * &lt;/receiver&gt;
-     * </pre>
-     *
-     * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
-     */
-    public static final String SUPPORT_TRANSFER_OWNERSHIP_META_DATA =
-            "android.app.support_transfer_ownership";
-
     private DevicePolicyManager mManager;
     private ComponentName mWho;
 
diff --git a/core/java/android/app/admin/DevicePolicyCache.java b/core/java/android/app/admin/DevicePolicyCache.java
new file mode 100644
index 0000000..fbb8ddf
--- /dev/null
+++ b/core/java/android/app/admin/DevicePolicyCache.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package android.app.admin;
+
+import android.annotation.UserIdInt;
+
+import com.android.server.LocalServices;
+
+/**
+ * Stores a copy of the set of device policies maintained by {@link DevicePolicyManager} that
+ * can be accessed from any place without risking dead locks.
+ *
+ * @hide
+ */
+public abstract class DevicePolicyCache {
+    protected DevicePolicyCache() {
+    }
+
+    /**
+     * @return the instance.
+     */
+    public static DevicePolicyCache getInstance() {
+        final DevicePolicyManagerInternal dpmi =
+                LocalServices.getService(DevicePolicyManagerInternal.class);
+        return (dpmi != null) ? dpmi.getDevicePolicyCache() : EmptyDevicePolicyCache.INSTANCE;
+    }
+
+    /**
+     * See {@link DevicePolicyManager#getScreenCaptureDisabled}
+     */
+    public abstract boolean getScreenCaptureDisabled(@UserIdInt int userHandle);
+
+    /**
+     * Empty implementation.
+     */
+    private static class EmptyDevicePolicyCache extends DevicePolicyCache {
+        private static final EmptyDevicePolicyCache INSTANCE = new EmptyDevicePolicyCache();
+
+        @Override
+        public boolean getScreenCaptureDisabled(int userHandle) {
+            return false;
+        }
+    }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index d42fa99..6511f21 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9302,9 +9302,10 @@
      * after calling this method.
      *
      * <p>The incoming target administrator must have the
-     * {@link DeviceAdminReceiver#SUPPORT_TRANSFER_OWNERSHIP_META_DATA} <code>meta-data</code> tag
-     * included in its corresponding <code>receiver</code> component with a value of {@code true}.
-     * Otherwise an {@link IllegalArgumentException} will be thrown.
+     * <code>&lt;support-transfer-ownership /&gt;</code> tag inside the
+     * <code>&lt;device-admin&gt;&lt;/device-admin&gt;</code> tags in the xml file referenced by
+     * {@link DeviceAdminReceiver#DEVICE_ADMIN_META_DATA}. Otherwise an
+     * {@link IllegalArgumentException} will be thrown.
      *
      * @param admin which {@link DeviceAdminReceiver} this request is associated with
      * @param target which {@link DeviceAdminReceiver} we want the new administrator to be
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index ebaf464..de92978 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -141,4 +141,10 @@
      * @return localized error message
      */
     public abstract CharSequence getPrintingDisabledReasonForUser(@UserIdInt int userId);
+
+    /**
+     * @return cached version of DPM policies that can be accessed without risking deadlocks.
+     * Do not call it directly. Use {@link DevicePolicyCache#getInstance()} instead.
+     */
+    protected abstract DevicePolicyCache getDevicePolicyCache();
 }
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index c5ea9b2..67a72ec 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -273,7 +273,8 @@
      */
     public @Nullable Uri mapIntentToUri(@NonNull Intent intent) {
         Preconditions.checkNotNull(intent, "intent");
-        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null,
+        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null
+                || intent.getData() != null,
                 "Slice intent must be explicit %s", intent);
         ContentResolver resolver = mContext.getContentResolver();
 
@@ -337,7 +338,8 @@
     public @Nullable Slice bindSlice(@NonNull Intent intent,
             @NonNull List<SliceSpec> supportedSpecs) {
         Preconditions.checkNotNull(intent, "intent");
-        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null,
+        Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null
+                || intent.getData() != null,
                 "Slice intent must be explicit %s", intent);
         ContentResolver resolver = mContext.getContentResolver();
 
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 75ce4fb..6dd85ca 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -16,6 +16,7 @@
 
 package android.appwidget;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -32,6 +33,9 @@
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Describes the meta data for an installed AppWidget provider.  The fields in this class
  * correspond to the fields in the <code>&lt;appwidget-provider&gt;</code> xml tag.
@@ -55,6 +59,14 @@
      */
     public static final int RESIZE_BOTH = RESIZE_HORIZONTAL | RESIZE_VERTICAL;
 
+    /** @hide */
+    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+            RESIZE_HORIZONTAL,
+            RESIZE_VERTICAL,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ResizeModeFlags {}
+
     /**
      * Indicates that the widget can be displayed on the home screen. This is the default value.
      */
@@ -70,6 +82,15 @@
      */
     public static final int WIDGET_CATEGORY_SEARCHBOX = 4;
 
+    /** @hide */
+    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+            WIDGET_CATEGORY_HOME_SCREEN,
+            WIDGET_CATEGORY_KEYGUARD,
+            WIDGET_CATEGORY_SEARCHBOX,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CategoryFlags {}
+
     /**
      * The widget can be reconfigured anytime after it is bound by starting the
      * {@link #configure} activity.
@@ -87,6 +108,14 @@
      */
     public static final int WIDGET_FEATURE_HIDE_FROM_PICKER = 2;
 
+    /** @hide */
+    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+            WIDGET_FEATURE_RECONFIGURABLE,
+            WIDGET_FEATURE_HIDE_FROM_PICKER,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FeatureFlags {}
+
     /**
      * Identity of this AppWidget component.  This component should be a {@link
      * android.content.BroadcastReceiver}, and it will be sent the AppWidget intents
@@ -215,6 +244,7 @@
      * <p>This field corresponds to the <code>android:resizeMode</code> attribute in
      * the AppWidget meta-data file.
      */
+    @ResizeModeFlags
     public int resizeMode;
 
     /**
@@ -226,6 +256,7 @@
      * <p>This field corresponds to the <code>widgetCategory</code> attribute in
      * the AppWidget meta-data file.
      */
+    @CategoryFlags
     public int widgetCategory;
 
     /**
@@ -235,6 +266,7 @@
      * @see #WIDGET_FEATURE_RECONFIGURABLE
      * @see #WIDGET_FEATURE_HIDE_FROM_PICKER
      */
+    @FeatureFlags
     public int widgetFeatures;
 
     /** @hide */
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 6feb170..dff51f7 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -547,4 +547,18 @@
     /** Updates the flags for the given permission. */
     public abstract void updatePermissionFlagsTEMP(@NonNull String permName,
             @NonNull String packageName, int flagMask, int flagValues, int userId);
+
+    /**
+     * Returns true if it's still safe to restore data backed up from this app's version
+     * that was signed with restoringFromSigHash.
+     */
+    public abstract boolean isDataRestoreSafe(@NonNull byte[] restoringFromSigHash,
+            @NonNull String packageName);
+
+    /**
+     * Returns true if it's still safe to restore data backed up from this app's version
+     * that was signed with restoringFromSig.
+     */
+    public abstract boolean isDataRestoreSafe(@NonNull Signature restoringFromSig,
+            @NonNull String packageName);
 }
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 52aefcc..14c2865 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1435,9 +1435,11 @@
      * for the external flash. Otherwise, this mode acts like ON.</p>
      * <p>When the external flash is turned off, AE mode should be changed to one of the
      * other available AE modes.</p>
-     * <p>If the camera device supports AE external flash mode, aeState must be
-     * FLASH_REQUIRED after the camera device finishes AE scan and it's too dark without
+     * <p>If the camera device supports AE external flash mode, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} must
+     * be FLASH_REQUIRED after the camera device finishes AE scan and it's too dark without
      * flash.</p>
+     *
+     * @see CaptureResult#CONTROL_AE_STATE
      * @see CaptureRequest#CONTROL_AE_MODE
      */
     public static final int CONTROL_AE_MODE_ON_EXTERNAL_FLASH = 5;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index e14dfa8..e84e48f 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1001,8 +1001,8 @@
      * </tbody>
      * </table>
      * <p>If the camera device supports AE external flash mode (ON_EXTERNAL_FLASH is included in
-     * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}), aeState must be FLASH_REQUIRED after the camera device
-     * finishes AE scan and it's too dark without flash.</p>
+     * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}), {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} must be FLASH_REQUIRED after
+     * the camera device finishes AE scan and it's too dark without flash.</p>
      * <p>For the above table, the camera device may skip reporting any state changes that happen
      * without application intervention (i.e. mode switch, trigger, locking). Any state that
      * can be skipped in that manner is called a transient state.</p>
@@ -1081,6 +1081,7 @@
      * @see CaptureRequest#CONTROL_AE_LOCK
      * @see CaptureRequest#CONTROL_AE_MODE
      * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
+     * @see CaptureResult#CONTROL_AE_STATE
      * @see CaptureRequest#CONTROL_MODE
      * @see CaptureRequest#CONTROL_SCENE_MODE
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index b3bf092..b4c8a5e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -20,6 +20,8 @@
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
 import android.annotation.CallSuper;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
@@ -239,19 +241,89 @@
     static final boolean DEBUG = false;
 
     /**
-     * The back button will close the input window.
+     * Allows the system to optimize the back button affordance based on the presence of software
+     * keyboard.
+     *
+     * <p>For instance, on devices that have navigation bar and software-rendered back button, the
+     * system may use a different icon while {@link #isInputViewShown()} returns {@code true}, to
+     * indicate that the back button has "dismiss" affordance.</p>
+     *
+     * <p>Note that {@link KeyEvent#KEYCODE_BACK} events continue to be sent to
+     * {@link #onKeyDown(int, KeyEvent)} even when this mode is specified. The default
+     * implementation of {@link #onKeyDown(int, KeyEvent)} for {@link KeyEvent#KEYCODE_BACK} does
+     * not take this mode into account.</p>
+     *
+     * <p>For API level {@link android.os.Build.VERSION_CODES#O_MR1} and lower devices, this is the
+     * only mode you can safely specify without worrying about the compatibility.</p>
+     *
+     * @see #setBackDisposition(int)
      */
-    public static final int BACK_DISPOSITION_DEFAULT = 0;  // based on window
+    public static final int BACK_DISPOSITION_DEFAULT = 0;
 
     /**
-     * This input method will not consume the back key.
+     * Deprecated flag.
+     *
+     * <p>To avoid compatibility issues, IME developers should not use this flag.</p>
+     *
+     * @deprecated on {@link android.os.Build.VERSION_CODES#P} and later devices, this flag is
+     *             handled as a synonym of {@link #BACK_DISPOSITION_DEFAULT}. On
+     *             {@link android.os.Build.VERSION_CODES#O_MR1} and prior devices, expected behavior
+     *             of this mode had not been well defined. Most likely the end result would be the
+     *             same as {@link #BACK_DISPOSITION_DEFAULT}. Either way it is not recommended to
+     *             use this mode
+     * @see #setBackDisposition(int)
      */
-    public static final int BACK_DISPOSITION_WILL_NOT_DISMISS = 1; // back
+    @Deprecated
+    public static final int BACK_DISPOSITION_WILL_NOT_DISMISS = 1;
 
     /**
-     * This input method will consume the back key.
+     * Deprecated flag.
+     *
+     * <p>To avoid compatibility issues, IME developers should not use this flag.</p>
+     *
+     * @deprecated on {@link android.os.Build.VERSION_CODES#P} and later devices, this flag is
+     *             handled as a synonym of {@link #BACK_DISPOSITION_DEFAULT}. On
+     *             {@link android.os.Build.VERSION_CODES#O_MR1} and prior devices, expected behavior
+     *             of this mode had not been well defined. In AOSP implementation running on devices
+     *             that have navigation bar, specifying this flag could change the software back
+     *             button to "Dismiss" icon no matter whether the software keyboard is shown or not,
+     *             but there would be no easy way to restore the icon state even after IME lost the
+     *             connection to the application. To avoid user confusions, do not specify this mode
+     *             anyway
+     * @see #setBackDisposition(int)
      */
-    public static final int BACK_DISPOSITION_WILL_DISMISS = 2; // down
+    @Deprecated
+    public static final int BACK_DISPOSITION_WILL_DISMISS = 2;
+
+    /**
+     * Asks the system to not adjust the back button affordance even when the software keyboard is
+     * shown.
+     *
+     * <p>This mode is useful for UI modes where IME's main soft input window is used for some
+     * supplemental UI, such as floating candidate window for languages such as Chinese and
+     * Japanese, where users expect the back button is, or at least looks to be, handled by the
+     * target application rather than the UI shown by the IME even while {@link #isInputViewShown()}
+     * returns {@code true}.</p>
+     *
+     * <p>Note that {@link KeyEvent#KEYCODE_BACK} events continue to be sent to
+     * {@link #onKeyDown(int, KeyEvent)} even when this mode is specified. The default
+     * implementation of {@link #onKeyDown(int, KeyEvent)} for {@link KeyEvent#KEYCODE_BACK} does
+     * not take this mode into account.</p>
+     *
+     * @see #setBackDisposition(int)
+     */
+    public static final int BACK_DISPOSITION_ADJUST_NOTHING = 3;
+
+    /**
+     * Enum flag to be used for {@link #setBackDisposition(int)}.
+     *
+     * @hide
+     */
+    @Retention(SOURCE)
+    @IntDef(value = {BACK_DISPOSITION_DEFAULT, BACK_DISPOSITION_WILL_NOT_DISMISS,
+            BACK_DISPOSITION_WILL_DISMISS, BACK_DISPOSITION_ADJUST_NOTHING},
+            prefix = "BACK_DISPOSITION_")
+    public @interface BackDispositionMode {}
 
     /**
      * @hide
@@ -267,7 +339,7 @@
 
     // Min and max values for back disposition.
     private static final int BACK_DISPOSITION_MIN = BACK_DISPOSITION_DEFAULT;
-    private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_WILL_DISMISS;
+    private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_ADJUST_NOTHING;
 
     InputMethodManager mImm;
     
@@ -331,6 +403,8 @@
     boolean mIsInputViewShown;
     
     int mStatusIcon;
+
+    @BackDispositionMode
     int mBackDisposition;
 
     /**
@@ -1015,8 +1089,19 @@
     public Dialog getWindow() {
         return mWindow;
     }
-    
-    public void setBackDisposition(int disposition) {
+
+    /**
+     * Sets the disposition mode that indicates the expected affordance for the back button.
+     *
+     * <p>Keep in mind that specifying this flag does not change the the default behavior of
+     * {@link #onKeyDown(int, KeyEvent)}.  It is IME developers' responsibility for making sure that
+     * their custom implementation of {@link #onKeyDown(int, KeyEvent)} is consistent with the mode
+     * specified to this API.</p>
+     *
+     * @see #getBackDisposition()
+     * @param disposition disposition mode to be set
+     */
+    public void setBackDisposition(@BackDispositionMode int disposition) {
         if (disposition == mBackDisposition) {
             return;
         }
@@ -1029,6 +1114,13 @@
                 mBackDisposition);
     }
 
+    /**
+     * Retrieves the current disposition mode that indicates the expected back button affordance.
+     *
+     * @see #setBackDisposition(int)
+     * @return currently selected disposition mode
+     */
+    @BackDispositionMode
     public int getBackDisposition() {
         return mBackDisposition;
     }
@@ -1894,7 +1986,6 @@
         mInputStarted = false;
         mStartedInputConnection = null;
         mCurCompletions = null;
-        mBackDisposition = BACK_DISPOSITION_DEFAULT;
     }
 
     void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) {
@@ -2096,25 +2187,31 @@
         return mExtractEditText;
     }
 
+
     /**
-     * Override this to intercept key down events before they are processed by the
-     * application.  If you return true, the application will not 
-     * process the event itself.  If you return false, the normal application processing
-     * will occur as if the IME had not seen the event at all.
-     * 
-     * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
-     * KeyEvent.KEYCODE_BACK} if the IME is currently shown, to
-     * possibly hide it when the key goes up (if not canceled or long pressed).  In
-     * addition, in fullscreen mode only, it will consume DPAD movement
-     * events to move the cursor in the extracted text view, not allowing
-     * them to perform navigation in the underlying application.
+     * Called back when a {@link KeyEvent} is forwarded from the target application.
+     *
+     * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK} if the IME is
+     * currently shown , to possibly hide it when the key goes up (if not canceled or long pressed).
+     * In addition, in fullscreen mode only, it will consume DPAD movement events to move the cursor
+     * in the extracted text view, not allowing them to perform navigation in the underlying
+     * application.</p>
+     *
+     * <p>The default implementation does not take flags specified to
+     * {@link #setBackDisposition(int)} into account, even on API version
+     * {@link android.os.Build.VERSION_CODES#P} and later devices.  IME developers are responsible
+     * for making sure that their special handling for {@link KeyEvent#KEYCODE_BACK} are consistent
+     * with the flag they specified to {@link #setBackDisposition(int)}.</p>
+     *
+     * @param keyCode The value in {@code event.getKeyCode()}
+     * @param event Description of the key event
+     *
+     * @return {@code true} if the event is consumed by the IME and the application no longer needs
+     *         to consume it.  Return {@code false} when the event should be handled as if the IME
+     *         had not seen the event at all.
      */
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-
         if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
-            if (mBackDisposition == BACK_DISPOSITION_WILL_NOT_DISMISS) {
-                return false;
-            }
             final ExtractEditText eet = getExtractEditTextIfVisible();
             if (eet != null && eet.handleBackInTextActionModeIfNeeded(event)) {
                 return true;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 60f7295..2b5cece 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10378,6 +10378,17 @@
         public static final String SYS_UIDCPUPOWER = "sys_uidcpupower";
 
         /**
+        * traced global setting. This controls weather the deamons: traced and
+        * traced_probes run. This links the sys.traced system property.
+        * The following values are supported:
+        * 0 -> traced and traced_probes are disabled
+        * 1 -> traced and traced_probes are enabled
+        * Any other value defaults to disabled.
+        * @hide
+        */
+        public static final String SYS_TRACED = "sys_traced";
+
+        /**
          * An integer to reduce the FPS by this factor. Only for experiments. Need to reboot the
          * device for this setting to take full effect.
          *
diff --git a/core/java/android/security/keystore/recovery/BadCertificateFormatException.java b/core/java/android/security/keystore/recovery/BadCertificateFormatException.java
deleted file mode 100644
index 4275c29..0000000
--- a/core/java/android/security/keystore/recovery/BadCertificateFormatException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.
- */
-
-package android.security.keystore.recovery;
-
-/**
- * @deprecated Not used.
- * @hide
- */
-public class BadCertificateFormatException extends RecoveryControllerException {
-    public BadCertificateFormatException(String msg) {
-        super(msg);
-    }
-}
diff --git a/core/java/android/security/keystore/recovery/RecoveryControllerException.java b/core/java/android/security/keystore/recovery/RecoveryControllerException.java
deleted file mode 100644
index 1af61ce..0000000
--- a/core/java/android/security/keystore/recovery/RecoveryControllerException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.
- */
-
-package android.security.keystore.recovery;
-
-import java.security.GeneralSecurityException;
-
-/**
- * @deprecated Not used.
- * @hide
- */
-public abstract class RecoveryControllerException extends GeneralSecurityException {
-    RecoveryControllerException() { }
-
-    RecoveryControllerException(String msg) {
-        super(msg);
-    }
-
-    public RecoveryControllerException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index 3350f3e..789131c 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import android.os.Process;
+
 /**
  * StatsLog provides an API for developers to send events to statsd. The events can be used to
  * define custom metrics inside statsd. We will rate-limit how often the calls can be made inside
@@ -34,7 +36,8 @@
      */
     public static boolean logStart(int label) {
         if (label >= 0 && label < 16) {
-            StatsLog.write(APP_BREADCRUMB_REPORTED, label, APP_BREADCRUMB_REPORTED__STATE__START);
+            StatsLog.write(APP_BREADCRUMB_REPORTED, Process.myUid(),
+                    label, APP_BREADCRUMB_REPORTED__STATE__START);
             return true;
         }
         return false;
@@ -48,7 +51,8 @@
      */
     public static boolean logStop(int label) {
         if (label >= 0 && label < 16) {
-            StatsLog.write(APP_BREADCRUMB_REPORTED, label, APP_BREADCRUMB_REPORTED__STATE__STOP);
+            StatsLog.write(APP_BREADCRUMB_REPORTED, Process.myUid(),
+                    label, APP_BREADCRUMB_REPORTED__STATE__STOP);
             return true;
         }
         return false;
@@ -62,7 +66,7 @@
      */
     public static boolean logEvent(int label) {
         if (label >= 0 && label < 16) {
-            StatsLog.write(APP_BREADCRUMB_REPORTED, label,
+            StatsLog.write(APP_BREADCRUMB_REPORTED, Process.myUid(), label,
                     APP_BREADCRUMB_REPORTED__STATE__UNSPECIFIED);
             return true;
         }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 77a74e2..d172fb5 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -181,9 +181,10 @@
     void setStrictModeVisualIndicatorPreference(String enabled);
 
     /**
-     * Set whether screen capture is disabled for all windows of a specific user
+     * Set whether screen capture is disabled for all windows of a specific user from
+     * the device policy cache.
      */
-    void setScreenCaptureDisabled(int userId, boolean disabled);
+    void refreshScreenCaptureDisabled(int userId);
 
     // These can only be called with the SET_ORIENTATION permission.
     /**
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 75fc538..bbdf15c 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1182,12 +1182,12 @@
      * determine where to position the view on the screen.  If the view is not contained
      * within a relative layout, these attributes are ignored.
      *
-     * See the <a href=“https://developer.android.com/guide/topics/ui/layout/relative.html”>
+     * See the <a href="/guide/topics/ui/layout/relative.html">
      * Relative Layout</a> guide for example code demonstrating how to use relative layout’s
      * layout parameters in a layout XML.
      *
      * To learn more about layout parameters and how they differ from typical view attributes,
-     * see the <a href=“https://developer.android.com/guide/topics/ui/declaring-layout.html#attributes”>
+     * see the <a href="/guide/topics/ui/declaring-layout.html#attributes">
      *     Layouts guide</a>.
      *
      *
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 3b081ef..f831c05 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -155,12 +155,6 @@
         env->SetObjectField(options, gOptions_outColorSpaceFieldID, 0);
     }
 
-    SkBitmapRegionDecoder* brd = reinterpret_cast<SkBitmapRegionDecoder*>(brdHandle);
-
-    SkColorType decodeColorType = brd->computeOutputColorType(colorType);
-    sk_sp<SkColorSpace> decodeColorSpace = brd->computeOutputColorSpace(
-            decodeColorType, colorSpace);
-
     // Recycle a bitmap if possible.
     android::Bitmap* recycledBitmap = nullptr;
     size_t recycledBytes = 0;
@@ -172,6 +166,9 @@
         recycledBytes = bitmap::getBitmapAllocationByteCount(env, javaBitmap);
     }
 
+    SkBitmapRegionDecoder* brd = reinterpret_cast<SkBitmapRegionDecoder*>(brdHandle);
+    SkColorType decodeColorType = brd->computeOutputColorType(colorType);
+
     // Set up the pixel allocator
     SkBRDAllocator* allocator = nullptr;
     RecyclingClippingPixelAllocator recycleAlloc(recycledBitmap, recycledBytes);
@@ -184,6 +181,9 @@
         allocator = &heapAlloc;
     }
 
+    sk_sp<SkColorSpace> decodeColorSpace = brd->computeOutputColorSpace(
+            decodeColorType, colorSpace);
+
     // Decode the region.
     SkIRect subset = SkIRect::MakeXYWH(inputX, inputY, inputWidth, inputHeight);
     SkBitmap bitmap;
diff --git a/core/proto/android/service/diskstats.proto b/core/proto/android/service/diskstats.proto
index 3d7ee91..e5bdc8b 100644
--- a/core/proto/android/service/diskstats.proto
+++ b/core/proto/android/service/diskstats.proto
@@ -55,25 +55,25 @@
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     // Total app code size, in kilobytes
-    optional int64 agg_apps_size = 1;
+    optional int64 agg_apps_size_kb = 1;
     // Total app cache size, in kilobytes
-    optional int64 agg_apps_cache_size = 2;
+    optional int64 agg_apps_cache_size_kb = 2;
     // Size of image files, in kilobytes
-    optional int64 photos_size = 3;
+    optional int64 photos_size_kb = 3;
     // Size of video files, in kilobytes
-    optional int64 videos_size = 4;
+    optional int64 videos_size_kb = 4;
     // Size of audio files, in kilobytes
-    optional int64 audio_size = 5;
+    optional int64 audio_size_kb = 5;
     // Size of downloads, in kilobytes
-    optional int64 downloads_size = 6;
+    optional int64 downloads_size_kb = 6;
     // Size of system directory, in kilobytes
-    optional int64 system_size = 7;
+    optional int64 system_size_kb = 7;
     // Size of other files, in kilobytes
-    optional int64 other_size = 8;
+    optional int64 other_size_kb = 8;
     // Sizes of individual packages
     repeated DiskStatsAppSizesProto app_sizes = 9;
     // Total app data size, in kilobytes
-    optional int64 agg_apps_data_size = 10;
+    optional int64 agg_apps_data_size_kb = 10;
 }
 
 message DiskStatsAppSizesProto {
@@ -82,11 +82,11 @@
     // Name of the package
     optional string package_name = 1;
     // App's code size in kilobytes
-    optional int64 app_size = 2;
+    optional int64 app_size_kb = 2;
     // App's cache size in kilobytes
-    optional int64 cache_size = 3;
+    optional int64 cache_size_kb = 3;
     // App's data size in kilobytes
-    optional int64 app_data_size = 4;
+    optional int64 app_data_size_kb = 4;
 }
 
 message DiskStatsFreeSpaceProto {
@@ -103,7 +103,7 @@
     // Which folder?
     optional Folder folder = 1;
     // Available space, in kilobytes
-    optional int64 available_space = 2;
+    optional int64 available_space_kb = 2;
     // Total space, in kilobytes
-    optional int64 total_space = 3;
+    optional int64 total_space_kb = 3;
 }
diff --git a/core/proto/android/service/graphicsstats.proto b/core/proto/android/service/graphicsstats.proto
index f422065..c2fedf5 100644
--- a/core/proto/android/service/graphicsstats.proto
+++ b/core/proto/android/service/graphicsstats.proto
@@ -56,7 +56,7 @@
     // Number of "missed vsync" events.
     optional int32 missed_vsync_count = 3;
 
-    // Number of "high input latency" events.
+    // Number of frames in triple-buffering scenario (high input latency)
     optional int32 high_input_latency_count = 4;
 
     // Number of "slow UI thread" events.
@@ -67,6 +67,9 @@
 
     // Number of "slow draw" events.
     optional int32 slow_draw_count = 7;
+
+    // Number of frames that missed their deadline (aka, visibly janked)
+    optional int32 missed_deadline_count = 8;
 }
 
 message GraphicsStatsHistogramBucketProto {
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6c0be1b..0a56ef7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -160,13 +160,13 @@
     <string name="RestrictedStateContent">Temporarily turned off by your carrier</string>
 
     <!-- Displayed to tell the user that they should switch their network preference. -->
-    <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string>
+    <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach mobile network</string>
     <!-- Displayed to tell the user that they should switch their network preference. -->
-    <string name="NetworkPreferenceSwitchSummary">To improve reception, try changing the type selected at Settings &gt; Network &amp; internet &gt; Mobile networks &gt; Preferred network type."</string>
+    <string name="NetworkPreferenceSwitchSummary">Try changing preferred network. Tap to change.</string>
     <!-- Displayed to tell the user that emergency calls might not be available. -->
-    <string name="EmergencyCallWarningTitle">Wi\u2011Fi calling is active</string>
+    <string name="EmergencyCallWarningTitle">Emergency calling unavailable</string>
     <!-- Displayed to tell the user that emergency calls might not be available. -->
-    <string name="EmergencyCallWarningSummary">Emergency calls require a mobile network.</string>
+    <string name="EmergencyCallWarningSummary">Can\u2019t make emergency calls over Wi\u2011Fi</string>
 
     <!-- Telephony notification channel name for a channel containing network alert notifications. -->
     <string name="notification_channel_network_alert">Alerts</string>
diff --git a/core/tests/coretests/BinderProxyCountingTestApp/Android.mk b/core/tests/coretests/BinderProxyCountingTestApp/Android.mk
index c3af6bd..4642694 100644
--- a/core/tests/coretests/BinderProxyCountingTestApp/Android.mk
+++ b/core/tests/coretests/BinderProxyCountingTestApp/Android.mk
@@ -24,5 +24,6 @@
 LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
+LOCAL_COMPATIBILITY_SUITE := device-tests
 include $(BUILD_PACKAGE)
 
diff --git a/core/tests/coretests/BinderProxyCountingTestService/Android.mk b/core/tests/coretests/BinderProxyCountingTestService/Android.mk
index 34016ed..f852c7a 100644
--- a/core/tests/coretests/BinderProxyCountingTestService/Android.mk
+++ b/core/tests/coretests/BinderProxyCountingTestService/Android.mk
@@ -24,5 +24,6 @@
 LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
+LOCAL_COMPATIBILITY_SUITE := device-tests
 include $(BUILD_PACKAGE)
 
diff --git a/core/tests/coretests/BstatsTestApp/Android.mk b/core/tests/coretests/BstatsTestApp/Android.mk
index e04536b..a5872a5 100644
--- a/core/tests/coretests/BstatsTestApp/Android.mk
+++ b/core/tests/coretests/BstatsTestApp/Android.mk
@@ -30,4 +30,5 @@
 LOCAL_DEX_PREOPT := false
 LOCAL_PROGUARD_ENABLED := disabled
 
-include $(BUILD_PACKAGE)
\ No newline at end of file
+LOCAL_COMPATIBILITY_SUITE := device-tests
+include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 22a261e..73fb713 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -383,6 +383,7 @@
                     Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE,
                     Settings.Global.SYS_VDSO,
                     Settings.Global.SYS_UIDCPUPOWER,
+                    Settings.Global.SYS_TRACED,
                     Settings.Global.FPS_DEVISOR,
                     Settings.Global.TCP_DEFAULT_INIT_RWND,
                     Settings.Global.TETHER_DUN_APN,
diff --git a/core/tests/featureflagtests/AndroidTest.xml b/core/tests/featureflagtests/AndroidTest.xml
index 44f9c3e..38c048a 100644
--- a/core/tests/featureflagtests/AndroidTest.xml
+++ b/core/tests/featureflagtests/AndroidTest.xml
@@ -15,14 +15,16 @@
   limitations under the License.
   -->
 <configuration description="Runs Frameworks Utility Tests.">
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="FrameworksCoreFeatureFlagTests.apk" />
     </target_preparer>
 
-    <option name="test-suite-tag" value="apct" />
     <option name="test-tag" value="FrameworksCoreFeatureFlagTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.coretests.featureflagtests" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
diff --git a/core/tests/overlaytests/device/AndroidTest.xml b/core/tests/overlaytests/device/AndroidTest.xml
index f069835..6507839 100644
--- a/core/tests/overlaytests/device/AndroidTest.xml
+++ b/core/tests/overlaytests/device/AndroidTest.xml
@@ -17,8 +17,10 @@
 <configuration description="Test module config for OverlayDeviceTests">
     <option name="test-tag" value="OverlayDeviceTests" />
     <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
 
     <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="OverlayDeviceTests.apk" />
         <option name="test-file-name" value="OverlayDeviceTests_AppOverlayOne.apk" />
         <option name="test-file-name" value="OverlayDeviceTests_AppOverlayTwo.apk" />
@@ -42,6 +44,5 @@
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
         <option name="package" value="com.android.overlaytest" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
diff --git a/core/tests/privacytests/AndroidTest.xml b/core/tests/privacytests/AndroidTest.xml
index a43f48e..8098c14 100644
--- a/core/tests/privacytests/AndroidTest.xml
+++ b/core/tests/privacytests/AndroidTest.xml
@@ -14,12 +14,14 @@
      limitations under the License.
 -->
 <configuration description="Runs Privacy Tests.">
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="FrameworksPrivacyLibraryTests.apk" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.coretests.privacy" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/core/tests/utiltests/AndroidTest.xml b/core/tests/utiltests/AndroidTest.xml
index 65bb8de..270d773 100644
--- a/core/tests/utiltests/AndroidTest.xml
+++ b/core/tests/utiltests/AndroidTest.xml
@@ -14,14 +14,16 @@
      limitations under the License.
 -->
 <configuration description="Runs Frameworks Utility Tests.">
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="FrameworksUtilTests.apk" />
     </target_preparer>
 
-    <option name="test-suite-tag" value="apct" />
     <option name="test-tag" value="FrameworksUtilTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.utiltests" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
diff --git a/core/tests/webkit/AndroidTest.xml b/core/tests/webkit/AndroidTest.xml
index 78cfa46..4c50b7d 100644
--- a/core/tests/webkit/AndroidTest.xml
+++ b/core/tests/webkit/AndroidTest.xml
@@ -14,7 +14,9 @@
      limitations under the License.
 -->
 <configuration description="Runs Frameworks WebView Loading Tests.">
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="test-file-name" value="WebViewLoadingTests.apk" />
         <option name="test-file-name" value="WebViewLoadingOnDiskTestApk.apk" />
         <option name="test-file-name" value="WebViewLoadingFromApkTestApk.apk" />
@@ -24,6 +26,5 @@
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.webkit.tests" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
diff --git a/core/tests/webkit/apk_with_native_libs/Android.mk b/core/tests/webkit/apk_with_native_libs/Android.mk
index c51de6a..e18a7e0 100644
--- a/core/tests/webkit/apk_with_native_libs/Android.mk
+++ b/core/tests/webkit/apk_with_native_libs/Android.mk
@@ -45,6 +45,7 @@
 LOCAL_SDK_VERSION := $(MY_SDK_VERSION)
 LOCAL_PROGUARD_ENABLED := $(MY_PROGUARD_ENABLED)
 LOCAL_MULTILIB := $(MY_MULTILIB)
+LOCAL_COMPATIBILITY_SUITE := device-tests
 
 include $(BUILD_PACKAGE)
 
@@ -65,5 +66,6 @@
 LOCAL_SDK_VERSION := $(MY_SDK_VERSION)
 LOCAL_PROGUARD_ENABLED := $(MY_PROGUARD_ENABLED)
 LOCAL_MULTILIB := $(MY_MULTILIB)
+LOCAL_COMPATIBILITY_SUITE := device-tests
 
 include $(BUILD_PACKAGE)
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index cf29e43..8110664 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -129,22 +129,42 @@
             totalDuration -= forgiveAmount;
         }
     }
+
     LOG_ALWAYS_FATAL_IF(totalDuration <= 0, "Impossible totalDuration %" PRId64, totalDuration);
     mData->reportFrame(totalDuration);
     (*mGlobalData)->reportFrame(totalDuration);
 
-    // Keep the fast path as fast as possible.
-    if (CC_LIKELY(totalDuration < mFrameInterval)) {
-        return;
-    }
-
     // Only things like Surface.lockHardwareCanvas() are exempt from tracking
-    if (frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS) {
+    if (CC_UNLIKELY(frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS)) {
         return;
     }
 
-    mData->reportJank();
-    (*mGlobalData)->reportJank();
+    if (totalDuration > mFrameInterval) {
+        mData->reportJank();
+        (*mGlobalData)->reportJank();
+    }
+
+    bool isTripleBuffered = mSwapDeadline > frame[FrameInfoIndex::IntendedVsync];
+
+    mSwapDeadline = std::max(mSwapDeadline + mFrameInterval,
+                             frame[FrameInfoIndex::IntendedVsync] + mFrameInterval);
+
+    // If we hit the deadline, cool!
+    if (frame[FrameInfoIndex::FrameCompleted] < mSwapDeadline) {
+        if (isTripleBuffered) {
+            mData->reportJankType(JankType::kHighInputLatency);
+            (*mGlobalData)->reportJankType(JankType::kHighInputLatency);
+        }
+        return;
+    }
+
+    mData->reportJankType(JankType::kMissedDeadline);
+    (*mGlobalData)->reportJankType(JankType::kMissedDeadline);
+
+    // Janked, reset the swap deadline
+    nsecs_t jitterNanos = frame[FrameInfoIndex::FrameCompleted] - frame[FrameInfoIndex::Vsync];
+    nsecs_t lastFrameOffset = jitterNanos % mFrameInterval;
+    mSwapDeadline = frame[FrameInfoIndex::FrameCompleted] - lastFrameOffset + mFrameInterval;
 
     for (int i = 0; i < NUM_BUCKETS; i++) {
         int64_t delta = frame.duration(COMPARISONS[i].start, COMPARISONS[i].end);
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index dc6a7ff..110211e 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -75,6 +75,7 @@
 
     std::array<int64_t, NUM_BUCKETS> mThresholds;
     int64_t mFrameInterval;
+    nsecs_t mSwapDeadline;
     // The amount of time we will erase from the total duration to account
     // for SF vsync offsets with HWC2 blocking dequeueBuffers.
     // (Vsync + mDequeueBlockTolerance) is the point at which we expect
diff --git a/libs/hwui/ProfileData.cpp b/libs/hwui/ProfileData.cpp
index b392ecd..f9cf549 100644
--- a/libs/hwui/ProfileData.cpp
+++ b/libs/hwui/ProfileData.cpp
@@ -23,8 +23,7 @@
 
 static const char* JANK_TYPE_NAMES[] = {
         "Missed Vsync",        "High input latency",       "Slow UI thread",
-        "Slow bitmap uploads", "Slow issue draw commands",
-};
+        "Slow bitmap uploads", "Slow issue draw commands", "Frame deadline missed"};
 
 // The bucketing algorithm controls so to speak
 // If a frame is <= to this it goes in bucket 0
diff --git a/libs/hwui/ProfileData.h b/libs/hwui/ProfileData.h
index 1e688ab..564920b 100644
--- a/libs/hwui/ProfileData.h
+++ b/libs/hwui/ProfileData.h
@@ -33,6 +33,7 @@
     kSlowUI,
     kSlowSync,
     kSlowRT,
+    kMissedDeadline,
 
     // must be last
     NUM_BUCKETS,
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 25c76eb..62d78e7 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -148,31 +148,6 @@
 // Recording Canvas draw operations: Bitmaps
 // ----------------------------------------------------------------------------
 
-inline static const SkPaint* bitmapPaint(const SkPaint* origPaint, SkPaint* tmpPaint,
-                                         sk_sp<SkColorFilter> colorSpaceFilter) {
-    if ((origPaint && origPaint->isAntiAlias()) || colorSpaceFilter) {
-        if (origPaint) {
-            *tmpPaint = *origPaint;
-        }
-
-        if (colorSpaceFilter) {
-            if (tmpPaint->getColorFilter()) {
-                tmpPaint->setColorFilter(
-                        SkColorFilter::MakeComposeFilter(tmpPaint->refColorFilter(), colorSpaceFilter));
-            } else {
-                tmpPaint->setColorFilter(colorSpaceFilter);
-            }
-            LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
-        }
-
-
-        // disabling AA on bitmap draws matches legacy HWUI behavior
-        tmpPaint->setAntiAlias(false);
-        return tmpPaint;
-    } else {
-        return origPaint;
-    }
-}
 
 void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
     SkPaint tmpPaint;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 0e5dbdb..93807a5 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -88,6 +88,45 @@
      *  @param height used to calculate recording bounds.
      */
     void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height);
+
+    inline static const SkPaint* bitmapPaint(const SkPaint* origPaint, SkPaint* tmpPaint,
+                                             sk_sp<SkColorFilter> colorSpaceFilter) {
+        bool fixBlending = false;
+        bool fixAA = false;
+        if (origPaint) {
+            // kClear blend mode is drawn as kDstOut on HW for compatibility with Android O and
+            // older.
+            fixBlending = sApiLevel <= 27 && origPaint->getBlendMode() == SkBlendMode::kClear;
+            fixAA = origPaint->isAntiAlias();
+        }
+
+        if (fixBlending || fixAA || colorSpaceFilter) {
+            if (origPaint) {
+                *tmpPaint = *origPaint;
+            }
+
+            if (fixBlending) {
+                tmpPaint->setBlendMode(SkBlendMode::kDstOut);
+            }
+
+            if (colorSpaceFilter) {
+                if (tmpPaint->getColorFilter()) {
+                    tmpPaint->setColorFilter(SkColorFilter::MakeComposeFilter(
+                            tmpPaint->refColorFilter(), colorSpaceFilter));
+                } else {
+                    tmpPaint->setColorFilter(colorSpaceFilter);
+                }
+                LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
+            }
+
+            // disabling AA on bitmap draws matches legacy HWUI behavior
+            tmpPaint->setAntiAlias(false);
+            return tmpPaint;
+        } else {
+            return origPaint;
+        }
+    }
+
 };
 
 };  // namespace skiapipeline
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index e0303a8..599226b 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -176,6 +176,8 @@
     summary->set_slow_bitmap_upload_count(summary->slow_bitmap_upload_count() +
                                           data->jankTypeCount(kSlowSync));
     summary->set_slow_draw_count(summary->slow_draw_count() + data->jankTypeCount(kSlowRT));
+    summary->set_missed_deadline_count(summary->missed_deadline_count()
+            + data->jankTypeCount(kMissedDeadline));
 
     bool creatingHistogram = false;
     if (proto->histogram_size() == 0) {
@@ -246,6 +248,7 @@
     dprintf(fd, "\nNumber Slow UI thread: %d", summary.slow_ui_thread_count());
     dprintf(fd, "\nNumber Slow bitmap uploads: %d", summary.slow_bitmap_upload_count());
     dprintf(fd, "\nNumber Slow issue draw commands: %d", summary.slow_draw_count());
+    dprintf(fd, "\nNumber Frame deadline missed: %d", summary.missed_deadline_count());
     dprintf(fd, "\nHISTOGRAM:");
     for (const auto& it : proto->histogram()) {
         dprintf(fd, " %dms=%d", it.render_millis(), it.frame_count());
diff --git a/libs/hwui/tests/common/scenes/JankyScene.cpp b/libs/hwui/tests/common/scenes/JankyScene.cpp
new file mode 100644
index 0000000..f5e6b31
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/JankyScene.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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 "TestSceneBase.h"
+
+#include <unistd.h>
+
+class JankyScene;
+
+static TestScene::Registrar _JankyScene(TestScene::Info{
+        "janky",
+        "A scene that intentionally janks just enough to stay in "
+        "triple buffering.",
+        TestScene::simpleCreateScene<JankyScene>});
+
+class JankyScene : public TestScene {
+public:
+    sp<RenderNode> card;
+
+    void createContent(int width, int height, Canvas& canvas) override {
+        card = TestUtils::createNode(0, 0, 200, 200, [](RenderProperties& props, Canvas& canvas) {
+            canvas.drawColor(0xFF0000FF, SkBlendMode::kSrcOver);
+        });
+        canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);  // background
+        canvas.drawRenderNode(card.get());
+    }
+
+    void doFrame(int frameNr) override {
+        int curFrame = frameNr % 150;
+        if (curFrame & 1) {
+            usleep(15000);
+        }
+        // we animate left and top coordinates, which in turn animates width and
+        // height (bottom/right coordinates are fixed)
+        card->mutateStagingProperties().setLeftTop(curFrame, curFrame);
+        card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+    }
+};
\ No newline at end of file
diff --git a/libs/incident/proto/android/privacy.proto b/libs/incident/proto/android/privacy.proto
index 7590b22..f29f57f 100644
--- a/libs/incident/proto/android/privacy.proto
+++ b/libs/incident/proto/android/privacy.proto
@@ -23,13 +23,10 @@
 
 package android;
 
-// TODO: It's better to track this by semantic types and set policy for those.
-// Do this for now to bootstrap the tools.
 enum Destination {
     // Fields or messages annotated with DEST_LOCAL must never be
     // extracted from the device automatically. They can be accessed
-    // by tools on the developer's workstation, and if they are sent
-    // to another device that must be by the user, with a PII warning. (TBD)
+    // by tools on the developer's workstation or test lab devices.
     DEST_LOCAL = 0;
 
     // Fields or messages annotated with DEST_EXPLICIT can be sent
@@ -43,25 +40,27 @@
     DEST_AUTOMATIC = 200;
 
     // This is the default value, which could be overridden by other values.
-    // The reason to pick 255 is it fits into one byte.
+    // The reason to pick 255 is it fits into one byte. UNSET fields are treated
+    // as EXPLICIT.
     DEST_UNSET = 255;
 
     // Currently use 0, 100, 200 and 255, values in between are reserved for futures.
 }
 
 message PrivacyFlags {
-  optional Destination dest = 1 [ default = DEST_UNSET ];
+    optional Destination dest = 1 [ default = DEST_UNSET ];
 
-  // regex to filter pii sensitive info from a string field type
-  repeated string patterns = 2;
+    // regex to filter pii sensitive info from a string field type.
+    repeated string patterns = 2;
 }
 
 extend google.protobuf.FieldOptions {
-    // Flags for automatically filtering statistics
+    // Flags used to annotate a field with right privacy level.
     optional PrivacyFlags privacy = 102672883;
 }
 
 extend google.protobuf.MessageOptions {
-    // Flags used to annotate a message which all its unset primitive types inhert this tag.
+    // Flags used to annotate a message which all its unset primitive fields inhert this tag.
     optional PrivacyFlags msg_privacy = 102672883;
 }
+
diff --git a/media/OWNERS b/media/OWNERS
index f198f43..182f661 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -4,3 +4,6 @@
 marcone@google.com
 sungsoo@google.com
 wjia@google.com
+jaewan@google.com
+chz@google.com
+
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 3d5f6bc..8a742b7 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -1602,7 +1602,9 @@
     private EventHandler mCallbackHandler;
     private Callback mCallback;
     private OnFrameRenderedListener mOnFrameRenderedListener;
-    private Object mListenerLock = new Object();
+    private final Object mListenerLock = new Object();
+    private MediaCodecInfo mCodecInfo;
+    private final Object mCodecInfoLock = new Object();
 
     private static final int EVENT_CALLBACK = 1;
     private static final int EVENT_SET_CALLBACK = 2;
@@ -3469,10 +3471,26 @@
      */
     @NonNull
     public MediaCodecInfo getCodecInfo() {
-        return MediaCodecList.getInfoFor(getName());
+        // Get the codec name first. If the codec is already released,
+        // IllegalStateException will be thrown here.
+        String name = getName();
+        synchronized (mCodecInfoLock) {
+            if (mCodecInfo == null) {
+                // Get the codec info for this codec itself first. Only initialize
+                // the full codec list if this somehow fails because it can be slow.
+                mCodecInfo = getOwnCodecInfo();
+                if (mCodecInfo == null) {
+                    mCodecInfo = MediaCodecList.getInfoFor(name);
+                }
+            }
+            return mCodecInfo;
+        }
     }
 
     @NonNull
+    private native final MediaCodecInfo getOwnCodecInfo();
+
+    @NonNull
     private native final ByteBuffer[] getBuffers(boolean input);
 
     @Nullable
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 3dd6879..2a601f9 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -829,14 +829,24 @@
 
         /** @hide */
         public CodecCapabilities dup() {
-            return new CodecCapabilities(
-                // clone writable arrays
-                Arrays.copyOf(profileLevels, profileLevels.length),
-                Arrays.copyOf(colorFormats, colorFormats.length),
-                isEncoder(),
-                mFlagsVerified,
-                mDefaultFormat,
-                mCapabilitiesInfo);
+            CodecCapabilities caps = new CodecCapabilities();
+
+            // profileLevels and colorFormats may be modified by client.
+            caps.profileLevels = Arrays.copyOf(profileLevels, profileLevels.length);
+            caps.colorFormats = Arrays.copyOf(colorFormats, colorFormats.length);
+
+            caps.mMime = mMime;
+            caps.mMaxSupportedInstances = mMaxSupportedInstances;
+            caps.mFlagsRequired = mFlagsRequired;
+            caps.mFlagsSupported = mFlagsSupported;
+            caps.mFlagsVerified = mFlagsVerified;
+            caps.mAudioCaps = mAudioCaps;
+            caps.mVideoCaps = mVideoCaps;
+            caps.mEncoderCaps = mEncoderCaps;
+            caps.mDefaultFormat = mDefaultFormat;
+            caps.mCapabilitiesInfo = mCapabilitiesInfo;
+
+            return caps;
         }
 
         /**
@@ -898,13 +908,13 @@
 
             if (mMime.toLowerCase().startsWith("audio/")) {
                 mAudioCaps = AudioCapabilities.create(info, this);
-                mAudioCaps.setDefaultFormat(mDefaultFormat);
+                mAudioCaps.getDefaultFormat(mDefaultFormat);
             } else if (mMime.toLowerCase().startsWith("video/")) {
                 mVideoCaps = VideoCapabilities.create(info, this);
             }
             if (encoder) {
                 mEncoderCaps = EncoderCapabilities.create(info, this);
-                mEncoderCaps.setDefaultFormat(mDefaultFormat);
+                mEncoderCaps.getDefaultFormat(mDefaultFormat);
             }
 
             final Map<String, Object> global = MediaCodecList.getGlobalSettings();
@@ -990,8 +1000,7 @@
             return caps;
         }
 
-        /** @hide */
-        public void init(MediaFormat info, CodecCapabilities parent) {
+        private void init(MediaFormat info, CodecCapabilities parent) {
             mParent = parent;
             initWithPlatformLimits();
             applyLevelLimits();
@@ -1171,7 +1180,7 @@
         }
 
         /** @hide */
-        public void setDefaultFormat(MediaFormat format) {
+        public void getDefaultFormat(MediaFormat format) {
             // report settings that have only a single choice
             if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) {
                 format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower());
@@ -1585,8 +1594,7 @@
             return caps;
         }
 
-        /** @hide */
-        public void init(MediaFormat info, CodecCapabilities parent) {
+        private void init(MediaFormat info, CodecCapabilities parent) {
             mParent = parent;
             initWithPlatformLimits();
             applyLevelLimits();
@@ -2707,8 +2715,7 @@
             return caps;
         }
 
-        /** @hide */
-        public void init(MediaFormat info, CodecCapabilities parent) {
+        private void init(MediaFormat info, CodecCapabilities parent) {
             // no support for complexity or quality yet
             mParent = parent;
             mComplexityRange = Range.create(0, 0);
@@ -2789,7 +2796,7 @@
         }
 
         /** @hide */
-        public void setDefaultFormat(MediaFormat format) {
+        public void getDefaultFormat(MediaFormat format) {
             // don't list trivial quality/complexity as default for now
             if (!mQualityRange.getUpper().equals(mQualityRange.getLower())
                     && mDefaultQuality != null) {
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index b51c662..40be018 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -836,20 +836,30 @@
     }
 
     /**
-     * Sets the index of current DataSourceDesc in the play list to be played.
+     * Skips to the item in the playlist.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)}.
      *
-     * @param item the index of DataSourceDesc in the play list you want to play
-     * @throws IllegalArgumentException if the play list is null
-     * @throws NullPointerException if index is outside play list range
+     * @param item The item in the playlist you want to play
      */
     public void skipToPlaylistItem(@NonNull MediaItem2 item) {
         mProvider.skipToPlaylistItem_impl(item);
     }
 
+    /**
+     * Skips to the previous item in the playlist.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToPreviousItem()}.
+     */
     public void skipToPreviousItem() {
         mProvider.skipToPreviousItem_impl();
     }
 
+    /**
+     * Skips to the next item in the playlist.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToNextItem()}.
+     */
     public void skipToNextItem() {
         mProvider.skipToNextItem_impl();
     }
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 1c4d898..56423fd 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -82,7 +82,6 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicInteger;
 
-
 /**
  * @hide
  */
@@ -116,8 +115,9 @@
     private boolean mNextSourcePlayPending = false;
     //--- guarded by |mSrcLock| end
 
-    private AtomicInteger mBufferedPercentageCurrent;
-    private AtomicInteger mBufferedPercentageNext;
+    private AtomicInteger mBufferedPercentageCurrent = new AtomicInteger(0);
+    private AtomicInteger mBufferedPercentageNext = new AtomicInteger(0);
+    private volatile float mVolume = 1.0f;
 
     // Modular DRM
     private final Object mDrmLock = new Object();
@@ -553,6 +553,7 @@
         addTask(new Task(CALL_COMPLETED_SET_PLAYER_VOLUME, false) {
             @Override
             void process() {
+                mVolume = volume;
                 _setVolume(volume, volume);
             }
         });
@@ -567,8 +568,7 @@
      */
     @Override
     public float getPlayerVolume() {
-        // TODO: get real volume
-        return 1.0f;
+        return mVolume;
     }
 
     /**
@@ -3227,9 +3227,7 @@
     @Override
     public void clearMediaPlayer2EventCallback() {
         synchronized (mEventCbLock) {
-            for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
-                mEventCallbackRecords.remove(cb);
-            }
+            mEventCallbackRecords.clear();
         }
     }
 
@@ -3300,9 +3298,7 @@
     @Override
     public void clearDrmEventCallback() {
         synchronized (mDrmEventCbLock) {
-            for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
-                mDrmEventCallbackRecords.remove(cb);
-            }
+            mDrmEventCallbackRecords.clear();
         }
     }
 
diff --git a/media/java/android/media/MediaPlaylistAgent.java b/media/java/android/media/MediaPlaylistAgent.java
index 1d7520f..14a3c6d 100644
--- a/media/java/android/media/MediaPlaylistAgent.java
+++ b/media/java/android/media/MediaPlaylistAgent.java
@@ -266,10 +266,16 @@
         mProvider.skipToPlaylistItem_impl(item);
     }
 
+    /**
+     * Skips to the previous item in the playlist.
+     */
     public void skipToPreviousItem() {
         mProvider.skipToPreviousItem_impl();
     }
 
+    /**
+     * Skips to the next item in the playlist.
+     */
     public void skipToNextItem() {
         mProvider.skipToNextItem_impl();
     }
@@ -323,4 +329,19 @@
     public void setShuffleMode(@ShuffleMode int shuffleMode) {
         mProvider.setShuffleMode_impl(shuffleMode);
     }
+
+    /**
+     * Gets a {@link MediaItem2} in the playlist that matches given {@code dsd}.
+     * You can override this method to have more finer control of updating {@link DataSourceDesc}
+     * on items in the playlist.
+     *
+     * @return A {@link MediaItem2} object in the playlist that matches given {@code dsd}.
+     *         {@code null} if playlist is not set, or if the playlist has no matching item.
+     * @throws IllegalArgumentException if {@code dsd} is null
+     * @hide
+     */
+    // TODO(jaewan): Unhide
+    public @Nullable MediaItem2 getMediaItem(@NonNull DataSourceDesc dsd) {
+        return mProvider.getMediaItem_impl(dsd);
+    }
 }
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index 91bface..8008c65 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -1651,6 +1651,7 @@
      * @return player state
      * @hide
      */
+    // TODO(jaewan): Unhide (b/74578458)
     public @PlayerState int getPlayerState() {
         // TODO(jaewan): implement this (b/74578458)
         return PLAYER_STATE_IDLE;
@@ -1662,6 +1663,7 @@
      * @return position
      * @hide
      */
+    // TODO(jaewan): Unhide (b/74578458)
     public long getCurrentPosition() {
         // TODO(jaewan): implement this (b/74578458)
         return -1;
@@ -1673,6 +1675,7 @@
      * @return buffered position
      * @hide
      */
+    // TODO(jaewan): Unhide (b/74578458)
     public long getBufferedPosition() {
         // TODO(jaewan): implement this (b/74578458)
         return -1;
@@ -1779,20 +1782,41 @@
     }
 
     /**
-     * Skip to the item in the play list.
+     * Skips to the item in the playlist.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)} and the behavior depends
+     * on the playlist agent implementation, especially with the shuffle/repeat mode.
      *
-     * @param item item in the play list you want to play
-     * @throws IllegalArgumentException if the play list is null
-     * @throws NullPointerException if index is outside play list range
+     * @param item The item in the playlist you want to play
+     * @see #getShuffleMode()
+     * @see #getRepeatMode()
      */
     public void skipToPlaylistItem(@NonNull MediaItem2 item) {
         mProvider.skipToPlaylistItem_impl(item);
     }
 
+    /**
+     * Skips to the previous item.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToPreviousItem()} and the behavior depends on the
+     * playlist agent implementation, especially with the shuffle/repeat mode.
+     *
+     * @see #getShuffleMode()
+     * @see #getRepeatMode()
+     **/
     public void skipToPreviousItem() {
         mProvider.skipToPreviousItem_impl();
     }
 
+    /**
+     * Skips to the next item.
+     * <p>
+     * This calls {@link MediaPlaylistAgent#skipToNextItem()} and the behavior depends on the
+     * playlist agent implementation, especially with the shuffle/repeat mode.
+     *
+     * @see #getShuffleMode()
+     * @see #getRepeatMode()
+     */
     public void skipToNextItem() {
         mProvider.skipToNextItem_impl();
     }
diff --git a/media/java/android/media/update/MediaPlaylistAgentProvider.java b/media/java/android/media/update/MediaPlaylistAgentProvider.java
index b27d5a1..e1522cf 100644
--- a/media/java/android/media/update/MediaPlaylistAgentProvider.java
+++ b/media/java/android/media/update/MediaPlaylistAgentProvider.java
@@ -16,6 +16,7 @@
 
 package android.media.update;
 
+import android.media.DataSourceDesc;
 import android.media.MediaItem2;
 import android.media.MediaMetadata2;
 import android.media.MediaPlaylistAgent.PlaylistEventCallback;
@@ -50,4 +51,5 @@
     void setRepeatMode_impl(int repeatMode);
     int getShuffleMode_impl();
     void setShuffleMode_impl(int shuffleMode);
+    MediaItem2 getMediaItem_impl(DataSourceDesc dsd);
 }
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index a1022c0..000317e 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -29,6 +29,7 @@
 #include "android_util_Binder.h"
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
 
@@ -98,6 +99,13 @@
     jint AesCbc;
 } gCryptoModes;
 
+static struct {
+    jclass capsClazz;
+    jmethodID capsCtorId;
+    jclass profileLevelClazz;
+    jfieldID profileField;
+    jfieldID levelField;
+} gCodecInfo;
 
 struct fields_t {
     jfieldID context;
@@ -625,6 +633,103 @@
     return OK;
 }
 
+static jobject getCodecCapabilitiesObject(
+        JNIEnv *env, const char *mime, bool isEncoder,
+        const sp<MediaCodecInfo::Capabilities> &capabilities) {
+    Vector<MediaCodecInfo::ProfileLevel> profileLevels;
+    Vector<uint32_t> colorFormats;
+
+    sp<AMessage> defaultFormat = new AMessage();
+    defaultFormat->setString("mime", mime);
+
+    capabilities->getSupportedColorFormats(&colorFormats);
+    capabilities->getSupportedProfileLevels(&profileLevels);
+    uint32_t flags = capabilities->getFlags();
+    sp<AMessage> details = capabilities->getDetails();
+
+    jobject defaultFormatObj = NULL;
+    if (ConvertMessageToMap(env, defaultFormat, &defaultFormatObj)) {
+        return NULL;
+    }
+    ScopedLocalRef<jobject> defaultFormatRef(env, defaultFormatObj);
+
+    jobject detailsObj = NULL;
+    if (ConvertMessageToMap(env, details, &detailsObj)) {
+        return NULL;
+    }
+    ScopedLocalRef<jobject> detailsRef(env, detailsObj);
+
+    ScopedLocalRef<jobjectArray> profileLevelArray(env, env->NewObjectArray(
+            profileLevels.size(), gCodecInfo.profileLevelClazz, NULL));
+
+    for (size_t i = 0; i < profileLevels.size(); ++i) {
+        const MediaCodecInfo::ProfileLevel &src = profileLevels.itemAt(i);
+
+        ScopedLocalRef<jobject> srcRef(env, env->AllocObject(
+                gCodecInfo.profileLevelClazz));
+
+        env->SetIntField(srcRef.get(), gCodecInfo.profileField, src.mProfile);
+        env->SetIntField(srcRef.get(), gCodecInfo.levelField, src.mLevel);
+
+        env->SetObjectArrayElement(profileLevelArray.get(), i, srcRef.get());
+    }
+
+    ScopedLocalRef<jintArray> colorFormatsArray(
+            env, env->NewIntArray(colorFormats.size()));
+    for (size_t i = 0; i < colorFormats.size(); ++i) {
+        jint val = colorFormats.itemAt(i);
+        env->SetIntArrayRegion(colorFormatsArray.get(), i, 1, &val);
+    }
+
+    return env->NewObject(
+            gCodecInfo.capsClazz, gCodecInfo.capsCtorId,
+            profileLevelArray.get(), colorFormatsArray.get(), isEncoder, flags,
+            defaultFormatRef.get(), detailsRef.get());
+}
+
+status_t JMediaCodec::getCodecInfo(JNIEnv *env, jobject *codecInfoObject) const {
+    sp<MediaCodecInfo> codecInfo;
+
+    status_t err = mCodec->getCodecInfo(&codecInfo);
+
+    if (err != OK) {
+        return err;
+    }
+
+    ScopedLocalRef<jstring> nameObject(env,
+            env->NewStringUTF(codecInfo->getCodecName()));
+
+    bool isEncoder = codecInfo->isEncoder();
+
+    Vector<AString> mimes;
+    codecInfo->getSupportedMimes(&mimes);
+
+    ScopedLocalRef<jobjectArray> capsArrayObj(env,
+        env->NewObjectArray(mimes.size(), gCodecInfo.capsClazz, NULL));
+
+    for (size_t i = 0; i < mimes.size(); i++) {
+        const sp<MediaCodecInfo::Capabilities> caps =
+                codecInfo->getCapabilitiesFor(mimes[i].c_str());
+
+        ScopedLocalRef<jobject> capsObj(env, getCodecCapabilitiesObject(
+                env, mimes[i].c_str(), isEncoder, caps));
+
+        env->SetObjectArrayElement(capsArrayObj.get(), i, capsObj.get());
+    }
+
+    ScopedLocalRef<jclass> codecInfoClazz(env,
+            env->FindClass("android/media/MediaCodecInfo"));
+    CHECK(codecInfoClazz.get() != NULL);
+
+    jmethodID codecInfoCtorID = env->GetMethodID(codecInfoClazz.get(), "<init>",
+            "(Ljava/lang/String;Z[Landroid/media/MediaCodecInfo$CodecCapabilities;)V");
+
+    *codecInfoObject = env->NewObject(codecInfoClazz.get(), codecInfoCtorID,
+            nameObject.get(), isEncoder, capsArrayObj.get());
+
+    return OK;
+}
+
 status_t JMediaCodec::getMetrics(JNIEnv *, MediaAnalyticsItem * &reply) const {
 
     status_t status = mCodec->getMetrics(reply);
@@ -1665,6 +1770,29 @@
     return NULL;
 }
 
+static jobject android_media_MediaCodec_getOwnCodecInfo(
+        JNIEnv *env, jobject thiz) {
+    ALOGV("android_media_MediaCodec_getOwnCodecInfo");
+
+    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+    if (codec == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return NULL;
+    }
+
+    jobject codecInfoObj;
+    status_t err = codec->getCodecInfo(env, &codecInfoObj);
+
+    if (err == OK) {
+        return codecInfoObj;
+    }
+
+    throwExceptionAsNecessary(env, err);
+
+    return NULL;
+}
+
 static jobject
 android_media_MediaCodec_native_getMetrics(JNIEnv *env, jobject thiz)
 {
@@ -1877,6 +2005,28 @@
     field = env->GetFieldID(clazz.get(), "mPersistentObject", "J");
     CHECK(field != NULL);
     gPersistentSurfaceClassInfo.mPersistentObject = field;
+
+    clazz.reset(env->FindClass("android/media/MediaCodecInfo$CodecCapabilities"));
+    CHECK(clazz.get() != NULL);
+    gCodecInfo.capsClazz = (jclass)env->NewGlobalRef(clazz.get());
+
+    method = env->GetMethodID(clazz.get(), "<init>",
+            "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZI"
+            "Ljava/util/Map;Ljava/util/Map;)V");
+    CHECK(method != NULL);
+    gCodecInfo.capsCtorId = method;
+
+    clazz.reset(env->FindClass("android/media/MediaCodecInfo$CodecProfileLevel"));
+    CHECK(clazz.get() != NULL);
+    gCodecInfo.profileLevelClazz = (jclass)env->NewGlobalRef(clazz.get());
+
+    field = env->GetFieldID(clazz.get(), "profile", "I");
+    CHECK(field != NULL);
+    gCodecInfo.profileField = field;
+
+    field = env->GetFieldID(clazz.get(), "level", "I");
+    CHECK(field != NULL);
+    gCodecInfo.levelField = field;
 }
 
 static void android_media_MediaCodec_native_setup(
@@ -2002,6 +2152,9 @@
     { "getName", "()Ljava/lang/String;",
       (void *)android_media_MediaCodec_getName },
 
+    { "getOwnCodecInfo", "()Landroid/media/MediaCodecInfo;",
+        (void *)android_media_MediaCodec_getOwnCodecInfo },
+
     { "native_getMetrics", "()Landroid/os/PersistableBundle;",
       (void *)android_media_MediaCodec_native_getMetrics},
 
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 2ec8703..985f55a 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -120,6 +120,8 @@
 
     status_t getName(JNIEnv *env, jstring *name) const;
 
+    status_t getCodecInfo(JNIEnv *env, jobject *codecInfo) const;
+
     status_t getMetrics(JNIEnv *env, MediaAnalyticsItem * &reply) const;
 
     status_t setParameters(const sp<AMessage> &params);
diff --git a/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java b/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java
index 4709d35..9ba7e09 100644
--- a/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java
+++ b/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java
@@ -15,6 +15,8 @@
  */
 package android.ext.services.autofill;
 
+import static android.ext.services.autofill.EditDistanceScorer.DEFAULT_ALGORITHM;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
@@ -29,8 +31,6 @@
 public class AutofillFieldClassificationServiceImpl extends AutofillFieldClassificationService {
 
     private static final String TAG = "AutofillFieldClassificationServiceImpl";
-    // TODO(b/70291841): set to false before launching
-    private static final boolean DEBUG = true;
 
     @Nullable
     @Override
@@ -40,30 +40,13 @@
         if (ArrayUtils.isEmpty(actualValues) || ArrayUtils.isEmpty(userDataValues)) {
             Log.w(TAG, "getScores(): empty currentvalues (" + actualValues + ") or userValues ("
                     + userDataValues + ")");
-            // TODO(b/70939974): add unit test
             return null;
         }
-        if (algorithmName != null && !algorithmName.equals(EditDistanceScorer.NAME)) {
+        if (algorithmName != null && !algorithmName.equals(DEFAULT_ALGORITHM)) {
             Log.w(TAG, "Ignoring invalid algorithm (" + algorithmName + ") and using "
-                    + EditDistanceScorer.NAME + " instead");
+                    + DEFAULT_ALGORITHM + " instead");
         }
 
-        final String actualAlgorithmName = EditDistanceScorer.NAME;
-        final int actualValuesSize = actualValues.size();
-        final int userDataValuesSize = userDataValues.size();
-        if (DEBUG) {
-            Log.d(TAG, "getScores() will return a " + actualValuesSize + "x"
-                    + userDataValuesSize + " matrix for " + actualAlgorithmName);
-        }
-        final float[][] scores = new float[actualValuesSize][userDataValuesSize];
-
-        final EditDistanceScorer algorithm = EditDistanceScorer.getInstance();
-        for (int i = 0; i < actualValuesSize; i++) {
-            for (int j = 0; j < userDataValuesSize; j++) {
-                final float score = algorithm.getScore(actualValues.get(i), userDataValues.get(j));
-                scores[i][j] = score;
-            }
-        }
-        return scores;
+        return EditDistanceScorer.getScores(actualValues, userDataValues);
     }
 }
diff --git a/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java b/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
index d2e804a..302b160 100644
--- a/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
+++ b/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
@@ -16,53 +16,133 @@
 package android.ext.services.autofill;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
 import android.view.autofill.AutofillValue;
 
-/**
- * Helper used to calculate the classification score between an actual {@link AutofillValue} filled
- * by the user and the expected value predicted by an autofill service.
- */
-// TODO(b/70291841): explain algorithm once it's fully implemented
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.List;
+
 final class EditDistanceScorer {
 
-    private static final EditDistanceScorer sInstance = new EditDistanceScorer();
+    private static final String TAG = "EditDistanceScorer";
 
-    public static final String NAME = "EDIT_DISTANCE";
+    // TODO(b/70291841): STOPSHIP - set to false before launching
+    private static final boolean DEBUG = true;
+
+    static final String DEFAULT_ALGORITHM = "EDIT_DISTANCE";
 
     /**
-     * Gets the singleton instance.
-     */
-    public static EditDistanceScorer getInstance() {
-        return sInstance;
-    }
-
-    private EditDistanceScorer() {
-    }
-
-    /**
-     * Returns the classification score between an actual {@link AutofillValue} filled
-     * by the user and the expected value predicted by an autofill service.
+     * Gets the field classification score of 2 values based on the edit distance between them.
      *
-     * <p>A full-match is {@code 1.0} (representing 100%), a full mismatch is {@code 0.0} and
-     * partial mathces are something in between, typically using edit-distance algorithms.
-     *
+     * <p>The score is defined as: @(max_length - edit_distance) / max_length
      */
-    public float getScore(@NonNull AutofillValue actualValue, @NonNull String userDataValue) {
+    @VisibleForTesting
+    static float getScore(@Nullable AutofillValue actualValue, @Nullable String userDataValue) {
         if (actualValue == null || !actualValue.isText() || userDataValue == null) return 0;
-        // TODO(b/70291841): implement edit distance - currently it's returning either 0, 100%, or
-        // partial match when number of chars match
-        final String textValue = actualValue.getTextValue().toString();
-        final int total = textValue.length();
-        if (total != userDataValue.length()) return 0F;
 
-        int matches = 0;
-        for (int i = 0; i < total; i++) {
-            if (Character.toLowerCase(textValue.charAt(i)) == Character
-                    .toLowerCase(userDataValue.charAt(i))) {
-                matches++;
+        final String actualValueText = actualValue.getTextValue().toString();
+        final int actualValueLength = actualValueText.length();
+        final int userDatalength = userDataValue.length();
+        if (userDatalength == 0) {
+            return (actualValueLength == 0) ? 1 : 0;
+        }
+
+        final int distance = editDistance(actualValueText.toLowerCase(),
+                userDataValue.toLowerCase());
+        final int maxLength = Math.max(actualValueLength, userDatalength);
+        return ((float) maxLength - distance) / maxLength;
+    }
+
+    /**
+     * Computes the edit distance (number of insertions, deletions or substitutions to edit one
+     * string into the other) between two strings. In particular, this will compute the Levenshtein
+     * distance.
+     *
+     * <p>See http://en.wikipedia.org/wiki/Levenshtein_distance for details.
+     *
+     * @param s the first string to compare
+     * @param t the second string to compare
+     * @return the edit distance between the two strings
+     */
+    // Note: copied verbatim from com.android.tools.lint.detector.api.LintUtils.java
+    public static int editDistance(@NonNull String s, @NonNull String t) {
+        return editDistance(s, t, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Computes the edit distance (number of insertions, deletions or substitutions to edit one
+     * string into the other) between two strings. In particular, this will compute the Levenshtein
+     * distance.
+     *
+     * <p>See http://en.wikipedia.org/wiki/Levenshtein_distance for details.
+     *
+     * @param s the first string to compare
+     * @param t the second string to compare
+     * @param max the maximum edit distance that we care about; if for example the string length
+     *     delta is greater than this we don't bother computing the exact edit distance since the
+     *     caller has indicated they're not interested in the result
+     * @return the edit distance between the two strings, or some other value greater than that if
+     *     the edit distance is at least as big as the {@code max} parameter
+     */
+    // Note: copied verbatim from com.android.tools.lint.detector.api.LintUtils.java
+    private static int editDistance(@NonNull String s, @NonNull String t, int max) {
+        if (s.equals(t)) {
+            return 0;
+        }
+
+        if (Math.abs(s.length() - t.length()) > max) {
+            // The string lengths differ more than the allowed edit distance;
+            // no point in even attempting to compute the edit distance (requires
+            // O(n*m) storage and O(n*m) speed, where n and m are the string lengths)
+            return Integer.MAX_VALUE;
+        }
+
+        int m = s.length();
+        int n = t.length();
+        int[][] d = new int[m + 1][n + 1];
+        for (int i = 0; i <= m; i++) {
+            d[i][0] = i;
+        }
+        for (int j = 0; j <= n; j++) {
+            d[0][j] = j;
+        }
+        for (int j = 1; j <= n; j++) {
+            for (int i = 1; i <= m; i++) {
+                if (s.charAt(i - 1) == t.charAt(j - 1)) {
+                    d[i][j] = d[i - 1][j - 1];
+                } else {
+                    int deletion = d[i - 1][j] + 1;
+                    int insertion = d[i][j - 1] + 1;
+                    int substitution = d[i - 1][j - 1] + 1;
+                    d[i][j] = Math.min(deletion, Math.min(insertion, substitution));
+                }
             }
         }
 
-        return ((float) matches) / total;
+        return d[m][n];
     }
+    /**
+     * Gets the scores in a batch.
+     */
+    static float[][] getScores(@NonNull List<AutofillValue> actualValues,
+            @NonNull List<String> userDataValues) {
+        final int actualValuesSize = actualValues.size();
+        final int userDataValuesSize = userDataValues.size();
+        if (DEBUG) {
+            Log.d(TAG, "getScores() will return a " + actualValuesSize + "x"
+                    + userDataValuesSize + " matrix for " + DEFAULT_ALGORITHM);
+        }
+        final float[][] scores = new float[actualValuesSize][userDataValuesSize];
+
+        for (int i = 0; i < actualValuesSize; i++) {
+            for (int j = 0; j < userDataValuesSize; j++) {
+                final float score = getScore(actualValues.get(i), userDataValues.get(j));
+                scores[i][j] = score;
+            }
+        }
+        return scores;
+    }
+
 }
diff --git a/packages/ExtServices/tests/src/android/ext/services/autofill/AutofillFieldClassificationServiceImplTest.java b/packages/ExtServices/tests/src/android/ext/services/autofill/AutofillFieldClassificationServiceImplTest.java
new file mode 100644
index 0000000..48c076e
--- /dev/null
+++ b/packages/ExtServices/tests/src/android/ext/services/autofill/AutofillFieldClassificationServiceImplTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+package android.ext.services.autofill;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.view.autofill.AutofillValue;
+
+/**
+ * Contains the base tests that does not rely on the specific algorithm implementation.
+ */
+public class AutofillFieldClassificationServiceImplTest {
+
+    private final AutofillFieldClassificationServiceImpl mService =
+            new AutofillFieldClassificationServiceImpl();
+
+    @Test
+    public void testOnGetScores_nullActualValues() {
+        assertThat(mService.onGetScores(null, null, null, Arrays.asList("whatever"))).isNull();
+    }
+
+    @Test
+    public void testOnGetScores_emptyActualValues() {
+        assertThat(mService.onGetScores(null, null, Collections.emptyList(),
+                Arrays.asList("whatever"))).isNull();
+    }
+
+    @Test
+    public void testOnGetScores_nullUserDataValues() {
+        assertThat(mService.onGetScores(null, null,
+                Arrays.asList(AutofillValue.forText("whatever")), null)).isNull();
+    }
+
+    @Test
+    public void testOnGetScores_emptyUserDataValues() {
+        assertThat(mService.onGetScores(null, null,
+                Arrays.asList(AutofillValue.forText("whatever")), Collections.emptyList()))
+                        .isNull();
+    }
+}
diff --git a/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java b/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
index cc15719..afe2236 100644
--- a/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -13,65 +13,109 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package android.ext.services.autofill;
 
-import static com.google.common.truth.Truth.assertThat;
+import static android.ext.services.autofill.EditDistanceScorer.getScore;
+import static android.ext.services.autofill.EditDistanceScorer.getScores;
+import static android.view.autofill.AutofillValue.forText;
 
-import android.support.test.runner.AndroidJUnit4;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import android.view.autofill.AutofillValue;
 
 import org.junit.Test;
-import org.junit.runner.RunWith;
 
-@RunWith(AndroidJUnit4.class)
+import java.util.Arrays;
+import java.util.List;
+
 public class EditDistanceScorerTest {
 
-    private final EditDistanceScorer mScorer = EditDistanceScorer.getInstance();
-
     @Test
     public void testGetScore_nullValue() {
-        assertFloat(mScorer.getScore(null, "D'OH!"), 0);
+        assertFloat(getScore(null, "D'OH!"), 0);
     }
 
     @Test
     public void testGetScore_nonTextValue() {
-        assertFloat(mScorer.getScore(AutofillValue.forToggle(true), "D'OH!"), 0);
+        assertFloat(getScore(AutofillValue.forToggle(true), "D'OH!"), 0);
     }
 
     @Test
     public void testGetScore_nullUserData() {
-        assertFloat(mScorer.getScore(AutofillValue.forText("D'OH!"), null), 0);
+        assertFloat(getScore(AutofillValue.forText("D'OH!"), null), 0);
     }
 
     @Test
     public void testGetScore_fullMatch() {
-        assertFloat(mScorer.getScore(AutofillValue.forText("D'OH!"), "D'OH!"), 1);
+        assertFloat(getScore(AutofillValue.forText("D'OH!"), "D'OH!"), 1);
+        assertFloat(getScore(AutofillValue.forText(""), ""), 1);
     }
 
     @Test
     public void testGetScore_fullMatchMixedCase() {
-        assertFloat(mScorer.getScore(AutofillValue.forText("D'OH!"), "D'oH!"), 1);
+        assertFloat(getScore(AutofillValue.forText("D'OH!"), "D'oH!"), 1);
     }
 
-    // TODO(b/70291841): might need to change it once it supports different sizes
     @Test
     public void testGetScore_mismatchDifferentSizes() {
-        assertFloat(mScorer.getScore(AutofillValue.forText("One"), "MoreThanOne"), 0);
-        assertFloat(mScorer.getScore(AutofillValue.forText("MoreThanOne"), "One"), 0);
+        assertFloat(getScore(AutofillValue.forText("X"), "Xy"), 0.50F);
+        assertFloat(getScore(AutofillValue.forText("Xy"), "X"), 0.50F);
+        assertFloat(getScore(AutofillValue.forText("One"), "MoreThanOne"), 0.27F);
+        assertFloat(getScore(AutofillValue.forText("MoreThanOne"), "One"), 0.27F);
+        assertFloat(getScore(AutofillValue.forText("1600 Amphitheatre Parkway"),
+                "1600 Amphitheatre Pkwy"), 0.88F);
+        assertFloat(getScore(AutofillValue.forText("1600 Amphitheatre Pkwy"),
+                "1600 Amphitheatre Parkway"), 0.88F);
     }
 
     @Test
     public void testGetScore_partialMatch() {
-        assertFloat(mScorer.getScore(AutofillValue.forText("Dude"), "Dxxx"), 0.25F);
-        assertFloat(mScorer.getScore(AutofillValue.forText("Dude"), "DUxx"), 0.50F);
-        assertFloat(mScorer.getScore(AutofillValue.forText("Dude"), "DUDx"), 0.75F);
-        assertFloat(mScorer.getScore(AutofillValue.forText("Dxxx"), "Dude"), 0.25F);
-        assertFloat(mScorer.getScore(AutofillValue.forText("DUxx"), "Dude"), 0.50F);
-        assertFloat(mScorer.getScore(AutofillValue.forText("DUDx"), "Dude"), 0.75F);
+        assertFloat(getScore(AutofillValue.forText("Dude"), "Dxxx"), 0.25F);
+        assertFloat(getScore(AutofillValue.forText("Dude"), "DUxx"), 0.50F);
+        assertFloat(getScore(AutofillValue.forText("Dude"), "DUDx"), 0.75F);
+        assertFloat(getScore(AutofillValue.forText("Dxxx"), "Dude"), 0.25F);
+        assertFloat(getScore(AutofillValue.forText("DUxx"), "Dude"), 0.50F);
+        assertFloat(getScore(AutofillValue.forText("DUDx"), "Dude"), 0.75F);
+    }
+
+    @Test
+    public void testGetScores() {
+        final List<AutofillValue> actualValues = Arrays.asList(forText("A"), forText("b"));
+        final List<String> userDataValues = Arrays.asList("a", "B", "ab", "c");
+        final float[][] expectedScores = new float[][] {
+            new float[] { 1F, 0F, 0.5F, 0F },
+            new float[] { 0F, 1F, 0.5F, 0F }
+        };
+        final float[][] actualScores = getScores(actualValues, userDataValues);
+
+        // Unfortunately, Truth does not have an easy way to compare float matrices and show useful
+        // messages in case of error, so we need to check.
+        assertWithMessage("actual=%s, expected=%s", toString(actualScores),
+                toString(expectedScores)).that(actualScores.length).isEqualTo(2);
+        assertWithMessage("actual=%s, expected=%s", toString(actualScores),
+                toString(expectedScores)).that(actualScores[0].length).isEqualTo(4);
+        assertWithMessage("actual=%s, expected=%s", toString(actualScores),
+                toString(expectedScores)).that(actualScores[1].length).isEqualTo(4);
+        for (int i = 0; i < actualScores.length; i++) {
+            final float[] line = actualScores[i];
+            for (int j = 0; j < line.length; j++) {
+                float cell = line[j];
+                assertWithMessage("wrong score at [%s, %s]", i, j).that(cell).isWithin(0.01F)
+                        .of(expectedScores[i][j]);
+            }
+        }
     }
 
     public static void assertFloat(float actualValue, float expectedValue) {
-        assertThat(actualValue).isWithin(1.0e-10f).of(expectedValue);
+        assertThat(actualValue).isWithin(0.01F).of(expectedValue);
+    }
+
+    public static String toString(float[][] matrix) {
+        final StringBuilder string = new StringBuilder("[ ");
+        for (int i = 0; i < matrix.length; i++) {
+            string.append(Arrays.toString(matrix[i])).append(" ");
+        }
+        return string.append(" ]").toString();
     }
 }
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
index 93df340..461d62e 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
@@ -24,7 +24,7 @@
             <group android:name="icon" android:pivotX="12" android:pivotY="12">
                 <!-- Tint color to be set directly -->
                 <path android:fillColor="#FFFFFFFF"
-                      android:pathData="M17,1.01L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3c0,-1.1 -0.9,-1.99 -2,-1.99zM17,19H7V5h10v14z"/>
+                    android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7l0,-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7z"/>
             </group>
         </vector>
     </aapt:attr>
diff --git a/packages/SystemUI/res/layout/wireless_charging_layout.xml b/packages/SystemUI/res/layout/wireless_charging_layout.xml
index 113282b..85a325a 100644
--- a/packages/SystemUI/res/layout/wireless_charging_layout.xml
+++ b/packages/SystemUI/res/layout/wireless_charging_layout.xml
@@ -44,13 +44,6 @@
             android:layout_gravity="center"
             android:textSize="32sp"
             android:textColor="?attr/wallpaperTextColor"/>
-
-        <TextView
-            android:id="@+id/wireless_charging_secondary_text"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:textColor="?attr/wallpaperTextColor"/>
     </LinearLayout>
 
 </FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2c73f1e..60129e6 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -519,8 +519,8 @@
     <string name="accessibility_quick_settings_airplane_changed_off">Airplane mode turned off.</string>
     <!-- Announcement made when the airplane mode changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_airplane_changed_on">Airplane mode turned on.</string>
-    <!-- Content description of the do not disturb tile in quick settings when on in priority (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_quick_settings_dnd_priority_on">Do not disturb on, priority only.</string>
+    <!-- Content description of the do not disturb tile in quick settings when on in the default priority mode (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_dnd_priority_on">Do not disturb on.</string>
     <!-- Content description of the do not disturb tile in quick settings when on in none (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_dnd_none_on">Do not disturb on, total silence.</string>
     <!-- Content description of the do not disturb tile in quick settings when on in alarms only (not shown on the screen). [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
index b8a07cd..63b7ae2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
@@ -60,7 +60,7 @@
                                         .setMessage(R.string.error_disable_esim_msg)
                                         .setTitle(R.string.error_disable_esim_title)
                                         .setCancelable(false /* cancelable */)
-                                        .setNeutralButton(R.string.ok, null /* listener */);
+                                        .setPositiveButton(R.string.ok, null /* listener */);
                         AlertDialog alertDialog = builder.create();
                         alertDialog.getWindow().setType(
                                 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index e790061..9a20c81 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -388,6 +388,7 @@
                 mBounds.set(mInfo.displayCutout.getBounds());
                 localBounds(mBoundingRect);
                 mInfo.displayCutout.getBounds().getBoundaryPath(mBoundingPath);
+                invalidate();
                 newVisible = VISIBLE;
             } else {
                 newVisible = GONE;
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index 8f87d64..9887533 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -65,9 +65,6 @@
         // amount of battery:
         final TextView mPercentage = findViewById(R.id.wireless_charging_percentage);
 
-        // (optional) time until full charge if available
-        final TextView mSecondaryText = findViewById(R.id.wireless_charging_secondary_text);
-
         if (batteryLevel != UNKNOWN_BATTERY_LEVEL) {
             mPercentage.setText(NumberFormat.getPercentInstance().format(mBatteryLevel / 100f));
             mPercentage.setAlpha(0);
@@ -110,17 +107,10 @@
         circleFadeAnimator.setInterpolator(Interpolators.LINEAR);
         circleFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset);
 
-        // Animation Opacity: secondary text animation fades from 1 to 0 opacity
-        ValueAnimator secondaryTextFadeAnimator = ObjectAnimator.ofFloat(mSecondaryText, "alpha",
-                1, 0);
-        circleFadeAnimator.setDuration(chargingAnimationFadeDuration);
-        secondaryTextFadeAnimator.setInterpolator(Interpolators.LINEAR);
-        secondaryTextFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset);
-
         // play all animations together
         AnimatorSet animatorSet = new AnimatorSet();
         animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator,
-                circleFadeAnimator, secondaryTextFadeAnimator);
+                circleFadeAnimator);
         animatorSet.start();
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index f3a2ae3..8427e32 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -215,15 +215,18 @@
         switch (zen) {
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
                 state.contentDescription = mContext.getString(
-                        R.string.accessibility_quick_settings_dnd_priority_on);
+                        R.string.accessibility_quick_settings_dnd_priority_on) + ", "
+                        + state.secondaryLabel;
                 break;
             case Global.ZEN_MODE_NO_INTERRUPTIONS:
                 state.contentDescription = mContext.getString(
-                        R.string.accessibility_quick_settings_dnd_none_on);
+                        R.string.accessibility_quick_settings_dnd_none_on) + ", "
+                        + state.secondaryLabel;
                 break;
             case ZEN_MODE_ALARMS:
                 state.contentDescription = mContext.getString(
-                        R.string.accessibility_quick_settings_dnd_alarms_on);
+                        R.string.accessibility_quick_settings_dnd_alarms_on) + ", "
+                        + state.secondaryLabel;
                 break;
             default:
                 state.contentDescription = mContext.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
index 5c21fd1..6560f8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.database.ContentObserver;
+import android.media.AudioAttributes;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.UserHandle;
@@ -30,6 +31,11 @@
     private final Vibrator mVibrator;
     private final Context mContext;
     private boolean mHapticFeedbackEnabled;
+    private static final AudioAttributes STATUS_BAR_VIBRATION_ATTRIBUTES =
+            new AudioAttributes.Builder()
+                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+                    .build();
 
     final private ContentObserver mVibrationObserver = new ContentObserver(Handler.getMain()) {
         @Override
@@ -51,7 +57,8 @@
     public void vibrate(final int effectId) {
         if (mHapticFeedbackEnabled) {
             AsyncTask.execute(() ->
-                    mVibrator.vibrate(VibrationEffect.get(effectId, false /* fallback */)));
+                    mVibrator.vibrate(VibrationEffect.get(effectId, false /* fallback */),
+                            STATUS_BAR_VIBRATION_ATTRIBUTES));
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index ce8e746..91483bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -112,6 +112,7 @@
 
     public static final String TAG = "NavigationBar";
     private static final boolean DEBUG = false;
+    private static final boolean DEBUG_ROTATION = true;
     private static final String EXTRA_DISABLE_STATE = "disabled_state";
 
     private final static int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
@@ -343,10 +344,19 @@
             boolean showImeSwitcher) {
         boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0;
         int hints = mNavigationIconHints;
-        if (imeShown && backDisposition != InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS) {
-            hints |= NAVIGATION_HINT_BACK_ALT;
-        } else {
-            hints &= ~NAVIGATION_HINT_BACK_ALT;
+        switch (backDisposition) {
+            case InputMethodService.BACK_DISPOSITION_DEFAULT:
+            case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS:
+            case InputMethodService.BACK_DISPOSITION_WILL_DISMISS:
+                if (imeShown) {
+                    hints |= NAVIGATION_HINT_BACK_ALT;
+                } else {
+                    hints &= ~NAVIGATION_HINT_BACK_ALT;
+                }
+                break;
+            case InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING:
+                hints &= ~NAVIGATION_HINT_BACK_ALT;
+                break;
         }
         if (showImeSwitcher) {
             hints |= NAVIGATION_HINT_IME_SHOWN;
@@ -387,6 +397,16 @@
 
     @Override
     public void onRotationProposal(final int rotation, boolean isValid) {
+        final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
+        if (DEBUG_ROTATION) {
+            Log.v(TAG, "onRotationProposal proposedRotation=" + Surface.rotationToString(rotation)
+                    + ", winRotation=" + Surface.rotationToString(winRotation)
+                    + ", isValid=" + isValid + ", mNavBarWindowState="
+                    + StatusBarManager.windowStateToString(mNavigationBarWindowState)
+                    + ", isRotateButtonVisible=" + (mNavigationBarView == null ? "null" :
+                        mNavigationBarView.isRotateButtonVisible()));
+        }
+
         // This method will be called on rotation suggestion changes even if the proposed rotation
         // is not valid for the top app. Use invalid rotation choices as a signal to remove the
         // rotate button if shown.
@@ -396,7 +416,6 @@
         }
 
         // If window rotation matches suggested rotation, remove any current suggestions
-        final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
         if (rotation == winRotation) {
             getView().removeCallbacks(mRemoveRotationProposal);
             setRotateSuggestionButtonState(false);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 89e7dd1..ee6748e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -26,8 +26,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.database.ContentObserver;
-import android.media.AudioDeviceCallback;
-import android.media.AudioDeviceInfo;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.media.IVolumeController;
@@ -40,6 +39,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.service.notification.Condition;
@@ -59,9 +59,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -77,6 +75,11 @@
 
     private static final int DYNAMIC_STREAM_START_INDEX = 100;
     private static final int VIBRATE_HINT_DURATION = 50;
+    private static final AudioAttributes SONFICIATION_VIBRATION_ATTRIBUTES =
+            new AudioAttributes.Builder()
+                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+                    .build();
 
     static final ArrayMap<Integer, Integer> STREAMS = new ArrayMap<>();
     static {
@@ -299,7 +302,8 @@
 
     public void vibrate() {
         if (mHasVibrator) {
-            mVibrator.vibrate(VIBRATE_HINT_DURATION);
+            mVibrator.vibrate(VibrationEffect.createOneShot(VIBRATE_HINT_DURATION,
+                    VibrationEffect.DEFAULT_AMPLITUDE), SONFICIATION_VIBRATION_ATTRIBUTES);
         }
     }
 
@@ -308,7 +312,7 @@
     }
 
     private void onNotifyVisibleW(boolean visible) {
-        if (mDestroyed) return;
+        if (mDestroyed) return; 
         mAudio.notifyVolumeControllerVisible(mVolumeController, visible);
         if (!visible) {
             if (updateActiveStreamW(-1)) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 91314fe..e94d6bd 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -897,6 +897,9 @@
     }
 
     private String getStreamLabelH(StreamState ss) {
+        if (ss == null) {
+            return "";
+        }
         if (ss.remoteLabel != null) {
             return ss.remoteLabel;
         }
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 74efec9..0763fa1 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -926,6 +926,34 @@
   // total time within the logging window that aware was enabled
   optional int64 enabled_time_ms = 40;
 
+  // maximum number of concurrent publish sessions enabling ranging in a single app
+  optional int32 max_concurrent_publish_with_ranging_in_app = 41;
+
+  // maximum number of concurrent subscribe sessions specifying a geofence in a single app
+  optional int32 max_concurrent_subscribe_with_ranging_in_app = 42;
+
+  // maximum number of concurrent publish sessions enabling ranging in the system
+  optional int32 max_concurrent_publish_with_ranging_in_system = 43;
+
+  // maximum number of concurrent subscribe sessions specifying a geofence in the system
+  optional int32 max_concurrent_subscribe_with_ranging_in_system = 44;
+
+  // histogram of subscribe session geofence minimum (only when specified)
+  repeated HistogramBucket histogram_subscribe_geofence_min = 45;
+
+  // histogram of subscribe session geofence maximum (only when specified)
+  repeated HistogramBucket histogram_subscribe_geofence_max = 46;
+
+  // total number of subscribe sessions which enabled ranging
+  optional int32 num_subscribes_with_ranging = 47;
+
+  // total number of matches (service discovery indication) with ranging provided
+  optional int32 num_matches_with_ranging = 48;
+
+  // total number of matches (service discovery indication) for service discovery with ranging
+  // enabled which did not trigger ranging
+  optional int32 num_matches_without_ranging_for_ranging_enabled_subscribes = 49;
+
   // Histogram bucket for Wi-Fi Aware logs. Range is [start, end)
   message HistogramBucket {
     // lower range of the bucket (inclusive)
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index b6e2dca..d6f6c6c 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1398,7 +1398,7 @@
     // Returns the set of all applications that define an android:backupAgent attribute
     private List<PackageInfo> allAgentPackages() {
         // !!! TODO: cache this and regenerate only when necessary
-        int flags = PackageManager.GET_SIGNATURES;
+        int flags = PackageManager.GET_SIGNING_CERTIFICATES;
         List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags);
         int N = packages.size();
         for (int a = N - 1; a >= 0; a--) {
@@ -1643,7 +1643,7 @@
             }
             try {
                 PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
-                        PackageManager.GET_SIGNATURES);
+                        PackageManager.GET_SIGNING_CERTIFICATES);
                 if (!AppBackupUtils.appIsEligibleForBackup(packageInfo.applicationInfo,
                         mPackageManager)) {
                     BackupObserverUtils.sendBackupOnPackageResult(observer, packageName,
@@ -2353,7 +2353,8 @@
         if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName + " on " + transportName);
         PackageInfo info;
         try {
-            info = mPackageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+            info = mPackageManager.getPackageInfo(packageName,
+                    PackageManager.GET_SIGNING_CERTIFICATES);
         } catch (NameNotFoundException e) {
             Slog.d(TAG, "No such package '" + packageName + "' - not clearing backup data");
             return;
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index 3cf374f..dc28cd1 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -23,6 +23,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.Signature;
@@ -30,6 +31,7 @@
 import android.os.ParcelFileDescriptor;
 import android.util.Slog;
 
+import com.android.server.LocalServices;
 import com.android.server.backup.utils.AppBackupUtils;
 
 import java.io.BufferedInputStream;
@@ -154,7 +156,7 @@
 
     public static List<PackageInfo> getStorableApplications(PackageManager pm) {
         List<PackageInfo> pkgs;
-        pkgs = pm.getInstalledPackages(PackageManager.GET_SIGNATURES);
+        pkgs = pm.getInstalledPackages(PackageManager.GET_SIGNING_CERTIFICATES);
         int N = pkgs.size();
         for (int a = N-1; a >= 0; a--) {
             PackageInfo pkg = pkgs.get(a);
@@ -235,10 +237,17 @@
         if (home != null) {
             try {
                 homeInfo = mPackageManager.getPackageInfo(home.getPackageName(),
-                        PackageManager.GET_SIGNATURES);
+                        PackageManager.GET_SIGNING_CERTIFICATES);
                 homeInstaller = mPackageManager.getInstallerPackageName(home.getPackageName());
                 homeVersion = homeInfo.getLongVersionCode();
-                homeSigHashes = BackupUtils.hashSignatureArray(homeInfo.signatures);
+                Signature[][] signingHistory = homeInfo.signingCertificateHistory;
+                if (signingHistory == null || signingHistory.length == 0) {
+                    Slog.e(TAG, "Home app has no signing history");
+                } else {
+                    // retrieve the newest sigs to back up
+                    Signature[] homeInfoSignatures = signingHistory[signingHistory.length - 1];
+                    homeSigHashes = BackupUtils.hashSignatureArray(homeInfoSignatures);
+                }
             } catch (NameNotFoundException e) {
                 Slog.w(TAG, "Can't access preferred home info");
                 // proceed as though there were no preferred home set
@@ -252,10 +261,11 @@
             //    2. the home app [or absence] we now use differs from the prior state,
             // OR 3. it looks like we use the same home app + version as before, but
             //       the signatures don't match so we treat them as different apps.
+            PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
             final boolean needHomeBackup = (homeVersion != mStoredHomeVersion)
                     || !Objects.equals(home, mStoredHomeComponent)
                     || (home != null
-                        && !BackupUtils.signaturesMatch(mStoredHomeSigHashes, homeInfo));
+                        && !BackupUtils.signaturesMatch(mStoredHomeSigHashes, homeInfo, pmi));
             if (needHomeBackup) {
                 if (DEBUG) {
                     Slog.i(TAG, "Home preference changed; backing up new state " + home);
@@ -304,7 +314,7 @@
                     PackageInfo info = null;
                     try {
                         info = mPackageManager.getPackageInfo(packName,
-                                PackageManager.GET_SIGNATURES);
+                                PackageManager.GET_SIGNING_CERTIFICATES);
                     } catch (NameNotFoundException e) {
                         // Weird; we just found it, and now are told it doesn't exist.
                         // Treat it as having been removed from the device.
@@ -323,9 +333,9 @@
                             continue;
                         }
                     }
-                    
-                    if (info.signatures == null || info.signatures.length == 0)
-                    {
+
+                    Signature[][] signingHistory = info.signingCertificateHistory;
+                    if (signingHistory == null || signingHistory.length == 0) {
                         Slog.w(TAG, "Not backing up package " + packName
                                 + " since it appears to have no signatures.");
                         continue;
@@ -347,8 +357,10 @@
                     } else {
                         outputBufferStream.writeInt(info.versionCode);
                     }
+                    // retrieve the newest sigs to back up
+                    Signature[] infoSignatures = signingHistory[signingHistory.length - 1];
                     writeSignatureHashArray(outputBufferStream,
-                            BackupUtils.hashSignatureArray(info.signatures));
+                            BackupUtils.hashSignatureArray(infoSignatures));
 
                     if (DEBUG) {
                         Slog.v(TAG, "+ writing metadata for " + packName
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index 2e2d3eb..821cca1 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -129,7 +129,7 @@
                 try {
                     PackageInfo info = backupManagerService.getPackageManager().getPackageInfo(
                             pkgName,
-                            PackageManager.GET_SIGNATURES);
+                            PackageManager.GET_SIGNING_CERTIFICATES);
                     set.put(pkgName, info);
                 } catch (NameNotFoundException e) {
                     Slog.w(TAG, "Unknown package " + pkgName + ", skipping");
@@ -240,7 +240,8 @@
 
         // doAllApps supersedes the package set if any
         if (mAllApps) {
-            List<PackageInfo> allPackages = pm.getInstalledPackages(PackageManager.GET_SIGNATURES);
+            List<PackageInfo> allPackages = pm.getInstalledPackages(
+                    PackageManager.GET_SIGNING_CERTIFICATES);
             for (int i = 0; i < allPackages.size(); i++) {
                 PackageInfo pkg = allPackages.get(i);
                 // Exclude system apps if we've been asked to do so
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index f9c36699..2c2dd85 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -181,7 +181,7 @@
         for (String pkg : whichPackages) {
             try {
                 PackageManager pm = backupManagerService.getPackageManager();
-                PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
+                PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNING_CERTIFICATES);
                 mCurrentPackage = info;
                 if (!AppBackupUtils.appIsEligibleForBackup(info.applicationInfo, pm)) {
                     // Cull any packages that have indicated that backups are not permitted,
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index 0ba83cf..11394e66 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -422,7 +422,8 @@
         // package's backup agent.
         try {
             PackageManager pm = backupManagerService.getPackageManager();
-            mCurrentPackage = pm.getPackageInfo(request.packageName, PackageManager.GET_SIGNATURES);
+            mCurrentPackage = pm.getPackageInfo(request.packageName,
+                    PackageManager.GET_SIGNING_CERTIFICATES);
             if (!AppBackupUtils.appIsEligibleForBackup(mCurrentPackage.applicationInfo, pm)) {
                 // The manifest has changed but we had a stale backup request pending.
                 // This won't happen again because the app won't be requesting further
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index 0ca4f25..c1a1c1d 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -36,11 +36,13 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.util.Slog;
 
+import com.android.server.LocalServices;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.FileMetadata;
 import com.android.server.backup.KeyValueAdbRestoreEngine;
@@ -207,8 +209,11 @@
                 if (info.path.equals(BACKUP_MANIFEST_FILENAME)) {
                     Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(
                             info);
+                    PackageManagerInternal pmi = LocalServices.getService(
+                            PackageManagerInternal.class);
                     RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
-                            mBackupManagerService.getPackageManager(), allowApks, info, signatures);
+                            mBackupManagerService.getPackageManager(), allowApks, info, signatures,
+                            pmi);
                     mManifestSignatures.put(info.packageName, signatures);
                     mPackagePolicies.put(pkg, restorePolicy);
                     mPackageInstallers.put(pkg, info.installerPackageName);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index e576b3c..dacde0b 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -40,6 +40,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
@@ -47,6 +48,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.FileMetadata;
 import com.android.server.backup.KeyValueAdbRestoreEngine;
@@ -470,9 +472,11 @@
                 if (info.path.equals(BACKUP_MANIFEST_FILENAME)) {
                     Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(
                             info);
+                    PackageManagerInternal pmi = LocalServices.getService(
+                            PackageManagerInternal.class);
                     RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
                             mBackupManagerService.getPackageManager(), allowApks,
-                            info, signatures);
+                            info, signatures, pmi);
                     mManifestSignatures.put(info.packageName, signatures);
                     mPackagePolicies.put(pkg, restorePolicy);
                     mPackageInstallers.put(pkg, info.installerPackageName);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 3caa1e7..4b467e5 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -43,6 +43,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Bundle;
 import android.os.Message;
@@ -57,6 +58,7 @@
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.AppWidgetBackupBridge;
 import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.BackupUtils;
 import com.android.server.backup.PackageManagerBackupAgent;
@@ -504,7 +506,7 @@
 
             try {
                 mCurrentPackage = backupManagerService.getPackageManager().getPackageInfo(
-                        pkgName, PackageManager.GET_SIGNATURES);
+                        pkgName, PackageManager.GET_SIGNING_CERTIFICATES);
             } catch (NameNotFoundException e) {
                 // Whoops, we thought we could restore this package but it
                 // turns out not to be present.  Skip it.
@@ -619,7 +621,8 @@
         }
 
         Metadata metaInfo = mPmAgent.getRestoredMetadata(packageName);
-        if (!BackupUtils.signaturesMatch(metaInfo.sigHashes, mCurrentPackage)) {
+        PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+        if (!BackupUtils.signaturesMatch(metaInfo.sigHashes, mCurrentPackage, pmi)) {
             Slog.w(TAG, "Signature mismatch restoring " + packageName);
             mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
                     BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH, mCurrentPackage,
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 6780563..5518374 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -25,6 +25,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.os.Process;
 import android.util.Slog;
@@ -37,6 +38,9 @@
  * Utility methods wrapping operations on ApplicationInfo and PackageInfo.
  */
 public class AppBackupUtils {
+
+    private static final boolean DEBUG = false;
+
     /**
      * Returns whether app is eligible for backup.
      *
@@ -88,7 +92,8 @@
     public static boolean appIsRunningAndEligibleForBackupWithTransport(
             @Nullable TransportClient transportClient, String packageName, PackageManager pm) {
         try {
-            PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+            PackageInfo packageInfo = pm.getPackageInfo(packageName,
+                    PackageManager.GET_SIGNING_CERTIFICATES);
             ApplicationInfo applicationInfo = packageInfo.applicationInfo;
             if (!appIsEligibleForBackup(applicationInfo, pm)
                     || appIsStopped(applicationInfo)
@@ -165,13 +170,19 @@
      *
      * <ul>
      *   <li>Source and target have at least one signature each
-     *   <li>Target contains all signatures in source
+     *   <li>Target contains all signatures in source, and nothing more
      * </ul>
      *
+     * or if both source and target have exactly one signature, and they don't match, we check
+     * if the app was ever signed with source signature (i.e. app has rotated key)
+     * Note: key rotation is only supported for apps ever signed with one key, and those apps will
+     * not be allowed to be signed by more certificates in the future
+     *
      * Note that if {@param target} is null we return false.
      */
-    public static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
-        if (target == null) {
+    public static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target,
+            PackageManagerInternal pmi) {
+        if (target == null || target.packageName == null) {
             return false;
         }
 
@@ -187,33 +198,52 @@
             return true;
         }
 
-        Signature[] deviceSigs = target.signatures;
-        if (MORE_DEBUG) {
-            Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceSigs);
-        }
-
         // Don't allow unsigned apps on either end
-        if (ArrayUtils.isEmpty(storedSigs) || ArrayUtils.isEmpty(deviceSigs)) {
+        if (ArrayUtils.isEmpty(storedSigs)) {
             return false;
         }
 
-        // Signatures can be added over time, so the target-device apk needs to contain all the
-        // source-device apk signatures, but not necessarily the other way around.
-        int nStored = storedSigs.length;
-        int nDevice = deviceSigs.length;
+        Signature[][] deviceHistorySigs = target.signingCertificateHistory;
+        if (ArrayUtils.isEmpty(deviceHistorySigs)) {
+            Slog.w(TAG, "signingCertificateHistory is empty, app was either unsigned or the flag" +
+                    " PackageManager#GET_SIGNING_CERTIFICATES was not specified");
+            return false;
+        }
 
-        for (int i = 0; i < nStored; i++) {
-            boolean match = false;
-            for (int j = 0; j < nDevice; j++) {
-                if (storedSigs[i].equals(deviceSigs[j])) {
-                    match = true;
-                    break;
+        if (DEBUG) {
+            Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceHistorySigs);
+        }
+
+        final int nStored = storedSigs.length;
+        if (nStored == 1) {
+            // if the app is only signed with one sig, it's possible it has rotated its key
+            // (the checks with signing history are delegated to PackageManager)
+            // TODO(b/73988180): address the case that app has declared restoreAnyVersion and is
+            // restoring from higher version to lower after having rotated the key (i.e. higher
+            // version has different sig than lower version that we want to restore to)
+            return pmi.isDataRestoreSafe(storedSigs[0], target.packageName);
+        } else {
+            // the app couldn't have rotated keys, since it was signed with multiple sigs - do
+            // a check to see if we find a match for all stored sigs
+            // since app hasn't rotated key, we only need to check with deviceHistorySigs[0]
+            Signature[] deviceSigs = deviceHistorySigs[0];
+            int nDevice = deviceSigs.length;
+
+            // ensure that each stored sig matches an on-device sig
+            for (int i = 0; i < nStored; i++) {
+                boolean match = false;
+                for (int j = 0; j < nDevice; j++) {
+                    if (storedSigs[i].equals(deviceSigs[j])) {
+                        match = true;
+                        break;
+                    }
+                }
+                if (!match) {
+                    return false;
                 }
             }
-            if (!match) {
-                return false;
-            }
+            // we have found a match for all stored sigs
+            return true;
         }
-        return true;
     }
 }
diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
index d2ab099..994d5a9 100644
--- a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
@@ -104,11 +104,16 @@
         printer.println((installerName != null) ? installerName : "");
 
         printer.println(withApk ? "1" : "0");
-        if (pkg.signatures == null) {
+
+        // write the signature block
+        Signature[][] signingHistory = pkg.signingCertificateHistory;
+        if (signingHistory == null) {
             printer.println("0");
         } else {
-            printer.println(Integer.toString(pkg.signatures.length));
-            for (Signature sig : pkg.signatures) {
+            // retrieve the newest sigs to write
+            Signature[] signatures = signingHistory[signingHistory.length - 1];
+            printer.println(Integer.toString(signatures.length));
+            for (Signature sig : signatures) {
                 printer.println(sig.toCharsString());
             }
         }
diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
index 10f0695..df7e6d4 100644
--- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
@@ -30,6 +30,7 @@
 import android.content.pm.PackageInstaller.Session;
 import android.content.pm.PackageInstaller.SessionParams;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -37,6 +38,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.LocalServices;
 import com.android.server.backup.FileMetadata;
 import com.android.server.backup.restore.RestoreDeleteObserver;
 import com.android.server.backup.restore.RestorePolicy;
@@ -142,9 +144,8 @@
                     uninstall = true;
                 } else {
                     try {
-                        PackageInfo pkg = packageManager.getPackageInfo(
-                                info.packageName,
-                                PackageManager.GET_SIGNATURES);
+                        PackageInfo pkg = packageManager.getPackageInfo(info.packageName,
+                                PackageManager.GET_SIGNING_CERTIFICATES);
                         if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP)
                                 == 0) {
                             Slog.w(TAG, "Restore stream contains apk of package "
@@ -154,7 +155,9 @@
                         } else {
                             // So far so good -- do the signatures match the manifest?
                             Signature[] sigs = manifestSignatures.get(info.packageName);
-                            if (AppBackupUtils.signaturesMatch(sigs, pkg)) {
+                            PackageManagerInternal pmi = LocalServices.getService(
+                                    PackageManagerInternal.class);
+                            if (AppBackupUtils.signaturesMatch(sigs, pkg, pmi)) {
                                 // If this is a system-uid app without a declared backup agent,
                                 // don't restore any of the file data.
                                 if ((pkg.applicationInfo.uid < Process.FIRST_APPLICATION_UID)
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index cc26ff8..6dd5284 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -50,6 +50,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.os.Bundle;
 import android.os.Process;
@@ -385,7 +386,8 @@
      * @return a restore policy constant.
      */
     public RestorePolicy chooseRestorePolicy(PackageManager packageManager,
-            boolean allowApks, FileMetadata info, Signature[] signatures) {
+            boolean allowApks, FileMetadata info, Signature[] signatures,
+            PackageManagerInternal pmi) {
         if (signatures == null) {
             return RestorePolicy.IGNORE;
         }
@@ -395,7 +397,7 @@
         // Okay, got the manifest info we need...
         try {
             PackageInfo pkgInfo = packageManager.getPackageInfo(
-                    info.packageName, PackageManager.GET_SIGNATURES);
+                    info.packageName, PackageManager.GET_SIGNING_CERTIFICATES);
             // Fall through to IGNORE if the app explicitly disallows backup
             final int flags = pkgInfo.applicationInfo.flags;
             if ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0) {
@@ -411,7 +413,7 @@
                     // such packages are signed with the platform cert instead of
                     // the app developer's cert, so they're different on every
                     // device.
-                    if (AppBackupUtils.signaturesMatch(signatures, pkgInfo)) {
+                    if (AppBackupUtils.signaturesMatch(signatures, pkgInfo, pmi)) {
                         if ((pkgInfo.applicationInfo.flags
                                 & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
                             Slog.i(TAG, "Package has restoreAnyVersion; taking data");
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index ecf80ba..9756d17 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -1346,8 +1346,9 @@
                 return;
             }
             if (!client.mStartedOps.remove(op)) {
-                throw new IllegalStateException("Operation not started: uid" + op.uid
+                Slog.wtf(TAG, "Operation not started: uid" + op.uid
                         + " pkg=" + op.packageName + " op=" + op.op);
+                return;
             }
             finishOperationLocked(op, /*finishNested*/ false);
             if (op.nesting <= 0) {
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index e884de0..8ea3dd6 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -171,8 +171,8 @@
             if (proto != null) {
                 long freeSpaceToken = proto.start(DiskStatsServiceDumpProto.PARTITIONS_FREE_SPACE);
                 proto.write(DiskStatsFreeSpaceProto.FOLDER, folderType);
-                proto.write(DiskStatsFreeSpaceProto.AVAILABLE_SPACE, avail * bsize / 1024);
-                proto.write(DiskStatsFreeSpaceProto.TOTAL_SPACE, total * bsize / 1024);
+                proto.write(DiskStatsFreeSpaceProto.AVAILABLE_SPACE_KB, avail * bsize / 1024);
+                proto.write(DiskStatsFreeSpaceProto.TOTAL_SPACE_KB, total * bsize / 1024);
                 proto.end(freeSpaceToken);
             } else {
                 pw.print(name);
@@ -247,23 +247,23 @@
             JSONObject json = new JSONObject(jsonString);
             long cachedValuesToken = proto.start(DiskStatsServiceDumpProto.CACHED_FOLDER_SIZES);
 
-            proto.write(DiskStatsCachedValuesProto.AGG_APPS_SIZE,
+            proto.write(DiskStatsCachedValuesProto.AGG_APPS_SIZE_KB,
                     json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY));
-            proto.write(DiskStatsCachedValuesProto.AGG_APPS_DATA_SIZE,
+            proto.write(DiskStatsCachedValuesProto.AGG_APPS_DATA_SIZE_KB,
                     json.getLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY));
-            proto.write(DiskStatsCachedValuesProto.AGG_APPS_CACHE_SIZE,
+            proto.write(DiskStatsCachedValuesProto.AGG_APPS_CACHE_SIZE_KB,
                     json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY));
-            proto.write(DiskStatsCachedValuesProto.PHOTOS_SIZE,
+            proto.write(DiskStatsCachedValuesProto.PHOTOS_SIZE_KB,
                     json.getLong(DiskStatsFileLogger.PHOTOS_KEY));
-            proto.write(DiskStatsCachedValuesProto.VIDEOS_SIZE,
+            proto.write(DiskStatsCachedValuesProto.VIDEOS_SIZE_KB,
                     json.getLong(DiskStatsFileLogger.VIDEOS_KEY));
-            proto.write(DiskStatsCachedValuesProto.AUDIO_SIZE,
+            proto.write(DiskStatsCachedValuesProto.AUDIO_SIZE_KB,
                     json.getLong(DiskStatsFileLogger.AUDIO_KEY));
-            proto.write(DiskStatsCachedValuesProto.DOWNLOADS_SIZE,
+            proto.write(DiskStatsCachedValuesProto.DOWNLOADS_SIZE_KB,
                     json.getLong(DiskStatsFileLogger.DOWNLOADS_KEY));
-            proto.write(DiskStatsCachedValuesProto.SYSTEM_SIZE,
+            proto.write(DiskStatsCachedValuesProto.SYSTEM_SIZE_KB,
                     json.getLong(DiskStatsFileLogger.SYSTEM_KEY));
-            proto.write(DiskStatsCachedValuesProto.OTHER_SIZE,
+            proto.write(DiskStatsCachedValuesProto.OTHER_SIZE_KB,
                     json.getLong(DiskStatsFileLogger.MISC_KEY));
 
             JSONArray packageNamesArray = json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY);
@@ -279,9 +279,9 @@
 
                     proto.write(DiskStatsAppSizesProto.PACKAGE_NAME,
                             packageNamesArray.getString(i));
-                    proto.write(DiskStatsAppSizesProto.APP_SIZE, appSizesArray.getLong(i));
-                    proto.write(DiskStatsAppSizesProto.APP_DATA_SIZE, appDataSizesArray.getLong(i));
-                    proto.write(DiskStatsAppSizesProto.CACHE_SIZE, cacheSizesArray.getLong(i));
+                    proto.write(DiskStatsAppSizesProto.APP_SIZE_KB, appSizesArray.getLong(i));
+                    proto.write(DiskStatsAppSizesProto.APP_DATA_SIZE_KB, appDataSizesArray.getLong(i));
+                    proto.write(DiskStatsAppSizesProto.CACHE_SIZE_KB, cacheSizesArray.getLong(i));
 
                     proto.end(packageToken);
                 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 96633da..31ae472 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -256,6 +256,7 @@
 import android.app.WaitResult;
 import android.app.WindowConfiguration.ActivityType;
 import android.app.WindowConfiguration.WindowingMode;
+import android.app.admin.DevicePolicyCache;
 import android.app.admin.DevicePolicyManager;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
@@ -13727,9 +13728,7 @@
             }
             userId = activity.userId;
         }
-        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-        return (dpm == null) || (!dpm.getScreenCaptureDisabled(null, userId));
+        return !DevicePolicyCache.getInstance().getScreenCaptureDisabled(userId);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
index d7d18a9..690d985 100644
--- a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
@@ -43,6 +43,7 @@
         {Settings.Global.FPS_DEVISOR, ThreadedRenderer.DEBUG_FPS_DIVISOR},
         {Settings.Global.DISPLAY_PANEL_LPM, "sys.display_panel_lpm"},
         {Settings.Global.SYS_UIDCPUPOWER, "sys.uidcpupower"},
+        {Settings.Global.SYS_TRACED, "persist.traced.enable"},
     };
 
 
diff --git a/services/core/java/com/android/server/backup/BackupUtils.java b/services/core/java/com/android/server/backup/BackupUtils.java
index e5d564d..d817534 100644
--- a/services/core/java/com/android/server/backup/BackupUtils.java
+++ b/services/core/java/com/android/server/backup/BackupUtils.java
@@ -18,9 +18,12 @@
 
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.util.Slog;
 
+import com.android.internal.util.ArrayUtils;
+
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
@@ -30,13 +33,13 @@
 public class BackupUtils {
     private static final String TAG = "BackupUtils";
 
-    private static final boolean DEBUG = false; // STOPSHIP if true
+    private static final boolean DEBUG = false;
 
-    public static boolean signaturesMatch(ArrayList<byte[]> storedSigHashes, PackageInfo target) {
-        if (target == null) {
+    public static boolean signaturesMatch(ArrayList<byte[]> storedSigHashes, PackageInfo target,
+            PackageManagerInternal pmi) {
+        if (target == null || target.packageName == null) {
             return false;
         }
-
         // If the target resides on the system partition, we allow it to restore
         // data from the like-named package in a restore set even if the signatures
         // do not match.  (Unlike general applications, those flashed to the system
@@ -47,48 +50,53 @@
             return true;
         }
 
-        // Allow unsigned apps, but not signed on one device and unsigned on the other
-        // !!! TODO: is this the right policy?
-        Signature[] deviceSigs = target.signatures;
-        if (DEBUG) Slog.v(TAG, "signaturesMatch(): stored=" + storedSigHashes
-                + " device=" + deviceSigs);
-        if ((storedSigHashes == null || storedSigHashes.size() == 0)
-                && (deviceSigs == null || deviceSigs.length == 0)) {
-            return true;
-        }
-        if (storedSigHashes == null || deviceSigs == null) {
+        // Don't allow unsigned apps on either end
+        if (ArrayUtils.isEmpty(storedSigHashes)) {
             return false;
         }
 
-        // !!! TODO: this demands that every stored signature match one
-        // that is present on device, and does not demand the converse.
-        // Is this this right policy?
-        final int nStored = storedSigHashes.size();
-        final int nDevice = deviceSigs.length;
-
-        // hash each on-device signature
-        ArrayList<byte[]> deviceHashes = new ArrayList<byte[]>(nDevice);
-        for (int i = 0; i < nDevice; i++) {
-            deviceHashes.add(hashSignature(deviceSigs[i]));
+        Signature[][] deviceHistorySigs = target.signingCertificateHistory;
+        if (ArrayUtils.isEmpty(deviceHistorySigs)) {
+            Slog.w(TAG, "signingCertificateHistory is empty, app was either unsigned or the flag" +
+                    " PackageManager#GET_SIGNING_CERTIFICATES was not specified");
+            return false;
         }
 
-        // now ensure that each stored sig (hash) matches an on-device sig (hash)
-        for (int n = 0; n < nStored; n++) {
-            boolean match = false;
-            final byte[] storedHash = storedSigHashes.get(n);
-            for (int i = 0; i < nDevice; i++) {
-                if (Arrays.equals(storedHash, deviceHashes.get(i))) {
-                    match = true;
-                    break;
+        if (DEBUG) {
+            Slog.v(TAG, "signaturesMatch(): stored=" + storedSigHashes
+                    + " device=" + deviceHistorySigs);
+        }
+
+        final int nStored = storedSigHashes.size();
+        if (nStored == 1) {
+            // if the app is only signed with one sig, it's possible it has rotated its key
+            // the checks with signing history are delegated to PackageManager
+            // TODO(b/73988180): address the case that app has declared restoreAnyVersion and is
+            // restoring from higher version to lower after having rotated the key (i.e. higher
+            // version has different sig than lower version that we want to restore to)
+            return pmi.isDataRestoreSafe(storedSigHashes.get(0), target.packageName);
+        } else {
+            // the app couldn't have rotated keys, since it was signed with multiple sigs - do
+            // a check to see if we find a match for all stored sigs
+            // since app hasn't rotated key, we only need to check with deviceHistorySigs[0]
+            ArrayList<byte[]> deviceHashes = hashSignatureArray(deviceHistorySigs[0]);
+            int nDevice = deviceHashes.size();
+            // ensure that each stored sig matches an on-device sig
+            for (int i = 0; i < nStored; i++) {
+                boolean match = false;
+                for (int j = 0; j < nDevice; j++) {
+                    if (Arrays.equals(storedSigHashes.get(i), deviceHashes.get(j))) {
+                        match = true;
+                        break;
+                    }
+                }
+                if (!match) {
+                    return false;
                 }
             }
-            // match is false when no on-device sig matched one of the stored ones
-            if (!match) {
-                return false;
-            }
+            // we have found a match for all stored sigs
+            return true;
         }
-
-        return true;
     }
 
     public static byte[] hashSignature(byte[] signature) {
diff --git a/services/core/java/com/android/server/media/OWNERS b/services/core/java/com/android/server/media/OWNERS
index 755c1d6..8adea0e 100644
--- a/services/core/java/com/android/server/media/OWNERS
+++ b/services/core/java/com/android/server/media/OWNERS
@@ -1,3 +1,4 @@
 lajos@google.com
 elaurent@google.com
 sungsoo@google.com
+jaewan@google.com
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index ab55553..efca159 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2852,6 +2852,32 @@
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
 
+            } else if ("month_over".equals(fake)) {
+                plans.add(SubscriptionPlan.Builder
+                        .createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"))
+                        .setTitle("G-Mobile is the carriers name who this plan belongs to")
+                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                                SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
+                        .setDataUsage(6 * TrafficStats.GB_IN_BYTES,
+                                ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
+                        .build());
+                plans.add(SubscriptionPlan.Builder
+                        .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
+                        .setTitle("G-Mobile, Throttled after limit")
+                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                                SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
+                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                                ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
+                        .build());
+                plans.add(SubscriptionPlan.Builder
+                        .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
+                        .setTitle("G-Mobile, No data connection after limit")
+                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                                SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
+                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                                ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
+                        .build());
+
             } else if ("month_none".equals(fake)) {
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"))
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1082478..f4360e4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -176,6 +176,7 @@
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.PackageParser.ParseFlags;
 import android.content.pm.PackageParser.ServiceIntentInfo;
+import android.content.pm.PackageParser.SigningDetails;
 import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
 import android.content.pm.PackageStats;
 import android.content.pm.PackageUserState;
@@ -4086,14 +4087,24 @@
             @Nullable ComponentName component, @ComponentType int type) {
         if (type == TYPE_ACTIVITY) {
             final PackageParser.Activity activity = mActivities.mActivities.get(component);
-            return activity != null
-                    ? (activity.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
-                    : false;
+            if (activity == null) {
+                return false;
+            }
+            final boolean visibleToInstantApp =
+                    (activity.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
+            final boolean explicitlyVisibleToInstantApp =
+                    (activity.info.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
+            return visibleToInstantApp && explicitlyVisibleToInstantApp;
         } else if (type == TYPE_RECEIVER) {
             final PackageParser.Activity activity = mReceivers.mActivities.get(component);
-            return activity != null
-                    ? (activity.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
-                    : false;
+            if (activity == null) {
+                return false;
+            }
+            final boolean visibleToInstantApp =
+                    (activity.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
+            final boolean explicitlyVisibleToInstantApp =
+                    (activity.info.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
+            return visibleToInstantApp && !explicitlyVisibleToInstantApp;
         } else if (type == TYPE_SERVICE) {
             final PackageParser.Service service = mServices.mServices.get(component);
             return service != null
@@ -4138,6 +4149,10 @@
             return false;
         }
         if (callerIsInstantApp) {
+            // both caller and target are both instant, but, different applications, filter
+            if (ps.getInstantApp(userId)) {
+                return true;
+            }
             // request for a specific component; if it hasn't been explicitly exposed through
             // property or instrumentation target, filter
             if (component != null) {
@@ -4150,7 +4165,7 @@
                 return !isComponentVisibleToInstantApp(component, componentType);
             }
             // request for application; if no components have been explicitly exposed, filter
-            return ps.getInstantApp(userId) || !ps.pkg.visibleToInstantApps;
+            return !ps.pkg.visibleToInstantApps;
         }
         if (ps.getInstantApp(userId)) {
             // caller can see all components of all instant applications, don't filter
@@ -23383,6 +23398,36 @@
         }
 
         @Override
+        public boolean isDataRestoreSafe(byte[] restoringFromSigHash, String packageName) {
+            SigningDetails sd = getSigningDetails(packageName);
+            if (sd == null) {
+                return false;
+            }
+            return sd.hasSha256Certificate(restoringFromSigHash,
+                    SigningDetails.CertCapabilities.INSTALLED_DATA);
+        }
+
+        @Override
+        public boolean isDataRestoreSafe(Signature restoringFromSig, String packageName) {
+            SigningDetails sd = getSigningDetails(packageName);
+            if (sd == null) {
+                return false;
+            }
+            return sd.hasCertificate(restoringFromSig,
+                    SigningDetails.CertCapabilities.INSTALLED_DATA);
+        }
+
+        private SigningDetails getSigningDetails(@NonNull String packageName) {
+            synchronized (mPackages) {
+                PackageParser.Package p = mPackages.get(packageName);
+                if (p == null) {
+                    return null;
+                }
+                return p.mSigningDetails;
+            }
+        }
+
+        @Override
         public int getPermissionFlagsTEMP(String permName, String packageName, int userId) {
             return PackageManagerService.this.getPermissionFlags(permName, packageName, userId);
         }
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
index 520ed25..eeaa333 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
@@ -18,10 +18,13 @@
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ShortcutInfo;
+import android.content.pm.Signature;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
 import com.android.server.backup.BackupUtils;
 
 import libcore.util.HexEncoding;
@@ -137,7 +140,8 @@
 
     //@DisabledReason
     public int canRestoreTo(ShortcutService s, PackageInfo currentPackage, boolean anyVersionOkay) {
-        if (!BackupUtils.signaturesMatch(mSigHashes, currentPackage)) {
+        PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+        if (!BackupUtils.signaturesMatch(mSigHashes, currentPackage, pmi)) {
             Slog.w(TAG, "Can't restore: Package signature mismatch");
             return ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH;
         }
@@ -159,13 +163,15 @@
     public static ShortcutPackageInfo generateForInstalledPackageForTest(
             ShortcutService s, String packageName, @UserIdInt int packageUserId) {
         final PackageInfo pi = s.getPackageInfoWithSignatures(packageName, packageUserId);
-        if (pi.signatures == null || pi.signatures.length == 0) {
+        // retrieve the newest sigs
+        Signature[][] signingHistory = pi.signingCertificateHistory;
+        if (signingHistory == null || signingHistory.length == 0) {
             Slog.e(TAG, "Can't get signatures: package=" + packageName);
             return null;
         }
+        Signature[] signatures = signingHistory[signingHistory.length - 1];
         final ShortcutPackageInfo ret = new ShortcutPackageInfo(pi.getLongVersionCode(),
-                pi.lastUpdateTime, BackupUtils.hashSignatureArray(pi.signatures),
-                /* shadow=*/ false);
+                pi.lastUpdateTime, BackupUtils.hashSignatureArray(signatures), /* shadow=*/ false);
 
         ret.mBackupSourceBackupAllowed = s.shouldBackupApp(pi);
         ret.mBackupSourceVersionCode = pi.getLongVersionCode();
@@ -185,7 +191,15 @@
             Slog.w(TAG, "Package not found: " + pkg.getPackageName());
             return;
         }
-        mSigHashes = BackupUtils.hashSignatureArray(pi.signatures);
+        // retrieve the newest sigs
+        Signature[][] signingHistory = pi.signingCertificateHistory;
+        if (signingHistory == null || signingHistory.length == 0) {
+            Slog.w(TAG, "Not refreshing signature for " + pkg.getPackageName()
+                    + " since it appears to have no signature history.");
+            return;
+        }
+        Signature[] signatures = signingHistory[signingHistory.length - 1];
+        mSigHashes = BackupUtils.hashSignatureArray(signatures);
     }
 
     public void saveToXml(ShortcutService s, XmlSerializer out, boolean forBackup)
@@ -221,7 +235,6 @@
 
     public void loadFromXml(XmlPullParser parser, boolean fromBackup)
             throws IOException, XmlPullParserException {
-
         // Don't use the version code from the backup file.
         final long versionCode = ShortcutService.parseLongAttribute(parser, ATTR_VERSION,
                 ShortcutInfo.VERSION_CODE_UNKNOWN);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 265cc8e..15b4617 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -3121,7 +3121,8 @@
         try {
             return mIPackageManager.getPackageInfo(
                     packageName, PACKAGE_MATCH_FLAGS
-                            | (getSignatures ? PackageManager.GET_SIGNATURES : 0), userId);
+                            | (getSignatures ? PackageManager.GET_SIGNING_CERTIFICATES : 0),
+                    userId);
         } catch (RemoteException e) {
             // Shouldn't happen.
             Slog.wtf(TAG, "RemoteException", e);
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 954627b..afcedcc 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -720,11 +720,13 @@
         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
         mKernelUidCpuFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
             for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
-                StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3);
-                e.writeInt(uid);
-                e.writeInt(freqIndex);
-                e.writeLong(cpuFreqTimeMs[freqIndex]);
-                pulledData.add(e);
+                if(cpuFreqTimeMs[freqIndex] != 0) {
+                    StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3);
+                    e.writeInt(uid);
+                    e.writeInt(freqIndex);
+                    e.writeLong(cpuFreqTimeMs[freqIndex]);
+                    pulledData.add(e);
+                }
             }
         });
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index be009d2..c2cc191 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -25,7 +25,6 @@
 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
 import static android.app.StatusBarManager.DISABLE_MASK;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
-import static android.content.Intent.ACTION_USER_REMOVED;
 import static android.content.Intent.EXTRA_USER_HANDLE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Process.SYSTEM_UID;
@@ -122,6 +121,7 @@
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.app.IAssistDataReceiver;
+import android.app.admin.DevicePolicyCache;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -380,14 +380,6 @@
                 case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED:
                     mKeyguardDisableHandler.sendEmptyMessage(KEYGUARD_POLICY_CHANGED);
                     break;
-                case ACTION_USER_REMOVED:
-                    final int userId = intent.getIntExtra(EXTRA_USER_HANDLE, USER_NULL);
-                    if (userId != USER_NULL) {
-                        synchronized (mWindowMap) {
-                            mScreenCaptureDisabled.remove(userId);
-                        }
-                    }
-                    break;
             }
         }
     };
@@ -519,13 +511,6 @@
     /** List of window currently causing non-system overlay windows to be hidden. */
     private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
 
-    /**
-     * Stores for each user whether screencapture is disabled
-     * This array is essentially a cache for all userId for
-     * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
-     */
-    private SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
-
     IInputMethodManager mInputMethodManager;
 
     AccessibilityController mAccessibilityController;
@@ -1039,8 +1024,6 @@
         IntentFilter filter = new IntentFilter();
         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
         filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
-        // Listen to user removal broadcasts so that we can remove the user-specific data.
-        filter.addAction(Intent.ACTION_USER_REMOVED);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
         mLatencyTracker = LatencyTracker.getInstance(context);
@@ -1572,41 +1555,32 @@
         }
     }
 
-    /**
-     * Returns whether screen capture is disabled for all windows of a specific user.
-     */
-    boolean isScreenCaptureDisabledLocked(int userId) {
-        Boolean disabled = mScreenCaptureDisabled.get(userId);
-        if (disabled == null) {
-            return false;
-        }
-        return disabled;
-    }
-
     boolean isSecureLocked(WindowState w) {
         if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
             return true;
         }
-        if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) {
+        if (DevicePolicyCache.getInstance().getScreenCaptureDisabled(
+                UserHandle.getUserId(w.mOwnerUid))) {
             return true;
         }
         return false;
     }
 
     /**
-     * Set mScreenCaptureDisabled for specific user
+     * Set whether screen capture is disabled for all windows of a specific user from
+     * the device policy cache.
      */
     @Override
-    public void setScreenCaptureDisabled(int userId, boolean disabled) {
+    public void refreshScreenCaptureDisabled(int userId) {
         int callingUid = Binder.getCallingUid();
         if (callingUid != SYSTEM_UID) {
-            throw new SecurityException("Only system can call setScreenCaptureDisabled.");
+            throw new SecurityException("Only system can call refreshScreenCaptureDisabled.");
         }
 
         synchronized(mWindowMap) {
-            mScreenCaptureDisabled.put(userId, disabled);
             // Update secure surface for all windows belonging to this user.
-            mRoot.setSecureSurfaceState(userId, disabled);
+            mRoot.setSecureSurfaceState(userId,
+                    DevicePolicyCache.getInstance().getScreenCaptureDisabled(userId));
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index ab139db..6e0ccfd 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -70,8 +70,6 @@
                     return runDisplayOverscan(pw);
                 case "scaling":
                     return runDisplayScaling(pw);
-                case "screen-capture":
-                    return runSetScreenCapture(pw);
                 case "dismiss-keyguard":
                     return runDismissKeyguard(pw);
                 case "tracing":
@@ -210,24 +208,6 @@
         return 0;
     }
 
-    private int runSetScreenCapture(PrintWriter pw) throws RemoteException {
-        String userIdStr = getNextArg();
-        String enableStr = getNextArg();
-        int userId;
-        boolean disable;
-
-        try {
-            userId = Integer.parseInt(userIdStr);
-        } catch (NumberFormatException e) {
-            getErrPrintWriter().println("Error: bad number " + e);
-            return -1;
-        }
-
-        disable = !Boolean.parseBoolean(enableStr);
-        mInternal.setScreenCaptureDisabled(userId, disable);
-        return 0;
-    }
-
     private int runDismissKeyguard(PrintWriter pw) throws RemoteException {
         mInterface.dismissKeyguard(null /* callback */, null /* message */);
         return 0;
@@ -265,8 +245,6 @@
         pw.println("    Set overscan area for display.");
         pw.println("  scaling [off|auto]");
         pw.println("    Set display scaling mode.");
-        pw.println("  screen-capture [userId] [true|false]");
-        pw.println("    Enable or disable screen capture.");
         pw.println("  dismiss-keyguard");
         pw.println("    Dismiss the keyguard, prompting user for auth if necessary.");
         if (!IS_USER) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
new file mode 100644
index 0000000..37b5ad1
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package com.android.server.devicepolicy;
+
+import android.app.admin.DevicePolicyCache;
+import android.util.SparseBooleanArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * Implementation of {@link DevicePolicyCache}, to which {@link DevicePolicyManagerService} pushes
+ * policies.
+ *
+ * TODO Move other copies of policies into this class too.
+ */
+public class DevicePolicyCacheImpl extends DevicePolicyCache {
+    /**
+     * Lock object. For simplicity we just always use this as the lock. We could use each object
+     * as a lock object to make it more fine-grained, but that'd make copy-paste error-prone.
+     */
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private final SparseBooleanArray mScreenCaptureDisabled = new SparseBooleanArray();
+
+    public void onUserRemoved(int userHandle) {
+        synchronized (mLock) {
+            mScreenCaptureDisabled.delete(userHandle);
+        }
+    }
+
+    @Override
+    public boolean getScreenCaptureDisabled(int userHandle) {
+        synchronized (mLock) {
+            return mScreenCaptureDisabled.get(userHandle);
+        }
+    }
+
+    public void setScreenCaptureDisabled(int userHandle, boolean disabled) {
+        synchronized (mLock) {
+            mScreenCaptureDisabled.put(userHandle, disabled);
+        }
+    }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ab8a6c4..c7ae570 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -98,6 +98,7 @@
 import android.app.StatusBarManager;
 import android.app.admin.DeviceAdminInfo;
 import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyCache;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.NetworkEvent;
@@ -436,6 +437,8 @@
     private final DeviceAdminServiceController mDeviceAdminServiceController;
     private final OverlayPackagesProvider mOverlayPackagesProvider;
 
+    private final DevicePolicyCacheImpl mPolicyCache = new DevicePolicyCacheImpl();
+
     /**
      * Contains (package-user) pairs to remove. An entry (p, u) implies that removal of package p
      * is requested for user u.
@@ -2176,6 +2179,8 @@
                 Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring.");
                 return;
             }
+            mPolicyCache.onUserRemoved(userHandle);
+
             mOwners.removeProfileOwner(userHandle);
             mOwners.writeProfileOwner(userHandle);
 
@@ -2188,7 +2193,6 @@
             policyFile.delete();
             Slog.i(LOG_TAG, "Removed device policy file " + policyFile.getAbsolutePath());
         }
-        updateScreenCaptureDisabledInWindowManager(userHandle, false /* default value */);
     }
 
     void loadOwners() {
@@ -3395,7 +3399,7 @@
 
     @Override
     void handleStartUser(int userId) {
-        updateScreenCaptureDisabledInWindowManager(userId,
+        updateScreenCaptureDisabled(userId,
                 getScreenCaptureDisabled(null, userId));
         pushUserRestrictions(userId);
 
@@ -6632,7 +6636,7 @@
             if (ap.disableScreenCapture != disabled) {
                 ap.disableScreenCapture = disabled;
                 saveSettingsLocked(userHandle);
-                updateScreenCaptureDisabledInWindowManager(userHandle, disabled);
+                updateScreenCaptureDisabled(userHandle, disabled);
             }
         }
     }
@@ -6664,13 +6668,13 @@
         }
     }
 
-    private void updateScreenCaptureDisabledInWindowManager(final int userHandle,
-            final boolean disabled) {
+    private void updateScreenCaptureDisabled(int userHandle, boolean disabled) {
+        mPolicyCache.setScreenCaptureDisabled(userHandle, disabled);
         mHandler.post(new Runnable() {
             @Override
             public void run() {
                 try {
-                    mInjector.getIWindowManager().setScreenCaptureDisabled(userHandle, disabled);
+                    mInjector.getIWindowManager().refreshScreenCaptureDisabled(userHandle);
                 } catch (RemoteException e) {
                     Log.w(LOG_TAG, "Unable to notify WindowManager.", e);
                 }
@@ -10502,6 +10506,11 @@
                         .getResources().getString(R.string.printing_disabled_by, appLabel);
             }
         }
+
+        @Override
+        protected DevicePolicyCache getDevicePolicyCache() {
+            return mPolicyCache;
+        }
     }
 
     private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
@@ -12658,8 +12667,7 @@
         final DeviceAdminInfo incomingDeviceInfo = findAdmin(target, callingUserId,
                 /* throwForMissingPermission= */ true);
         checkActiveAdminPrecondition(target, incomingDeviceInfo, policy);
-        if (!incomingDeviceInfo.getActivityInfo().metaData
-                .getBoolean(DeviceAdminReceiver.SUPPORT_TRANSFER_OWNERSHIP_META_DATA, false)) {
+        if (!incomingDeviceInfo.supportsTransferOwnership()) {
             throw new IllegalArgumentException("Provided target does not support "
                     + "ownership transfer.");
         }
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
index 86c83d6..d37db20 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
@@ -18,9 +18,14 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.os.Process;
 import android.platform.test.annotations.Presubmit;
@@ -30,6 +35,7 @@
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.testutils.PackageManagerStub;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -45,7 +51,14 @@
     private static final Signature SIGNATURE_3 = generateSignature((byte) 3);
     private static final Signature SIGNATURE_4 = generateSignature((byte) 4);
 
-    private final PackageManagerStub mPackageManagerStub = new PackageManagerStub();
+    private PackageManagerStub mPackageManagerStub;
+    private PackageManagerInternal mMockPackageManagerInternal;
+
+    @Before
+    public void setUp() throws Exception {
+        mPackageManagerStub = new PackageManagerStub();
+        mMockPackageManagerInternal = mock(PackageManagerInternal.class);
+    }
 
     @Test
     public void appIsEligibleForBackup_backupNotAllowed_returnsFalse() throws Exception {
@@ -358,7 +371,8 @@
 
     @Test
     public void signaturesMatch_targetIsNull_returnsFalse() throws Exception {
-        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, null);
+        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, null,
+                mMockPackageManagerInternal);
 
         assertThat(result).isFalse();
     }
@@ -366,10 +380,12 @@
     @Test
     public void signaturesMatch_systemApplication_returnsTrue() throws Exception {
         PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
         packageInfo.applicationInfo = new ApplicationInfo();
         packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
 
-        boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
+        boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo,
+                mMockPackageManagerInternal);
 
         assertThat(result).isTrue();
     }
@@ -378,10 +394,12 @@
     public void signaturesMatch_disallowsUnsignedApps_storedSignatureNull_returnsFalse()
             throws Exception {
         PackageInfo packageInfo = new PackageInfo();
-        packageInfo.signatures = new Signature[] {SIGNATURE_1};
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
         packageInfo.applicationInfo = new ApplicationInfo();
 
-        boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
+        boolean result = AppBackupUtils.signaturesMatch(null, packageInfo,
+                mMockPackageManagerInternal);
 
         assertThat(result).isFalse();
     }
@@ -390,10 +408,12 @@
     public void signaturesMatch_disallowsUnsignedApps_storedSignatureEmpty_returnsFalse()
             throws Exception {
         PackageInfo packageInfo = new PackageInfo();
-        packageInfo.signatures = new Signature[] {SIGNATURE_1};
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
         packageInfo.applicationInfo = new ApplicationInfo();
 
-        boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
+        boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo,
+                mMockPackageManagerInternal);
 
         assertThat(result).isFalse();
     }
@@ -404,11 +424,12 @@
     signaturesMatch_disallowsUnsignedApps_targetSignatureEmpty_returnsFalse()
             throws Exception {
         PackageInfo packageInfo = new PackageInfo();
-        packageInfo.signatures = new Signature[0];
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[0][0];
         packageInfo.applicationInfo = new ApplicationInfo();
 
-        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1},
-                packageInfo);
+        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, packageInfo,
+                mMockPackageManagerInternal);
 
         assertThat(result).isFalse();
     }
@@ -418,11 +439,12 @@
     signaturesMatch_disallowsUnsignedApps_targetSignatureNull_returnsFalse()
             throws Exception {
         PackageInfo packageInfo = new PackageInfo();
-        packageInfo.signatures = null;
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = null;
         packageInfo.applicationInfo = new ApplicationInfo();
 
-        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1},
-                packageInfo);
+        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, packageInfo,
+                mMockPackageManagerInternal);
 
         assertThat(result).isFalse();
     }
@@ -431,10 +453,11 @@
     public void signaturesMatch_disallowsUnsignedApps_bothSignaturesNull_returnsFalse()
             throws Exception {
         PackageInfo packageInfo = new PackageInfo();
-        packageInfo.signatures = null;
+        packageInfo.signingCertificateHistory = null;
         packageInfo.applicationInfo = new ApplicationInfo();
 
-        boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
+        boolean result = AppBackupUtils.signaturesMatch(null, packageInfo,
+                mMockPackageManagerInternal);
 
         assertThat(result).isFalse();
     }
@@ -443,10 +466,12 @@
     public void signaturesMatch_disallowsUnsignedApps_bothSignaturesEmpty_returnsFalse()
             throws Exception {
         PackageInfo packageInfo = new PackageInfo();
-        packageInfo.signatures = new Signature[0];
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[0][0];
         packageInfo.applicationInfo = new ApplicationInfo();
 
-        boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
+        boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo,
+                mMockPackageManagerInternal);
 
         assertThat(result).isFalse();
     }
@@ -458,11 +483,15 @@
         Signature signature3Copy = new Signature(SIGNATURE_3.toByteArray());
 
         PackageInfo packageInfo = new PackageInfo();
-        packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3};
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {
+                {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
+        };
         packageInfo.applicationInfo = new ApplicationInfo();
 
         boolean result = AppBackupUtils.signaturesMatch(
-                new Signature[]{signature3Copy, signature1Copy, signature2Copy}, packageInfo);
+                new Signature[] {signature3Copy, signature1Copy, signature2Copy}, packageInfo,
+                mMockPackageManagerInternal);
 
         assertThat(result).isTrue();
     }
@@ -473,11 +502,15 @@
         Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
 
         PackageInfo packageInfo = new PackageInfo();
-        packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3};
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {
+                {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
+        };
         packageInfo.applicationInfo = new ApplicationInfo();
 
         boolean result = AppBackupUtils.signaturesMatch(
-                new Signature[]{signature2Copy, signature1Copy}, packageInfo);
+                new Signature[]{signature2Copy, signature1Copy}, packageInfo,
+                mMockPackageManagerInternal);
 
         assertThat(result).isTrue();
     }
@@ -488,11 +521,15 @@
         Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
 
         PackageInfo packageInfo = new PackageInfo();
-        packageInfo.signatures = new Signature[]{signature1Copy, signature2Copy};
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {
+                {signature1Copy, signature2Copy}
+        };
         packageInfo.applicationInfo = new ApplicationInfo();
 
         boolean result = AppBackupUtils.signaturesMatch(
-                new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}, packageInfo);
+                new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}, packageInfo,
+                mMockPackageManagerInternal);
 
         assertThat(result).isFalse();
     }
@@ -503,11 +540,77 @@
         Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
 
         PackageInfo packageInfo = new PackageInfo();
-        packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3};
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {
+                {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
+        };
         packageInfo.applicationInfo = new ApplicationInfo();
 
         boolean result = AppBackupUtils.signaturesMatch(
-                new Signature[]{signature1Copy, signature2Copy, SIGNATURE_4}, packageInfo);
+                new Signature[]{signature1Copy, signature2Copy, SIGNATURE_4}, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void signaturesMatch_singleStoredSignatureNoRotation_returnsTrue()
+            throws Exception {
+        Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(signature1Copy,
+                packageInfo.packageName);
+
+        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {signature1Copy},
+                packageInfo, mMockPackageManagerInternal);
+
+        assertThat(result).isTrue();
+    }
+
+    @Test
+    public void signaturesMatch_singleStoredSignatureWithRotationAssumeDataCapability_returnsTrue()
+            throws Exception {
+        Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}, {SIGNATURE_2}};
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        // we know signature1Copy is in history, and we want to assume it has
+        // SigningDetails.CertCapabilities.INSTALLED_DATA capability
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(signature1Copy,
+                packageInfo.packageName);
+
+        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {signature1Copy},
+                packageInfo, mMockPackageManagerInternal);
+
+        assertThat(result).isTrue();
+    }
+
+    @Test
+    public void
+            signaturesMatch_singleStoredSignatureWithRotationAssumeNoDataCapability_returnsFalse()
+            throws Exception {
+        Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}, {SIGNATURE_2}};
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        // we know signature1Copy is in history, but we want to assume it does not have
+        // SigningDetails.CertCapabilities.INSTALLED_DATA capability
+        doReturn(false).when(mMockPackageManagerInternal).isDataRestoreSafe(signature1Copy,
+                packageInfo.packageName);
+
+        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {signature1Copy},
+                packageInfo, mMockPackageManagerInternal);
 
         assertThat(result).isFalse();
     }
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
index 0cdf04b..5f052ce 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
@@ -28,6 +28,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.verifyZeroInteractions;
@@ -37,6 +40,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.os.Bundle;
 import android.os.Process;
@@ -79,6 +83,7 @@
 
     @Mock private BytesReadListener mBytesReadListenerMock;
     @Mock private IBackupManagerMonitor mBackupManagerMonitorMock;
+    @Mock private PackageManagerInternal mMockPackageManagerInternal;
 
     private final PackageManagerStub mPackageManagerStub = new PackageManagerStub();
     private Context mContext;
@@ -139,7 +144,8 @@
         Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(
                 fileMetadata);
         RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
-                mPackageManagerStub, false /* allowApks */, fileMetadata, signatures);
+                mPackageManagerStub, false /* allowApks */, fileMetadata, signatures,
+                mMockPackageManagerInternal);
 
         assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
         assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
@@ -152,7 +158,8 @@
         signatures = tarBackupReader.readAppManifestAndReturnSignatures(
                 fileMetadata);
         restorePolicy = tarBackupReader.chooseRestorePolicy(
-                mPackageManagerStub, false /* allowApks */, fileMetadata, signatures);
+                mPackageManagerStub, false /* allowApks */, fileMetadata, signatures,
+                mMockPackageManagerInternal);
 
         assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
         assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
@@ -214,7 +221,8 @@
                 mBytesReadListenerMock, mBackupManagerMonitorMock);
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                true /* allowApks */, new FileMetadata(), null /* signatures */);
+                true /* allowApks */, new FileMetadata(), null /* signatures */,
+                mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         verifyZeroInteractions(mBackupManagerMonitorMock);
@@ -234,7 +242,8 @@
         PackageManagerStub.sPackageInfo = null;
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                true /* allowApks */, info, new Signature[0] /* signatures */);
+                true /* allowApks */, info, new Signature[0] /* signatures */,
+                mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -258,7 +267,8 @@
         PackageManagerStub.sPackageInfo = null;
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                true /* allowApks */, info, new Signature[0] /* signatures */);
+                true /* allowApks */, info, new Signature[0] /* signatures */,
+                mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -283,7 +293,8 @@
         PackageManagerStub.sPackageInfo = null;
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */);
+                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
+                mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -307,7 +318,8 @@
         PackageManagerStub.sPackageInfo = packageInfo;
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */);
+                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
+                mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -333,7 +345,8 @@
         PackageManagerStub.sPackageInfo = packageInfo;
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */);
+                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
+                mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -358,11 +371,11 @@
         packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
         packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         packageInfo.applicationInfo.backupAgentName = null;
-        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_2};
+        packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_2}};
         PackageManagerStub.sPackageInfo = packageInfo;
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                false /* allowApks */, new FileMetadata(), signatures);
+                false /* allowApks */, new FileMetadata(), signatures, mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -383,16 +396,19 @@
         Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
 
         PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
         packageInfo.applicationInfo = new ApplicationInfo();
         packageInfo.applicationInfo.flags |=
                 ApplicationInfo.FLAG_ALLOW_BACKUP | ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
         packageInfo.applicationInfo.uid = Process.SYSTEM_UID;
         packageInfo.applicationInfo.backupAgentName = "backup.agent";
-        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
+        packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_1}};
         PackageManagerStub.sPackageInfo = packageInfo;
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
+                packageInfo.packageName);
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                false /* allowApks */, new FileMetadata(), signatures);
+                false /* allowApks */, new FileMetadata(), signatures, mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -412,16 +428,19 @@
         Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
 
         PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
         packageInfo.applicationInfo = new ApplicationInfo();
         packageInfo.applicationInfo.flags |=
                 ApplicationInfo.FLAG_ALLOW_BACKUP | ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
         packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         packageInfo.applicationInfo.backupAgentName = null;
-        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
+        packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_1}};
         PackageManagerStub.sPackageInfo = packageInfo;
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
+                packageInfo.packageName);
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                false /* allowApks */, new FileMetadata(), signatures);
+                false /* allowApks */, new FileMetadata(), signatures, mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -444,17 +463,20 @@
         info.version = 1;
 
         PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
         packageInfo.applicationInfo = new ApplicationInfo();
         packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
         packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
         packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         packageInfo.applicationInfo.backupAgentName = null;
-        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
+        packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_1}};
         packageInfo.versionCode = 2;
         PackageManagerStub.sPackageInfo = packageInfo;
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
+                packageInfo.packageName);
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                false /* allowApks */, info, signatures);
+                false /* allowApks */, info, signatures, mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -479,17 +501,20 @@
         info.hasApk = true;
 
         PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
         packageInfo.applicationInfo = new ApplicationInfo();
         packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
         packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
         packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         packageInfo.applicationInfo.backupAgentName = null;
-        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
+        packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_1}};
         packageInfo.versionCode = 1;
         PackageManagerStub.sPackageInfo = packageInfo;
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
+                packageInfo.packageName);
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                true /* allowApks */, info, signatures);
+                true /* allowApks */, info, signatures, mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
         verifyNoMoreInteractions(mBackupManagerMonitorMock);
@@ -510,17 +535,20 @@
         info.version = 2;
 
         PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
         packageInfo.applicationInfo = new ApplicationInfo();
         packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
         packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
         packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         packageInfo.applicationInfo.backupAgentName = null;
-        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
+        packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_1}};
         packageInfo.versionCode = 1;
         PackageManagerStub.sPackageInfo = packageInfo;
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
+                packageInfo.packageName);
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
-                false /* allowApks */, info, signatures);
+                false /* allowApks */, info, signatures, mMockPackageManagerInternal);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 51d27fe..1974750 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -1015,7 +1015,8 @@
                 | ApplicationInfo.FLAG_ALLOW_BACKUP;
         pi.versionCode = version;
         pi.applicationInfo.versionCode = version;
-        pi.signatures = genSignatures(signatures);
+        pi.signatures = null;
+        pi.signingCertificateHistory = new Signature[][] {genSignatures(signatures)};
 
         return pi;
     }
@@ -1103,7 +1104,8 @@
                 !mDisabledPackages.contains(PackageWithUser.of(userId, packageName));
 
         if (getSignatures) {
-            ret.signatures = pi.signatures;
+            ret.signatures = null;
+            ret.signingCertificateHistory = pi.signingCertificateHistory;
         }
 
         return ret;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 845e05d..7815004 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -62,6 +62,7 @@
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -3987,6 +3988,10 @@
         if (!nowBackupAllowed) {
             pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP;
         }
+
+        doReturn(expected != DISABLED_REASON_SIGNATURE_MISMATCH).when(
+                mMockPackageManagerInternal).isDataRestoreSafe(any(byte[].class), anyString());
+
         assertEquals(expected, spi.canRestoreTo(mService, pi, anyVersionOk));
     }
 
@@ -4959,6 +4964,9 @@
         assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
         assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_P0, LAUNCHER_1)));
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(any(byte[].class),
+                anyString());
+
         installPackage(USER_0, CALLING_PACKAGE_1);
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertWith(getCallerVisibleShortcuts())
@@ -5151,6 +5159,10 @@
 
     protected void checkBackupAndRestore_publisherNotRestored(
             int package1DisabledReason) {
+        doReturn(package1DisabledReason != ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH).when(
+                mMockPackageManagerInternal).isDataRestoreSafe(any(byte[].class),
+                eq(CALLING_PACKAGE_1));
+
         installPackage(USER_0, CALLING_PACKAGE_1);
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
@@ -5159,6 +5171,8 @@
         assertFalse(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0)
                 .getPackageInfo().isShadow());
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(
+                any(byte[].class), anyString());
 
         installPackage(USER_0, CALLING_PACKAGE_2);
         runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
@@ -5276,7 +5290,7 @@
 
         addPackage(LAUNCHER_1, LAUNCHER_UID_1, 10, "sigx"); // different signature
 
-        checkBackupAndRestore_launcherNotRestored();
+        checkBackupAndRestore_launcherNotRestored(true);
     }
 
     public void testBackupAndRestore_launcherNoLongerBackupTarget() {
@@ -5285,10 +5299,13 @@
         updatePackageInfo(LAUNCHER_1,
                 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
 
-        checkBackupAndRestore_launcherNotRestored();
+        checkBackupAndRestore_launcherNotRestored(false);
     }
 
-    protected void checkBackupAndRestore_launcherNotRestored() {
+    protected void checkBackupAndRestore_launcherNotRestored(boolean differentSignatures) {
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(
+                any(byte[].class), anyString());
+
         installPackage(USER_0, CALLING_PACKAGE_1);
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
@@ -5307,6 +5324,9 @@
                     "s1", "s2", "s3");
         });
 
+        doReturn(!differentSignatures).when(mMockPackageManagerInternal).isDataRestoreSafe(
+                any(byte[].class), eq(LAUNCHER_1));
+
         // Now we try to restore launcher 1.  Then we realize it's not restorable, so L1 has no pinned
         // shortcuts.
         installPackage(USER_0, LAUNCHER_1);
@@ -5333,6 +5353,9 @@
                     "s2");
         });
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(
+                any(byte[].class), anyString());
+
         installPackage(USER_0, LAUNCHER_2);
         runWithCaller(LAUNCHER_2, USER_0, () -> {
             assertShortcutIds(assertAllPinned(
@@ -5388,6 +5411,8 @@
     }
 
     protected void checkBackupAndRestore_publisherAndLauncherNotRestored() {
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(any(byte[].class),
+                anyString());
         installPackage(USER_0, CALLING_PACKAGE_1);
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
@@ -5501,6 +5526,9 @@
         assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
         assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_P0, LAUNCHER_1)));
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(any(byte[].class),
+                anyString());
+
         installPackage(USER_0, CALLING_PACKAGE_1);
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertWith(getCallerVisibleShortcuts())
@@ -5586,6 +5614,8 @@
                     .areAllDisabled();
         });
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(
+                any(byte[].class), anyString());
         backupAndRestore();
 
         // When re-installing the app, the manifest shortcut should be re-published.
@@ -5695,6 +5725,8 @@
                     .haveIds("s1", "ms1");
         });
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(any(byte[].class),
+                anyString());
         // Backup and *without restarting the service, just call applyRestore()*.
         {
             int prevUid = mInjectedCallingUid;
@@ -5768,6 +5800,9 @@
                     list("ms1", "ms2", "ms3", "ms4", "s1", "s2"), HANDLE_USER_0);
         });
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(
+                any(byte[].class), anyString());
+
         backupAndRestore();
 
         // Lower the version and remove the manifest shortcuts.
@@ -5994,6 +6029,9 @@
         addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "22222");
         addPackage(LAUNCHER_1, LAUNCHER_UID_1, 10, "11111");
 
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(
+                any(byte[].class), anyString());
+
         runWithSystemUid(() -> mService.applyRestore(payload, USER_0));
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java
index 29c98dc..cd7feea 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java
@@ -76,11 +76,13 @@
                 mMyPackage, mMyUserId, /*signature*/ false);
         assertEquals(mMyPackage, pi.packageName);
         assertNull(pi.signatures);
+        assertNull(pi.signingCertificateHistory);
 
         pi = mShortcutService.getPackageInfo(
                 mMyPackage, mMyUserId, /*signature*/ true);
         assertEquals(mMyPackage, pi.packageName);
-        assertNotNull(pi.signatures);
+        assertNull(pi.signatures);
+        assertNotNull(pi.signingCertificateHistory);
 
         pi = mShortcutService.getPackageInfo(
                 "no.such.package", mMyUserId, /*signature*/ true);
diff --git a/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
index c016e61..1ac7cb8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
@@ -15,73 +15,309 @@
  */
 package com.android.server.pm.backup;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser.Package;
 import android.content.pm.Signature;
-import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
 
 import com.android.server.backup.BackupUtils;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 
 @SmallTest
-public class BackupUtilsTest extends AndroidTestCase {
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class BackupUtilsTest {
 
-    private Signature[] genSignatures(String... signatures) {
-        final Signature[] sigs = new Signature[signatures.length];
-        for (int i = 0; i < signatures.length; i++){
-            sigs[i] = new Signature(signatures[i].getBytes());
-        }
-        return sigs;
+    private static final Signature SIGNATURE_1 = generateSignature((byte) 1);
+    private static final Signature SIGNATURE_2 = generateSignature((byte) 2);
+    private static final Signature SIGNATURE_3 = generateSignature((byte) 3);
+    private static final Signature SIGNATURE_4 = generateSignature((byte) 4);
+    private static final byte[] SIGNATURE_HASH_1 = BackupUtils.hashSignature(SIGNATURE_1);
+    private static final byte[] SIGNATURE_HASH_2 = BackupUtils.hashSignature(SIGNATURE_2);
+    private static final byte[] SIGNATURE_HASH_3 = BackupUtils.hashSignature(SIGNATURE_3);
+    private static final byte[] SIGNATURE_HASH_4 = BackupUtils.hashSignature(SIGNATURE_4);
+
+    private PackageManagerInternal mMockPackageManagerInternal;
+
+    @Before
+    public void setUp() throws Exception {
+        mMockPackageManagerInternal = mock(PackageManagerInternal.class);
     }
 
-    private PackageInfo genPackage(String... signatures) {
-        final PackageInfo pi = new PackageInfo();
-        pi.packageName = "package";
-        pi.applicationInfo = new ApplicationInfo();
-        pi.signatures = genSignatures(signatures);
+    @Test
+    public void signaturesMatch_targetIsNull_returnsFalse() throws Exception {
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, null,
+                mMockPackageManagerInternal);
 
-        return pi;
+        assertThat(result).isFalse();
     }
 
-    public void testSignaturesMatch() {
-        final ArrayList<byte[]> stored1 = BackupUtils.hashSignatureArray(Arrays.asList(
-                "abc".getBytes()));
-        final ArrayList<byte[]> stored2 = BackupUtils.hashSignatureArray(Arrays.asList(
-                "abc".getBytes(), "def".getBytes()));
+    @Test
+    public void signaturesMatch_systemApplication_returnsTrue() throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
 
-        PackageInfo pi;
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
 
-        // False for null package.
-        assertFalse(BackupUtils.signaturesMatch(stored1, null));
-
-        // If it's a system app, signatures don't matter.
-        pi = genPackage("xyz");
-        pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
-        assertTrue(BackupUtils.signaturesMatch(stored1, pi));
-
-        // Non system apps.
-        assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("abc")));
-
-        // Superset is okay.
-        assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("abc", "xyz")));
-        assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("xyz", "abc")));
-
-        assertFalse(BackupUtils.signaturesMatch(stored1, genPackage("xyz")));
-        assertFalse(BackupUtils.signaturesMatch(stored1, genPackage("xyz", "def")));
-
-        assertTrue(BackupUtils.signaturesMatch(stored2, genPackage("def", "abc")));
-        assertTrue(BackupUtils.signaturesMatch(stored2, genPackage("x", "def", "abc", "y")));
-
-        // Subset is not okay.
-        assertFalse(BackupUtils.signaturesMatch(stored2, genPackage("abc")));
-        assertFalse(BackupUtils.signaturesMatch(stored2, genPackage("def")));
+        assertThat(result).isTrue();
     }
 
+    @Test
+    public void signaturesMatch_disallowsUnsignedApps_storedSignatureNull_returnsFalse()
+            throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        boolean result = BackupUtils.signaturesMatch(null, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void signaturesMatch_disallowsUnsignedApps_storedSignatureEmpty_returnsFalse()
+            throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isFalse();
+    }
+
+
+    @Test
+    public void
+    signaturesMatch_disallowsUnsignedApps_targetSignatureEmpty_returnsFalse()
+            throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[0][0];
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void
+    signaturesMatch_disallowsUnsignedApps_targetSignatureNull_returnsFalse()
+            throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = null;
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void signaturesMatch_disallowsUnsignedApps_bothSignaturesNull_returnsFalse()
+            throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = null;
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        boolean result = BackupUtils.signaturesMatch(null, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void signaturesMatch_disallowsUnsignedApps_bothSignaturesEmpty_returnsFalse()
+            throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[0][0];
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void signaturesMatch_equalSignatures_returnsTrue() throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {
+                {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
+        };
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        storedSigHashes.add(SIGNATURE_HASH_2);
+        storedSigHashes.add(SIGNATURE_HASH_3);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isTrue();
+    }
+
+    @Test
+    public void signaturesMatch_extraSignatureInTarget_returnsTrue() throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {
+                {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
+        };
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        storedSigHashes.add(SIGNATURE_HASH_2);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isTrue();
+    }
+
+    @Test
+    public void signaturesMatch_extraSignatureInStored_returnsFalse() throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1, SIGNATURE_2}};
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        storedSigHashes.add(SIGNATURE_HASH_2);
+        storedSigHashes.add(SIGNATURE_HASH_3);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void signaturesMatch_oneNonMatchingSignature_returnsFalse() throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {
+                {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
+        };
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        storedSigHashes.add(SIGNATURE_HASH_2);
+        storedSigHashes.add(SIGNATURE_HASH_4);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
+    public void signaturesMatch_singleStoredSignatureNoRotation_returnsTrue()
+            throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(SIGNATURE_HASH_1,
+                packageInfo.packageName);
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isTrue();
+    }
+
+    @Test
+    public void signaturesMatch_singleStoredSignatureWithRotationAssumeDataCapability_returnsTrue()
+            throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}, {SIGNATURE_2}};
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        // we know SIGNATURE_1 is in history, and we want to assume it has
+        // SigningDetails.CertCapabilities.INSTALLED_DATA capability
+        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(SIGNATURE_HASH_1,
+                packageInfo.packageName);
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isTrue();
+    }
+
+    @Test
+    public void
+            signaturesMatch_singleStoredSignatureWithRotationAssumeNoDataCapability_returnsFalse()
+            throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test";
+        packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}, {SIGNATURE_2}};
+        packageInfo.applicationInfo = new ApplicationInfo();
+
+        // we know SIGNATURE_1 is in history, but we want to assume it does not have
+        // SigningDetails.CertCapabilities.INSTALLED_DATA capability
+        doReturn(false).when(mMockPackageManagerInternal).isDataRestoreSafe(SIGNATURE_HASH_1,
+                packageInfo.packageName);
+
+        ArrayList<byte[]> storedSigHashes = new ArrayList<>();
+        storedSigHashes.add(SIGNATURE_HASH_1);
+        boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
+                mMockPackageManagerInternal);
+
+        assertThat(result).isFalse();
+    }
+
+    @Test
     public void testHashSignature() {
         final byte[] sig1 = "abc".getBytes();
         final byte[] sig2 = "def".getBytes();
@@ -115,4 +351,10 @@
         MoreAsserts.assertEquals(hash2a, listA.get(1));
         MoreAsserts.assertEquals(hash2a, listB.get(1));
     }
+
+    private static Signature generateSignature(byte i) {
+        byte[] signatureBytes = new byte[256];
+        signatureBytes[0] = i;
+        return new Signature(signatureBytes);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index b36c7d9..edac8a5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -169,6 +169,7 @@
         verify(mMockAnimationSpec, atLeastOnce()).apply(any(), any(), eq(0L));
     }
 
+    @FlakyTest(bugId = 74780584)
     @Test
     public void testDeferStartingAnimations() throws Exception {
         mSurfaceAnimationRunner.deferStartingAnimations();
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 8219150..7e922e6 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -427,6 +427,7 @@
                 printf("    new GZipSection(%d,", field->number());
                 splitAndPrint(s.args());
                 printf(" NULL),\n");
+                break;
             case SECTION_TOMBSTONE:
                 printf("    new TombstoneSection(%d, \"%s\"),\n", field->number(), s.args().c_str());
                 break;