diff options
365 files changed, 9612 insertions, 4177 deletions
diff --git a/Android.mk b/Android.mk index bbe2faf2e9ed..e2f88e8990bd 100644 --- a/Android.mk +++ b/Android.mk @@ -868,8 +868,12 @@ include $(BUILD_STATIC_JAVA_LIBRARY) $(eval $(call copy-one-file,frameworks/base/config/hiddenapi-blacklist.txt,\ $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST))) -$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-light-greylist.txt,\ - $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST))) + +# Temporarily merge light greylist from two files. Vendor list will become dark +# grey once we remove the UI toast. +$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): frameworks/base/config/hiddenapi-light-greylist.txt \ + frameworks/base/config/hiddenapi-vendor-list.txt + sort $^ > $@ # Generate dark greylist as private API minus (blacklist plus light greylist). diff --git a/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java b/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java index 7a32c0ccda07..e2b75c3f5746 100644 --- a/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java +++ b/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java @@ -118,6 +118,52 @@ public class SQLiteDatabasePerfTest { } @Test + public void testCursorIterateForward() { + // A larger dataset is needed to exceed default CursorWindow size + int datasetSize = DEFAULT_DATASET_SIZE * 50; + insertT1TestDataSet(datasetSize); + + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + try (Cursor cursor = mDatabase + .rawQuery("SELECT _ID, COL_A, COL_B, COL_C FROM T1 ORDER BY _ID", null)) { + int i = 0; + while(cursor.moveToNext()) { + assertEquals(i, cursor.getInt(0)); + assertEquals(i, cursor.getInt(1)); + assertEquals("T1Value" + i, cursor.getString(2)); + assertEquals(1.1 * i, cursor.getDouble(3), 0.0000001d); + i++; + } + assertEquals(datasetSize, i); + } + } + } + + @Test + public void testCursorIterateBackwards() { + // A larger dataset is needed to exceed default CursorWindow size + int datasetSize = DEFAULT_DATASET_SIZE * 50; + insertT1TestDataSet(datasetSize); + + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + try (Cursor cursor = mDatabase + .rawQuery("SELECT _ID, COL_A, COL_B, COL_C FROM T1 ORDER BY _ID", null)) { + int i = datasetSize - 1; + while(cursor.moveToPosition(i)) { + assertEquals(i, cursor.getInt(0)); + assertEquals(i, cursor.getInt(1)); + assertEquals("T1Value" + i, cursor.getString(2)); + assertEquals(1.1 * i, cursor.getDouble(3), 0.0000001d); + i--; + } + assertEquals(-1, i); + } + } + } + + @Test public void testInnerJoin() { mDatabase.setForeignKeyConstraintsEnabled(true); mDatabase.beginTransaction(); @@ -201,8 +247,12 @@ public class SQLiteDatabasePerfTest { } private void insertT1TestDataSet() { + insertT1TestDataSet(DEFAULT_DATASET_SIZE); + } + + private void insertT1TestDataSet(int size) { mDatabase.beginTransaction(); - for (int i = 0; i < DEFAULT_DATASET_SIZE; i++) { + for (int i = 0; i < size; i++) { mDatabase.execSQL("INSERT INTO T1 VALUES (?, ?, ?, ?)", new Object[]{i, i, "T1Value" + i, i * 1.1}); } diff --git a/apct-tests/perftests/core/src/android/text/TextPerfUtils.java b/apct-tests/perftests/core/src/android/text/TextPerfUtils.java index dccb34be9d07..fefda64b51a7 100644 --- a/apct-tests/perftests/core/src/android/text/TextPerfUtils.java +++ b/apct-tests/perftests/core/src/android/text/TextPerfUtils.java @@ -76,7 +76,7 @@ public class TextPerfUtils { } SpannableStringBuilder ssb = new SpannableStringBuilder(cs); - for (int i = 0; i < ssb.length(); i += wordLen) { + for (int i = 0; i < ssb.length(); i += wordLen + 1) { final int spanStart = i; final int spanEnd = (i + wordLen) > ssb.length() ? ssb.length() : i + wordLen; diff --git a/api/current.txt b/api/current.txt index 52ffe6097e77..9c0e630355fc 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5196,6 +5196,7 @@ package android.app { field public static final java.lang.String CATEGORY_ERROR = "err"; field public static final java.lang.String CATEGORY_EVENT = "event"; field public static final java.lang.String CATEGORY_MESSAGE = "msg"; + field public static final java.lang.String CATEGORY_NAVIGATION = "navigation"; field public static final java.lang.String CATEGORY_PROGRESS = "progress"; field public static final java.lang.String CATEGORY_PROMO = "promo"; field public static final java.lang.String CATEGORY_RECOMMENDATION = "recommendation"; @@ -6330,6 +6331,7 @@ package android.app.admin { 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; @@ -6394,7 +6396,6 @@ package android.app.admin { 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 { @@ -7266,6 +7267,7 @@ package android.app.slice { public class SliceManager { method public android.app.slice.Slice bindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public android.app.slice.Slice bindSlice(android.content.Intent, java.util.List<android.app.slice.SliceSpec>); + method public java.util.List<android.net.Uri> getPinnedSlices(); method public java.util.List<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri); method public java.util.Collection<android.net.Uri> getSliceDescendants(android.net.Uri); method public android.net.Uri mapIntentToUri(android.content.Intent); @@ -7418,12 +7420,14 @@ package android.app.usage { method public int getEventType(); method public java.lang.String getPackageName(); method public java.lang.String getShortcutId(); + method public int getStandbyBucket(); method public long getTimeStamp(); field public static final int CONFIGURATION_CHANGE = 5; // 0x5 field public static final int MOVE_TO_BACKGROUND = 2; // 0x2 field public static final int MOVE_TO_FOREGROUND = 1; // 0x1 field public static final int NONE = 0; // 0x0 field public static final int SHORTCUT_INVOCATION = 8; // 0x8 + field public static final int STANDBY_BUCKET_CHANGED = 11; // 0xb field public static final int USER_INTERACTION = 7; // 0x7 } @@ -14436,6 +14440,7 @@ package android.graphics { method public static android.graphics.Typeface createFromFile(java.lang.String); method public static android.graphics.Typeface defaultFromStyle(int); method public int getStyle(); + method public int getWeight(); method public final boolean isBold(); method public final boolean isItalic(); field public static final int BOLD = 1; // 0x1 @@ -16434,8 +16439,8 @@ package android.hardware.camera2.params { } public final class SessionConfiguration { - ctor public SessionConfiguration(int, java.util.List<android.hardware.camera2.params.OutputConfiguration>, java.util.concurrent.Executor, android.hardware.camera2.CameraCaptureSession.StateCallback); - method public java.util.concurrent.Executor getExecutor(); + ctor public SessionConfiguration(int, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler); + method public android.os.Handler getHandler(); method public android.hardware.camera2.params.InputConfiguration getInputConfiguration(); method public java.util.List<android.hardware.camera2.params.OutputConfiguration> getOutputConfigurations(); method public android.hardware.camera2.CaptureRequest getSessionParameters(); @@ -21244,9 +21249,10 @@ package android.inputmethodservice { 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 { @@ -28676,7 +28682,7 @@ package android.net.wifi { field public static final int IEEE8021X = 3; // 0x3 field public static final int NONE = 0; // 0x0 field public static final int WPA_EAP = 2; // 0x2 - field public static final deprecated int WPA_PSK = 1; // 0x1 + field public static final int WPA_PSK = 1; // 0x1 field public static final java.lang.String[] strings; field public static final java.lang.String varName = "key_mgmt"; } @@ -44035,7 +44041,7 @@ package android.text { method public abstract int getSpanTypeId(); } - public class PrecomputedText implements android.text.Spanned { + public class PrecomputedText implements android.text.Spannable { method public char charAt(int); method public static android.text.PrecomputedText create(java.lang.CharSequence, android.text.PrecomputedText.Params); method public int getParagraphCount(); @@ -44049,6 +44055,8 @@ package android.text { method public java.lang.CharSequence getText(); method public int length(); method public int nextSpanTransition(int, int, java.lang.Class); + method public void removeSpan(java.lang.Object); + method public void setSpan(java.lang.Object, int, int, int); method public java.lang.CharSequence subSequence(int, int); } diff --git a/api/system-current.txt b/api/system-current.txt index d543629ad2d9..af783caf7c12 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -261,6 +261,7 @@ package android.app { public class AppOpsManager { method public static java.lang.String[] getOpStrs(); + method public void setMode(java.lang.String, int, java.lang.String, int); method public void setUidMode(java.lang.String, int, int); field public static final java.lang.String OPSTR_ACCEPT_HANDOVER = "android:accept_handover"; field public static final java.lang.String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications"; @@ -335,6 +336,9 @@ package android.app { } public class Notification implements android.os.Parcelable { + field public static final java.lang.String CATEGORY_CAR_EMERGENCY = "car_emergency"; + field public static final java.lang.String CATEGORY_CAR_INFORMATION = "car_information"; + field public static final java.lang.String CATEGORY_CAR_WARNING = "car_warning"; field public static final java.lang.String EXTRA_ALLOW_DURING_SETUP = "android.allowDuringSetup"; field public static final java.lang.String EXTRA_SUBSTITUTE_APP_NAME = "android.substName"; field public static final int FLAG_AUTOGROUP_SUMMARY = 1024; // 0x400 @@ -718,10 +722,8 @@ package android.app.usage { public static final class UsageEvents.Event { method public java.lang.String getNotificationChannelId(); - method public int getStandbyBucket(); field public static final int NOTIFICATION_INTERRUPTION = 12; // 0xc field public static final int NOTIFICATION_SEEN = 10; // 0xa - field public static final int STANDBY_BUCKET_CHANGED = 11; // 0xb } public final class UsageStatsManager { @@ -5261,12 +5263,13 @@ package android.telephony { } public class UiccSlotInfo implements android.os.Parcelable { - ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int); + ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int, boolean); method public int describeContents(); method public java.lang.String getCardId(); method public int getCardStateInfo(); method public boolean getIsActive(); method public boolean getIsEuicc(); + method public boolean getIsExtendedApduSupported(); method public int getLogicalSlotIdx(); method public void writeToParcel(android.os.Parcel, int); field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1 diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp index 35701446e9d9..2b85ec08f9a6 100644 --- a/cmds/incidentd/src/FdBuffer.cpp +++ b/cmds/incidentd/src/FdBuffer.cpp @@ -34,11 +34,11 @@ FdBuffer::FdBuffer() 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 @@ status_t FdBuffer::read(int fd, int64_t timeout) { 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 @@ status_t FdBuffer::read(int fd, int64_t timeout) { return NO_ERROR; } -status_t FdBuffer::readFully(int fd) { +status_t FdBuffer::readFully(unique_fd* fd) { mStartTime = uptimeMillis(); while (true) { @@ -99,10 +99,10 @@ status_t FdBuffer::readFully(int fd) { } 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 @@ status_t FdBuffer::readFully(int fd) { 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 @@ status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64 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 @@ status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64 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 @@ status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64 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 @@ status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64 // 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 @@ status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64 } // 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 34ebcf50905d..db3a74b78178 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 @@ public: * 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 @@ public: * * 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 d02b4dd99067..aeccefdd15c0 100644 --- a/cmds/incidentd/src/IncidentService.cpp +++ b/cmds/incidentd/src/IncidentService.cpp @@ -352,7 +352,8 @@ status_t IncidentService::cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<Str 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 5cde5a94e2dd..ab4e764d92a4 100644 --- a/cmds/incidentd/src/Section.cpp +++ b/cmds/incidentd/src/Section.cpp @@ -277,8 +277,8 @@ FileSection::~FileSection() {} 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 @@ status_t FileSection::Execute(ReportRequestSet* requests) const { } // 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 @@ GZipSection::~GZipSection() {} 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 @@ status_t GZipSection::Execute(ReportRequestSet* requests) const { 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 @@ status_t GZipSection::Execute(ReportRequestSet* requests) const { // ================================================================================ struct WorkerThreadData : public virtual RefBase { const WorkerThreadSection* section; - int fds[2]; + Fpipe pipe; // Lock protects these fields mutex lock; @@ -433,16 +432,10 @@ struct WorkerThreadData : public virtual RefBase { 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 @@ WorkerThreadSection::~WorkerThreadSection() {} 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 @@ static void* worker_thread_func(void* cookie) { 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 @@ status_t WorkerThreadSection::Execute(ReportRequestSet* requests) const { 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 @@ status_t WorkerThreadSection::Execute(ReportRequestSet* requests) const { 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 @@ status_t WorkerThreadSection::Execute(ReportRequestSet* requests) const { // 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 @@ status_t CommandSection::Execute(ReportRequestSet* requests) const { // 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 @@ status_t CommandSection::Execute(ReportRequestSet* requests) const { 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 @@ status_t TombstoneSection::BlockingCall(int pipeWriteFd) const { 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 @@ status_t TombstoneSection::BlockingCall(int pipeWriteFd) const { 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 @@ status_t TombstoneSection::BlockingCall(int pipeWriteFd) const { 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 c869c7a8d1d4..d7995133c722 100644 --- a/cmds/incidentd/src/incidentd_util.cpp +++ b/cmds/incidentd/src/incidentd_util.cpp @@ -53,16 +53,17 @@ bool Fpipe::close() { 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 @@ pid_t fork_execute_cmd(const char* cmd, char* const argv[], Fpipe* input, Fpipe* _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 3f7df91e7e50..228d7762fc81 100644 --- a/cmds/incidentd/src/incidentd_util.h +++ b/cmds/incidentd/src/incidentd_util.h @@ -41,8 +41,8 @@ public: 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 0e5eec6c7023..bf770173793f 100644 --- a/cmds/incidentd/tests/FdBuffer_test.cpp +++ b/cmds/incidentd/tests/FdBuffer_test.cpp @@ -37,6 +37,7 @@ class FdBufferTest : public Test { 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 @@ public: 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 @@ public: protected: FdBuffer buffer; TemporaryFile tf; + unique_fd tffd; Fpipe p2cPipe; Fpipe c2pPipe; @@ -85,7 +87,7 @@ protected: 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, IterateEmpty) { 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 @@ TEST_F(FdBufferTest, ReadTimeout) { 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 @@ TEST_F(FdBufferTest, ReadInStreamAndWrite) { 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 @@ TEST_F(FdBufferTest, ReadInStreamAndWriteAllAtOnce) { 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 @@ TEST_F(FdBufferTest, ReadInStreamEmpty) { 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, ReadInStreamEmpty) { 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 @@ TEST_F(FdBufferTest, ReadInStreamTimeOut) { 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 c7c69a746f0a..5edc0c79785b 100644 --- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp +++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp @@ -58,7 +58,8 @@ public: 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 7f0a26c1714e..5d6a1d1a6c15 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -17,7 +17,6 @@ LOCAL_PATH:= $(call my-dir) 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 \ @@ -82,10 +81,8 @@ statsd_common_static_libraries := \ statsd_common_shared_libraries := \ libbase \ libbinder \ - libcutils \ libincident \ liblog \ - libselinux \ libutils \ libservices \ libprotoutil \ @@ -198,7 +195,7 @@ LOCAL_SRC_FILES := \ tests/e2e/WakelockDuration_e2e_test.cpp \ tests/e2e/MetricConditionLink_e2e_test.cpp \ tests/e2e/Attribution_e2e_test.cpp \ - tests/e2e/GaugeMetric_e2e_test.cpp \ + tests/e2e/GaugeMetric_e2e_push_test.cpp \ tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp \ tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp \ tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp @@ -226,7 +223,6 @@ LOCAL_MODULE := statsdprotolite LOCAL_SRC_FILES := \ src/stats_log.proto \ - src/stats_log_common.proto \ src/statsd_config.proto \ src/perfetto/perfetto_config.proto \ src/atoms.proto @@ -308,4 +304,4 @@ statsd_common_static_libraries:= statsd_common_shared_libraries:= -include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/cmds/statsd/benchmark/filter_value_benchmark.cpp b/cmds/statsd/benchmark/filter_value_benchmark.cpp index 66c4defe7adb..cfe477d7ca8f 100644 --- a/cmds/statsd/benchmark/filter_value_benchmark.cpp +++ b/cmds/statsd/benchmark/filter_value_benchmark.cpp @@ -54,28 +54,12 @@ static void BM_FilterValue(benchmark::State& state) { translateFieldMatcher(field_matcher, &matchers); while (state.KeepRunning()) { - vector<HashableDimensionKey> output; - filterValues(matchers, event.getValues(), &output); - } -} - -BENCHMARK(BM_FilterValue); - -static void BM_FilterValue2(benchmark::State& state) { - LogEvent event(1, 100000); - FieldMatcher field_matcher; - createLogEventAndMatcher(&event, &field_matcher); - - std::vector<Matcher> matchers; - translateFieldMatcher(field_matcher, &matchers); - - while (state.KeepRunning()) { HashableDimensionKey output; filterValues(matchers, event.getValues(), &output); } } -BENCHMARK(BM_FilterValue2); +BENCHMARK(BM_FilterValue); } // namespace statsd } // namespace os diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp index 0c9b7016eaff..dfd8705f83aa 100644 --- a/cmds/statsd/src/FieldValue.cpp +++ b/cmds/statsd/src/FieldValue.cpp @@ -48,6 +48,11 @@ bool Field::matches(const Matcher& matcher) const { return true; } + if (matcher.hasAllPositionMatcher() && + (mField & (matcher.mMask & kClearAllPositionMatcherMask)) == matcher.mMatcher.getField()) { + return true; + } + return false; } @@ -67,6 +72,10 @@ void translateFieldMatcher(int tag, const FieldMatcher& matcher, int depth, int* return; } switch (matcher.position()) { + case Position::ALL: + pos[depth] = 0x00; + mask[depth] = 0x7f; + break; case Position::ANY: pos[depth] = 0; mask[depth] = 0; diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h index 0e3ae06033e7..f7ce23b04339 100644 --- a/cmds/statsd/src/FieldValue.h +++ b/cmds/statsd/src/FieldValue.h @@ -30,6 +30,7 @@ const int32_t kAttributionField = 1; const int32_t kMaxLogDepth = 2; const int32_t kLastBitMask = 0x80; const int32_t kClearLastBitDeco = 0x7f; +const int32_t kClearAllPositionMatcherMask = 0xffff00ff; enum Type { UNKNOWN, INT, LONG, FLOAT, STRING }; @@ -205,6 +206,7 @@ public: * First: [Matcher Field] 0x02010101 [Mask]0xff7f7f7f * Last: [Matcher Field] 0x02018001 [Mask]0xff7f807f * Any: [Matcher Field] 0x02010001 [Mask]0xff7f007f + * All: [Matcher Field] 0x02010001 [Mask]0xff7f7f7f * * [To match a log Field with a Matcher] we apply the bit mask to the log Field and check if * the result is equal to the Matcher Field. That's a bit wise AND operation + check if 2 ints are @@ -226,9 +228,21 @@ struct Matcher { return mMask; } + inline int32_t getRawMaskAtDepth(int32_t depth) const { + int32_t field = (mMask & 0x00ffffff); + int32_t shift = 8 * (kMaxLogDepth - depth); + int32_t mask = 0xff << shift; + + return (field & mask) >> shift; + } + + bool hasAllPositionMatcher() const { + return mMatcher.getDepth() == 2 && getRawMaskAtDepth(1) == 0x7f; + } + bool hasAnyPositionMatcher(int* prefix) const { - if (mMatcher.getDepth() == 2 && mMatcher.getRawPosAtDepth(2) == 0) { - (*prefix) = mMatcher.getPrefix(2); + if (mMatcher.getDepth() == 2 && mMatcher.getRawPosAtDepth(1) == 0) { + (*prefix) = mMatcher.getPrefix(1); return true; } return false; diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp index d0c83119dc43..71030345b0aa 100644 --- a/cmds/statsd/src/HashableDimensionKey.cpp +++ b/cmds/statsd/src/HashableDimensionKey.cpp @@ -61,125 +61,22 @@ android::hash_t hashDimension(const HashableDimensionKey& value) { bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue>& values, HashableDimensionKey* output) { - for (size_t i = 0; i < matcherFields.size(); ++i) { - const auto& matcher = matcherFields[i]; - bool found = false; - for (const auto& value : values) { + size_t num_matches = 0; + for (const auto& value : values) { + for (size_t i = 0; i < matcherFields.size(); ++i) { + const auto& matcher = matcherFields[i]; // TODO: potential optimization here to break early because all fields are naturally // sorted. if (value.mField.matches(matcher)) { output->addValue(value); - output->mutableValue(i)->mField.setTag(value.mField.getTag()); - output->mutableValue(i)->mField.setField(value.mField.getField() & matcher.mMask); - found = true; - break; - } - } - - if (!found) { - VLOG("We can't find a dimension value for matcher (%d)%#x.", matcher.mMatcher.getTag(), - matcher.mMatcher.getField()); - return false; - } - } - - return true; -} - -// Filter fields using the matchers and output the results as a HashableDimensionKey. -// Note: HashableDimensionKey is just a wrapper for vector<FieldValue> -bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue>& values, - vector<HashableDimensionKey>* output) { - output->push_back(HashableDimensionKey()); - // Top level is only tag id. Now take the real child matchers - int prevAnyMatcherPrefix = 0; - size_t prevPrevFanout = 0; - size_t prevFanout = 0; - - // For each matcher get matched results. - vector<FieldValue> matchedResults(2); - for (const auto& matcher : matcherFields) { - size_t num_matches = 0; - for (const auto& value : values) { - // TODO: potential optimization here to break early because all fields are naturally - // sorted. - if (value.mField.matches(matcher)) { - if (num_matches >= matchedResults.size()) { - matchedResults.resize(num_matches * 2); - } - matchedResults[num_matches].mField.setTag(value.mField.getTag()); - matchedResults[num_matches].mField.setField(value.mField.getField() & matcher.mMask); - matchedResults[num_matches].mValue = value.mValue; + output->mutableValue(num_matches)->mField.setTag(value.mField.getTag()); + output->mutableValue(num_matches)->mField.setField( + value.mField.getField() & matcher.mMask); num_matches++; } } - - if (num_matches == 0) { - VLOG("We can't find a dimension value for matcher (%d)%#x.", matcher.mMatcher.getTag(), - matcher.mMatcher.getField()); - continue; - } - - if (num_matches == 1) { - for (auto& dimension : *output) { - dimension.addValue(matchedResults[0]); - } - prevAnyMatcherPrefix = 0; - prevFanout = 0; - continue; - } - - // All the complexity below is because we support ANY in dimension. - bool createFanout = true; - // createFanout is true when the matcher doesn't need to follow the prev matcher's - // order. - // e.g., get (uid, tag) from any position in attribution. because we have translated - // it as 2 matchers, they need to follow the same ordering, we can't create a cross - // product of all uid and tags. - // However, if the 2 matchers have different prefix, they will create a cross product - // e.g., [any uid] [any some other repeated field], we will create a cross product for them - if (prevAnyMatcherPrefix != 0) { - int anyMatcherPrefix = 0; - bool isAnyMatcher = matcher.hasAnyPositionMatcher(&anyMatcherPrefix); - if (isAnyMatcher && anyMatcherPrefix == prevAnyMatcherPrefix) { - createFanout = false; - } else { - prevAnyMatcherPrefix = anyMatcherPrefix; - } - } - - // Each matcher should match exact one field, unless position is ANY - // When x number of fields matches a matcher, the returned dimension - // size is multiplied by x. - int oldSize; - if (createFanout) { - // First create fanout (fanout size is matchedResults.Size which could be one, - // which means we do nothing here) - oldSize = output->size(); - for (size_t i = 1; i < num_matches; i++) { - output->insert(output->end(), output->begin(), output->begin() + oldSize); - } - prevPrevFanout = oldSize; - prevFanout = num_matches; - } else { - // If we should not create fanout, e.g., uid tag from same position should be remain - // together. - oldSize = prevPrevFanout; - if (prevFanout != num_matches) { - // sanity check. - ALOGE("2 Any matcher result in different output"); - return false; - } - } - // now add the matched field value to output - for (size_t i = 0; i < num_matches; i++) { - for (int j = 0; j < oldSize; j++) { - (*output)[i * oldSize + j].addValue(matchedResults[i]); - } - } } - - return output->size() > 0 && (*output)[0].getValues().size() > 0; + return num_matches > 0; } void filterGaugeValues(const std::vector<Matcher>& matcherFields, diff --git a/cmds/statsd/src/HashableDimensionKey.h b/cmds/statsd/src/HashableDimensionKey.h index 4cfed883ec07..6f4941f717ee 100644 --- a/cmds/statsd/src/HashableDimensionKey.h +++ b/cmds/statsd/src/HashableDimensionKey.h @@ -122,17 +122,14 @@ android::hash_t hashDimension(const HashableDimensionKey& key); /** * Creating HashableDimensionKeys from FieldValues using matcher. * - * This function may make modifications to the Field if the matcher has Position=LAST or ANY in - * it. This is because: for example, when we create dimension from last uid in attribution chain, + * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL + * in it. This is because: for example, when we create dimension from last uid in attribution chain, * In one event, uid 1000 is at position 5 and it's the last * In another event, uid 1000 is at position 6, and it's the last * these 2 events should be mapped to the same dimension. So we will remove the original position * from the dimension key for the uid field (by applying 0x80 bit mask). */ bool filterValues(const std::vector<Matcher>& matcherFields, const std::vector<FieldValue>& values, - std::vector<HashableDimensionKey>* output); -// This function is used when there is at most one output dimension key. (no ANY matcher) -bool filterValues(const std::vector<Matcher>& matcherFields, const std::vector<FieldValue>& values, HashableDimensionKey* output); /** diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 02d4dc985e84..652ec9dccf23 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -62,6 +62,9 @@ const int FIELD_ID_ID = 2; const int FIELD_ID_UID_MAP = 2; const int FIELD_ID_LAST_REPORT_ELAPSED_NANOS = 3; const int FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS = 4; +const int FIELD_ID_LAST_REPORT_WALL_CLOCK_NANOS = 5; +const int FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS = 6; + #define STATS_DATA_DIR "/data/misc/stats-data" @@ -260,22 +263,26 @@ void StatsLogProcessor::onDumpReportLocked(const ConfigKey& key, const uint64_t proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS); int64_t lastReportTimeNs = it->second->getLastReportTimeNs(); + int64_t lastReportWallClockNs = it->second->getLastReportWallClockNs(); + // First, fill in ConfigMetricsReport using current data on memory, which // starts from filling in StatsLogReport's. 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, (long long)lastReportTimeNs); proto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS, (long long)dumpTimeStampNs); + proto.write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_WALL_CLOCK_NANOS, + (long long)lastReportWallClockNs); + proto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS, + (long long)getWallClockNs()); // End of ConfigMetricsReport (reports). proto.end(reportsToken); diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index 8db82006d082..8b42146c6621 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -121,7 +121,8 @@ private: FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3); FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1); FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2); - FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice); + FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid); + FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain); FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent); FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition); @@ -138,6 +139,7 @@ private: FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition); + }; } // namespace statsd diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 8ba35b76435f..298f49457f38 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -110,6 +110,11 @@ message Atom { BluetoothEnabledStateChanged bluetooth_enabled_state_changed = 67; BluetoothConnectionStateChanged bluetooth_connection_state_changed = 68; BluetoothA2dpAudioStateChanged bluetooth_a2dp_audio_state_changed = 69; + UsbConnectorStateChanged usb_connector_changed = 70; + SpeakerImpedanceReported speaker_impedance_reported = 71; + HardwareFailed hardware_failed = 72; + PhysicalDropDetected physical_drop_detected = 73; + ChargeCyclesReported charge_cycles_reported = 74; // TODO: Reorder the numbering so that the most frequent occur events occur in the first 15. } @@ -965,6 +970,108 @@ message BluetoothA2dpAudioStateChanged { } /** + * Logs when something is plugged into or removed from the USB-C connector. + * + * Logged from: + * Vendor USB HAL. + */ +message UsbConnectorStateChanged { + enum State { + DISCONNECTED = 0; + CONNECTED = 1; + } + optional State state = 1; +} + +/** + * Logs the reported speaker impedance. + * + * Logged from: + * Vendor audio implementation. + */ +message SpeakerImpedanceReported { + optional int32 speaker_location = 1; + optional int32 impedance = 2; +} + +/** + * Logs the report of a failed hardware. + * + * Logged from: + * Vendor HALs. + * + */ +message HardwareFailed { + enum HardwareType { + HARDWARE_FAILED_UNKNOWN = 0; + HARDWARE_FAILED_MICROPHONE = 1; + HARDWARE_FAILED_CODEC = 2; + HARDWARE_FAILED_SPEAKER = 3; + HARDWARE_FAILED_FINGERPRINT = 4; + } + optional HardwareType hardware_type = 1; + + /* hardware_location allows vendors to differentiate between multiple instances of + * the same hardware_type. The specific locations are vendor defined integers, + * referring to board-specific numbering schemes. + */ + optional int32 hardware_location = 2; + + /* failure_code is specific to the HardwareType of the failed hardware. + * It should use the enum values defined below. + */ + enum MicrophoneFailureCode { + MICROPHONE_FAILURE_COMPLETE = 0; + } + enum CodecFailureCode { + CODEC_FAILURE_COMPLETE = 0; + } + enum SpeakerFailureCode { + SPEAKER_FAILURE_COMPLETE = 0; + SPEAKER_FAILURE_HIGH_Z = 1; + SPEAKER_FAILURE_SHORT = 2; + } + enum FingerprintFailureCode { + FINGERPRINT_FAILURE_COMPLETE = 0; + FINGERPRINT_SENSOR_BROKEN = 1; + FINGERPRINT_TOO_MANY_DEAD_PIXELS = 2; + } + optional int32 failure_code = 3; +} + +/** + * Log an event when the device has been physically dropped. + * Reported from the /vendor partition. + */ +message PhysicalDropDetected { + // Confidence that the event was actually a drop, 0 -> 100 + optional int32 confidence_pctg = 1; + // Peak acceleration of the drop, in 1/1000s of a g. + optional int32 accel_peak_thousandths_g = 2; +} + +/** + * Log bucketed battery charge cycles. + * + * Each bucket represents cycles of the battery past + * a given charge point. For example, bucket 1 is the + * lowest 1/8th of the battery, and bucket 8 is 100%. + * + * Logged from: + * /sys/class/power_supply/bms/cycle_count, via Vendor. + */ +message ChargeCyclesReported { + optional int32 cycle_bucket_1 = 1; + optional int32 cycle_bucket_2 = 2; + optional int32 cycle_bucket_3 = 3; + optional int32 cycle_bucket_4 = 4; + optional int32 cycle_bucket_5 = 5; + optional int32 cycle_bucket_6 = 6; + optional int32 cycle_bucket_7 = 7; + optional int32 cycle_bucket_8 = 8; +} + +/** * Logs the duration of a davey (jank of >=700ms) when it occurs * * Logged from: diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp index 4913aef3347f..73efb39ac119 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp +++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp @@ -327,25 +327,7 @@ void SimpleConditionTracker::evaluateCondition( // have both sliced and unsliced version of a predicate. handleConditionEvent(outputValue, matchedState == 1, &overallState, &overallChanged); } else { - std::vector<HashableDimensionKey> outputValues; - filterValues(mOutputDimensions, event.getValues(), &outputValues); - - // If this event has multiple nodes in the attribution chain, this log event probably will - // generate multiple dimensions. If so, we will find if the condition changes for any - // dimension and ask the corresponding metric producer to verify whether the actual sliced - // condition has changed or not. - // A high level assumption is that a predicate is either sliced or unsliced. We will never - // have both sliced and unsliced version of a predicate. - for (const HashableDimensionKey& outputValue : outputValues) { - ConditionState tempState; - bool tempChanged = false; - handleConditionEvent(outputValue, matchedState == 1, &tempState, &tempChanged); - if (tempChanged) { - overallChanged = true; - } - // ConditionState's | operator is overridden - overallState = overallState | tempState; - } + ALOGE("The condition tracker should not be sliced by ANY position matcher."); } conditionCache[mIndex] = overallState; conditionChangedCache[mIndex] = overallChanged; diff --git a/cmds/statsd/src/condition/StateTracker.cpp b/cmds/statsd/src/condition/StateTracker.cpp index c68875c58162..fe1740b24dd4 100644 --- a/cmds/statsd/src/condition/StateTracker.cpp +++ b/cmds/statsd/src/condition/StateTracker.cpp @@ -137,21 +137,18 @@ void StateTracker::evaluateCondition(const LogEvent& event, VLOG("StateTracker evaluate event %s", event.ToString().c_str()); - vector<HashableDimensionKey> keys; - vector<HashableDimensionKey> outputs; - filterValues(mPrimaryKeys, event.getValues(), &keys); - filterValues(mOutputDimensions, event.getValues(), &outputs); - if (keys.size() != 1 || outputs.size() != 1) { - ALOGE("More than 1 states in the event?? panic now!"); + // Primary key can exclusive fields must be simple fields. so there won't be more than + // one keys matched. + HashableDimensionKey primaryKey; + HashableDimensionKey state; + if (!filterValues(mPrimaryKeys, event.getValues(), &primaryKey) || + !filterValues(mOutputDimensions, event.getValues(), &state)) { + ALOGE("Failed to filter fields in the event?? panic now!"); conditionCache[mIndex] = mSlicedState.size() > 0 ? ConditionState::kTrue : ConditionState::kFalse; conditionChangedCache[mIndex] = false; return; } - // Primary key can exclusive fields must be simple fields. so there won't be more than - // one keys matched. - const auto& primaryKey = keys[0]; - const auto& state = outputs[0]; hitGuardRail(primaryKey); VLOG("StateTracker: key %s state %s", primaryKey.toString().c_str(), state.toString().c_str()); diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp index d0f55abe7033..f5310a419c92 100644 --- a/cmds/statsd/src/config/ConfigManager.cpp +++ b/cmds/statsd/src/config/ConfigManager.cpp @@ -68,12 +68,25 @@ void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& confi { lock_guard <mutex> lock(mMutex); + auto it = mConfigs.find(key); + + const int numBytes = config.ByteSize(); + vector<uint8_t> buffer(numBytes); + config.SerializeToArray(&buffer[0], numBytes); + + const bool isDuplicate = + it != mConfigs.end() && + StorageManager::hasIdenticalConfig(key, buffer); + + // Update saved file on disk. We still update timestamp of file when + // there exists a duplicate configuration to avoid garbage collection. + update_saved_configs_locked(key, buffer, numBytes); + + if (isDuplicate) return; + // Add to set mConfigs.insert(key); - // Save to disk - update_saved_configs_locked(key, config); - for (sp<ConfigListener> listener : mListeners) { broadcastList.push_back(listener); } @@ -137,7 +150,6 @@ void ConfigManager::RemoveConfigs(int uid) { { lock_guard <mutex> lock(mMutex); - for (auto it = mConfigs.begin(); it != mConfigs.end();) { // Remove from map if (it->GetUid() == uid) { @@ -230,16 +242,16 @@ void ConfigManager::Dump(FILE* out) { } } -void ConfigManager::update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config) { +void ConfigManager::update_saved_configs_locked(const ConfigKey& key, + const vector<uint8_t>& buffer, + const int numBytes) { // If there is a pre-existing config with same key we should first delete it. remove_saved_configs(key); // Then we save the latest config. - string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr), - key.GetUid(), (long long)key.GetId()); - const int numBytes = config.ByteSize(); - vector<uint8_t> buffer(numBytes); - config.SerializeToArray(&buffer[0], numBytes); + string file_name = + StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr), + key.GetUid(), (long long)key.GetId()); StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes); } diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h index a0c1c1cb16f8..9a38188a120c 100644 --- a/cmds/statsd/src/config/ConfigManager.h +++ b/cmds/statsd/src/config/ConfigManager.h @@ -115,7 +115,9 @@ private: /** * Save the configs to disk. */ - void update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config); + void update_saved_configs_locked(const ConfigKey& key, + const std::vector<uint8_t>& buffer, + const int numBytes); /** * Remove saved configs from disk. @@ -123,7 +125,7 @@ private: void remove_saved_configs(const ConfigKey& key); /** - * The Configs that have been set. Each config should + * Config keys that have been set. */ std::set<ConfigKey> mConfigs; diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp index c6c4d135ad3f..7a55f6065e88 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.cpp +++ b/cmds/statsd/src/guardrail/StatsdStats.cpp @@ -21,6 +21,7 @@ #include <android/util/ProtoOutputStream.h> #include "../stats_log_util.h" #include "statslog.h" +#include "storage/StorageManager.h" namespace android { namespace os { @@ -403,6 +404,8 @@ void StatsdStats::dumpStats(FILE* out) const { fprintf(out, "alert %lld declared %d times\n", (long long)stats.first, stats.second); } } + fprintf(out, "********Disk Usage stats***********\n"); + StorageManager::printStats(out); fprintf(out, "********Pushed Atom stats***********\n"); const size_t atomCounts = mPushedAtomStats.size(); for (size_t i = 2; i < atomCounts; i++) { diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h index d05c91b8d188..c42514a04925 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.cpp b/cmds/statsd/src/matchers/matcher_util.cpp index 364d4e9d5c94..b7105b351a10 100644 --- a/cmds/statsd/src/matchers/matcher_util.cpp +++ b/cmds/statsd/src/matchers/matcher_util.cpp @@ -185,6 +185,9 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher, ranges.push_back(std::make_pair(newStart, end)); break; } + case Position::ALL: + ALOGE("Not supported: field matcher with ALL position."); + break; case Position::POSITION_UNKNOWN: break; } diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h index ae946d16b352..15b4a9799a93 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/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp index 22b2a30af328..8e8a529bfff1 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.cpp +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -99,6 +99,24 @@ CountMetricProducer::~CountMetricProducer() { VLOG("~CountMetricProducer() called"); } +void CountMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const { + if (mCurrentSlicedCounter == nullptr || + mCurrentSlicedCounter->size() == 0) { + return; + } + + fprintf(out, "CountMetric %lld dimension size %lu\n", (long long)mMetricId, + (unsigned long)mCurrentSlicedCounter->size()); + if (verbose) { + for (const auto& it : *mCurrentSlicedCounter) { + fprintf(out, "\t(what)%s\t(condition)%s %lld\n", + it.first.getDimensionKeyInWhat().toString().c_str(), + it.first.getDimensionKeyInCondition().toString().c_str(), + (unsigned long long)it.second); + } + } +} + void CountMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) { VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId); } @@ -249,7 +267,6 @@ void CountMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) } else { info.mBucketEndNs = fullBucketEndTimeNs; } - info.mBucketNum = mCurrentBucketNum; for (const auto& counter : *mCurrentSlicedCounter) { info.mCount = counter.second; auto& bucketList = mPastBuckets[counter.first]; diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h index 1d8e42be635c..ef738acd5772 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.h +++ b/cmds/statsd/src/metrics/CountMetricProducer.h @@ -36,7 +36,6 @@ struct CountBucket { int64_t mBucketStartNs; int64_t mBucketEndNs; int64_t mCount; - uint64_t mBucketNum; }; class CountMetricProducer : public MetricProducer { @@ -67,7 +66,7 @@ private: // Internal function to calculate the current used bytes. size_t byteSizeLocked() const override; - void dumpStatesLocked(FILE* out, bool verbose) const override{}; + void dumpStatesLocked(FILE* out, bool verbose) const override; void dropDataLocked(const uint64_t dropTimeNs) override; diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index bc09683d79ad..c6b9405e424d 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -88,6 +88,12 @@ DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const Durat translateFieldMatcher(internalDimensions, &mInternalDimensions); mContainANYPositionInInternalDimensions = HasPositionANY(internalDimensions); } + if (mContainANYPositionInInternalDimensions) { + ALOGE("Position ANY in internal dimension not supported."); + } + if (mContainANYPositionInDimensionsInWhat) { + ALOGE("Position ANY in dimension_in_what not supported."); + } if (metric.has_dimensions_in_condition()) { translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition); @@ -589,18 +595,10 @@ void DurationMetricProducer::handleStartEvent(const MetricDimensionKey& eventKey it->second->noteStart(DEFAULT_DIMENSION_KEY, condition, event.GetElapsedTimestampNs(), conditionKeys); } else { - if (mContainANYPositionInInternalDimensions) { - std::vector<HashableDimensionKey> dimensionKeys; - filterValues(mInternalDimensions, event.getValues(), &dimensionKeys); - for (const auto& key : dimensionKeys) { - it->second->noteStart(key, condition, event.GetElapsedTimestampNs(), conditionKeys); - } - } else { - HashableDimensionKey dimensionKey = DEFAULT_DIMENSION_KEY; - filterValues(mInternalDimensions, event.getValues(), &dimensionKey); - it->second->noteStart( - dimensionKey, condition, event.GetElapsedTimestampNs(), conditionKeys); - } + HashableDimensionKey dimensionKey = DEFAULT_DIMENSION_KEY; + filterValues(mInternalDimensions, event.getValues(), &dimensionKey); + it->second->noteStart( + dimensionKey, condition, event.GetElapsedTimestampNs(), conditionKeys); } } @@ -612,8 +610,8 @@ void DurationMetricProducer::onMatchedLogEventInternalLocked( ALOGW("Not used in duration tracker."); } -void DurationMetricProducer::onMatchedLogEventLocked_simple(const size_t matcherIndex, - const LogEvent& event) { +void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, + const LogEvent& event) { uint64_t eventTimeNs = event.GetElapsedTimestampNs(); if (eventTimeNs < mStartTimeNs) { return; @@ -712,117 +710,6 @@ void DurationMetricProducer::onMatchedLogEventLocked_simple(const size_t matcher } } -void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, - const LogEvent& event) { - if (!mContainANYPositionInDimensionsInWhat) { - onMatchedLogEventLocked_simple(matcherIndex, event); - return; - } - - uint64_t eventTimeNs = event.GetElapsedTimestampNs(); - if (eventTimeNs < mStartTimeNs) { - return; - } - - flushIfNeededLocked(event.GetElapsedTimestampNs()); - - // Handles Stopall events. - if (matcherIndex == mStopAllIndex) { - for (auto& whatIt : mCurrentSlicedDurationTrackerMap) { - for (auto& pair : whatIt.second) { - pair.second->noteStopAll(event.GetElapsedTimestampNs()); - } - } - return; - } - - vector<HashableDimensionKey> dimensionInWhatValues; - if (!mDimensionsInWhat.empty()) { - filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhatValues); - } else { - dimensionInWhatValues.push_back(DEFAULT_DIMENSION_KEY); - } - - // Handles Stop events. - if (matcherIndex == mStopIndex) { - if (mUseWhatDimensionAsInternalDimension) { - for (const HashableDimensionKey& whatKey : dimensionInWhatValues) { - auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatKey); - if (whatIt != mCurrentSlicedDurationTrackerMap.end()) { - for (const auto& condIt : whatIt->second) { - condIt.second->noteStop(whatKey, event.GetElapsedTimestampNs(), false); - } - } - } - return; - } - - HashableDimensionKey internalDimensionKey = DEFAULT_DIMENSION_KEY; - if (!mInternalDimensions.empty()) { - filterValues(mInternalDimensions, event.getValues(), &internalDimensionKey); - } - - for (const HashableDimensionKey& whatDimension : dimensionInWhatValues) { - auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatDimension); - if (whatIt != mCurrentSlicedDurationTrackerMap.end()) { - for (const auto& condIt : whatIt->second) { - condIt.second->noteStop( - internalDimensionKey, event.GetElapsedTimestampNs(), false); - } - } - } - return; - } - - bool condition; - ConditionKey conditionKey; - std::unordered_set<HashableDimensionKey> dimensionKeysInCondition; - if (mConditionSliced) { - for (const auto& link : mMetric2ConditionLinks) { - getDimensionForCondition(event.getValues(), link, &conditionKey[link.conditionId]); - } - - auto conditionState = - mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition, - !mSameConditionDimensionsInTracker, - !mHasLinksToAllConditionDimensionsInTracker, - &dimensionKeysInCondition); - condition = (conditionState == ConditionState::kTrue); - if (mDimensionsInCondition.empty() && condition) { - dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY); - } - } else { - condition = mCondition; - if (condition) { - dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY); - } - } - - for (const auto& whatDimension : dimensionInWhatValues) { - if (dimensionKeysInCondition.empty()) { - handleStartEvent(MetricDimensionKey(whatDimension, DEFAULT_DIMENSION_KEY), - conditionKey, condition, event); - } else { - auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatDimension); - // If the what dimension is already there, we should update all the trackers even - // the condition is false. - if (whatIt != mCurrentSlicedDurationTrackerMap.end()) { - for (const auto& condIt : whatIt->second) { - const bool cond = dimensionKeysInCondition.find(condIt.first) != - dimensionKeysInCondition.end(); - handleStartEvent(MetricDimensionKey(whatDimension, condIt.first), - conditionKey, cond, event); - dimensionKeysInCondition.erase(condIt.first); - } - } - for (const auto& conditionDimension : dimensionKeysInCondition) { - handleStartEvent(MetricDimensionKey(whatDimension, conditionDimension), - conditionKey, condition, event); - } - } - } -} - size_t DurationMetricProducer::byteSizeLocked() const { size_t totalSize = 0; for (const auto& pair : mPastBuckets) { diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h index 6746e116333f..985749df63dd 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.h +++ b/cmds/statsd/src/metrics/DurationMetricProducer.h @@ -52,8 +52,6 @@ public: protected: void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) override; - void onMatchedLogEventLocked_simple(const size_t matcherIndex, const LogEvent& event); - void onMatchedLogEventInternalLocked( const size_t matcherIndex, const MetricDimensionKey& eventKey, const ConditionKey& conditionKeys, bool condition, diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index e479e5caec2f..55a281ed61a0 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -56,6 +56,7 @@ const int FIELD_ID_START_BUCKET_ELAPSED_NANOS = 1; const int FIELD_ID_END_BUCKET_ELAPSED_NANOS = 2; const int FIELD_ID_ATOM = 3; const int FIELD_ID_ELAPSED_ATOM_TIMESTAMP = 4; +const int FIELD_ID_WALL_CLOCK_ATOM_TIMESTAMP = 5; GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric, const int conditionIndex, @@ -126,6 +127,24 @@ GaugeMetricProducer::~GaugeMetricProducer() { } } +void GaugeMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const { + if (mCurrentSlicedBucket == nullptr || + mCurrentSlicedBucket->size() == 0) { + return; + } + + fprintf(out, "GaugeMetric %lld dimension size %lu\n", (long long)mMetricId, + (unsigned long)mCurrentSlicedBucket->size()); + if (verbose) { + for (const auto& it : *mCurrentSlicedBucket) { + fprintf(out, "\t(what)%s\t(condition)%s %d atoms\n", + it.first.getDimensionKeyInWhat().toString().c_str(), + it.first.getDimensionKeyInCondition().toString().c_str(), + (int)it.second.size()); + } + } +} + void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, ProtoOutputStream* protoOutput) { VLOG("gauge metric %lld report now...", (long long)mMetricId); @@ -168,21 +187,28 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, (long long)bucket.mBucketEndNs); if (!bucket.mGaugeAtoms.empty()) { - uint64_t atomsToken = - protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ATOM); for (const auto& atom : bucket.mGaugeAtoms) { + uint64_t atomsToken = + protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | + FIELD_ID_ATOM); writeFieldValueTreeToStream(mTagId, *(atom.mFields), protoOutput); + protoOutput->end(atomsToken); } - protoOutput->end(atomsToken); + const bool truncateTimestamp = + android::util::kNotTruncatingTimestampAtomWhiteList.find(mTagId) == + android::util::kNotTruncatingTimestampAtomWhiteList.end(); + const int64_t wall_clock_ns = truncateTimestamp ? + truncateTimestampNsToFiveMinutes(getWallClockNs()) : getWallClockNs(); for (const auto& atom : bucket.mGaugeAtoms) { - const bool truncateTimestamp = - android::util::kNotTruncatingTimestampAtomWhiteList.find(mTagId) == - android::util::kNotTruncatingTimestampAtomWhiteList.end(); int64_t timestampNs = truncateTimestamp ? truncateTimestampNsToFiveMinutes(atom.mTimestamps) : atom.mTimestamps; protoOutput->write( FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_ELAPSED_ATOM_TIMESTAMP, (long long)timestampNs); + protoOutput->write( + FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | + FIELD_ID_WALL_CLOCK_ATOM_TIMESTAMP, + (long long)wall_clock_ns); } } protoOutput->end(bucketInfoToken); @@ -393,7 +419,6 @@ void GaugeMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) } else { info.mBucketEndNs = fullBucketEndTimeNs; } - info.mBucketNum = mCurrentBucketNum; for (const auto& slice : *mCurrentSlicedBucket) { info.mGaugeAtoms = slice.second; diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h index ca8dc7582680..dd6aff4130de 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.h +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h @@ -44,7 +44,6 @@ struct GaugeBucket { int64_t mBucketStartNs; int64_t mBucketEndNs; std::vector<GaugeAtom> mGaugeAtoms; - uint64_t mBucketNum; }; typedef std::unordered_map<MetricDimensionKey, std::vector<GaugeAtom>> @@ -106,7 +105,7 @@ private: // Internal function to calculate the current used bytes. size_t byteSizeLocked() const override; - void dumpStatesLocked(FILE* out, bool verbose) const override{}; + void dumpStatesLocked(FILE* out, bool verbose) const override; void dropDataLocked(const uint64_t dropTimeNs) override; diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp index 6c90b031a9cc..f4495a19d700 100644 --- a/cmds/statsd/src/metrics/MetricProducer.cpp +++ b/cmds/statsd/src/metrics/MetricProducer.cpp @@ -53,39 +53,17 @@ void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const Lo dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY); } - if (mContainANYPositionInDimensionsInWhat) { - vector<HashableDimensionKey> dimensionInWhatValues; - if (!mDimensionsInWhat.empty()) { - filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhatValues); - } else { - dimensionInWhatValues.push_back(DEFAULT_DIMENSION_KEY); - } - - for (const auto& whatDimension : dimensionInWhatValues) { - for (const auto& conditionDimensionKey : dimensionKeysInCondition) { - onMatchedLogEventInternalLocked( - matcherIndex, MetricDimensionKey(whatDimension, conditionDimensionKey), - conditionKey, condition, event); - } - if (dimensionKeysInCondition.empty()) { - onMatchedLogEventInternalLocked( - matcherIndex, MetricDimensionKey(whatDimension, DEFAULT_DIMENSION_KEY), - conditionKey, condition, event); - } - } - } else { - HashableDimensionKey dimensionInWhat; - filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat); - MetricDimensionKey metricKey(dimensionInWhat, DEFAULT_DIMENSION_KEY); - for (const auto& conditionDimensionKey : dimensionKeysInCondition) { - metricKey.setDimensionKeyInCondition(conditionDimensionKey); - onMatchedLogEventInternalLocked( - matcherIndex, metricKey, conditionKey, condition, event); - } - if (dimensionKeysInCondition.empty()) { - onMatchedLogEventInternalLocked( - matcherIndex, metricKey, conditionKey, condition, event); - } + HashableDimensionKey dimensionInWhat; + filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat); + MetricDimensionKey metricKey(dimensionInWhat, DEFAULT_DIMENSION_KEY); + for (const auto& conditionDimensionKey : dimensionKeysInCondition) { + metricKey.setDimensionKeyInCondition(conditionDimensionKey); + onMatchedLogEventInternalLocked( + matcherIndex, metricKey, conditionKey, condition, event); + } + if (dimensionKeysInCondition.empty()) { + onMatchedLogEventInternalLocked( + matcherIndex, metricKey, conditionKey, condition, event); } } diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index 1ca59a366fcb..6209bbe75812 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -53,7 +53,9 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap> &uidMap, const sp<AlarmMonitor>& anomalyAlarmMonitor, const sp<AlarmMonitor>& periodicAlarmMonitor) - : mConfigKey(key), mUidMap(uidMap), mLastReportTimeNs(timeBaseSec * NS_PER_SEC) { + : mConfigKey(key), mUidMap(uidMap), + mLastReportTimeNs(timeBaseSec * NS_PER_SEC), + mLastReportWallClockNs(getWallClockNs()) { mConfigValid = initStatsdConfig(key, config, *uidMap, anomalyAlarmMonitor, periodicAlarmMonitor, timeBaseSec, mTagIds, mAllAtomMatchers, @@ -193,6 +195,7 @@ void MetricsManager::onDumpReport(const uint64_t dumpTimeStampNs, ProtoOutputStr } } mLastReportTimeNs = dumpTimeStampNs; + mLastReportWallClockNs = getWallClockNs(); VLOG("=========================Metric Reports End=========================="); } diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index dbab81431743..46a9b34c21a1 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -69,10 +69,14 @@ public: void dumpStates(FILE* out, bool verbose); // Returns the elapsed realtime when this metric manager last reported metrics. - uint64_t getLastReportTimeNs() { + inline int64_t getLastReportTimeNs() const { return mLastReportTimeNs; }; + inline int64_t getLastReportWallClockNs() const { + return mLastReportWallClockNs; + }; + virtual void dropData(const uint64_t dropTimeNs); // Config source owner can call onDumpReport() to get all the metrics collected. @@ -89,7 +93,8 @@ private: bool mConfigValid = false; - uint64_t mLastReportTimeNs; + int64_t mLastReportTimeNs; + int64_t mLastReportWallClockNs; // The uid log sources from StatsdConfig. std::vector<int32_t> mAllowedUid; @@ -158,7 +163,8 @@ private: FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions); FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks); - FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice); + FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid); + FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain); FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent); FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition); FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition); diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index 09913dc513fd..767260d26351 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -243,6 +243,23 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven } } +void ValueMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const { + if (mCurrentSlicedBucket.size() == 0) { + return; + } + + fprintf(out, "ValueMetric %lld dimension size %lu\n", (long long)mMetricId, + (unsigned long)mCurrentSlicedBucket.size()); + if (verbose) { + for (const auto& it : mCurrentSlicedBucket) { + fprintf(out, "\t(what)%s\t(condition)%s (value)%lld\n", + it.first.getDimensionKeyInWhat().toString().c_str(), + it.first.getDimensionKeyInCondition().toString().c_str(), + (unsigned long long)it.second.sum); + } + } +} + bool ValueMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) { // ===========GuardRail============== // 1. Report the tuple count if the tuple count > soft limit @@ -355,7 +372,6 @@ void ValueMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) } else { info.mBucketEndNs = fullBucketEndTimeNs; } - info.mBucketNum = mCurrentBucketNum; int tainted = 0; for (const auto& slice : mCurrentSlicedBucket) { diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index 5e42bd255df4..be57183bd926 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -34,7 +34,6 @@ struct ValueBucket { int64_t mBucketStartNs; int64_t mBucketEndNs; int64_t mValue; - uint64_t mBucketNum; }; class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver { @@ -99,7 +98,7 @@ private: // Internal function to calculate the current used bytes. size_t byteSizeLocked() const override; - void dumpStatesLocked(FILE* out, bool verbose) const override{}; + void dumpStatesLocked(FILE* out, bool verbose) const override; // Util function to flush the old packet. void flushIfNeededLocked(const uint64_t& eventTime) override; diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h index 7b3393fda7e6..bfb1ec7e06d6 100644 --- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h @@ -55,7 +55,6 @@ struct DurationBucket { uint64_t mBucketStartNs; uint64_t mBucketEndNs; uint64_t mDuration; - uint64_t mBucketNum; }; class DurationTracker { diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp index 8e0bf2678fea..058940d11b46 100644 --- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp +++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp @@ -219,7 +219,6 @@ bool MaxDurationTracker::flushCurrentBucket( DurationBucket info; info.mBucketStartNs = mCurrentBucketStartTimeNs; info.mBucketEndNs = currentBucketEndTimeNs; - info.mBucketNum = mCurrentBucketNum; info.mDuration = mDuration; (*output)[mEventKey].push_back(info); VLOG(" final duration for last bucket: %lld", (long long)mDuration); diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp index 2358415dfaf7..c8a5016c1db8 100644 --- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp +++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp @@ -165,13 +165,12 @@ bool OringDurationTracker::flushCurrentBucket( DurationBucket current_info; current_info.mBucketStartNs = mCurrentBucketStartTimeNs; current_info.mBucketEndNs = currentBucketEndTimeNs; - current_info.mBucketNum = mCurrentBucketNum; current_info.mDuration = mDuration; (*output)[mEventKey].push_back(current_info); mDurationFullBucket += mDuration; if (eventTimeNs > fullBucketEnd) { // End of full bucket, can send to anomaly tracker now. - addPastBucketToAnomalyTrackers(mDurationFullBucket, current_info.mBucketNum); + addPastBucketToAnomalyTrackers(mDurationFullBucket, mCurrentBucketNum); mDurationFullBucket = 0; } VLOG(" duration: %lld", (long long)current_info.mDuration); @@ -182,12 +181,11 @@ bool OringDurationTracker::flushCurrentBucket( DurationBucket info; info.mBucketStartNs = fullBucketEnd + mBucketSizeNs * (i - 1); info.mBucketEndNs = info.mBucketStartNs + mBucketSizeNs; - info.mBucketNum = mCurrentBucketNum + i; info.mDuration = mBucketSizeNs; (*output)[mEventKey].push_back(info); // Safe to send these buckets to anomaly tracker since they must be full buckets. // If it's a partial bucket, numBucketsForward would be 0. - addPastBucketToAnomalyTrackers(info.mDuration, info.mBucketNum); + addPastBucketToAnomalyTrackers(info.mDuration, mCurrentBucketNum + i); VLOG(" add filling bucket with duration %lld", (long long)info.mDuration); } } diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp index e322ca4bb1ac..efbe96eebb25 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 @@ void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid, 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]); } - - 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]); + proto.end(token); + + // 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 @@ void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const i { 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 @@ void UidMap::ensureBytesUsedBelowLimit() { 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 @@ void UidMap::removeApp(const int64_t& timestamp, const String16& app_16, const i { 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 @@ int UidMap::getHostUidOrSelf(int uid) const { } 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 @@ size_t UidMap::getBytesUsed() const { 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 @@ void UidMap::OnConfigUpdated(const ConfigKey& key) { // 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 c41e0aaca3d2..b0181f7280b5 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 @@ struct AppData { 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 @@ public: // 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 @@ private: 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 @@ private: // 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 3c5f5a2b9907..dd3b37c8c2d7 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -22,7 +22,6 @@ option java_package = "com.android.os"; 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; @@ -46,7 +45,7 @@ message EventMetricData { optional Atom atom = 2; - optional int64 wall_clock_timestamp_sec = 3; + optional int64 wall_clock_timestamp_nanos = 3; } message CountBucketInfo { @@ -105,6 +104,8 @@ message GaugeBucketInfo { repeated Atom atom = 3; repeated int64 elapsed_timestamp_nanos = 4; + + repeated int64 wall_clock_timestamp_nanos = 5; } message GaugeMetricData { @@ -146,6 +147,33 @@ message StatsLogReport { } } +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; @@ -154,6 +182,10 @@ message ConfigMetricsReport { optional int64 last_report_elapsed_nanos = 3; optional int64 current_report_elapsed_nanos = 4; + + optional int64 last_report_wall_clock_nanos = 5; + + optional int64 current_report_wall_clock_nanos = 6; } message ConfigMetricsReportList { diff --git a/cmds/statsd/src/stats_log_common.proto b/cmds/statsd/src/stats_log_common.proto deleted file mode 100644 index c41f31ebaa3f..000000000000 --- 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 c512e3c63bcf..97220500073d 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 80e46d604b21..e0206d10e6ad 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/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto index 1c99e2ad03bc..2c701915f429 100644 --- a/cmds/statsd/src/statsd_config.proto +++ b/cmds/statsd/src/statsd_config.proto @@ -31,6 +31,8 @@ enum Position { LAST = 2; ANY = 3; + + ALL = 4; } enum TimeUnit { diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp index 781ecede1700..cd41f533fecf 100644 --- a/cmds/statsd/src/storage/StorageManager.cpp +++ b/cmds/statsd/src/storage/StorageManager.cpp @@ -245,6 +245,45 @@ void StorageManager::readConfigFromDisk(map<ConfigKey, StatsdConfig>& configsMap } } +bool StorageManager::hasIdenticalConfig(const ConfigKey& key, + const vector<uint8_t>& config) { + unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), + closedir); + if (dir == NULL) { + VLOG("Directory does not exist: %s", STATS_SERVICE_DIR); + return false; + } + + const char* suffix = + StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId()).c_str(); + + dirent* de; + while ((de = readdir(dir.get()))) { + char* name = de->d_name; + if (name[0] == '.') { + continue; + } + size_t nameLen = strlen(name); + size_t suffixLen = strlen(suffix); + // There can be at most one file that matches this suffix (config key). + if (suffixLen <= nameLen && + strncmp(name + nameLen - suffixLen, suffix, suffixLen) == 0) { + int fd = open(StringPrintf("%s/%s", STATS_SERVICE_DIR, name).c_str(), + O_RDONLY | O_CLOEXEC); + if (fd != -1) { + string content; + if (android::base::ReadFdToString(fd, &content)) { + vector<uint8_t> vec(content.begin(), content.end()); + if (vec == config) { + return true; + } + } + } + } + } + return false; +} + void StorageManager::trimToFit(const char* path) { unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir); if (dir == NULL) { @@ -306,6 +345,53 @@ void StorageManager::trimToFit(const char* path) { } } +void StorageManager::printStats(FILE* out) { + printDirStats(out, STATS_SERVICE_DIR); + printDirStats(out, STATS_DATA_DIR); +} + +void StorageManager::printDirStats(FILE* out, const char* path) { + fprintf(out, "Printing stats of %s\n", path); + unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir); + if (dir == NULL) { + VLOG("Path %s does not exist", path); + return; + } + dirent* de; + int fileCount = 0; + int totalFileSize = 0; + while ((de = readdir(dir.get()))) { + char* name = de->d_name; + if (name[0] == '.') { + continue; + } + int64_t result[3]; + parseFileName(name, result); + if (result[0] == -1) continue; + int64_t timestamp = result[0]; + int64_t uid = result[1]; + int64_t configID = result[2]; + fprintf(out, "\t #%d, Last updated: %lld, UID: %d, Config ID: %lld", + fileCount + 1, + (long long)timestamp, + (int)uid, + (long long)configID); + string file_name = getFilePath(path, timestamp, uid, configID); + ifstream file(file_name.c_str(), ifstream::in | ifstream::binary); + if (file.is_open()) { + file.seekg(0, ios::end); + int fileSize = file.tellg(); + file.close(); + fprintf(out, ", File Size: %d bytes", fileSize); + totalFileSize += fileSize; + } + fprintf(out, "\n"); + fileCount++; + } + fprintf(out, "\tTotal number of files: %d, Total size of files: %d bytes.\n", + fileCount, totalFileSize); +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/storage/StorageManager.h b/cmds/statsd/src/storage/StorageManager.h index 6c8ed0a96704..4b7562855f30 100644 --- a/cmds/statsd/src/storage/StorageManager.h +++ b/cmds/statsd/src/storage/StorageManager.h @@ -78,6 +78,23 @@ public: * files, accumulation of outdated files. */ static void trimToFit(const char* dir); + + /** + * Returns true if there already exists identical configuration on device. + */ + static bool hasIdenticalConfig(const ConfigKey& key, + const vector<uint8_t>& config); + + /** + * Prints disk usage statistics related to statsd. + */ + static void printStats(FILE* out); + +private: + /** + * Prints disk usage statistics about a directory related to statsd. + */ + static void printDirStats(FILE* out, const char* path); }; } // namespace statsd diff --git a/cmds/statsd/tests/FieldValue_test.cpp b/cmds/statsd/tests/FieldValue_test.cpp index 5846761cb8e9..73e7c44dc3da 100644 --- a/cmds/statsd/tests/FieldValue_test.cpp +++ b/cmds/statsd/tests/FieldValue_test.cpp @@ -45,20 +45,41 @@ TEST(AtomMatcherTest, TestFieldTranslation) { const auto& matcher12 = output[0]; EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag()); - EXPECT_EQ((int32_t)0x2010001, matcher12.mMatcher.getField()); + EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField()); EXPECT_EQ((int32_t)0xff7f007f, matcher12.mMask); } -TEST(AtomMatcherTest, TestFilter) { +TEST(AtomMatcherTest, TestFieldTranslation_ALL) { FieldMatcher matcher1; matcher1.set_field(10); FieldMatcher* child = matcher1.add_child(); child->set_field(1); - child->set_position(Position::ANY); + child->set_position(Position::ALL); child = child->add_child(); child->set_field(1); + vector<Matcher> output; + translateFieldMatcher(matcher1, &output); + + EXPECT_EQ((size_t)1, output.size()); + + const auto& matcher12 = output[0]; + EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag()); + EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField()); + EXPECT_EQ((int32_t)0xff7f7f7f, matcher12.mMask); +} + +TEST(AtomMatcherTest, TestFilter_ALL) { + FieldMatcher matcher1; + matcher1.set_field(10); + FieldMatcher* child = matcher1.add_child(); + child->set_field(1); + child->set_position(Position::ALL); + + child->add_child()->set_field(1); + child->add_child()->set_field(2); + child = matcher1.add_child(); child->set_field(2); @@ -85,32 +106,28 @@ TEST(AtomMatcherTest, TestFilter) { event.write("some value"); // Convert to a LogEvent event.init(); - vector<HashableDimensionKey> output; + HashableDimensionKey output; filterValues(matchers, event.getValues(), &output); - EXPECT_EQ((size_t)(3), output.size()); - - const auto& key1 = output[0]; - EXPECT_EQ((size_t)2, key1.getValues().size()); - EXPECT_EQ((int32_t)0x02010001, key1.getValues()[0].mField.getField()); - EXPECT_EQ((int32_t)1111, key1.getValues()[0].mValue.int_value); - EXPECT_EQ((int32_t)0x00020000, key1.getValues()[1].mField.getField()); - EXPECT_EQ("some value", key1.getValues()[1].mValue.str_value); - - const auto& key2 = output[1]; - EXPECT_EQ((size_t)2, key2.getValues().size()); - EXPECT_EQ((int32_t)0x02010001, key2.getValues()[0].mField.getField()); - EXPECT_EQ((int32_t)2222, key2.getValues()[0].mValue.int_value); - EXPECT_EQ((int32_t)0x00020000, key2.getValues()[1].mField.getField()); - EXPECT_EQ("some value", key2.getValues()[1].mValue.str_value); - - const auto& key3 = output[2]; - EXPECT_EQ((size_t)2, key3.getValues().size()); - EXPECT_EQ((int32_t)0x02010001, key3.getValues()[0].mField.getField()); - EXPECT_EQ((int32_t)3333, key3.getValues()[0].mValue.int_value); - EXPECT_EQ((int32_t)0x00020000, key3.getValues()[1].mField.getField()); - EXPECT_EQ("some value", key3.getValues()[1].mValue.str_value); + EXPECT_EQ((size_t)7, output.getValues().size()); + EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField()); + EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value); + EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField()); + EXPECT_EQ("location1", output.getValues()[1].mValue.str_value); + + EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField()); + EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value); + EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField()); + EXPECT_EQ("location2", output.getValues()[3].mValue.str_value); + + EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField()); + EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value); + EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField()); + EXPECT_EQ("location3", output.getValues()[5].mValue.str_value); + + EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField()); + EXPECT_EQ("some value", output.getValues()[6].mValue.str_value); } TEST(AtomMatcherTest, TestSubDimension) { diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp index ca656ed9ab35..ee7d770ec53d 100644 --- a/cmds/statsd/tests/UidMap_test.cpp +++ b/cmds/statsd/tests/UidMap_test.cpp @@ -174,41 +174,52 @@ TEST(UidMapTest, TestClearingOutput) { 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 @@ TEST(UidMapTest, TestMemoryComputed) { 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 @@ TEST(UidMapTest, TestMemoryGuardrail) { 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/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp index 7a7e000fb98f..2574ba79f9d3 100644 --- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp @@ -28,7 +28,7 @@ namespace statsd { namespace { -StatsdConfig CreateStatsdConfig() { +StatsdConfig CreateStatsdConfig(const Position position) { StatsdConfig config; auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher(); auto attributionNodeMatcher = @@ -46,15 +46,15 @@ StatsdConfig CreateStatsdConfig() { countMetric->set_what(wakelockAcquireMatcher.id()); *countMetric->mutable_dimensions_in_what() = CreateAttributionUidAndTagDimensions( - android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST}); + android::util::WAKELOCK_STATE_CHANGED, {position}); countMetric->set_bucket(FIVE_MINUTES); return config; } } // namespace -TEST(AttributionE2eTest, TestAttributionMatchAndSlice) { - auto config = CreateStatsdConfig(); +TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) { + auto config = CreateStatsdConfig(Position::FIRST); int64_t bucketStartTimeNs = 10000000000; int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000; @@ -199,6 +199,215 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSlice) { EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); } +TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) { + auto config = CreateStatsdConfig(Position::ALL); + int64_t bucketStartTimeNs = 10000000000; + int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000; + + ConfigKey cfgKey; + auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + + // Here it assumes that GMS core has two uids. + processor->getUidMap()->updateApp( + android::String16("com.android.gmscore"), 222 /* uid */, 1 /* version code*/); + processor->getUidMap()->updateApp( + android::String16("com.android.gmscore"), 444 /* uid */, 1 /* version code*/); + processor->getUidMap()->updateApp( + android::String16("app1"), 111 /* uid */, 2 /* version code*/); + processor->getUidMap()->updateApp( + android::String16("APP3"), 333 /* uid */, 2 /* version code*/); + + // GMS core node is in the middle. + std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"), + CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(333, "App3")}; + + // GMS core node is the last one. + std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"), + CreateAttribution(333, "App3"), + CreateAttribution(222, "GMSCoreModule1")}; + + // GMS core node is the first one. + std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"), + CreateAttribution(333, "App3")}; + + // Single GMS core node. + std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")}; + + // GMS core has another uid. + std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"), + CreateAttribution(444, "GMSCoreModule2"), + CreateAttribution(333, "App3")}; + + // Multiple GMS core nodes. + std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"), + CreateAttribution(222, "GMSCoreModule1")}; + + // No GMS core nodes. + std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"), + CreateAttribution(333, "App3")}; + std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")}; + + // GMS core node with isolated uid. + const int isolatedUid = 666; + std::vector<AttributionNodeInternal> attributions9 = { + CreateAttribution(isolatedUid, "GMSCoreModule1")}; + + std::vector<std::unique_ptr<LogEvent>> events; + // Events 1~4 are in the 1st bucket. + events.push_back(CreateAcquireWakelockEvent( + attributions1, "wl1", bucketStartTimeNs + 2)); + events.push_back(CreateAcquireWakelockEvent( + attributions2, "wl1", bucketStartTimeNs + 200)); + events.push_back(CreateAcquireWakelockEvent( + attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1)); + events.push_back(CreateAcquireWakelockEvent( + attributions4, "wl1", bucketStartTimeNs + bucketSizeNs)); + + // Events 5~8 are in the 3rd bucket. + events.push_back(CreateAcquireWakelockEvent( + attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1)); + events.push_back(CreateAcquireWakelockEvent( + attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100)); + events.push_back(CreateAcquireWakelockEvent( + attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2)); + events.push_back(CreateAcquireWakelockEvent( + attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs)); + events.push_back(CreateAcquireWakelockEvent( + attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1)); + events.push_back(CreateAcquireWakelockEvent( + attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100)); + events.push_back(CreateIsolatedUidChangedEvent( + isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1)); + events.push_back(CreateIsolatedUidChangedEvent( + isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10)); + + sortLogEventsByTimestamp(&events); + + for (const auto& event : events) { + processor->OnLogEvent(event.get()); + } + ConfigMetricsReportList reports; + vector<uint8_t> buffer; + processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, &buffer); + EXPECT_TRUE(buffer.size() > 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + EXPECT_EQ(reports.reports_size(), 1); + EXPECT_EQ(reports.reports(0).metrics_size(), 1); + + StatsLogReport::CountMetricDataWrapper countMetrics; + sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); + EXPECT_EQ(countMetrics.data_size(), 6); + + auto data = countMetrics.data(0); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1"); + EXPECT_EQ(2, data.bucket_info_size()); + EXPECT_EQ(1, data.bucket_info(0).count()); + EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, + data.bucket_info(0).start_bucket_elapsed_nanos()); + EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, + data.bucket_info(0).end_bucket_elapsed_nanos()); + EXPECT_EQ(1, data.bucket_info(1).count()); + EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, + data.bucket_info(1).start_bucket_elapsed_nanos()); + EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs, + data.bucket_info(1).end_bucket_elapsed_nanos()); + + data = countMetrics.data(1); + ValidateUidDimension( + data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1"); + ValidateUidDimension( + data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3"); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); + EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); + + data = countMetrics.data(2); + ValidateUidDimension( + data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2"); + ValidateUidDimension( + data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1"); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, + data.bucket_info(0).start_bucket_elapsed_nanos()); + EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, + data.bucket_info(0).end_bucket_elapsed_nanos()); + + data = countMetrics.data(3); + ValidateUidDimension( + data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1"); + ValidateUidDimension( + data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1"); + ValidateUidDimension( + data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3"); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(bucketStartTimeNs, + data.bucket_info(0).start_bucket_elapsed_nanos()); + EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, + data.bucket_info(0).end_bucket_elapsed_nanos()); + + data = countMetrics.data(4); + ValidateUidDimension( + data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1"); + ValidateUidDimension( + data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3"); + ValidateUidDimension( + data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1"); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(bucketStartTimeNs, + data.bucket_info(0).start_bucket_elapsed_nanos()); + EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, + data.bucket_info(0).end_bucket_elapsed_nanos()); + + data = countMetrics.data(5); + ValidateUidDimension( + data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1"); + ValidateUidDimension( + data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2"); + ValidateUidDimension( + data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333); + ValidateAttributionUidAndTagDimension( + data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3"); + EXPECT_EQ(data.bucket_info_size(), 1); + EXPECT_EQ(data.bucket_info(0).count(), 1); + EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, + data.bucket_info(0).start_bucket_elapsed_nanos()); + EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, + data.bucket_info(0).end_bucket_elapsed_nanos()); +} + #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp new file mode 100644 index 000000000000..9ceffc816e68 --- /dev/null +++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp @@ -0,0 +1,281 @@ +// 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. + +#include <gtest/gtest.h> + +#include "src/StatsLogProcessor.h" +#include "src/stats_log_util.h" +#include "tests/statsd_test_util.h" + +#include <vector> + +namespace android { +namespace os { +namespace statsd { + +#ifdef __ANDROID__ + +namespace { + +StatsdConfig CreateStatsdConfigForPushedEvent(const GaugeMetric::SamplingType sampling_type) { + StatsdConfig config; + *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher(); + *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher(); + + auto atomMatcher = CreateSimpleAtomMatcher("", android::util::APP_START_CHANGED); + *config.add_atom_matcher() = atomMatcher; + + auto isInBackgroundPredicate = CreateIsInBackgroundPredicate(); + *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() = + CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ }); + *config.add_predicate() = isInBackgroundPredicate; + + auto gaugeMetric = config.add_gauge_metric(); + gaugeMetric->set_id(123456); + gaugeMetric->set_what(atomMatcher.id()); + gaugeMetric->set_condition(isInBackgroundPredicate.id()); + gaugeMetric->mutable_gauge_fields_filter()->set_include_all(false); + gaugeMetric->set_sampling_type(sampling_type); + auto fieldMatcher = gaugeMetric->mutable_gauge_fields_filter()->mutable_fields(); + fieldMatcher->set_field(android::util::APP_START_CHANGED); + fieldMatcher->add_child()->set_field(3); // type (enum) + fieldMatcher->add_child()->set_field(4); // activity_name(str) + fieldMatcher->add_child()->set_field(7); // activity_start_msec(int64) + *gaugeMetric->mutable_dimensions_in_what() = + CreateDimensions(android::util::APP_START_CHANGED, {1 /* uid field */ }); + gaugeMetric->set_bucket(FIVE_MINUTES); + + auto links = gaugeMetric->add_links(); + links->set_condition(isInBackgroundPredicate.id()); + auto dimensionWhat = links->mutable_fields_in_what(); + dimensionWhat->set_field(android::util::APP_START_CHANGED); + dimensionWhat->add_child()->set_field(1); // uid field. + auto dimensionCondition = links->mutable_fields_in_condition(); + dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED); + dimensionCondition->add_child()->set_field(1); // uid field. + return config; +} + +std::unique_ptr<LogEvent> CreateAppStartChangedEvent( + const int uid, const string& pkg_name, AppStartChanged::TransitionType type, + const string& activity_name, const string& calling_pkg_name, const bool is_instant_app, + int64_t activity_start_msec, uint64_t timestampNs) { + auto logEvent = std::make_unique<LogEvent>( + android::util::APP_START_CHANGED, timestampNs); + logEvent->write(uid); + logEvent->write(pkg_name); + logEvent->write(type); + logEvent->write(activity_name); + logEvent->write(calling_pkg_name); + logEvent->write(is_instant_app); + logEvent->write(activity_start_msec); + logEvent->init(); + return logEvent; +} + +} // namespace + +TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) { + for (const auto& sampling_type : + { GaugeMetric::ALL_CONDITION_CHANGES, GaugeMetric:: RANDOM_ONE_SAMPLE }) { + auto config = CreateStatsdConfigForPushedEvent(sampling_type); + int64_t bucketStartTimeNs = 10000000000; + int64_t bucketSizeNs = + TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000; + + ConfigKey cfgKey; + auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + + int appUid1 = 123; + int appUid2 = 456; + std::vector<std::unique_ptr<LogEvent>> events; + events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15)); + events.push_back(CreateMoveToForegroundEvent( + appUid1, bucketStartTimeNs + bucketSizeNs + 250)); + events.push_back(CreateMoveToBackgroundEvent( + appUid1, bucketStartTimeNs + bucketSizeNs + 350)); + events.push_back(CreateMoveToForegroundEvent( + appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100)); + + + events.push_back(CreateAppStartChangedEvent( + appUid1, "app1", AppStartChanged::WARM, "activity_name1", "calling_pkg_name1", + true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10)); + events.push_back(CreateAppStartChangedEvent( + appUid1, "app1", AppStartChanged::HOT, "activity_name2", "calling_pkg_name2", + true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20)); + events.push_back(CreateAppStartChangedEvent( + appUid1, "app1", AppStartChanged::COLD, "activity_name3", "calling_pkg_name3", + true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30)); + events.push_back(CreateAppStartChangedEvent( + appUid1, "app1", AppStartChanged::WARM, "activity_name4", "calling_pkg_name4", + true /*is_instant_app*/, 104 /*activity_start_msec*/, + bucketStartTimeNs + bucketSizeNs + 30)); + events.push_back(CreateAppStartChangedEvent( + appUid1, "app1", AppStartChanged::COLD, "activity_name5", "calling_pkg_name5", + true /*is_instant_app*/, 105 /*activity_start_msec*/, + bucketStartTimeNs + 2 * bucketSizeNs)); + events.push_back(CreateAppStartChangedEvent( + appUid1, "app1", AppStartChanged::HOT, "activity_name6", "calling_pkg_name6", + false /*is_instant_app*/, 106 /*activity_start_msec*/, + bucketStartTimeNs + 2 * bucketSizeNs + 10)); + + events.push_back(CreateMoveToBackgroundEvent( + appUid2, bucketStartTimeNs + bucketSizeNs + 10)); + events.push_back(CreateAppStartChangedEvent( + appUid2, "app2", AppStartChanged::COLD, "activity_name7", "calling_pkg_name7", + true /*is_instant_app*/, 201 /*activity_start_msec*/, + bucketStartTimeNs + 2 * bucketSizeNs + 10)); + + sortLogEventsByTimestamp(&events); + + for (const auto& event : events) { + processor->OnLogEvent(event.get()); + } + ConfigMetricsReportList reports; + vector<uint8_t> buffer; + processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, &buffer); + EXPECT_TRUE(buffer.size() > 0); + EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); + EXPECT_EQ(1, reports.reports_size()); + EXPECT_EQ(1, reports.reports(0).metrics_size()); + StatsLogReport::GaugeMetricDataWrapper gaugeMetrics; + sortMetricDataByDimensionsValue( + reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics); + EXPECT_EQ(2, gaugeMetrics.data_size()); + + auto data = gaugeMetrics.data(0); + EXPECT_EQ(android::util::APP_START_CHANGED, data.dimensions_in_what().field()); + EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size()); + EXPECT_EQ(1 /* uid field */, + data.dimensions_in_what().value_tuple().dimensions_value(0).field()); + EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int()); + EXPECT_EQ(3, data.bucket_info_size()); + if (sampling_type == GaugeMetric::ALL_CONDITION_CHANGES) { + EXPECT_EQ(2, data.bucket_info(0).atom_size()); + EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size()); + EXPECT_EQ(2, data.bucket_info(0).wall_clock_timestamp_nanos_size()); + EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_nanos()); + EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_nanos()); + EXPECT_EQ(AppStartChanged::HOT, data.bucket_info(0).atom(0).app_start_changed().type()); + EXPECT_EQ("activity_name2", + data.bucket_info(0).atom(0).app_start_changed().activity_name()); + EXPECT_EQ(102L, + data.bucket_info(0).atom(0).app_start_changed().activity_start_millis()); + EXPECT_EQ(AppStartChanged::COLD, + data.bucket_info(0).atom(1).app_start_changed().type()); + EXPECT_EQ("activity_name3", + data.bucket_info(0).atom(1).app_start_changed().activity_name()); + EXPECT_EQ(103L, + data.bucket_info(0).atom(1).app_start_changed().activity_start_millis()); + + EXPECT_EQ(1, data.bucket_info(1).atom_size()); + EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size()); + EXPECT_EQ(1, data.bucket_info(1).wall_clock_timestamp_nanos_size()); + EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(1).start_bucket_nanos()); + EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(1).end_bucket_nanos()); + EXPECT_EQ(AppStartChanged::WARM, + data.bucket_info(1).atom(0).app_start_changed().type()); + EXPECT_EQ("activity_name4", + data.bucket_info(1).atom(0).app_start_changed().activity_name()); + EXPECT_EQ(104L, + data.bucket_info(1).atom(0).app_start_changed().activity_start_millis()); + + EXPECT_EQ(2, data.bucket_info(2).atom_size()); + EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size()); + EXPECT_EQ(2, data.bucket_info(2).wall_clock_timestamp_nanos_size()); + EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, + data.bucket_info(2).start_bucket_nanos()); + EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, + data.bucket_info(2).end_bucket_nanos()); + EXPECT_EQ(AppStartChanged::COLD, + data.bucket_info(2).atom(0).app_start_changed().type()); + EXPECT_EQ("activity_name5", + data.bucket_info(2).atom(0).app_start_changed().activity_name()); + EXPECT_EQ(105L, + data.bucket_info(2).atom(0).app_start_changed().activity_start_millis()); + EXPECT_EQ(AppStartChanged::HOT, + data.bucket_info(2).atom(1).app_start_changed().type()); + EXPECT_EQ("activity_name6", + data.bucket_info(2).atom(1).app_start_changed().activity_name()); + EXPECT_EQ(106L, + data.bucket_info(2).atom(1).app_start_changed().activity_start_millis()); + } else { + EXPECT_EQ(1, data.bucket_info(0).atom_size()); + EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size()); + EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size()); + EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_nanos()); + EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_nanos()); + EXPECT_EQ(AppStartChanged::HOT, data.bucket_info(0).atom(0).app_start_changed().type()); + EXPECT_EQ("activity_name2", + data.bucket_info(0).atom(0).app_start_changed().activity_name()); + EXPECT_EQ(102L, + data.bucket_info(0).atom(0).app_start_changed().activity_start_millis()); + + EXPECT_EQ(1, data.bucket_info(1).atom_size()); + EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size()); + EXPECT_EQ(1, data.bucket_info(1).wall_clock_timestamp_nanos_size()); + EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(1).start_bucket_nanos()); + EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(1).end_bucket_nanos()); + EXPECT_EQ(AppStartChanged::WARM, + data.bucket_info(1).atom(0).app_start_changed().type()); + EXPECT_EQ("activity_name4", + data.bucket_info(1).atom(0).app_start_changed().activity_name()); + EXPECT_EQ(104L, + data.bucket_info(1).atom(0).app_start_changed().activity_start_millis()); + + EXPECT_EQ(1, data.bucket_info(2).atom_size()); + EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size()); + EXPECT_EQ(1, data.bucket_info(2).wall_clock_timestamp_nanos_size()); + EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, + data.bucket_info(2).start_bucket_nanos()); + EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, + data.bucket_info(2).end_bucket_nanos()); + EXPECT_EQ(AppStartChanged::COLD, + data.bucket_info(2).atom(0).app_start_changed().type()); + EXPECT_EQ("activity_name5", + data.bucket_info(2).atom(0).app_start_changed().activity_name()); + EXPECT_EQ(105L, + data.bucket_info(2).atom(0).app_start_changed().activity_start_millis()); + } + + data = gaugeMetrics.data(1); + + EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_CHANGED); + EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(1 /* uid field */, + data.dimensions_in_what().value_tuple().dimensions_value(0).field()); + EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int()); + EXPECT_EQ(1, data.bucket_info_size()); + EXPECT_EQ(1, data.bucket_info(0).atom_size()); + EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size()); + EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size()); + EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_nanos()); + EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_nanos()); + EXPECT_EQ(AppStartChanged::COLD, data.bucket_info(0).atom(0).app_start_changed().type()); + EXPECT_EQ("activity_name7", + data.bucket_info(0).atom(0).app_start_changed().activity_name()); + EXPECT_EQ(201L, data.bucket_info(0).atom(0).app_start_changed().activity_start_millis()); + } +} + +#else +GTEST_LOG_(INFO) << "This test does nothing.\n"; +#endif + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp deleted file mode 100644 index 3843e0a3c67d..000000000000 --- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp +++ /dev/null @@ -1,201 +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. - -#include <gtest/gtest.h> - -#include "src/StatsLogProcessor.h" -#include "src/stats_log_util.h" -#include "tests/statsd_test_util.h" - -#include <vector> - -namespace android { -namespace os { -namespace statsd { - -#ifdef __ANDROID__ - -namespace { - -StatsdConfig CreateStatsdConfigForPushedEvent() { - StatsdConfig config; - *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher(); - *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher(); - - auto atomMatcher = CreateSimpleAtomMatcher("", android::util::APP_START_CHANGED); - *config.add_atom_matcher() = atomMatcher; - - auto isInBackgroundPredicate = CreateIsInBackgroundPredicate(); - *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() = - CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ }); - *config.add_predicate() = isInBackgroundPredicate; - - auto gaugeMetric = config.add_gauge_metric(); - gaugeMetric->set_id(123456); - gaugeMetric->set_what(atomMatcher.id()); - gaugeMetric->set_condition(isInBackgroundPredicate.id()); - gaugeMetric->mutable_gauge_fields_filter()->set_include_all(false); - auto fieldMatcher = gaugeMetric->mutable_gauge_fields_filter()->mutable_fields(); - fieldMatcher->set_field(android::util::APP_START_CHANGED); - fieldMatcher->add_child()->set_field(3); // type (enum) - fieldMatcher->add_child()->set_field(4); // activity_name(str) - fieldMatcher->add_child()->set_field(7); // activity_start_msec(int64) - *gaugeMetric->mutable_dimensions_in_what() = - CreateDimensions(android::util::APP_START_CHANGED, {1 /* uid field */ }); - gaugeMetric->set_bucket(FIVE_MINUTES); - - auto links = gaugeMetric->add_links(); - links->set_condition(isInBackgroundPredicate.id()); - auto dimensionWhat = links->mutable_fields_in_what(); - dimensionWhat->set_field(android::util::APP_START_CHANGED); - dimensionWhat->add_child()->set_field(1); // uid field. - auto dimensionCondition = links->mutable_fields_in_condition(); - dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED); - dimensionCondition->add_child()->set_field(1); // uid field. - return config; -} - -std::unique_ptr<LogEvent> CreateAppStartChangedEvent( - const int uid, const string& pkg_name, AppStartChanged::TransitionType type, - const string& activity_name, const string& calling_pkg_name, const bool is_instant_app, - int64_t activity_start_msec, uint64_t timestampNs) { - auto logEvent = std::make_unique<LogEvent>( - android::util::APP_START_CHANGED, timestampNs); - logEvent->write(uid); - logEvent->write(pkg_name); - logEvent->write(type); - logEvent->write(activity_name); - logEvent->write(calling_pkg_name); - logEvent->write(is_instant_app); - logEvent->write(activity_start_msec); - logEvent->init(); - return logEvent; -} - -} // namespace - -TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) { - auto config = CreateStatsdConfigForPushedEvent(); - int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000; - - ConfigKey cfgKey; - auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - - int appUid1 = 123; - int appUid2 = 456; - std::vector<std::unique_ptr<LogEvent>> events; - events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15)); - events.push_back(CreateMoveToForegroundEvent(appUid1, bucketStartTimeNs + bucketSizeNs + 250)); - events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + bucketSizeNs + 350)); - events.push_back(CreateMoveToForegroundEvent( - appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100)); - - - events.push_back(CreateAppStartChangedEvent( - appUid1, "app1", AppStartChanged::WARM, "activity_name1", "calling_pkg_name1", - true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10)); - events.push_back(CreateAppStartChangedEvent( - appUid1, "app1", AppStartChanged::HOT, "activity_name2", "calling_pkg_name2", - true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20)); - events.push_back(CreateAppStartChangedEvent( - appUid1, "app1", AppStartChanged::COLD, "activity_name3", "calling_pkg_name3", - true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30)); - events.push_back(CreateAppStartChangedEvent( - appUid1, "app1", AppStartChanged::WARM, "activity_name4", "calling_pkg_name4", - true /*is_instant_app*/, 104 /*activity_start_msec*/, - bucketStartTimeNs + bucketSizeNs + 30)); - events.push_back(CreateAppStartChangedEvent( - appUid1, "app1", AppStartChanged::COLD, "activity_name5", "calling_pkg_name5", - true /*is_instant_app*/, 105 /*activity_start_msec*/, - bucketStartTimeNs + 2 * bucketSizeNs)); - events.push_back(CreateAppStartChangedEvent( - appUid1, "app1", AppStartChanged::HOT, "activity_name6", "calling_pkg_name6", - false /*is_instant_app*/, 106 /*activity_start_msec*/, - bucketStartTimeNs + 2 * bucketSizeNs + 10)); - - events.push_back(CreateMoveToBackgroundEvent(appUid2, bucketStartTimeNs + bucketSizeNs + 10)); - events.push_back(CreateAppStartChangedEvent( - appUid2, "app2", AppStartChanged::COLD, "activity_name7", "calling_pkg_name7", - true /*is_instant_app*/, 201 /*activity_start_msec*/, - bucketStartTimeNs + 2 * bucketSizeNs + 10)); - - sortLogEventsByTimestamp(&events); - - for (const auto& event : events) { - processor->OnLogEvent(event.get()); - } - ConfigMetricsReportList reports; - vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, &buffer); - EXPECT_TRUE(buffer.size() > 0); - EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); - EXPECT_EQ(reports.reports_size(), 1); - EXPECT_EQ(reports.reports(0).metrics_size(), 1); - StatsLogReport::GaugeMetricDataWrapper gaugeMetrics; - sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics); - EXPECT_EQ(gaugeMetrics.data_size(), 2); - - auto data = gaugeMetrics.data(0); - EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid1); - EXPECT_EQ(data.bucket_info_size(), 3); - EXPECT_EQ(data.bucket_info(0).atom_size(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::HOT); - EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name2"); - EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_millis(), 102L); - - EXPECT_EQ(data.bucket_info(1).atom_size(), 1); - EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().type(), AppStartChanged::WARM); - EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_name(), "activity_name4"); - EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_start_millis(), 104L); - - EXPECT_EQ(data.bucket_info(2).atom_size(), 1); - EXPECT_EQ(data.bucket_info(2).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(2).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().type(), AppStartChanged::COLD); - EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_name(), "activity_name5"); - EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_start_millis(), 105L); - - data = gaugeMetrics.data(1); - - EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_CHANGED); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */); - EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid2); - EXPECT_EQ(data.bucket_info_size(), 1); - EXPECT_EQ(data.bucket_info(0).atom_size(), 1); - EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); - EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::COLD); - EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name7"); - EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_millis(), 201L); -} - -#else -GTEST_LOG_(INFO) << "This test does nothing.\n"; -#endif - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index 77b3ace90aff..c0cc0b6ad218 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -112,7 +112,6 @@ TEST(GaugeMetricProducerTest, TestNoCondition) { it++; EXPECT_EQ(INT, it->mValue.getType()); EXPECT_EQ(11L, it->mValue.int_value); - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum); gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs); EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size()); @@ -125,7 +124,6 @@ TEST(GaugeMetricProducerTest, TestNoCondition) { it++; EXPECT_EQ(INT, it->mValue.getType()); EXPECT_EQ(25L, it->mValue.int_value); - EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum); } TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) { @@ -337,7 +335,6 @@ TEST(GaugeMetricProducerTest, TestWithCondition) { .mGaugeAtoms.front() .mFields->begin() ->mValue.int_value); - EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum); } TEST(GaugeMetricProducerTest, TestAnomalyDetection) { diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp index 2678c8a93463..0f785dff8e81 100644 --- a/cmds/statsd/tests/statsd_test_util.cpp +++ b/cmds/statsd/tests/statsd_test_util.cpp @@ -500,12 +500,42 @@ void ValidateUidDimension(const DimensionsValue& value, int atomId, int uid) { .value_tuple().dimensions_value(0).value_int(), uid); } +void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid) { + EXPECT_EQ(value.field(), atomId); + EXPECT_GT(value.value_tuple().dimensions_value_size(), node_idx); + // Attribution field. + EXPECT_EQ(value.value_tuple().dimensions_value(node_idx).field(), 1); + EXPECT_EQ(value.value_tuple().dimensions_value(node_idx) + .value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(value.value_tuple().dimensions_value(node_idx) + .value_tuple().dimensions_value(0).value_int(), uid); +} + +void ValidateAttributionUidAndTagDimension( + const DimensionsValue& value, int node_idx, int atomId, int uid, const std::string& tag) { + EXPECT_EQ(value.field(), atomId); + EXPECT_GT(value.value_tuple().dimensions_value_size(), node_idx); + // Attribution field. + EXPECT_EQ(1, value.value_tuple().dimensions_value(node_idx).field()); + // Uid only. + EXPECT_EQ(2, value.value_tuple().dimensions_value(node_idx) + .value_tuple().dimensions_value_size()); + EXPECT_EQ(1, value.value_tuple().dimensions_value(node_idx) + .value_tuple().dimensions_value(0).field()); + EXPECT_EQ(uid, value.value_tuple().dimensions_value(node_idx) + .value_tuple().dimensions_value(0).value_int()); + EXPECT_EQ(2, value.value_tuple().dimensions_value(node_idx) + .value_tuple().dimensions_value(1).field()); + EXPECT_EQ(tag, value.value_tuple().dimensions_value(node_idx) + .value_tuple().dimensions_value(1).value_str()); +} + void ValidateAttributionUidAndTagDimension( const DimensionsValue& value, int atomId, int uid, const std::string& tag) { EXPECT_EQ(value.field(), atomId); - EXPECT_EQ(value.value_tuple().dimensions_value_size(), 1); + EXPECT_EQ(1, value.value_tuple().dimensions_value_size()); // Attribution field. - EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1); + EXPECT_EQ(1, value.value_tuple().dimensions_value(0).field()); // Uid only. EXPECT_EQ(value.value_tuple().dimensions_value(0) .value_tuple().dimensions_value_size(), 2); diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h index 14eba1f67d9d..1ac630ccff96 100644 --- a/cmds/statsd/tests/statsd_test_util.h +++ b/cmds/statsd/tests/statsd_test_util.h @@ -180,9 +180,12 @@ void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events); int64_t StringToId(const string& str); +void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid); void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid); void ValidateAttributionUidAndTagDimension( const DimensionsValue& value, int atomId, int uid, const std::string& tag); +void ValidateAttributionUidAndTagDimension( + const DimensionsValue& value, int node_idx, int atomId, int uid, const std::string& tag); struct DimensionsPair { DimensionsPair(DimensionsValue m1, DimensionsValue m2) : dimInWhat(m1), dimInCondition(m2){}; diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt index f134e5488937..99d871e0f6f5 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-light-greylist.txt @@ -11,6 +11,7 @@ Landroid/app/ActivityManager;->clearApplicationUserData(Ljava/lang/String;Landro 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;->mLocalProviders:Landroid/util/ArrayMap; 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;->packageHasActiveAdmins(Ljava/lang/Strin 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/IAlarmManager$Stub;->TRANSACTION_set:I 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/TimePickerDialog;->mTimePicker:Landroid/widget/TimePicker; 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$PendingResult;-><init>(ILjava/lang/String;Lan 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;->mType:I 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;->privateFlags:I 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/IPackageStatsObserver$Stub;-><init>()V 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;->mTypedArrayPool:Landroid/util/Pools$Synchronize 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;-><init>([B)V 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/Bitmap;->reinit(IIZ)V 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/Movie;->mNativeMovie:J 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;->mProducer:J 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; @@ -649,6 +671,8 @@ Landroid/hardware/HardwareBuffer;->mNativeObject:J Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager; Landroid/hardware/input/IInputManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/hardware/input/InputManager;->getInstance()Landroid/hardware/input/InputManager; +Landroid/hardware/input/InputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z +Landroid/hardware/input/InputManager;->INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH:I Landroid/hardware/input/InputManager;->mIm:Landroid/hardware/input/IInputManager; Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V Landroid/hardware/SerialPort;->mNativeContext:I @@ -656,6 +680,7 @@ Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;->confidenceLevel:I Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;-><init>(II)V Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;->userId:I Landroid/hardware/soundtrigger/SoundTrigger$GenericRecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V +Landroid/hardware/soundtrigger/SoundTrigger$GenericSoundModel;-><init>(Ljava/util/UUID;Ljava/util/UUID;[B)V Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->id:I Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->locale:Ljava/lang/String; Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;)V @@ -674,6 +699,7 @@ Landroid/hardware/soundtrigger/SoundTriggerModule;->postEventFromNative(Ljava/la Landroid/hardware/soundtrigger/SoundTrigger$ModuleProperties;-><init>(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIZIZIZ)V Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->captureRequested:Z Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->data:[B +Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;-><init>(ZZ[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;[B)V Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->keyphrases:[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra; Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->data:[B @@ -690,8 +716,13 @@ Landroid/hardware/usb/UsbManager;->getPortStatus(Landroid/hardware/usb/UsbPort;) 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 @@ -769,7 +800,9 @@ Landroid/media/AudioFormat;->mEncoding:I 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 @@ -829,6 +862,7 @@ Landroid/media/AudioSystem;->getPrimaryOutputFrameCount()I 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 @@ -836,6 +870,9 @@ Landroid/media/AudioTrack;->mNativeTrackInJavaObj:J 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 @@ -890,6 +927,11 @@ Landroid/media/RemoteDisplay;->notifyDisplayDisconnected()V 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 +Landroid/media/soundtrigger/SoundTriggerManager;->startRecognition(Ljava/util/UUID;Landroid/app/PendingIntent;Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;)I Landroid/media/soundtrigger/SoundTriggerManager;->stopRecognition(Ljava/util/UUID;)I Landroid/media/soundtrigger/SoundTriggerManager;->unloadSoundModel(Ljava/util/UUID;)I Landroid/media/SubtitleController;->mHandler:Landroid/os/Handler; @@ -946,6 +988,7 @@ Landroid/net/NetworkCapabilities;->getTransportTypes()[I 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 @@ -958,7 +1001,9 @@ Landroid/net/NetworkStats;->tag:[I 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; @@ -1035,6 +1080,7 @@ Landroid/os/AsyncTask;->setDefaultExecutor(Ljava/util/concurrent/Executor;)V 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; @@ -1099,6 +1145,7 @@ Landroid/os/FileUtils;->stringToFile(Ljava/io/File;Ljava/lang/String;)V 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 @@ -1212,14 +1259,31 @@ Landroid/os/UpdateLock;->NOW_IS_CONVENIENT:Ljava/lang/String; 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 @@ -1230,10 +1294,23 @@ Landroid/os/UserManager;->getUserIcon(I)Landroid/graphics/Bitmap; 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; @@ -1288,6 +1365,8 @@ Landroid/provider/Browser;->clearSearches(Landroid/content/ContentResolver;)V 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; @@ -1556,10 +1635,65 @@ Landroid/service/media/MediaBrowserService;->KEY_MEDIA_ITEM:Ljava/lang/String; Landroid/service/media/MediaBrowserService$Result;->mFlags:I Landroid/service/notification/NotificationListenerService;->registerAsSystemService(Landroid/content/Context;Landroid/content/ComponentName;I)V Landroid/service/notification/NotificationListenerService;->unregisterAsSystemService()V +Landroid/service/voice/AlwaysOnHotwordDetector$EventPayload;->getCaptureSession()Ljava/lang/Integer; Landroid/service/voice/VoiceInteractionService;->isKeyphraseAndLocaleSupportedForHotword(Ljava/lang/String;Ljava/util/Locale;)Z 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; @@ -1571,6 +1705,7 @@ Landroid/telephony/CellSignalStrengthLte;->mRssnr:I Landroid/telephony/CellSignalStrengthLte;->mSignalStrength:I Landroid/telephony/CellSignalStrengthWcdma;->mBitErrorRate:I Landroid/telephony/CellSignalStrengthWcdma;->mSignalStrength:I +Landroid/telephony/PhoneNumberUtils;->isLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z Landroid/telephony/PhoneStateListener;->mSubId:Ljava/lang/Integer; Landroid/telephony/ServiceState;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/ServiceState; Landroid/telephony/SignalStrength;->getAsuLevel()I @@ -1581,6 +1716,7 @@ Landroid/telephony/SignalStrength;->getLteRsrp()I 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 @@ -1595,6 +1731,7 @@ Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_NONE_OR_UNKNOWN:I Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_POOR:I Landroid/telephony/SmsMessage;->getSubId()I Landroid/telephony/SmsMessage;->mWrappedSmsMessage:Lcom/android/internal/telephony/SmsMessageBase; +Landroid/telephony/SubscriptionManager;->getActiveSubscriptionIdList()[I Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoCount()I Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoList()Ljava/util/List; Landroid/telephony/SubscriptionManager;->getDefaultDataSubscriptionInfo()Landroid/telephony/SubscriptionInfo; @@ -1715,7 +1852,9 @@ Landroid/util/NtpTrustedTime;->getCachedNtpTime()J 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 @@ -1767,6 +1906,7 @@ Landroid/view/InputChannel;->mPtr:J Landroid/view/InputDevice;->addMotionRange(IIFFFFF)V Landroid/view/InputDevice;-><init>(IIILjava/lang/String;IILjava/lang/String;ZIILandroid/view/KeyCharacterMap;ZZZ)V Landroid/view/InputDevice;->isExternal()Z +Landroid/view/InputEvent;->getSequenceNumber()I Landroid/view/InputEventReceiver;->dispatchBatchedInputEventPending()V Landroid/view/InputEventReceiver;->dispatchInputEvent(ILandroid/view/InputEvent;I)V Landroid/view/InputEventSender;->dispatchInputEventFinished(IZ)V @@ -1885,6 +2025,7 @@ Landroid/view/View$AttachInfo;->mStableInsets:Landroid/graphics/Rect; Landroid/view/View;->clearAccessibilityFocus()V Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z Landroid/view/View;->computeOpaqueFlags()V +Landroid/view/ViewConfiguration;->getDoubleTapMinTime()I Landroid/view/ViewConfiguration;->mFadingMarqueeEnabled:Z Landroid/view/ViewConfiguration;->sHasPermanentMenuKeySet:Z Landroid/view/ViewConfiguration;->sHasPermanentMenuKey:Z @@ -1896,6 +2037,7 @@ Landroid/view/View;->dispatchDetachedFromWindow()V 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 @@ -2280,12 +2422,15 @@ Lcom/android/ims/internal/uce/presence/PresTupleInfo;-><init>()V 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 Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V 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 @@ -2500,7 +2645,13 @@ Lcom/android/internal/view/menu/MenuView$ItemView;->getItemData()Lcom/android/in Lcom/android/okhttp/ConnectionPool;->keepAliveDurationNs:J Lcom/android/okhttp/ConnectionPool;->maxIdleConnections:I Lcom/android/okhttp/ConnectionPool;->systemDefault:Lcom/android/okhttp/ConnectionPool; +Lcom/android/okhttp/HttpUrl;->encodedPath()Ljava/lang/String; +Lcom/android/okhttp/HttpUrl;->query()Ljava/lang/String; Lcom/android/okhttp/internal/http/HttpEngine;->httpStream:Lcom/android/okhttp/internal/http/HttpStream; +Lcom/android/okhttp/internal/http/HttpEngine;->networkRequest:Lcom/android/okhttp/Request; +Lcom/android/okhttp/internal/http/HttpEngine;->networkRequest(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Request; +Lcom/android/okhttp/internal/http/HttpEngine;->priorResponse:Lcom/android/okhttp/Response; +Lcom/android/okhttp/internal/http/HttpEngine;->userResponse:Lcom/android/okhttp/Response; Lcom/android/okhttp/OkHttpClient;->connectionPool:Lcom/android/okhttp/ConnectionPool; Lcom/android/okhttp/OkHttpClient;->DEFAULT_PROTOCOLS:Ljava/util/List; Lcom/android/okhttp/OkHttpClient;->dns:Lcom/android/okhttp/Dns; @@ -2508,6 +2659,14 @@ Lcom/android/okhttp/OkHttpClient;->setProtocols(Ljava/util/List;)Lcom/android/ok Lcom/android/okhttp/OkHttpClient;->setRetryOnConnectionFailure(Z)V Lcom/android/okhttp/okio/ByteString;->readObject(Ljava/io/ObjectInputStream;)V Lcom/android/okhttp/okio/ByteString;->writeObject(Ljava/io/ObjectOutputStream;)V +Lcom/android/okhttp/Request;->headers:Lcom/android/okhttp/Headers; +Lcom/android/okhttp/Request;->method:Ljava/lang/String; +Lcom/android/okhttp/Request;->url:Lcom/android/okhttp/HttpUrl; +Lcom/android/okhttp/Response;->code:I +Lcom/android/okhttp/Response;->headers:Lcom/android/okhttp/Headers; +Lcom/android/okhttp/Response;->message:Ljava/lang/String; +Lcom/android/okhttp/Response;->networkResponse:Lcom/android/okhttp/Response; +Lcom/android/okhttp/Response;->protocol:Lcom/android/okhttp/Protocol; Lcom/android/org/conscrypt/AbstractConscryptSocket;->getAlpnSelectedProtocol()[B Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocol()Ljava/lang/String; Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocols()[Ljava/lang/String; @@ -2564,6 +2723,7 @@ Ldalvik/system/DexFile;->isBackedByOatFile()Z 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/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt new file mode 100644 index 000000000000..952b28b8b820 --- /dev/null +++ b/config/hiddenapi-vendor-list.txt @@ -0,0 +1,552 @@ +Landroid/app/ActivityManager$RecentTaskInfo;->configuration:Landroid/content/res/Configuration; +Landroid/app/ActivityManager$TaskDescription;->loadTaskDescriptionIcon(Ljava/lang/String;I)Landroid/graphics/Bitmap; +Landroid/app/ActivityManager$TaskSnapshot;->getSnapshot()Landroid/graphics/GraphicBuffer; +Landroid/app/ActivityOptions;->makeRemoteAnimation(Landroid/view/RemoteAnimationAdapter;)Landroid/app/ActivityOptions; +Landroid/app/ActivityOptions;->setSplitScreenCreateMode(I)V +Landroid/app/Activity;->registerRemoteAnimations(Landroid/view/RemoteAnimationDefinition;)V +Landroid/app/IActivityController$Stub;-><init>()V +Landroid/app/IActivityManager;->cancelRecentsAnimation()V +Landroid/app/IActivityManager;->cancelTaskWindowTransition(I)V +Landroid/app/IActivityManager;->closeSystemDialogs(Ljava/lang/String;)V +Landroid/app/IActivityManager;->getCurrentUser()Landroid/content/pm/UserInfo; +Landroid/app/IActivityManager;->getFilteredTasks(III)Ljava/util/List; +Landroid/app/IActivityManager;->getLockTaskModeState()I +Landroid/app/IActivityManager;->getRecentTasks(III)Landroid/content/pm/ParceledListSlice; +Landroid/app/IActivityManager;->getTaskSnapshot(IZ)Landroid/app/ActivityManager$TaskSnapshot; +Landroid/app/IActivityManager;->registerTaskStackListener(Landroid/app/ITaskStackListener;)V +Landroid/app/IActivityManager;->removeTask(I)Z +Landroid/app/IActivityManager;->startActivityFromRecents(ILandroid/os/Bundle;)I +Landroid/app/IActivityManager;->startRecentsActivity(Landroid/content/Intent;Landroid/app/IAssistDataReceiver;Landroid/view/IRecentsAnimationRunner;)V +Landroid/app/IAssistDataReceiver;->onHandleAssistData(Landroid/os/Bundle;)V +Landroid/app/IAssistDataReceiver;->onHandleAssistScreenshot(Landroid/graphics/Bitmap;)V +Landroid/app/IAssistDataReceiver$Stub;-><init>()V +Landroid/app/KeyguardManager;->isDeviceLocked(I)Z +Landroid/app/StatusBarManager;->removeIcon(Ljava/lang/String;)V +Landroid/app/StatusBarManager;->setIcon(Ljava/lang/String;IILjava/lang/String;)V +Landroid/app/TaskStackListener;->onActivityDismissingDockedStack()V +Landroid/app/TaskStackListener;->onActivityForcedResizable(Ljava/lang/String;II)V +Landroid/app/TaskStackListener;->onActivityLaunchOnSecondaryDisplayFailed()V +Landroid/app/TaskStackListener;->onActivityPinned(Ljava/lang/String;III)V +Landroid/app/TaskStackListener;->onActivityRequestedOrientationChanged(II)V +Landroid/app/TaskStackListener;->onActivityUnpinned()V +Landroid/app/TaskStackListener;->onPinnedActivityRestartAttempt(Z)V +Landroid/app/TaskStackListener;->onPinnedStackAnimationEnded()V +Landroid/app/TaskStackListener;->onPinnedStackAnimationStarted()V +Landroid/app/TaskStackListener;->onTaskMovedToFront(I)V +Landroid/app/TaskStackListener;->onTaskProfileLocked(II)V +Landroid/app/TaskStackListener;->onTaskRemoved(I)V +Landroid/app/TaskStackListener;->onTaskSnapshotChanged(ILandroid/app/ActivityManager$TaskSnapshot;)V +Landroid/app/TaskStackListener;->onTaskStackChanged()V +Landroid/app/VrStateCallback;-><init>()V +Landroid/app/VrStateCallback;->onPersistentVrStateChanged(Z)V +Landroid/app/WallpaperColors;-><init>(Landroid/graphics/Color;Landroid/graphics/Color;Landroid/graphics/Color;I)V +Landroid/companion/AssociationRequest;->getDeviceFilters()Ljava/util/List; +Landroid/companion/AssociationRequest;->isSingleDevice()Z +Landroid/companion/BluetoothDeviceFilter;->getAddress()Ljava/lang/String; +Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceDisplayNameInternal(Landroid/bluetooth/BluetoothDevice;)Ljava/lang/String; +Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceDisplayNameInternal(Landroid/net/wifi/ScanResult;)Ljava/lang/String; +Landroid/companion/BluetoothDeviceFilterUtils;->getDeviceMacAddress(Landroid/os/Parcelable;)Ljava/lang/String; +Landroid/companion/BluetoothLeDeviceFilter;->getScanFilter()Landroid/bluetooth/le/ScanFilter; +Landroid/companion/DeviceFilter;->getDeviceDisplayName(Landroid/os/Parcelable;)Ljava/lang/String; +Landroid/companion/DeviceFilter;->matches(Landroid/os/Parcelable;)Z +Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V +Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V +Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V +Landroid/companion/IFindDeviceCallback;->onSuccess(Landroid/app/PendingIntent;)V +Landroid/content/Context;->getOpPackageName()Ljava/lang/String; +Landroid/content/Context;->registerReceiverAsUser(Landroid/content/BroadcastReceiver;Landroid/os/UserHandle;Landroid/content/IntentFilter;Ljava/lang/String;Landroid/os/Handler;)Landroid/content/Intent; +Landroid/content/Context;->startActivityAsUser(Landroid/content/Intent;Landroid/os/UserHandle;)V +Landroid/content/Context;->startServiceAsUser(Landroid/content/Intent;Landroid/os/UserHandle;)Landroid/content/ComponentName; +Landroid/content/ContextWrapper;->getThemeResId()I +Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V +Landroid/content/pm/IPackageDataObserver$Stub;-><init>()V +Landroid/content/pm/IPackageDeleteObserver;->packageDeleted(Ljava/lang/String;I)V +Landroid/content/pm/IPackageDeleteObserver$Stub;-><init>()V +Landroid/content/pm/IPackageManager;->getActivityInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ActivityInfo; +Landroid/content/pm/IPackageManager;->getHomeActivities(Ljava/util/List;)Landroid/content/ComponentName; +Landroid/content/pm/IPackageStatsObserver;->onGetStatsCompleted(Landroid/content/pm/PackageStats;Z)V +Landroid/database/sqlite/SqliteWrapper;->insert(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri; +Landroid/graphics/AvoidXfermode;-><init>(IILandroid/graphics/AvoidXfermode$Mode;)V +Landroid/graphics/Bitmap;->createGraphicBufferHandle()Landroid/graphics/GraphicBuffer; +Landroid/graphics/Bitmap;->createHardwareBitmap(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap; +Landroid/graphics/Canvas;->clipRegion(Landroid/graphics/Region;Landroid/graphics/Region$Op;)Z +Landroid/graphics/Canvas;->clipRegion(Landroid/graphics/Region;)Z +Landroid/graphics/drawable/Drawable;->isProjected()Z +Landroid/graphics/drawable/Drawable;->updateTintFilter(Landroid/graphics/PorterDuffColorFilter;Landroid/content/res/ColorStateList;Landroid/graphics/PorterDuff$Mode;)Landroid/graphics/PorterDuffColorFilter; +Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V +Landroid/hardware/location/GeofenceHardware;-><init>(Landroid/hardware/location/IGeofenceHardware;)V +Landroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V +Landroid/location/IFusedProvider;->onFusedLocationHardwareChange(Landroid/hardware/location/IFusedLocationHardware;)V +Landroid/location/IGeocodeProvider;->getFromLocation(DDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String; +Landroid/location/IGeocodeProvider;->getFromLocationName(Ljava/lang/String;DDDDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String; +Landroid/location/IGeofenceProvider;->setGeofenceHardware(Landroid/hardware/location/IGeofenceHardware;)V +Landroid/location/ILocationManager;->reportLocation(Landroid/location/Location;Z)V +Landroid/media/AudioManager;->registerAudioPortUpdateListener(Landroid/media/AudioManager$OnAudioPortUpdateListener;)V +Landroid/media/AudioManager;->unregisterAudioPortUpdateListener(Landroid/media/AudioManager$OnAudioPortUpdateListener;)V +Landroid/media/AudioSystem;->checkAudioFlinger()I +Landroid/media/AudioSystem;->getParameters(Ljava/lang/String;)Ljava/lang/String; +Landroid/media/AudioSystem;->setParameters(Ljava/lang/String;)I +Landroid/media/MediaDrm$Certificate;->getContent()[B +Landroid/media/MediaDrm$Certificate;->getWrappedPrivateKey()[B +Landroid/media/MediaDrm$CertificateRequest;->getData()[B +Landroid/media/MediaDrm$CertificateRequest;->getDefaultUrl()Ljava/lang/String; +Landroid/media/MediaDrm;->getCertificateRequest(ILjava/lang/String;)Landroid/media/MediaDrm$CertificateRequest; +Landroid/media/MediaDrm;->provideCertificateResponse([B)Landroid/media/MediaDrm$Certificate; +Landroid/media/MediaDrm;->signRSA([BLjava/lang/String;[B[B)[B +Landroid/media/tv/ITvRemoteProvider$Stub;-><init>()V +Landroid/media/tv/ITvRemoteServiceInput;->clearInputBridge(Landroid/os/IBinder;)V +Landroid/media/tv/ITvRemoteServiceInput;->closeInputBridge(Landroid/os/IBinder;)V +Landroid/media/tv/ITvRemoteServiceInput;->openInputBridge(Landroid/os/IBinder;Ljava/lang/String;III)V +Landroid/media/tv/ITvRemoteServiceInput;->sendKeyDown(Landroid/os/IBinder;I)V +Landroid/media/tv/ITvRemoteServiceInput;->sendKeyUp(Landroid/os/IBinder;I)V +Landroid/media/tv/ITvRemoteServiceInput;->sendPointerDown(Landroid/os/IBinder;III)V +Landroid/media/tv/ITvRemoteServiceInput;->sendPointerSync(Landroid/os/IBinder;)V +Landroid/media/tv/ITvRemoteServiceInput;->sendPointerUp(Landroid/os/IBinder;I)V +Landroid/media/tv/ITvRemoteServiceInput;->sendTimestamp(Landroid/os/IBinder;J)V +Landroid/net/ConnectivityManager$PacketKeepaliveCallback;-><init>()V +Landroid/net/ConnectivityManager$PacketKeepaliveCallback;->onError(I)V +Landroid/net/ConnectivityManager$PacketKeepaliveCallback;->onStarted()V +Landroid/net/ConnectivityManager$PacketKeepaliveCallback;->onStopped()V +Landroid/net/ConnectivityManager$PacketKeepalive;->stop()V +Landroid/net/ConnectivityManager;->startNattKeepalive(Landroid/net/Network;ILandroid/net/ConnectivityManager$PacketKeepaliveCallback;Ljava/net/InetAddress;ILjava/net/InetAddress;)Landroid/net/ConnectivityManager$PacketKeepalive; +Landroid/net/ConnectivityManager;->startUsingNetworkFeature(ILjava/lang/String;)I +Landroid/net/ConnectivityManager;->stopUsingNetworkFeature(ILjava/lang/String;)I +Landroid/net/DhcpResults;-><init>(Landroid/net/DhcpResults;)V +Landroid/net/DhcpResults;-><init>(Landroid/net/StaticIpConfiguration;)V +Landroid/net/DhcpResults;-><init>()V +Landroid/net/DhcpResults;->leaseDuration:I +Landroid/net/DhcpResults;->mtu:I +Landroid/net/DhcpResults;->serverAddress:Ljava/net/Inet4Address; +Landroid/net/DhcpResults;->vendorInfo:Ljava/lang/String; +Landroid/net/IConnectivityManager;->getAllNetworkState()[Landroid/net/NetworkState; +Landroid/net/INetd;->interfaceAddAddress(Ljava/lang/String;Ljava/lang/String;I)V +Landroid/net/INetd$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetd; +Landroid/net/INetworkPolicyManager;->getNetworkQuotaInfo(Landroid/net/NetworkState;)Landroid/net/NetworkQuotaInfo; +Landroid/net/INetworkPolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkPolicyManager; +Landroid/net/INetworkStatsService;->openSession()Landroid/net/INetworkStatsSession; +Landroid/net/INetworkStatsService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkStatsService; +Landroid/net/INetworkStatsSession;->getHistoryForNetwork(Landroid/net/NetworkTemplate;I)Landroid/net/NetworkStatsHistory; +Landroid/net/INetworkStatsSession;->getHistoryForUid(Landroid/net/NetworkTemplate;IIII)Landroid/net/NetworkStatsHistory; +Landroid/net/InterfaceConfiguration;-><init>()V +Landroid/net/InterfaceConfiguration;->setLinkAddress(Landroid/net/LinkAddress;)V +Landroid/net/LinkAddress;-><init>(Ljava/lang/String;)V +Landroid/net/LinkAddress;-><init>(Ljava/net/InetAddress;I)V +Landroid/net/LinkAddress;->isIPv6()Z +Landroid/net/LinkAddress;->isSameAddressAs(Landroid/net/LinkAddress;)Z +Landroid/net/LinkProperties;->addDnsServer(Ljava/net/InetAddress;)Z +Landroid/net/LinkProperties;->addRoute(Landroid/net/RouteInfo;)Z +Landroid/net/LinkProperties;->addStackedLink(Landroid/net/LinkProperties;)Z +Landroid/net/LinkProperties;->clear()V +Landroid/net/LinkProperties;->compareProvisioning(Landroid/net/LinkProperties;Landroid/net/LinkProperties;)Landroid/net/LinkProperties$ProvisioningChange; +Landroid/net/LinkProperties;->getMtu()I +Landroid/net/LinkProperties;->getStackedLinks()Ljava/util/List; +Landroid/net/LinkProperties;->hasGlobalIPv6Address()Z +Landroid/net/LinkProperties;->hasIPv4Address()Z +Landroid/net/LinkProperties;->hasIPv4DefaultRoute()Z +Landroid/net/LinkProperties;->hasIPv4DnsServer()Z +Landroid/net/LinkProperties;->hasIPv6DefaultRoute()Z +Landroid/net/LinkProperties;->hasIPv6DnsServer()Z +Landroid/net/LinkProperties;-><init>(Landroid/net/LinkProperties;)V +Landroid/net/LinkProperties;-><init>()V +Landroid/net/LinkProperties;->isIdenticalAddresses(Landroid/net/LinkProperties;)Z +Landroid/net/LinkProperties;->isIdenticalDnses(Landroid/net/LinkProperties;)Z +Landroid/net/LinkProperties;->isIdenticalRoutes(Landroid/net/LinkProperties;)Z +Landroid/net/LinkProperties;->isIdenticalStackedLinks(Landroid/net/LinkProperties;)Z +Landroid/net/LinkProperties;->isIPv6Provisioned()Z +Landroid/net/LinkProperties;->isProvisioned()Z +Landroid/net/LinkProperties;->isReachable(Ljava/net/InetAddress;)Z +Landroid/net/LinkProperties$ProvisioningChange;->GAINED_PROVISIONING:Landroid/net/LinkProperties$ProvisioningChange; +Landroid/net/LinkProperties$ProvisioningChange;->LOST_PROVISIONING:Landroid/net/LinkProperties$ProvisioningChange; +Landroid/net/LinkProperties$ProvisioningChange;->STILL_NOT_PROVISIONED:Landroid/net/LinkProperties$ProvisioningChange; +Landroid/net/LinkProperties$ProvisioningChange;->STILL_PROVISIONED:Landroid/net/LinkProperties$ProvisioningChange; +Landroid/net/LinkProperties$ProvisioningChange;->values()[Landroid/net/LinkProperties$ProvisioningChange; +Landroid/net/LinkProperties;->removeDnsServer(Ljava/net/InetAddress;)Z +Landroid/net/LinkProperties;->removeRoute(Landroid/net/RouteInfo;)Z +Landroid/net/LinkProperties;->setDnsServers(Ljava/util/Collection;)V +Landroid/net/LinkProperties;->setDomains(Ljava/lang/String;)V +Landroid/net/LinkProperties;->setInterfaceName(Ljava/lang/String;)V +Landroid/net/LinkProperties;->setLinkAddresses(Ljava/util/Collection;)V +Landroid/net/LinkProperties;->setMtu(I)V +Landroid/net/LinkProperties;->setTcpBufferSizes(Ljava/lang/String;)V +Landroid/net/MacAddress;->ALL_ZEROS_ADDRESS:Landroid/net/MacAddress; +Landroid/net/metrics/ApfProgramEvent;->actualLifetime:J +Landroid/net/metrics/ApfProgramEvent;->currentRas:I +Landroid/net/metrics/ApfProgramEvent;->filteredRas:I +Landroid/net/metrics/ApfProgramEvent;->flagsFor(ZZ)I +Landroid/net/metrics/ApfProgramEvent;->flags:I +Landroid/net/metrics/ApfProgramEvent;-><init>()V +Landroid/net/metrics/ApfProgramEvent;->lifetime:J +Landroid/net/metrics/ApfProgramEvent;->programLength:I +Landroid/net/metrics/ApfStats;->droppedRas:I +Landroid/net/metrics/ApfStats;->durationMs:J +Landroid/net/metrics/ApfStats;-><init>()V +Landroid/net/metrics/ApfStats;->matchingRas:I +Landroid/net/metrics/ApfStats;->maxProgramSize:I +Landroid/net/metrics/ApfStats;->parseErrors:I +Landroid/net/metrics/ApfStats;->programUpdatesAll:I +Landroid/net/metrics/ApfStats;->programUpdatesAllowingMulticast:I +Landroid/net/metrics/ApfStats;->programUpdates:I +Landroid/net/metrics/ApfStats;->receivedRas:I +Landroid/net/metrics/ApfStats;->zeroLifetimeRas:I +Landroid/net/metrics/DhcpClientEvent;-><init>(Ljava/lang/String;I)V +Landroid/net/metrics/DhcpErrorEvent;->BOOTP_TOO_SHORT:I +Landroid/net/metrics/DhcpErrorEvent;->BUFFER_UNDERFLOW:I +Landroid/net/metrics/DhcpErrorEvent;->DHCP_BAD_MAGIC_COOKIE:I +Landroid/net/metrics/DhcpErrorEvent;->DHCP_INVALID_OPTION_LENGTH:I +Landroid/net/metrics/DhcpErrorEvent;->DHCP_NO_COOKIE:I +Landroid/net/metrics/DhcpErrorEvent;->DHCP_NO_MSG_TYPE:I +Landroid/net/metrics/DhcpErrorEvent;->DHCP_UNKNOWN_MSG_TYPE:I +Landroid/net/metrics/DhcpErrorEvent;->errorCodeWithOption(II)I +Landroid/net/metrics/DhcpErrorEvent;-><init>(I)V +Landroid/net/metrics/DhcpErrorEvent;->L2_TOO_SHORT:I +Landroid/net/metrics/DhcpErrorEvent;->L2_WRONG_ETH_TYPE:I +Landroid/net/metrics/DhcpErrorEvent;->L3_INVALID_IP:I +Landroid/net/metrics/DhcpErrorEvent;->L3_NOT_IPV4:I +Landroid/net/metrics/DhcpErrorEvent;->L3_TOO_SHORT:I +Landroid/net/metrics/DhcpErrorEvent;->L4_NOT_UDP:I +Landroid/net/metrics/DhcpErrorEvent;->L4_WRONG_PORT:I +Landroid/net/metrics/DhcpErrorEvent;->PARSING_ERROR:I +Landroid/net/metrics/DhcpErrorEvent;->RECEIVE_ERROR:I +Landroid/net/metrics/IpConnectivityLog;-><init>()V +Landroid/net/metrics/IpConnectivityLog;->log(Landroid/os/Parcelable;)Z +Landroid/net/metrics/IpConnectivityLog;->log(Ljava/lang/String;Landroid/os/Parcelable;)Z +Landroid/net/metrics/IpManagerEvent;-><init>(IJ)V +Landroid/net/metrics/IpReachabilityEvent;-><init>(I)V +Landroid/net/metrics/IpReachabilityEvent;->nudFailureEventType(ZZ)I +Landroid/net/metrics/RaEvent$Builder;->build()Landroid/net/metrics/RaEvent; +Landroid/net/metrics/RaEvent$Builder;-><init>()V +Landroid/net/metrics/RaEvent$Builder;->updateDnsslLifetime(J)Landroid/net/metrics/RaEvent$Builder; +Landroid/net/metrics/RaEvent$Builder;->updatePrefixPreferredLifetime(J)Landroid/net/metrics/RaEvent$Builder; +Landroid/net/metrics/RaEvent$Builder;->updatePrefixValidLifetime(J)Landroid/net/metrics/RaEvent$Builder; +Landroid/net/metrics/RaEvent$Builder;->updateRdnssLifetime(J)Landroid/net/metrics/RaEvent$Builder; +Landroid/net/metrics/RaEvent$Builder;->updateRouteInfoLifetime(J)Landroid/net/metrics/RaEvent$Builder; +Landroid/net/metrics/RaEvent$Builder;->updateRouterLifetime(J)Landroid/net/metrics/RaEvent$Builder; +Landroid/net/NetworkCapabilities;->getNetworkSpecifier()Landroid/net/NetworkSpecifier; +Landroid/net/NetworkCapabilities;->getSignalStrength()I +Landroid/net/NetworkCapabilities;->hasSignalStrength()Z +Landroid/net/NetworkCapabilities;->transportNamesOf([I)Ljava/lang/String; +Landroid/net/Network;-><init>(I)V +Landroid/net/NetworkQuotaInfo;->getEstimatedBytes()J +Landroid/net/NetworkQuotaInfo;->getHardLimitBytes()J +Landroid/net/NetworkQuotaInfo;->getSoftLimitBytes()J +Landroid/net/NetworkRequest$Builder;->setSignalStrength(I)Landroid/net/NetworkRequest$Builder; +Landroid/net/NetworkStats;->combineValues(Landroid/net/NetworkStats$Entry;)Landroid/net/NetworkStats; +Landroid/net/NetworkStats$Entry;-><init>()V +Landroid/net/NetworkStatsHistory$Entry;->txBytes:J +Landroid/net/NetworkStatsHistory;->getStart()J +Landroid/net/NetworkStatsHistory;->getValues(JJLandroid/net/NetworkStatsHistory$Entry;)Landroid/net/NetworkStatsHistory$Entry; +Landroid/net/NetworkStats;-><init>(JI)V +Landroid/net/NetworkTemplate;->buildTemplateMobileAll(Ljava/lang/String;)Landroid/net/NetworkTemplate; +Landroid/net/NetworkUtils;->attachControlPacketFilter(Ljava/io/FileDescriptor;I)V +Landroid/net/NetworkUtils;->attachDhcpFilter(Ljava/io/FileDescriptor;)V +Landroid/net/NetworkUtils;->attachRaFilter(Ljava/io/FileDescriptor;I)V +Landroid/net/NetworkUtils;->getImplicitNetmask(Ljava/net/Inet4Address;)I +Landroid/net/NetworkUtils;->netmaskToPrefixLength(Ljava/net/Inet4Address;)I +Landroid/net/NetworkUtils;->protectFromVpn(Ljava/io/FileDescriptor;)Z +Landroid/net/RouteInfo;->hasGateway()Z +Landroid/net/RouteInfo;-><init>(Landroid/net/IpPrefix;Ljava/net/InetAddress;Ljava/lang/String;)V +Landroid/net/SntpClient;->getNtpTime()J +Landroid/net/SntpClient;->requestTime(Ljava/lang/String;I)Z +Landroid/net/StaticIpConfiguration;->dnsServers:Ljava/util/ArrayList; +Landroid/net/StaticIpConfiguration;->domains:Ljava/lang/String; +Landroid/net/StaticIpConfiguration;->gateway:Ljava/net/InetAddress; +Landroid/net/StaticIpConfiguration;->getRoutes(Ljava/lang/String;)Ljava/util/List; +Landroid/net/StaticIpConfiguration;->ipAddress:Landroid/net/LinkAddress; +Landroid/net/StringNetworkSpecifier;->specifier:Ljava/lang/String; +Landroid/net/TrafficStats;->getMobileTcpRxPackets()J +Landroid/net/TrafficStats;->getMobileTcpTxPackets()J +Landroid/net/wifi/WifiInfo;->is5GHz()Z +Landroid/net/wifi/WifiInfo;->score:I +Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable; +Landroid/os/AsyncResult;->forMessage(Landroid/os/Message;Ljava/lang/Object;Ljava/lang/Throwable;)Landroid/os/AsyncResult; +Landroid/os/AsyncResult;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Throwable;)V +Landroid/os/AsyncResult;->result:Ljava/lang/Object; +Landroid/os/AsyncResult;->userObj:Ljava/lang/Object; +Landroid/os/BatteryStats;->getNextHistoryLocked(Landroid/os/BatteryStats$HistoryItem;)Z +Landroid/os/BatteryStats$HistoryItem;->batteryLevel:B +Landroid/os/BatteryStats$HistoryItem;->cmd:B +Landroid/os/BatteryStats$HistoryItem;-><init>()V +Landroid/os/BatteryStats$HistoryItem;->states:I +Landroid/os/BatteryStats$HistoryItem;->time:J +Landroid/os/BatteryStats$Uid;->getWifiRunningTime(JI)J +Landroid/os/BatteryStats$Uid;-><init>()V +Landroid/os/BatteryStats$Uid$Wakelock;->getWakeTime(I)Landroid/os/BatteryStats$Timer; +Landroid/os/Handler;->getMain()Landroid/os/Handler; +Landroid/os/Handler;-><init>(Landroid/os/Looper;Landroid/os/Handler$Callback;Z)V +Landroid/os/HwBinder;->reportSyspropChanged()V +Landroid/os/INetworkManagementService;->clearInterfaceAddresses(Ljava/lang/String;)V +Landroid/os/INetworkManagementService;->disableIpv6(Ljava/lang/String;)V +Landroid/os/INetworkManagementService;->enableIpv6(Ljava/lang/String;)V +Landroid/os/INetworkManagementService;->registerObserver(Landroid/net/INetworkManagementEventObserver;)V +Landroid/os/INetworkManagementService;->setInterfaceConfig(Ljava/lang/String;Landroid/net/InterfaceConfiguration;)V +Landroid/os/INetworkManagementService;->setInterfaceIpv6PrivacyExtensions(Ljava/lang/String;Z)V +Landroid/os/INetworkManagementService;->setIPv6AddrGenMode(Ljava/lang/String;I)V +Landroid/os/INetworkManagementService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/INetworkManagementService; +Landroid/os/INetworkManagementService;->unregisterObserver(Landroid/net/INetworkManagementEventObserver;)V +Landroid/os/IPowerManager;->reboot(ZLjava/lang/String;Z)V +Landroid/os/IRemoteCallback$Stub;-><init>()V +Landroid/os/Message;->setCallback(Ljava/lang/Runnable;)Landroid/os/Message; +Landroid/os/Parcel;->readBlob()[B +Landroid/os/Parcel;->readStringArray()[Ljava/lang/String; +Landroid/os/Parcel;->writeBlob([B)V +Landroid/os/PowerManager;->isScreenBrightnessBoosted()Z +Landroid/os/Registrant;->clear()V +Landroid/os/Registrant;-><init>(Landroid/os/Handler;ILjava/lang/Object;)V +Landroid/os/RegistrantList;->add(Landroid/os/Registrant;)V +Landroid/os/RegistrantList;->addUnique(Landroid/os/Handler;ILjava/lang/Object;)V +Landroid/os/RegistrantList;-><init>()V +Landroid/os/RegistrantList;->notifyRegistrants(Landroid/os/AsyncResult;)V +Landroid/os/RegistrantList;->notifyRegistrants()V +Landroid/os/RegistrantList;->removeCleared()V +Landroid/os/RegistrantList;->remove(Landroid/os/Handler;)V +Landroid/os/Registrant;->notifyRegistrant(Landroid/os/AsyncResult;)V +Landroid/os/Registrant;->notifyRegistrant()V +Landroid/os/RemoteException;->rethrowFromSystemServer()Ljava/lang/RuntimeException; +Landroid/os/ServiceSpecificException;->errorCode:I +Landroid/os/SystemProperties;->reportSyspropChanged()V +Landroid/print/PrintDocumentAdapter$LayoutResultCallback;-><init>()V +Landroid/print/PrintDocumentAdapter$WriteResultCallback;-><init>()V +Landroid/provider/CalendarContract$Events;->PROVIDER_WRITABLE_COLUMNS:[Ljava/lang/String; +Landroid/service/vr/VrListenerService;->onCurrentVrActivityChanged(Landroid/content/ComponentName;ZI)V +Landroid/system/NetlinkSocketAddress;-><init>(II)V +Landroid/system/Os;->bind(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V +Landroid/system/Os;->connect(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V +Landroid/system/Os;->sendto(Ljava/io/FileDescriptor;[BIIILjava/net/SocketAddress;)I +Landroid/system/Os;->setsockoptIfreq(Ljava/io/FileDescriptor;IILjava/lang/String;)V +Landroid/system/Os;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V +Landroid/system/PacketSocketAddress;-><init>(I[B)V +Landroid/system/PacketSocketAddress;-><init>(SI)V +Landroid/telecom/TelecomManager;->from(Landroid/content/Context;)Landroid/telecom/TelecomManager; +Landroid/telecom/VideoProfile$CameraCapabilities;-><init>(IIZF)V +Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V +Landroid/telephony/ims/compat/ImsService;-><init>()V +Landroid/telephony/ims/compat/stub/ImsCallSessionImplBase;-><init>()V +Landroid/telephony/ims/compat/stub/ImsConfigImplBase;-><init>(Landroid/content/Context;)V +Landroid/telephony/ims/compat/stub/ImsUtListenerImplBase;-><init>()V +Landroid/telephony/ims/ImsCallForwardInfo;-><init>()V +Landroid/telephony/ims/ImsCallProfile;->presentationToOIR(I)I +Landroid/telephony/ims/ImsExternalCallState;-><init>(ILandroid/net/Uri;ZIIZ)V +Landroid/telephony/ims/ImsReasonInfo;-><init>(IILjava/lang/String;)V +Landroid/telephony/ims/ImsReasonInfo;-><init>(II)V +Landroid/telephony/ims/ImsStreamMediaProfile;-><init>()V +Landroid/telephony/PhoneNumberUtils;->isEmergencyNumber(ILjava/lang/String;)Z +Landroid/telephony/PhoneNumberUtils;->isPotentialEmergencyNumber(ILjava/lang/String;)Z +Landroid/telephony/PhoneNumberUtils;->isPotentialLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z +Landroid/telephony/PhoneStateListener;-><init>(Ljava/lang/Integer;Landroid/os/Looper;)V +Landroid/telephony/PhoneStateListener;-><init>(Ljava/lang/Integer;)V +Landroid/telephony/PreciseCallState;->getBackgroundCallState()I +Landroid/telephony/PreciseCallState;->getForegroundCallState()I +Landroid/telephony/RadioAccessFamily;->getRafFromNetworkType(I)I +Landroid/telephony/RadioAccessFamily;-><init>(II)V +Landroid/telephony/Rlog;->d(Ljava/lang/String;Ljava/lang/String;)I +Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;)I +Landroid/telephony/Rlog;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I +Landroid/telephony/Rlog;->i(Ljava/lang/String;Ljava/lang/String;)I +Landroid/telephony/ServiceState;->getDataRoaming()Z +Landroid/telephony/ServiceState;->getRilDataRadioTechnology()I +Landroid/telephony/ServiceState;->getVoiceRegState()I +Landroid/telephony/ServiceState;->isCdma(I)Z +Landroid/telephony/ServiceState;->isEmergencyOnly()Z +Landroid/telephony/ServiceState;->mergeServiceStates(Landroid/telephony/ServiceState;Landroid/telephony/ServiceState;)Landroid/telephony/ServiceState; +Landroid/telephony/SubscriptionManager;->getResourcesForSubId(Landroid/content/Context;I)Landroid/content/res/Resources; +Landroid/telephony/SubscriptionManager;->isActiveSubId(I)Z +Landroid/telephony/SubscriptionManager;->isUsableSubIdValue(I)Z +Landroid/telephony/SubscriptionManager;->isValidPhoneId(I)Z +Landroid/telephony/SubscriptionManager;->isValidSlotIndex(I)Z +Landroid/telephony/SubscriptionManager;->isValidSubscriptionId(I)Z +Landroid/telephony/SubscriptionManager;->putPhoneIdAndSubIdExtra(Landroid/content/Intent;II)V +Landroid/telephony/TelephonyManager;->getIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;I)I +Landroid/telephony/TelephonyManager;->getVoiceNetworkType(I)I +Landroid/telephony/TelephonyManager;->putIntAtIndex(Landroid/content/ContentResolver;Ljava/lang/String;II)Z +Landroid/util/FloatMath;->ceil(F)F +Landroid/util/FloatMath;->cos(F)F +Landroid/util/FloatMath;->exp(F)F +Landroid/util/FloatMath;->floor(F)F +Landroid/util/FloatMath;->sin(F)F +Landroid/util/FloatMath;->sqrt(F)F +Landroid/util/IconDrawableFactory;->getBadgedIcon(Landroid/content/pm/PackageItemInfo;Landroid/content/pm/ApplicationInfo;I)Landroid/graphics/drawable/Drawable; +Landroid/util/IconDrawableFactory;->newInstance(Landroid/content/Context;)Landroid/util/IconDrawableFactory; +Landroid/util/LocalLog;-><init>(I)V +Landroid/util/LocalLog;->log(Ljava/lang/String;)V +Landroid/util/LocalLog$ReadOnlyLocalLog;->dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V +Landroid/util/LocalLog;->readOnlyLocalLog()Landroid/util/LocalLog$ReadOnlyLocalLog; +Landroid/util/LongArray;->add(IJ)V +Landroid/util/LongArray;->get(I)J +Landroid/util/LongArray;-><init>()V +Landroid/util/LongArray;->size()I +Landroid/util/Slog;->wtf(Ljava/lang/String;Ljava/lang/String;)I +Landroid/view/AppTransitionAnimationSpec;-><init>(ILandroid/graphics/GraphicBuffer;Landroid/graphics/Rect;)V +Landroid/view/BatchedInputEventReceiver;-><init>(Landroid/view/InputChannel;Landroid/os/Looper;Landroid/view/Choreographer;)V +Landroid/view/Choreographer;->getSfInstance()Landroid/view/Choreographer; +Landroid/view/DisplayListCanvas;->drawRenderNode(Landroid/view/RenderNode;)V +Landroid/view/IAppTransitionAnimationSpecsFuture$Stub;-><init>()V +Landroid/view/InputEventReceiver;->onInputEvent(Landroid/view/InputEvent;I)V +Landroid/view/IRecentsAnimationController;->finish(Z)V +Landroid/view/IRecentsAnimationController;->screenshotTask(I)Landroid/app/ActivityManager$TaskSnapshot; +Landroid/view/IRecentsAnimationController;->setInputConsumerEnabled(Z)V +Landroid/view/IRecentsAnimationRunner;->onAnimationCanceled()V +Landroid/view/IRecentsAnimationRunner;->onAnimationStart(Landroid/view/IRecentsAnimationController;[Landroid/view/RemoteAnimationTarget;)V +Landroid/view/IRecentsAnimationRunner;->onAnimationStart_New(Landroid/view/IRecentsAnimationController;[Landroid/view/RemoteAnimationTarget;Landroid/graphics/Rect;Landroid/graphics/Rect;)V +Landroid/view/IRecentsAnimationRunner$Stub;-><init>()V +Landroid/view/IRemoteAnimationFinishedCallback;->onAnimationFinished()V +Landroid/view/IRemoteAnimationRunner;->onAnimationCancelled()V +Landroid/view/IRemoteAnimationRunner;->onAnimationStart([Landroid/view/RemoteAnimationTarget;Landroid/view/IRemoteAnimationFinishedCallback;)V +Landroid/view/IRemoteAnimationRunner$Stub;-><init>()V +Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;Landroid/view/InputChannel;)V +Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;)Z +Landroid/view/IWindowManager;->endProlongedAnimations()V +Landroid/view/IWindowManager;->getStableInsets(ILandroid/graphics/Rect;)V +Landroid/view/IWindowManager;->overridePendingAppTransitionMultiThumbFuture(Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/os/IRemoteCallback;Z)V +Landroid/view/IWindowManager;->overridePendingAppTransitionRemote(Landroid/view/RemoteAnimationAdapter;)V +Landroid/view/IWindowManager;->setNavBarVirtualKeyHapticFeedbackEnabled(Z)V +Landroid/view/RemoteAnimationAdapter;-><init>(Landroid/view/IRemoteAnimationRunner;JJ)V +Landroid/view/RemoteAnimationDefinition;->addRemoteAnimation(ILandroid/view/RemoteAnimationAdapter;)V +Landroid/view/RemoteAnimationDefinition;-><init>()V +Landroid/view/RenderNode;->create(Ljava/lang/String;Landroid/view/View;)Landroid/view/RenderNode; +Landroid/view/RenderNode;->end(Landroid/view/DisplayListCanvas;)V +Landroid/view/RenderNode;->isValid()Z +Landroid/view/RenderNode;->setClipToBounds(Z)Z +Landroid/view/RenderNode;->setLeftTopRightBottom(IIII)Z +Landroid/view/RenderNode;->start(II)Landroid/view/DisplayListCanvas; +Landroid/view/SurfaceControl$Transaction;->apply()V +Landroid/view/SurfaceControl$Transaction;->deferTransactionUntil(Landroid/view/SurfaceControl;Landroid/os/IBinder;J)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->deferTransactionUntilSurface(Landroid/view/SurfaceControl;Landroid/view/Surface;J)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->hide(Landroid/view/SurfaceControl;)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;-><init>()V +Landroid/view/SurfaceControl$Transaction;->setAlpha(Landroid/view/SurfaceControl;F)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->setColor(Landroid/view/SurfaceControl;[F)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->setFinalCrop(Landroid/view/SurfaceControl;Landroid/graphics/Rect;)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->setLayer(Landroid/view/SurfaceControl;I)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->setMatrix(Landroid/view/SurfaceControl;FFFF)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->setMatrix(Landroid/view/SurfaceControl;Landroid/graphics/Matrix;[F)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->setPosition(Landroid/view/SurfaceControl;FF)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->setSize(Landroid/view/SurfaceControl;II)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->setWindowCrop(Landroid/view/SurfaceControl;Landroid/graphics/Rect;)Landroid/view/SurfaceControl$Transaction; +Landroid/view/SurfaceControl$Transaction;->show(Landroid/view/SurfaceControl;)Landroid/view/SurfaceControl$Transaction; +Landroid/view/Surface;->getNextFrameNumber()J +Landroid/view/ThreadedRenderer;->createHardwareBitmap(Landroid/view/RenderNode;II)Landroid/graphics/Bitmap; +Landroid/view/View;->hideTooltip()V +Landroid/view/View;->setTooltip(Ljava/lang/CharSequence;)V +Landroid/webkit/WebSettings;->getPluginsPath()Ljava/lang/String; +Landroid/webkit/WebSettings;->getUseDoubleTree()Z +Landroid/webkit/WebSettings;->setPluginsPath(Ljava/lang/String;)V +Landroid/webkit/WebSettings;->setUseDoubleTree(Z)V +Landroid/webkit/WebView;->getPluginList()Landroid/webkit/PluginList; +Landroid/webkit/WebView;->getZoomControls()Landroid/view/View; +Landroid/webkit/WebView;->refreshPlugins(Z)V +Landroid/widget/ListView;->lookForSelectablePosition(IZ)I +Lcom/android/ims/ImsConfigListener;->onSetFeatureResponse(IIII)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionConferenceStateUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsConferenceState;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHandoverFailed(Lcom/android/ims/internal/IImsCallSession;IILandroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHandover(Lcom/android/ims/internal/IImsCallSession;IILandroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHeld(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHoldFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHoldReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionInviteParticipantsRequestDelivered(Lcom/android/ims/internal/IImsCallSession;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionInviteParticipantsRequestFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeComplete(Lcom/android/ims/internal/IImsCallSession;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeStarted(Lcom/android/ims/internal/IImsCallSession;Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMultipartyStateChanged(Lcom/android/ims/internal/IImsCallSession;Z)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionProgressing(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsStreamMediaProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumeFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumeReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionStarted(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionStartFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionSuppServiceReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsSuppServiceNotification;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTerminated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTtyModeReceived(Lcom/android/ims/internal/IImsCallSession;I)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationAssociatedUriChanged([Landroid/net/Uri;)V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationConnectedWithRadioTech(I)V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationDisconnected(Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationFeatureCapabilityChanged(I[I[I)V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationProgressingWithRadioTech(I)V +Lcom/android/ims/internal/IImsRegistrationListener;->voiceMessageCountUpdate(I)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallBarringQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsSsInfo;)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallForwardQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsCallForwardInfo;)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallWaitingQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsSsInfo;)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueried(Lcom/android/ims/internal/IImsUt;ILandroid/os/Bundle;)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueryFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdated(Lcom/android/ims/internal/IImsUt;I)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdateFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/uce/common/StatusCode;->getStatusCode()I +Lcom/android/ims/internal/uce/common/UceLong;->getClientId()I +Lcom/android/ims/internal/uce/common/UceLong;-><init>()V +Lcom/android/ims/internal/uce/common/UceLong;->setClientId(I)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->cmdStatus(Lcom/android/ims/internal/uce/options/OptionsCmdStatus;)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->getVersionCb(Ljava/lang/String;)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->incomingOptions(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;I)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->serviceAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->serviceUnavailable(Lcom/android/ims/internal/uce/common/StatusCode;)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->sipResponseReceived(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsSipResponse;Lcom/android/ims/internal/uce/options/OptionsCapInfo;)V +Lcom/android/ims/internal/uce/options/IOptionsService;->addListener(ILcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->getContactCap(ILjava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->getContactListCap(I[Ljava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->getMyInfo(II)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->getVersion(I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->responseIncomingOptions(IIILjava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;Z)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->setMyInfo(ILcom/android/ims/internal/uce/common/CapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService$Stub;-><init>()V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->capInfoReceived(Ljava/lang/String;[Lcom/android/ims/internal/uce/presence/PresTupleInfo;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->cmdStatus(Lcom/android/ims/internal/uce/presence/PresCmdStatus;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->getVersionCb(Ljava/lang/String;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->listCapInfoReceived(Lcom/android/ims/internal/uce/presence/PresRlmiInfo;[Lcom/android/ims/internal/uce/presence/PresResInfo;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->publishTriggering(Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->serviceAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->serviceUnAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->sipResponseReceived(Lcom/android/ims/internal/uce/presence/PresSipResponse;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->unpublishMessageSent()V +Lcom/android/ims/internal/uce/presence/IPresenceService;->addListener(ILcom/android/ims/internal/uce/presence/IPresenceListener;Lcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->getContactCap(ILjava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->getContactListCap(I[Ljava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->getVersion(I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->publishMyCap(ILcom/android/ims/internal/uce/presence/PresCapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->reenableService(II)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->setNewFeatureTag(ILjava/lang/String;Lcom/android/ims/internal/uce/presence/PresServiceInfo;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V +Lcom/android/ims/internal/uce/presence/PresSipResponse;->getCmdId()Lcom/android/ims/internal/uce/presence/PresCmdId; +Lcom/android/ims/internal/uce/presence/PresSipResponse;->getReasonPhrase()Ljava/lang/String; +Lcom/android/ims/internal/uce/presence/PresSipResponse;->getRequestId()I +Lcom/android/ims/internal/uce/presence/PresSipResponse;->getRetryAfter()I +Lcom/android/ims/internal/uce/presence/PresSipResponse;->getSipResponseCode()I +Lcom/android/ims/internal/uce/uceservice/IUceListener;->setStatus(I)V +Lcom/android/ims/internal/uce/uceservice/IUceService;->createOptionsService(Lcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)I +Lcom/android/ims/internal/uce/uceservice/IUceService;->createPresenceService(Lcom/android/ims/internal/uce/presence/IPresenceListener;Lcom/android/ims/internal/uce/common/UceLong;)I +Lcom/android/ims/internal/uce/uceservice/IUceService;->destroyOptionsService(I)V +Lcom/android/ims/internal/uce/uceservice/IUceService;->destroyPresenceService(I)V +Lcom/android/ims/internal/uce/uceservice/IUceService;->getOptionsService()Lcom/android/ims/internal/uce/options/IOptionsService; +Lcom/android/ims/internal/uce/uceservice/IUceService;->getPresenceService()Lcom/android/ims/internal/uce/presence/IPresenceService; +Lcom/android/ims/internal/uce/uceservice/IUceService;->getServiceStatus()Z +Lcom/android/ims/internal/uce/uceservice/IUceService;->isServiceStarted()Z +Lcom/android/ims/internal/uce/uceservice/IUceService;->startService(Lcom/android/ims/internal/uce/uceservice/IUceListener;)Z +Lcom/android/ims/internal/uce/uceservice/IUceService;->stopService()Z +Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V +Lcom/android/internal/location/ILocationProvider;->disable()V +Lcom/android/internal/location/ILocationProvider;->enable()V +Lcom/android/internal/location/ILocationProvider;->getProperties()Lcom/android/internal/location/ProviderProperties; +Lcom/android/internal/location/ILocationProvider;->getStatus(Landroid/os/Bundle;)I +Lcom/android/internal/location/ILocationProvider;->getStatusUpdateTime()J +Lcom/android/internal/location/ILocationProvider;->sendExtraCommand(Ljava/lang/String;Landroid/os/Bundle;)Z +Lcom/android/internal/location/ILocationProvider;->setRequest(Lcom/android/internal/location/ProviderRequest;Landroid/os/WorkSource;)V +Lcom/android/internal/os/BatteryStatsImpl;->getDischargeCurrentLevel()I +Lcom/android/internal/os/BatteryStatsImpl;->getDischargeStartLevel()I +Lcom/android/internal/os/BatteryStatsImpl;->getPhoneOnTime(JI)J +Lcom/android/internal/os/BatteryStatsImpl;->getPhoneSignalScanningTime(JI)J +Lcom/android/internal/os/BatteryStatsImpl;->getPhoneSignalStrengthTime(IJI)J +Lcom/android/internal/os/BatteryStatsImpl;->getScreenBrightnessTime(IJI)J +Lcom/android/internal/os/BatteryStatsImpl;->getWifiOnTime(JI)J +Lcom/android/internal/os/SomeArgs;->obtain()Lcom/android/internal/os/SomeArgs; +Lcom/android/internal/os/SomeArgs;->recycle()V +Lcom/android/internal/telephony/ITelephony;->getDataEnabled(I)Z +Lcom/android/internal/util/IndentingPrintWriter;->decreaseIndent()Lcom/android/internal/util/IndentingPrintWriter; +Lcom/android/internal/util/IndentingPrintWriter;->increaseIndent()Lcom/android/internal/util/IndentingPrintWriter; +Lcom/android/internal/util/IndentingPrintWriter;-><init>(Ljava/io/Writer;Ljava/lang/String;)V +Lcom/android/internal/util/XmlUtils;->beginDocument(Lorg/xmlpull/v1/XmlPullParser;Ljava/lang/String;)V +Lcom/android/internal/util/XmlUtils;->nextElement(Lorg/xmlpull/v1/XmlPullParser;)V +Ljava/lang/System;->arraycopy([BI[BII)V +Ljava/net/Inet4Address;->ALL:Ljava/net/InetAddress; +Ljava/net/Inet4Address;->ANY:Ljava/net/InetAddress; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index afcd51572d51..8dd0f428648e 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -704,7 +704,7 @@ public final class ActivityThread extends ClientTransactionHandler { streamingOutput); profiling = true; } catch (RuntimeException e) { - Slog.w(TAG, "Profiling failed on path " + profileFile); + Slog.w(TAG, "Profiling failed on path " + profileFile, e); try { profileFd.close(); profileFd = null; diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 05a9861f5a20..14edd31a48cf 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1609,6 +1609,7 @@ public class AppOpsManager { * @param mode The app op mode to set. * @hide */ + @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) public void setUidMode(int code, int uid, int mode) { try { mService.setUidMode(code, uid, mode); @@ -1628,7 +1629,7 @@ public class AppOpsManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) + @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) public void setUidMode(String appOp, int uid, int mode) { try { mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode); @@ -1660,6 +1661,7 @@ public class AppOpsManager { /** @hide */ @TestApi + @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) public void setMode(int code, int uid, String packageName, int mode) { try { mService.setMode(code, uid, packageName, mode); @@ -1669,6 +1671,27 @@ public class AppOpsManager { } /** + * Change the operating mode for the given op in the given app package. You must pass + * in both the uid and name of the application whose mode is being modified; if these + * do not match, the modification will not be applied. + * + * @param op The operation to modify. One of the OPSTR_* constants. + * @param uid The user id of the application whose mode will be changed. + * @param packageName The name of the application package name whose mode will + * be changed. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) + public void setMode(String op, int uid, String packageName, int mode) { + try { + mService.setMode(strOpToOp(op), uid, packageName, mode); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Set a non-persisted restriction on an audio operation at a stream-level. * Restrictions are temporary additional constraints imposed on top of the persisted rules * defined by {@link #setMode}. @@ -1679,6 +1702,7 @@ public class AppOpsManager { * @param exceptionPackages Optional list of packages to exclude from the restriction. * @hide */ + @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) public void setRestriction(int code, @AttributeUsage int usage, int mode, String[] exceptionPackages) { try { @@ -1690,6 +1714,7 @@ public class AppOpsManager { } /** @hide */ + @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) public void resetAllModes() { try { mService.resetAllModes(mContext.getUserId(), null); diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java index 41eeb9acb5ec..4531f53bd86f 100644 --- a/core/java/android/app/Application.java +++ b/core/java/android/app/Application.java @@ -16,8 +16,6 @@ package android.app; -import java.util.ArrayList; - import android.annotation.CallSuper; import android.content.ComponentCallbacks; import android.content.ComponentCallbacks2; @@ -26,8 +24,11 @@ import android.content.ContextWrapper; import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; +import android.util.Log; import android.view.autofill.AutofillManager; +import java.util.ArrayList; + /** * Base class for maintaining global application state. You can provide your own * implementation by creating a subclass and specifying the fully-qualified name @@ -46,6 +47,7 @@ import android.view.autofill.AutofillManager; * </p> */ public class Application extends ContextWrapper implements ComponentCallbacks2 { + private static final String TAG = "Application"; private ArrayList<ComponentCallbacks> mComponentCallbacks = new ArrayList<ComponentCallbacks>(); private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks = @@ -318,6 +320,9 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { if (client != null) { return client; } + if (android.view.autofill.Helper.sVerbose) { + Log.v(TAG, "getAutofillClient(): null on super, trying to find activity thread"); + } // Okay, ppl use the application context when they should not. This breaks // autofill among other things. We pick the focused activity since autofill // interacts only with the currently focused activity and we need the fill @@ -338,9 +343,16 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { continue; } if (activity.getWindow().getDecorView().hasFocus()) { - return record.activity; + if (android.view.autofill.Helper.sVerbose) { + Log.v(TAG, "getAutofillClient(): found activity for " + this + ": " + activity); + } + return activity; } } + if (android.view.autofill.Helper.sVerbose) { + Log.v(TAG, "getAutofillClient(): none of the " + activityCount + " activities on " + + this + " have focus"); + } return null; } } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 13a6be557dae..83d6003b5161 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -763,6 +763,11 @@ public class Notification implements Parcelable public static final String CATEGORY_CALL = "call"; /** + * Notification category: map turn-by-turn navigation. + */ + public static final String CATEGORY_NAVIGATION = "navigation"; + + /** * Notification category: incoming direct message (SMS, instant message, etc.). */ public static final String CATEGORY_MESSAGE = "msg"; @@ -835,6 +840,27 @@ public class Notification implements Parcelable public static final String CATEGORY_REMINDER = "reminder"; /** + * Notification category: extreme car emergencies. + * @hide + */ + @SystemApi + public static final String CATEGORY_CAR_EMERGENCY = "car_emergency"; + + /** + * Notification category: car warnings. + * @hide + */ + @SystemApi + public static final String CATEGORY_CAR_WARNING = "car_warning"; + + /** + * Notification category: general car system information. + * @hide + */ + @SystemApi + public static final String CATEGORY_CAR_INFORMATION = "car_information"; + + /** * One of the predefined notification categories (see the <code>CATEGORY_*</code> constants) * that best describes this Notification. May be used by the system for ranking and filtering. */ diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java index ed2aaf915ef2..5fbe5b398488 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 @@ public final class DeviceAdminInfo implements Parcelable { */ 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 @@ public final class DeviceAdminInfo implements Parcelable { + 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 @@ public final class DeviceAdminInfo implements Parcelable { DeviceAdminInfo(Parcel source) { mActivityInfo = ActivityInfo.CREATOR.createFromParcel(source); mUsesPolicies = source.readInt(); + mSupportsTransferOwnership = source.readBoolean(); } /** @@ -458,6 +471,13 @@ public final class DeviceAdminInfo implements Parcelable { 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 final class DeviceAdminInfo implements Parcelable { 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 8c30fc403713..1c9477d08cb3 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -505,31 +505,6 @@ public class DeviceAdminReceiver extends BroadcastReceiver { 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> - * <receiver name="..." android:permission="android.permission.BIND_DEVICE_ADMIN"> - * <meta-data - * android:name="android.app.device_admin" - * android:resource="@xml/..." /> - * <meta-data - * android:name="android.app.support_transfer_ownership" - * android:value="true" /> - * </receiver> - * </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 000000000000..fbb8ddfecad2 --- /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 d42fa996ceff..6511f214f19d 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -9302,9 +9302,10 @@ public class DevicePolicyManager { * 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><support-transfer-ownership /></code> tag inside the + * <code><device-admin></device-admin></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 ebaf4648d80a..de9297897158 100644 --- a/core/java/android/app/admin/DevicePolicyManagerInternal.java +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java @@ -141,4 +141,10 @@ public abstract class DevicePolicyManagerInternal { * @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/ISliceManager.aidl b/core/java/android/app/slice/ISliceManager.aidl index 20ec75a36ad3..74e3c3ee4c81 100644 --- a/core/java/android/app/slice/ISliceManager.aidl +++ b/core/java/android/app/slice/ISliceManager.aidl @@ -27,6 +27,7 @@ interface ISliceManager { SliceSpec[] getPinnedSpecs(in Uri uri, String pkg); int checkSlicePermission(in Uri uri, String pkg, int pid, int uid); void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices); + Uri[] getPinnedSlices(String pkg); byte[] getBackupPayload(int user); void applyRestore(in byte[] payload, int user); diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java index 4f3cd63841eb..67a72ec33fd8 100644 --- a/core/java/android/app/slice/SliceManager.java +++ b/core/java/android/app/slice/SliceManager.java @@ -184,6 +184,18 @@ public class SliceManager { } /** + * Get the list of currently pinned slices for this app. + * @see SliceProvider#onSlicePinned + */ + public @NonNull List<Uri> getPinnedSlices() { + try { + return Arrays.asList(mService.getPinnedSlices(mContext.getPackageName())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Obtains a list of slices that are descendants of the specified Uri. * <p> * Not all slice providers will implement this functionality, in which case, @@ -261,7 +273,8 @@ public class SliceManager { */ 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(); @@ -325,7 +338,8 @@ public class SliceManager { 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/app/slice/SliceSpec.java b/core/java/android/app/slice/SliceSpec.java index 8cc0384c1007..03ffe6df88ce 100644 --- a/core/java/android/app/slice/SliceSpec.java +++ b/core/java/android/app/slice/SliceSpec.java @@ -89,7 +89,7 @@ public final class SliceSpec implements Parcelable { * * @param candidate candidate format of data. * @return true if versions are compatible. - * @see androidx.app.slice.widget.SliceView + * @see androidx.slice.widget.SliceView */ public boolean canRender(@NonNull SliceSpec candidate) { if (!mType.equals(candidate.mType)) return false; diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index f7fb84ba9d0a..4c7e97bcb8da 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -109,11 +109,11 @@ public final class UsageEvents implements Parcelable { public static final int NOTIFICATION_SEEN = 10; /** - * An event type denoting a change in App Standby Bucket. Additional bucket information - * is contained in mBucketAndReason. - * @hide + * An event type denoting a change in App Standby Bucket. The new bucket can be + * retrieved by calling {@link #getStandbyBucket()}. + * + * @see UsageStatsManager#getAppStandbyBucket() */ - @SystemApi public static final int STANDBY_BUCKET_CHANGED = 11; /** @@ -254,8 +254,11 @@ public final class UsageEvents implements Parcelable { /** * The event type. * - * See {@link #MOVE_TO_BACKGROUND} - * See {@link #MOVE_TO_FOREGROUND} + * @see #MOVE_TO_BACKGROUND + * @see #MOVE_TO_FOREGROUND + * @see #CONFIGURATION_CHANGE + * @see #USER_INTERACTION + * @see #STANDBY_BUCKET_CHANGED */ public int getEventType() { return mEventType; @@ -283,9 +286,8 @@ public final class UsageEvents implements Parcelable { * Returns the standby bucket of the app, if the event is of type * {@link #STANDBY_BUCKET_CHANGED}, otherwise returns 0. * @return the standby bucket associated with the event. - * @hide + * */ - @SystemApi public int getStandbyBucket() { return (mBucketAndReason & 0xFFFF0000) >>> 16; } diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index 75ce4fbb60c7..6dd85caad628 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.os.UserHandle; 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><appwidget-provider></code> xml tag. @@ -55,6 +59,14 @@ public class AppWidgetProviderInfo implements Parcelable { */ 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 class AppWidgetProviderInfo implements Parcelable { */ 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 class AppWidgetProviderInfo implements Parcelable { */ 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 @@ public class AppWidgetProviderInfo implements Parcelable { * <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 @@ public class AppWidgetProviderInfo implements Parcelable { * <p>This field corresponds to the <code>widgetCategory</code> attribute in * the AppWidget meta-data file. */ + @CategoryFlags public int widgetCategory; /** @@ -235,6 +266,7 @@ public class AppWidgetProviderInfo implements Parcelable { * @see #WIDGET_FEATURE_RECONFIGURABLE * @see #WIDGET_FEATURE_HIDE_FROM_PICKER */ + @FeatureFlags public int widgetFeatures; /** @hide */ diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java index 5a1216b79b82..b528e397906f 100644 --- a/core/java/android/content/AbstractThreadedSyncAdapter.java +++ b/core/java/android/content/AbstractThreadedSyncAdapter.java @@ -16,9 +16,14 @@ package android.content; +import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; + import android.accounts.Account; +import android.annotation.MainThread; +import android.annotation.NonNull; import android.os.Build; import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; @@ -167,9 +172,10 @@ public abstract class AbstractThreadedSyncAdapter { private class ISyncAdapterImpl extends ISyncAdapter.Stub { @Override - public void onUnsyncableAccount(ISyncAdapterUnsyncableAccountCallback cb) - throws RemoteException { - cb.onUnsyncableAccountDone(AbstractThreadedSyncAdapter.this.onUnsyncableAccount()); + public void onUnsyncableAccount(ISyncAdapterUnsyncableAccountCallback cb) { + Handler.getMain().sendMessage(obtainMessage( + AbstractThreadedSyncAdapter::handleOnUnsyncableAccount, + AbstractThreadedSyncAdapter.this, cb)); } @Override @@ -381,6 +387,27 @@ public abstract class AbstractThreadedSyncAdapter { } /** + * Handle a call of onUnsyncableAccount. + * + * @param cb The callback to report the return value to + */ + private void handleOnUnsyncableAccount(@NonNull ISyncAdapterUnsyncableAccountCallback cb) { + boolean doSync; + try { + doSync = onUnsyncableAccount(); + } catch (RuntimeException e) { + Log.e(TAG, "Exception while calling onUnsyncableAccount, assuming 'true'", e); + doSync = true; + } + + try { + cb.onUnsyncableAccountDone(doSync); + } catch (RemoteException e) { + Log.e(TAG, "Could not report result of onUnsyncableAccount", e); + } + } + + /** * Allows to defer syncing until all accounts are properly set up. * * <p>Called when a account / authority pair @@ -393,9 +420,16 @@ public abstract class AbstractThreadedSyncAdapter { * * <p>This might be called on a different service connection as {@link #onPerformSync}. * + * <p>The system expects this method to immediately return. If the call stalls the system + * behaves as if this method returned {@code true}. If it is required to perform a longer task + * (such as interacting with the user), return {@code false} and proceed in a difference + * context, such as an {@link android.app.Activity}, or foreground service. The sync can then be + * rescheduled once the account becomes syncable. + * * @return If {@code false} syncing is deferred. Returns {@code true} by default, i.e. by * default syncing starts immediately. */ + @MainThread public boolean onUnsyncableAccount() { return true; } diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 10331d49dd36..ce7d3af8404a 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -2143,21 +2143,6 @@ public abstract class ContentResolver { } /** - * @hide - */ - public void releasePersistableUriPermission(@NonNull String toPackage, @NonNull Uri uri, - @Intent.AccessUriMode int modeFlags) { - Preconditions.checkNotNull(toPackage, "toPackage"); - Preconditions.checkNotNull(uri, "uri"); - try { - ActivityManager.getService().releasePersistableUriPermission( - ContentProvider.getUriWithoutUserId(uri), modeFlags, toPackage, - resolveUserId(uri)); - } catch (RemoteException e) { - } - } - - /** * Return list of all URI permission grants that have been persisted by the * calling app. That is, the returned permissions have been granted * <em>to</em> the calling app. Only persistable grants taken with diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index efa90d308ee0..387a836e6961 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -1188,7 +1188,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { if (category != CATEGORY_UNDEFINED) { pw.println(prefix + "category=" + category); } - pw.println("isAllowedToUseHiddenApi=" + isAllowedToUseHiddenApi()); + pw.println(prefix + "isAllowedToUseHiddenApi=" + isAllowedToUseHiddenApi()); } super.dumpBack(pw, prefix); } diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 5b3d3e595a91..dff51f77788e 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -451,6 +451,9 @@ public abstract class PackageManagerInternal { /** Whether the binder caller can access instant apps. */ public abstract boolean canAccessInstantApps(int callingUid, int userId); + /** Whether the binder caller can access the given component. */ + public abstract boolean canAccessComponent(int callingUid, ComponentName component, int userId); + /** * Returns {@code true} if a given package has instant application meta-data. * Otherwise, returns {@code false}. Meta-data is state (eg. cookie, app icon, etc) @@ -544,4 +547,18 @@ public abstract class PackageManagerInternal { /** 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/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 5d5a9782884a..bc7540fabc19 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -3492,7 +3492,7 @@ public class PackageParser { if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic, - true)) { + owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.P)) { ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC; } diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index f47d4640c09c..72db33f90c20 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -819,8 +819,7 @@ public abstract class CameraDevice implements AutoCloseable { * @param config A session configuration (see {@link SessionConfiguration}). * * @throws IllegalArgumentException In case the session configuration is invalid; or the output - * configurations are empty; or the session configuration - * executor is invalid. + * configurations are empty. * @throws CameraAccessException In case the camera device is no longer connected or has * encountered a fatal error. * @see #createCaptureSession(List, CameraCaptureSession.StateCallback, Handler) diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 52aefcc48304..14c2865cf3e3 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -1435,9 +1435,11 @@ public abstract class CameraMetadata<TKey> { * 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 e14dfa88fb8b..e84e48f8fbcb 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -1001,8 +1001,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * </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 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * @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/hardware/camera2/dispatch/ArgumentReplacingDispatcher.java b/core/java/android/hardware/camera2/dispatch/ArgumentReplacingDispatcher.java new file mode 100644 index 000000000000..866f370f5d5d --- /dev/null +++ b/core/java/android/hardware/camera2/dispatch/ArgumentReplacingDispatcher.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.camera2.dispatch; + +import java.lang.reflect.Method; + +import static com.android.internal.util.Preconditions.*; + +/** + * A dispatcher that replaces one argument with another; replaces any argument at an index + * with another argument. + * + * <p>For example, we can override an {@code void onSomething(int x)} calls to have {@code x} always + * equal to 1. Or, if using this with a duck typing dispatcher, we could even overwrite {@code x} to + * be something + * that's not an {@code int}.</p> + * + * @param <T> + * source dispatch type, whose methods with {@link #dispatch} will be called + * @param <TArg> + * argument replacement type, args in {@link #dispatch} matching {@code argumentIndex} + * will be overriden to objects of this type + */ +public class ArgumentReplacingDispatcher<T, TArg> implements Dispatchable<T> { + + private final Dispatchable<T> mTarget; + private final int mArgumentIndex; + private final TArg mReplaceWith; + + /** + * Create a new argument replacing dispatcher; dispatches are forwarded to {@code target} + * after the argument is replaced. + * + * <p>For example, if a method {@code onAction(T1 a, Integer b, T2 c)} is invoked, and we wanted + * to replace all occurrences of {@code b} with {@code 0xDEADBEEF}, we would set + * {@code argumentIndex = 1} and {@code replaceWith = 0xDEADBEEF}.</p> + * + * <p>If a method dispatched has less arguments than {@code argumentIndex}, it is + * passed through with the arguments unchanged.</p> + * + * @param target destination dispatch type, methods will be redirected to this dispatcher + * @param argumentIndex the numeric index of the argument {@code >= 0} + * @param replaceWith arguments matching {@code argumentIndex} will be replaced with this object + */ + public ArgumentReplacingDispatcher(Dispatchable<T> target, int argumentIndex, + TArg replaceWith) { + mTarget = checkNotNull(target, "target must not be null"); + mArgumentIndex = checkArgumentNonnegative(argumentIndex, + "argumentIndex must not be negative"); + mReplaceWith = checkNotNull(replaceWith, "replaceWith must not be null"); + } + + @Override + public Object dispatch(Method method, Object[] args) throws Throwable { + + if (args.length > mArgumentIndex) { + args = arrayCopy(args); // don't change in-place since it can affect upstream dispatches + args[mArgumentIndex] = mReplaceWith; + } + + return mTarget.dispatch(method, args); + } + + private static Object[] arrayCopy(Object[] array) { + int length = array.length; + Object[] newArray = new Object[length]; + for (int i = 0; i < length; ++i) { + newArray[i] = array[i]; + } + return newArray; + } +} diff --git a/core/java/android/hardware/camera2/dispatch/BroadcastDispatcher.java b/core/java/android/hardware/camera2/dispatch/BroadcastDispatcher.java new file mode 100644 index 000000000000..fe575b277616 --- /dev/null +++ b/core/java/android/hardware/camera2/dispatch/BroadcastDispatcher.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.camera2.dispatch; + + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +import static com.android.internal.util.Preconditions.*; + +/** + * Broadcast a single dispatch into multiple other dispatchables. + * + * <p>Every time {@link #dispatch} is invoked, all the broadcast targets will + * see the same dispatch as well. The first target's return value is returned.</p> + * + * <p>This enables a single listener to be converted into a multi-listener.</p> + */ +public class BroadcastDispatcher<T> implements Dispatchable<T> { + + private final List<Dispatchable<T>> mDispatchTargets; + + /** + * Create a broadcast dispatcher from the supplied dispatch targets. + * + * @param dispatchTargets one or more targets to dispatch to + */ + @SafeVarargs + public BroadcastDispatcher(Dispatchable<T>... dispatchTargets) { + mDispatchTargets = Arrays.asList( + checkNotNull(dispatchTargets, "dispatchTargets must not be null")); + } + + @Override + public Object dispatch(Method method, Object[] args) throws Throwable { + Object result = null; + boolean gotResult = false; + + for (Dispatchable<T> dispatchTarget : mDispatchTargets) { + Object localResult = dispatchTarget.dispatch(method, args); + + if (!gotResult) { + gotResult = true; + result = localResult; + } + } + + return result; + } +} diff --git a/core/java/android/hardware/camera2/dispatch/Dispatchable.java b/core/java/android/hardware/camera2/dispatch/Dispatchable.java new file mode 100644 index 000000000000..753103f45ea8 --- /dev/null +++ b/core/java/android/hardware/camera2/dispatch/Dispatchable.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.camera2.dispatch; + +import java.lang.reflect.Method; + +/** + * Dynamically dispatch a method and its argument to some object. + * + * <p>This can be used to intercept method calls and do work around them, redirect work, + * or block calls entirely.</p> + */ +public interface Dispatchable<T> { + /** + * Dispatch the method and arguments to this object. + * @param method a method defined in class {@code T} + * @param args arguments corresponding to said {@code method} + * @return the object returned when invoking {@code method} + * @throws Throwable any exception that might have been raised while invoking the method + */ + public Object dispatch(Method method, Object[] args) throws Throwable; +} diff --git a/core/java/android/hardware/camera2/dispatch/DuckTypingDispatcher.java b/core/java/android/hardware/camera2/dispatch/DuckTypingDispatcher.java new file mode 100644 index 000000000000..75f97e4656aa --- /dev/null +++ b/core/java/android/hardware/camera2/dispatch/DuckTypingDispatcher.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.camera2.dispatch; + + +import java.lang.reflect.Method; + +import static com.android.internal.util.Preconditions.*; + +/** + * Duck typing dispatcher; converts dispatch methods calls from one class to another by + * looking up equivalently methods at runtime by name. + * + * <p>For example, if two types have identical method names and arguments, but + * are not subclasses/subinterfaces of each other, this dispatcher will allow calls to be + * made from one type to the other.</p> + * + * @param <TFrom> source dispatch type, whose methods with {@link #dispatch} will be called + * @param <T> destination dispatch type, methods will be converted to the class of {@code T} + */ +public class DuckTypingDispatcher<TFrom, T> implements Dispatchable<TFrom> { + + private final MethodNameInvoker<T> mDuck; + + /** + * Create a new duck typing dispatcher. + * + * @param target destination dispatch type, methods will be redirected to this dispatcher + * @param targetClass destination dispatch class, methods will be converted to this class's + */ + public DuckTypingDispatcher(Dispatchable<T> target, Class<T> targetClass) { + checkNotNull(targetClass, "targetClass must not be null"); + checkNotNull(target, "target must not be null"); + + mDuck = new MethodNameInvoker<T>(target, targetClass); + } + + @Override + public Object dispatch(Method method, Object[] args) { + return mDuck.invoke(method.getName(), args); + } +} diff --git a/core/java/android/hardware/camera2/dispatch/HandlerDispatcher.java b/core/java/android/hardware/camera2/dispatch/HandlerDispatcher.java new file mode 100644 index 000000000000..f8e9d49a95c6 --- /dev/null +++ b/core/java/android/hardware/camera2/dispatch/HandlerDispatcher.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.camera2.dispatch; + +import android.hardware.camera2.utils.UncheckedThrow; +import android.os.Handler; +import android.util.Log; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import static com.android.internal.util.Preconditions.*; + +/** + * Forward all interface calls into a handler by posting it as a {@code Runnable}. + * + * <p>All calls will return immediately; functions with return values will return a default + * value of {@code null}, {@code 0}, or {@code false} where that value is legal.</p> + * + * <p>Any exceptions thrown on the handler while trying to invoke a method + * will be re-thrown. Throwing checked exceptions on a handler which doesn't expect any + * checked exceptions to be thrown will result in "undefined" behavior + * (although in practice it is usually thrown as normal).</p> + */ +public class HandlerDispatcher<T> implements Dispatchable<T> { + + private static final String TAG = "HandlerDispatcher"; + + private final Dispatchable<T> mDispatchTarget; + private final Handler mHandler; + + /** + * Create a dispatcher that forwards it's dispatch calls by posting + * them onto the {@code handler} as a {@code Runnable}. + * + * @param dispatchTarget the destination whose method calls will be redirected into the handler + * @param handler all calls into {@code dispatchTarget} will be posted onto this handler + * @param <T> the type of the element you want to wrap. + * @return a dispatcher that will forward it's dispatch calls to a handler + */ + public HandlerDispatcher(Dispatchable<T> dispatchTarget, Handler handler) { + mDispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null"); + mHandler = checkNotNull(handler, "handler must not be null"); + } + + @Override + public Object dispatch(final Method method, final Object[] args) throws Throwable { + mHandler.post(new Runnable() { + @Override + public void run() { + try { + mDispatchTarget.dispatch(method, args); + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + // Potential UB. Hopefully 't' is a runtime exception. + UncheckedThrow.throwAnyException(t); + } catch (IllegalAccessException e) { + // Impossible + Log.wtf(TAG, "IllegalAccessException while invoking " + method, e); + } catch (IllegalArgumentException e) { + // Impossible + Log.wtf(TAG, "IllegalArgumentException while invoking " + method, e); + } catch (Throwable e) { + UncheckedThrow.throwAnyException(e); + } + } + }); + + // TODO handle primitive return values that would avoid NPE if unboxed + return null; + } +} diff --git a/core/java/android/hardware/camera2/dispatch/InvokeDispatcher.java b/core/java/android/hardware/camera2/dispatch/InvokeDispatcher.java new file mode 100644 index 000000000000..ac5f52676df4 --- /dev/null +++ b/core/java/android/hardware/camera2/dispatch/InvokeDispatcher.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.camera2.dispatch; + +import android.hardware.camera2.utils.UncheckedThrow; +import android.util.Log; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import static com.android.internal.util.Preconditions.*; + + +public class InvokeDispatcher<T> implements Dispatchable<T> { + + private static final String TAG = "InvocationSink"; + private final T mTarget; + + public InvokeDispatcher(T target) { + mTarget = checkNotNull(target, "target must not be null"); + } + + @Override + public Object dispatch(Method method, Object[] args) { + try { + return method.invoke(mTarget, args); + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + // Potential UB. Hopefully 't' is a runtime exception. + UncheckedThrow.throwAnyException(t); + } catch (IllegalAccessException e) { + // Impossible + Log.wtf(TAG, "IllegalAccessException while invoking " + method, e); + } catch (IllegalArgumentException e) { + // Impossible + Log.wtf(TAG, "IllegalArgumentException while invoking " + method, e); + } + + // unreachable + return null; + } +} diff --git a/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java b/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java new file mode 100644 index 000000000000..8296b7a915a4 --- /dev/null +++ b/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.camera2.dispatch; + +import static com.android.internal.util.Preconditions.checkNotNull; + +import android.hardware.camera2.utils.UncheckedThrow; + +import java.lang.reflect.Method; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Invoke a method on a dispatchable by its name (without knowing the {@code Method} ahead of time). + * + * @param <T> destination dispatch type, methods will be looked up in the class of {@code T} + */ +public class MethodNameInvoker<T> { + + private final Dispatchable<T> mTarget; + private final Class<T> mTargetClass; + private final Method[] mTargetClassMethods; + private final ConcurrentHashMap<String, Method> mMethods = + new ConcurrentHashMap<>(); + + /** + * Create a new method name invoker. + * + * @param target destination dispatch type, invokes will be redirected to this dispatcher + * @param targetClass destination dispatch class, the invoked methods will be from this class + */ + public MethodNameInvoker(Dispatchable<T> target, Class<T> targetClass) { + mTargetClass = targetClass; + mTargetClassMethods = targetClass.getMethods(); + mTarget = target; + } + + /** + * Invoke a method by its name. + * + * <p>If more than one method exists in {@code targetClass}, the first method with the right + * number of arguments will be used, and later calls will all use that method.</p> + * + * @param methodName + * The name of the method, which will be matched 1:1 to the destination method + * @param params + * Variadic parameter list. + * @return + * The same kind of value that would normally be returned by calling {@code methodName} + * statically. + * + * @throws IllegalArgumentException if {@code methodName} does not exist on the target class + * @throws Throwable will rethrow anything that the target method would normally throw + */ + @SuppressWarnings("unchecked") + public <K> K invoke(String methodName, Object... params) { + checkNotNull(methodName, "methodName must not be null"); + + Method targetMethod = mMethods.get(methodName); + if (targetMethod == null) { + for (Method method : mTargetClassMethods) { + // TODO future: match types of params if possible + if (method.getName().equals(methodName) && + (params.length == method.getParameterTypes().length) ) { + targetMethod = method; + mMethods.put(methodName, targetMethod); + break; + } + } + + if (targetMethod == null) { + throw new IllegalArgumentException( + "Method " + methodName + " does not exist on class " + mTargetClass); + } + } + + try { + return (K) mTarget.dispatch(targetMethod, params); + } catch (Throwable e) { + UncheckedThrow.throwAnyException(e); + // unreachable + return null; + } + } +} diff --git a/core/java/android/security/keystore/recovery/RecoveryControllerException.java b/core/java/android/hardware/camera2/dispatch/NullDispatcher.java index 1af61ceac60a..fada075cba67 100644 --- a/core/java/android/security/keystore/recovery/RecoveryControllerException.java +++ b/core/java/android/hardware/camera2/dispatch/NullDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,23 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package android.hardware.camera2.dispatch; -package android.security.keystore.recovery; -import java.security.GeneralSecurityException; +import java.lang.reflect.Method; /** - * @deprecated Not used. - * @hide + * Do nothing when dispatching; follows the null object pattern. */ -public abstract class RecoveryControllerException extends GeneralSecurityException { - RecoveryControllerException() { } - - RecoveryControllerException(String msg) { - super(msg); +public class NullDispatcher<T> implements Dispatchable<T> { + /** + * Create a dispatcher that does nothing when dispatched to. + */ + public NullDispatcher() { } - public RecoveryControllerException(String message, Throwable cause) { - super(message, cause); + /** + * Do nothing; all parameters are ignored. + */ + @Override + public Object dispatch(Method method, Object[] args) { + return null; } } diff --git a/core/java/android/hardware/camera2/dispatch/package.html b/core/java/android/hardware/camera2/dispatch/package.html new file mode 100644 index 000000000000..783d0a1b54d5 --- /dev/null +++ b/core/java/android/hardware/camera2/dispatch/package.html @@ -0,0 +1,3 @@ +<body> +{@hide} +</body> diff --git a/core/java/android/hardware/camera2/impl/CallbackProxies.java b/core/java/android/hardware/camera2/impl/CallbackProxies.java index 9e4cb80b89f0..c9eecf10e3d3 100644 --- a/core/java/android/hardware/camera2/impl/CallbackProxies.java +++ b/core/java/android/hardware/camera2/impl/CallbackProxies.java @@ -15,17 +15,16 @@ */ package android.hardware.camera2.impl; -import android.os.Binder; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; import android.hardware.camera2.TotalCaptureResult; +import android.hardware.camera2.dispatch.Dispatchable; +import android.hardware.camera2.dispatch.MethodNameInvoker; import android.view.Surface; -import java.util.concurrent.Executor; - import static com.android.internal.util.Preconditions.*; /** @@ -35,86 +34,164 @@ import static com.android.internal.util.Preconditions.*; * to use our own proxy mechanism.</p> */ public class CallbackProxies { + + // TODO: replace with codegen + + public static class DeviceStateCallbackProxy extends CameraDeviceImpl.StateCallbackKK { + private final MethodNameInvoker<CameraDeviceImpl.StateCallbackKK> mProxy; + + public DeviceStateCallbackProxy( + Dispatchable<CameraDeviceImpl.StateCallbackKK> dispatchTarget) { + dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null"); + mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.StateCallbackKK.class); + } + + @Override + public void onOpened(CameraDevice camera) { + mProxy.invoke("onOpened", camera); + } + + @Override + public void onDisconnected(CameraDevice camera) { + mProxy.invoke("onDisconnected", camera); + } + + @Override + public void onError(CameraDevice camera, int error) { + mProxy.invoke("onError", camera, error); + } + + @Override + public void onUnconfigured(CameraDevice camera) { + mProxy.invoke("onUnconfigured", camera); + } + + @Override + public void onActive(CameraDevice camera) { + mProxy.invoke("onActive", camera); + } + + @Override + public void onBusy(CameraDevice camera) { + mProxy.invoke("onBusy", camera); + } + + @Override + public void onClosed(CameraDevice camera) { + mProxy.invoke("onClosed", camera); + } + + @Override + public void onIdle(CameraDevice camera) { + mProxy.invoke("onIdle", camera); + } + } + + @SuppressWarnings("deprecation") + public static class DeviceCaptureCallbackProxy implements CameraDeviceImpl.CaptureCallback { + private final MethodNameInvoker<CameraDeviceImpl.CaptureCallback> mProxy; + + public DeviceCaptureCallbackProxy( + Dispatchable<CameraDeviceImpl.CaptureCallback> dispatchTarget) { + dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null"); + mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.CaptureCallback.class); + } + + @Override + public void onCaptureStarted(CameraDevice camera, + CaptureRequest request, long timestamp, long frameNumber) { + mProxy.invoke("onCaptureStarted", camera, request, timestamp, frameNumber); + } + + @Override + public void onCapturePartial(CameraDevice camera, + CaptureRequest request, CaptureResult result) { + mProxy.invoke("onCapturePartial", camera, request, result); + } + + @Override + public void onCaptureProgressed(CameraDevice camera, + CaptureRequest request, CaptureResult partialResult) { + mProxy.invoke("onCaptureProgressed", camera, request, partialResult); + } + + @Override + public void onCaptureCompleted(CameraDevice camera, + CaptureRequest request, TotalCaptureResult result) { + mProxy.invoke("onCaptureCompleted", camera, request, result); + } + + @Override + public void onCaptureFailed(CameraDevice camera, + CaptureRequest request, CaptureFailure failure) { + mProxy.invoke("onCaptureFailed", camera, request, failure); + } + + @Override + public void onCaptureSequenceCompleted(CameraDevice camera, + int sequenceId, long frameNumber) { + mProxy.invoke("onCaptureSequenceCompleted", camera, sequenceId, frameNumber); + } + + @Override + public void onCaptureSequenceAborted(CameraDevice camera, + int sequenceId) { + mProxy.invoke("onCaptureSequenceAborted", camera, sequenceId); + } + + @Override + public void onCaptureBufferLost(CameraDevice camera, + CaptureRequest request, Surface target, long frameNumber) { + mProxy.invoke("onCaptureBufferLost", camera, request, target, frameNumber); + } + + } + public static class SessionStateCallbackProxy extends CameraCaptureSession.StateCallback { - private final Executor mExecutor; - private final CameraCaptureSession.StateCallback mCallback; + private final MethodNameInvoker<CameraCaptureSession.StateCallback> mProxy; - public SessionStateCallbackProxy(Executor executor, - CameraCaptureSession.StateCallback callback) { - mExecutor = checkNotNull(executor, "executor must not be null"); - mCallback = checkNotNull(callback, "callback must not be null"); + public SessionStateCallbackProxy( + Dispatchable<CameraCaptureSession.StateCallback> dispatchTarget) { + dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null"); + mProxy = new MethodNameInvoker<>(dispatchTarget, + CameraCaptureSession.StateCallback.class); } @Override public void onConfigured(CameraCaptureSession session) { - final long ident = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onConfigured(session)); - } finally { - Binder.restoreCallingIdentity(ident); - } + mProxy.invoke("onConfigured", session); } @Override public void onConfigureFailed(CameraCaptureSession session) { - final long ident = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onConfigureFailed(session)); - } finally { - Binder.restoreCallingIdentity(ident); - } + mProxy.invoke("onConfigureFailed", session); } @Override public void onReady(CameraCaptureSession session) { - final long ident = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onReady(session)); - } finally { - Binder.restoreCallingIdentity(ident); - } + mProxy.invoke("onReady", session); } @Override public void onActive(CameraCaptureSession session) { - final long ident = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onActive(session)); - } finally { - Binder.restoreCallingIdentity(ident); - } + mProxy.invoke("onActive", session); } @Override public void onCaptureQueueEmpty(CameraCaptureSession session) { - final long ident = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onCaptureQueueEmpty(session)); - } finally { - Binder.restoreCallingIdentity(ident); - } + mProxy.invoke("onCaptureQueueEmpty", session); } @Override public void onClosed(CameraCaptureSession session) { - final long ident = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onClosed(session)); - } finally { - Binder.restoreCallingIdentity(ident); - } + mProxy.invoke("onClosed", session); } @Override public void onSurfacePrepared(CameraCaptureSession session, Surface surface) { - final long ident = Binder.clearCallingIdentity(); - try { - mExecutor.execute(() -> mCallback.onSurfacePrepared(session, surface)); - } finally { - Binder.restoreCallingIdentity(ident); - } + mProxy.invoke("onSurfacePrepared", session, surface); } } diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index f3f6c84a7e0b..8b8bbc34f7d2 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -20,18 +20,20 @@ import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.ICameraDeviceUser; +import android.hardware.camera2.dispatch.ArgumentReplacingDispatcher; +import android.hardware.camera2.dispatch.BroadcastDispatcher; +import android.hardware.camera2.dispatch.DuckTypingDispatcher; +import android.hardware.camera2.dispatch.HandlerDispatcher; +import android.hardware.camera2.dispatch.InvokeDispatcher; import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.utils.TaskDrainer; import android.hardware.camera2.utils.TaskSingleDrainer; -import android.os.Binder; import android.os.Handler; -import android.os.HandlerExecutor; import android.util.Log; import android.view.Surface; import java.util.Arrays; import java.util.List; -import java.util.concurrent.Executor; import static android.hardware.camera2.impl.CameraDeviceImpl.checkHandler; import static com.android.internal.util.Preconditions.*; @@ -49,11 +51,11 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession private final Surface mInput; /** * User-specified state callback, used for outgoing events; calls to this object will be - * automatically invoked via {@code mStateExecutor}. + * automatically {@link Handler#post(Runnable) posted} to {@code mStateHandler}. */ private final CameraCaptureSession.StateCallback mStateCallback; - /** User-specified state executor used for outgoing state callback events */ - private final Executor mStateExecutor; + /** User-specified state handler used for outgoing state callback events */ + private final Handler mStateHandler; /** Internal camera device; used to translate calls into existing deprecated API */ private final android.hardware.camera2.impl.CameraDeviceImpl mDeviceImpl; @@ -85,7 +87,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession * (e.g. no pending captures, no repeating requests, no flush).</p> */ CameraCaptureSessionImpl(int id, Surface input, - CameraCaptureSession.StateCallback callback, Executor stateExecutor, + CameraCaptureSession.StateCallback callback, Handler stateHandler, android.hardware.camera2.impl.CameraDeviceImpl deviceImpl, Handler deviceStateHandler, boolean configureSuccess) { if (callback == null) { @@ -96,8 +98,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession mIdString = String.format("Session %d: ", mId); mInput = input; - mStateExecutor = checkNotNull(stateExecutor, "stateExecutor must not be null"); - mStateCallback = createUserStateCallbackProxy(mStateExecutor, callback); + mStateHandler = checkHandler(stateHandler); + mStateCallback = createUserStateCallbackProxy(mStateHandler, callback); mDeviceHandler = checkNotNull(deviceStateHandler, "deviceStateHandler must not be null"); mDeviceImpl = checkNotNull(deviceImpl, "deviceImpl must not be null"); @@ -108,12 +110,12 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession * This ensures total ordering between CameraDevice.StateCallback and * CameraDeviceImpl.CaptureCallback events. */ - mSequenceDrainer = new TaskDrainer<>(new HandlerExecutor(mDeviceHandler), - new SequenceDrainListener(), /*name*/"seq"); - mIdleDrainer = new TaskSingleDrainer(new HandlerExecutor(mDeviceHandler), - new IdleDrainListener(), /*name*/"idle"); - mAbortDrainer = new TaskSingleDrainer(new HandlerExecutor(mDeviceHandler), - new AbortDrainListener(), /*name*/"abort"); + mSequenceDrainer = new TaskDrainer<>(mDeviceHandler, new SequenceDrainListener(), + /*name*/"seq"); + mIdleDrainer = new TaskSingleDrainer(mDeviceHandler, new IdleDrainListener(), + /*name*/"idle"); + mAbortDrainer = new TaskSingleDrainer(mDeviceHandler, new AbortDrainListener(), + /*name*/"abort"); // CameraDevice should call configureOutputs and have it finish before constructing us @@ -444,140 +446,114 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession } /** - * Post calls into a CameraCaptureSession.StateCallback to the user-specified {@code executor}. + * Post calls into a CameraCaptureSession.StateCallback to the user-specified {@code handler}. */ - private StateCallback createUserStateCallbackProxy(Executor executor, StateCallback callback) { - return new CallbackProxies.SessionStateCallbackProxy(executor, callback); + private StateCallback createUserStateCallbackProxy(Handler handler, StateCallback callback) { + InvokeDispatcher<StateCallback> userCallbackSink = new InvokeDispatcher<>(callback); + HandlerDispatcher<StateCallback> handlerPassthrough = + new HandlerDispatcher<>(userCallbackSink, handler); + + return new CallbackProxies.SessionStateCallbackProxy(handlerPassthrough); } /** * Forward callbacks from * CameraDeviceImpl.CaptureCallback to the CameraCaptureSession.CaptureCallback. * + * <p>In particular, all calls are automatically split to go both to our own + * internal callback, and to the user-specified callback (by transparently posting + * to the user-specified handler).</p> + * * <p>When a capture sequence finishes, update the pending checked sequences set.</p> */ @SuppressWarnings("deprecation") private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxy( Handler handler, CaptureCallback callback) { - final Executor executor = (callback != null) ? CameraDeviceImpl.checkAndWrapHandler( - handler) : null; + CameraDeviceImpl.CaptureCallback localCallback = new CameraDeviceImpl.CaptureCallback() { - return new CameraDeviceImpl.CaptureCallback() { @Override public void onCaptureStarted(CameraDevice camera, CaptureRequest request, long timestamp, long frameNumber) { - if ((callback != null) && (executor != null)) { - final long ident = Binder.clearCallingIdentity(); - try { - executor.execute(() -> callback.onCaptureStarted( - CameraCaptureSessionImpl.this, request, timestamp, - frameNumber)); - } finally { - Binder.restoreCallingIdentity(ident); - } - } + // Do nothing } @Override public void onCapturePartial(CameraDevice camera, CaptureRequest request, android.hardware.camera2.CaptureResult result) { - if ((callback != null) && (executor != null)) { - final long ident = Binder.clearCallingIdentity(); - try { - executor.execute(() -> callback.onCapturePartial( - CameraCaptureSessionImpl.this, request, result)); - } finally { - Binder.restoreCallingIdentity(ident); - } - } + // Do nothing } @Override public void onCaptureProgressed(CameraDevice camera, CaptureRequest request, android.hardware.camera2.CaptureResult partialResult) { - if ((callback != null) && (executor != null)) { - final long ident = Binder.clearCallingIdentity(); - try { - executor.execute(() -> callback.onCaptureProgressed( - CameraCaptureSessionImpl.this, request, partialResult)); - } finally { - Binder.restoreCallingIdentity(ident); - } - } + // Do nothing } @Override public void onCaptureCompleted(CameraDevice camera, CaptureRequest request, android.hardware.camera2.TotalCaptureResult result) { - if ((callback != null) && (executor != null)) { - final long ident = Binder.clearCallingIdentity(); - try { - executor.execute(() -> callback.onCaptureCompleted( - CameraCaptureSessionImpl.this, request, result)); - } finally { - Binder.restoreCallingIdentity(ident); - } - } + // Do nothing } @Override public void onCaptureFailed(CameraDevice camera, CaptureRequest request, android.hardware.camera2.CaptureFailure failure) { - if ((callback != null) && (executor != null)) { - final long ident = Binder.clearCallingIdentity(); - try { - executor.execute(() -> callback.onCaptureFailed( - CameraCaptureSessionImpl.this, request, failure)); - } finally { - Binder.restoreCallingIdentity(ident); - } - } + // Do nothing } @Override public void onCaptureSequenceCompleted(CameraDevice camera, int sequenceId, long frameNumber) { - if ((callback != null) && (executor != null)) { - final long ident = Binder.clearCallingIdentity(); - try { - executor.execute(() -> callback.onCaptureSequenceCompleted( - CameraCaptureSessionImpl.this, sequenceId, frameNumber)); - } finally { - Binder.restoreCallingIdentity(ident); - } - } finishPendingSequence(sequenceId); } @Override public void onCaptureSequenceAborted(CameraDevice camera, int sequenceId) { - if ((callback != null) && (executor != null)) { - final long ident = Binder.clearCallingIdentity(); - try { - executor.execute(() -> callback.onCaptureSequenceAborted( - CameraCaptureSessionImpl.this, sequenceId)); - } finally { - Binder.restoreCallingIdentity(ident); - } - } finishPendingSequence(sequenceId); } @Override public void onCaptureBufferLost(CameraDevice camera, CaptureRequest request, Surface target, long frameNumber) { - if ((callback != null) && (executor != null)) { - final long ident = Binder.clearCallingIdentity(); - try { - executor.execute(() -> callback.onCaptureBufferLost( - CameraCaptureSessionImpl.this, request, target, frameNumber)); - } finally { - Binder.restoreCallingIdentity(ident); - } - } + // Do nothing } + }; + + /* + * Split the calls from the device callback into local callback and the following chain: + * - replace the first CameraDevice arg with a CameraCaptureSession + * - duck type from device callback to session callback + * - then forward the call to a handler + * - then finally invoke the destination method on the session callback object + */ + if (callback == null) { + // OK: API allows the user to not specify a callback, and the handler may + // also be null in that case. Collapse whole dispatch chain to only call the local + // callback + return localCallback; + } + + InvokeDispatcher<CameraDeviceImpl.CaptureCallback> localSink = + new InvokeDispatcher<>(localCallback); + + InvokeDispatcher<CaptureCallback> userCallbackSink = + new InvokeDispatcher<>(callback); + HandlerDispatcher<CaptureCallback> handlerPassthrough = + new HandlerDispatcher<>(userCallbackSink, handler); + DuckTypingDispatcher<CameraDeviceImpl.CaptureCallback, CaptureCallback> duckToSession + = new DuckTypingDispatcher<>(handlerPassthrough, CaptureCallback.class); + ArgumentReplacingDispatcher<CameraDeviceImpl.CaptureCallback, CameraCaptureSessionImpl> + replaceDeviceWithSession = new ArgumentReplacingDispatcher<>(duckToSession, + /*argumentIndex*/0, this); + + BroadcastDispatcher<CameraDeviceImpl.CaptureCallback> broadcaster = + new BroadcastDispatcher<CameraDeviceImpl.CaptureCallback>( + replaceDeviceWithSession, + localSink); + + return new CallbackProxies.DeviceCaptureCallbackProxy(broadcaster); } /** diff --git a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java index 4ee08bae84cb..06c2c25ab6bb 100644 --- a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java @@ -33,7 +33,6 @@ import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.concurrent.Executor; import static com.android.internal.util.Preconditions.*; @@ -60,14 +59,14 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl * (e.g. no pending captures, no repeating requests, no flush).</p> */ CameraConstrainedHighSpeedCaptureSessionImpl(int id, - CameraCaptureSession.StateCallback callback, Executor stateExecutor, + CameraCaptureSession.StateCallback callback, Handler stateHandler, android.hardware.camera2.impl.CameraDeviceImpl deviceImpl, Handler deviceStateHandler, boolean configureSuccess, CameraCharacteristics characteristics) { mCharacteristics = characteristics; CameraCaptureSession.StateCallback wrapperCallback = new WrapperCallback(callback); mSessionImpl = new CameraCaptureSessionImpl(id, /*input*/null, wrapperCallback, - stateExecutor, deviceImpl, deviceStateHandler, configureSuccess); + stateHandler, deviceImpl, deviceStateHandler, configureSuccess); } @Override diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index b328bb1726e9..511fa43a5441 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -35,10 +35,8 @@ import android.hardware.camera2.params.SessionConfiguration; import android.hardware.camera2.params.StreamConfigurationMap; import android.hardware.camera2.utils.SubmitInfo; import android.hardware.camera2.utils.SurfaceUtils; -import android.os.Binder; import android.os.Build; import android.os.Handler; -import android.os.HandlerExecutor; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; @@ -60,7 +58,6 @@ import java.util.List; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.Executor; /** * HAL2.1+ implementation of CameraDevice. Use CameraManager#open to instantiate @@ -504,9 +501,8 @@ public class CameraDeviceImpl extends CameraDevice for (Surface surface : outputs) { outConfigurations.add(new OutputConfiguration(surface)); } - createCaptureSessionInternal(null, outConfigurations, callback, - checkAndWrapHandler(handler), /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, - /*sessionParams*/ null); + createCaptureSessionInternal(null, outConfigurations, callback, handler, + /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null); } @Override @@ -521,7 +517,7 @@ public class CameraDeviceImpl extends CameraDevice // OutputConfiguration objects are immutable, but need to have our own array List<OutputConfiguration> currentOutputs = new ArrayList<>(outputConfigurations); - createCaptureSessionInternal(null, currentOutputs, callback, checkAndWrapHandler(handler), + createCaptureSessionInternal(null, currentOutputs, callback, handler, /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/null); } @@ -541,9 +537,8 @@ public class CameraDeviceImpl extends CameraDevice for (Surface surface : outputs) { outConfigurations.add(new OutputConfiguration(surface)); } - createCaptureSessionInternal(inputConfig, outConfigurations, callback, - checkAndWrapHandler(handler), /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, - /*sessionParams*/ null); + createCaptureSessionInternal(inputConfig, outConfigurations, callback, handler, + /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null); } @Override @@ -571,8 +566,8 @@ public class CameraDeviceImpl extends CameraDevice currentOutputs.add(new OutputConfiguration(output)); } createCaptureSessionInternal(inputConfig, currentOutputs, - callback, checkAndWrapHandler(handler), - /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null); + callback, handler, /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, + /*sessionParams*/ null); } @Override @@ -587,8 +582,7 @@ public class CameraDeviceImpl extends CameraDevice for (Surface surface : outputs) { outConfigurations.add(new OutputConfiguration(surface)); } - createCaptureSessionInternal(null, outConfigurations, callback, - checkAndWrapHandler(handler), + createCaptureSessionInternal(null, outConfigurations, callback, handler, /*operatingMode*/ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE, /*sessionParams*/ null); } @@ -603,8 +597,8 @@ public class CameraDeviceImpl extends CameraDevice for (OutputConfiguration output : outputs) { currentOutputs.add(new OutputConfiguration(output)); } - createCaptureSessionInternal(inputConfig, currentOutputs, callback, - checkAndWrapHandler(handler), operatingMode, /*sessionParams*/ null); + createCaptureSessionInternal(inputConfig, currentOutputs, callback, handler, operatingMode, + /*sessionParams*/ null); } @Override @@ -618,17 +612,14 @@ public class CameraDeviceImpl extends CameraDevice if (outputConfigs == null) { throw new IllegalArgumentException("Invalid output configurations"); } - if (config.getExecutor() == null) { - throw new IllegalArgumentException("Invalid executor"); - } createCaptureSessionInternal(config.getInputConfiguration(), outputConfigs, - config.getStateCallback(), config.getExecutor(), config.getSessionType(), + config.getStateCallback(), config.getHandler(), config.getSessionType(), config.getSessionParameters()); } private void createCaptureSessionInternal(InputConfiguration inputConfig, List<OutputConfiguration> outputConfigurations, - CameraCaptureSession.StateCallback callback, Executor executor, + CameraCaptureSession.StateCallback callback, Handler handler, int operatingMode, CaptureRequest sessionParams) throws CameraAccessException { synchronized(mInterfaceLock) { if (DEBUG) { @@ -682,11 +673,12 @@ public class CameraDeviceImpl extends CameraDevice SurfaceUtils.checkConstrainedHighSpeedSurfaces(surfaces, /*fpsRange*/null, config); newSession = new CameraConstrainedHighSpeedCaptureSessionImpl(mNextSessionId++, - callback, executor, this, mDeviceHandler, configureSuccess, + callback, handler, this, mDeviceHandler, configureSuccess, mCharacteristics); } else { newSession = new CameraCaptureSessionImpl(mNextSessionId++, input, - callback, executor, this, mDeviceHandler, configureSuccess); + callback, handler, this, mDeviceHandler, + configureSuccess); } // TODO: wait until current session closes, then create the new session @@ -971,12 +963,7 @@ public class CameraDeviceImpl extends CameraDevice } } }; - final long ident = Binder.clearCallingIdentity(); - try { - holder.getExecutor().execute(resultDispatch); - } finally { - Binder.restoreCallingIdentity(ident); - } + holder.getHandler().post(resultDispatch); } else { Log.w(TAG, String.format( "did not register callback to request %d", @@ -997,9 +984,9 @@ public class CameraDeviceImpl extends CameraDevice private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback, Handler handler, boolean repeating) throws CameraAccessException { - // Need a valid executor, or current thread needs to have a looper, if + // Need a valid handler, or current thread needs to have a looper, if // callback is valid - Executor executor = getExecutor(handler, callback); + handler = checkHandler(handler, callback); // Make sure that there all requests have at least 1 surface; all surfaces are non-null; // the surface isn't a physical stream surface for reprocessing request @@ -1053,7 +1040,7 @@ public class CameraDeviceImpl extends CameraDevice if (callback != null) { mCaptureCallbackMap.put(requestInfo.getRequestId(), new CaptureCallbackHolder( - callback, requestList, executor, repeating, mNextSessionId - 1)); + callback, requestList, handler, repeating, mNextSessionId - 1)); } else { if (DEBUG) { Log.d(TAG, "Listen for request " + requestInfo.getRequestId() + " is null"); @@ -1367,7 +1354,7 @@ public class CameraDeviceImpl extends CameraDevice private final boolean mRepeating; private final CaptureCallback mCallback; private final List<CaptureRequest> mRequestList; - private final Executor mExecutor; + private final Handler mHandler; private final int mSessionId; /** * <p>Determine if the callback holder is for a constrained high speed request list that @@ -1379,13 +1366,13 @@ public class CameraDeviceImpl extends CameraDevice private final boolean mHasBatchedOutputs; CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList, - Executor executor, boolean repeating, int sessionId) { - if (callback == null || executor == null) { + Handler handler, boolean repeating, int sessionId) { + if (callback == null || handler == null) { throw new UnsupportedOperationException( "Must have a valid handler and a valid callback"); } mRepeating = repeating; - mExecutor = executor; + mHandler = handler; mRequestList = new ArrayList<CaptureRequest>(requestList); mCallback = callback; mSessionId = sessionId; @@ -1438,8 +1425,8 @@ public class CameraDeviceImpl extends CameraDevice return getRequest(0); } - public Executor getExecutor() { - return mExecutor; + public Handler getHandler() { + return mHandler; } public int getSessionId() { @@ -1823,12 +1810,7 @@ public class CameraDeviceImpl extends CameraDevice } } }; - final long ident = Binder.clearCallingIdentity(); - try { - holder.getExecutor().execute(resultDispatch); - } finally { - Binder.restoreCallingIdentity(ident); - } + holder.getHandler().post(resultDispatch); } } } @@ -1879,7 +1861,7 @@ public class CameraDeviceImpl extends CameraDevice private void scheduleNotifyError(int code) { mInError = true; CameraDeviceImpl.this.mDeviceHandler.post(obtainRunnable( - CameraDeviceCallbacks::notifyError, this, code)); + CameraDeviceCallbacks::notifyError, this, code)); } private void notifyError(int code) { @@ -1947,41 +1929,36 @@ public class CameraDeviceImpl extends CameraDevice if (isClosed()) return; // Dispatch capture start notice - final long ident = Binder.clearCallingIdentity(); - try { - holder.getExecutor().execute( - new Runnable() { - @Override - public void run() { - if (!CameraDeviceImpl.this.isClosed()) { - final int subsequenceId = resultExtras.getSubsequenceId(); - final CaptureRequest request = holder.getRequest(subsequenceId); - - if (holder.hasBatchedOutputs()) { - // Send derived onCaptureStarted for requests within the - // batch - final Range<Integer> fpsRange = - request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE); - for (int i = 0; i < holder.getRequestCount(); i++) { - holder.getCallback().onCaptureStarted( - CameraDeviceImpl.this, - holder.getRequest(i), - timestamp - (subsequenceId - i) * - NANO_PER_SECOND/fpsRange.getUpper(), - frameNumber - (subsequenceId - i)); - } - } else { + holder.getHandler().post( + new Runnable() { + @Override + public void run() { + if (!CameraDeviceImpl.this.isClosed()) { + final int subsequenceId = resultExtras.getSubsequenceId(); + final CaptureRequest request = holder.getRequest(subsequenceId); + + if (holder.hasBatchedOutputs()) { + // Send derived onCaptureStarted for requests within the batch + final Range<Integer> fpsRange = + request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE); + for (int i = 0; i < holder.getRequestCount(); i++) { holder.getCallback().onCaptureStarted( CameraDeviceImpl.this, - holder.getRequest(resultExtras.getSubsequenceId()), - timestamp, frameNumber); + holder.getRequest(i), + timestamp - (subsequenceId - i) * + NANO_PER_SECOND/fpsRange.getUpper(), + frameNumber - (subsequenceId - i)); } + } else { + holder.getCallback().onCaptureStarted( + CameraDeviceImpl.this, + holder.getRequest(resultExtras.getSubsequenceId()), + timestamp, frameNumber); } } - }); - } finally { - Binder.restoreCallingIdentity(ident); - } + } + }); + } } @@ -2134,12 +2111,7 @@ public class CameraDeviceImpl extends CameraDevice finalResult = resultAsCapture; } - final long ident = Binder.clearCallingIdentity(); - try { - holder.getExecutor().execute(resultDispatch); - } finally { - Binder.restoreCallingIdentity(ident); - } + holder.getHandler().post(resultDispatch); // Collect the partials for a total result; or mark the frame as totally completed mFrameNumberTracker.updateTracker(frameNumber, finalResult, isPartialResult, @@ -2235,12 +2207,7 @@ public class CameraDeviceImpl extends CameraDevice } }; // Dispatch the failure callback - final long ident = Binder.clearCallingIdentity(); - try { - holder.getExecutor().execute(failureDispatch); - } finally { - Binder.restoreCallingIdentity(ident); - } + holder.getHandler().post(failureDispatch); } } else { boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT); @@ -2280,12 +2247,7 @@ public class CameraDeviceImpl extends CameraDevice checkAndFireSequenceComplete(); // Dispatch the failure callback - final long ident = Binder.clearCallingIdentity(); - try { - holder.getExecutor().execute(failureDispatch); - } finally { - Binder.restoreCallingIdentity(ident); - } + holder.getHandler().post(failureDispatch); } } @@ -2293,37 +2255,6 @@ public class CameraDeviceImpl extends CameraDevice } // public class CameraDeviceCallbacks /** - * Instantiate a new Executor. - * - * <p>If the callback isn't null, check the handler and instantiate a new executor, - * otherwise instantiate a new executor in case handler is valid.</p> - */ - static <T> Executor getExecutor(Handler handler, T callback) { - if (callback != null) { - return checkAndWrapHandler(handler); - } - - if (handler != null) { - return new HandlerExecutor(handler); - } - - return null; - } - - /** - * Wrap Handler in Executor. - * - * <p> - * If handler is null, get the current thread's - * Looper to create a Executor with. If no looper exists, throw - * {@code IllegalArgumentException}. - * </p> - */ - static Executor checkAndWrapHandler(Handler handler) { - return new HandlerExecutor(checkHandler(handler)); - } - - /** * Default handler management. * * <p> diff --git a/core/java/android/hardware/camera2/params/SessionConfiguration.java b/core/java/android/hardware/camera2/params/SessionConfiguration.java index 7bdb4a2f1339..a79a6c17f925 100644 --- a/core/java/android/hardware/camera2/params/SessionConfiguration.java +++ b/core/java/android/hardware/camera2/params/SessionConfiguration.java @@ -17,10 +17,10 @@ package android.hardware.camera2.params; -import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.IntDef; +import android.os.Handler; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; @@ -31,7 +31,6 @@ import android.hardware.camera2.params.OutputConfiguration; import java.util.Collections; import java.util.List; import java.util.ArrayList; -import java.util.concurrent.Executor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -79,7 +78,7 @@ public final class SessionConfiguration { private List<OutputConfiguration> mOutputConfigurations; private CameraCaptureSession.StateCallback mStateCallback; private int mSessionType; - private Executor mExecutor = null; + private Handler mHandler = null; private InputConfiguration mInputConfig = null; private CaptureRequest mSessionParameters = null; @@ -88,9 +87,10 @@ public final class SessionConfiguration { * * @param sessionType The session type. * @param outputs A list of output configurations for the capture session. - * @param executor The executor which should be used to invoke the callback. In general it is - * recommended that camera operations are not done on the main (UI) thread. * @param cb A state callback interface implementation. + * @param handler The handler on which the callback will be invoked. If it is + * set to null, the callback will be invoked on the current thread's + * {@link android.os.Looper looper}. * * @see #SESSION_REGULAR * @see #SESSION_HIGH_SPEED @@ -101,12 +101,11 @@ public final class SessionConfiguration { */ public SessionConfiguration(@SessionMode int sessionType, @NonNull List<OutputConfiguration> outputs, - @NonNull @CallbackExecutor Executor executor, - @NonNull CameraCaptureSession.StateCallback cb) { + @NonNull CameraCaptureSession.StateCallback cb, @Nullable Handler handler) { mSessionType = sessionType; mOutputConfigurations = Collections.unmodifiableList(new ArrayList<>(outputs)); mStateCallback = cb; - mExecutor = executor; + mHandler = handler; } /** @@ -137,12 +136,14 @@ public final class SessionConfiguration { } /** - * Retrieve the {@link java.util.concurrent.Executor} for the capture session. + * Retrieve the {@link CameraCaptureSession.StateCallback} for the capture session. * - * @return The Executor on which the callback will be invoked. + * @return The handler on which the callback will be invoked. If it is + * set to null, the callback will be invoked on the current thread's + * {@link android.os.Looper looper}. */ - public Executor getExecutor() { - return mExecutor; + public Handler getHandler() { + return mHandler; } /** diff --git a/core/java/android/hardware/camera2/utils/TaskDrainer.java b/core/java/android/hardware/camera2/utils/TaskDrainer.java index e71f26a18792..ed30ff34afc8 100644 --- a/core/java/android/hardware/camera2/utils/TaskDrainer.java +++ b/core/java/android/hardware/camera2/utils/TaskDrainer.java @@ -15,11 +15,11 @@ */ package android.hardware.camera2.utils; +import android.os.Handler; import android.util.Log; import java.util.HashSet; import java.util.Set; -import java.util.concurrent.Executor; import static com.android.internal.util.Preconditions.*; @@ -55,7 +55,7 @@ public class TaskDrainer<T> { private static final String TAG = "TaskDrainer"; private final boolean DEBUG = false; - private final Executor mExecutor; + private final Handler mHandler; private final DrainListener mListener; private final String mName; @@ -73,27 +73,28 @@ public class TaskDrainer<T> { /** * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener - * via the {@code executor}. + * via the {@code handler}. * - * @param executor a non-{@code null} executor to use for listener execution + * @param handler a non-{@code null} handler to use to post runnables to * @param listener a non-{@code null} listener where {@code onDrained} will be called */ - public TaskDrainer(Executor executor, DrainListener listener) { - mExecutor = checkNotNull(executor, "executor must not be null"); + public TaskDrainer(Handler handler, DrainListener listener) { + mHandler = checkNotNull(handler, "handler must not be null"); mListener = checkNotNull(listener, "listener must not be null"); mName = null; } /** * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener - * via the {@code executor}. + * via the {@code handler}. * - * @param executor a non-{@code null} executor to use for listener execution + * @param handler a non-{@code null} handler to use to post runnables to * @param listener a non-{@code null} listener where {@code onDrained} will be called * @param name an optional name used for debug logging */ - public TaskDrainer(Executor executor, DrainListener listener, String name) { - mExecutor = checkNotNull(executor, "executor must not be null"); + public TaskDrainer(Handler handler, DrainListener listener, String name) { + // XX: Probably don't need a handler at all here + mHandler = checkNotNull(handler, "handler must not be null"); mListener = checkNotNull(listener, "listener must not be null"); mName = name; } @@ -199,12 +200,15 @@ public class TaskDrainer<T> { } private void postDrained() { - mExecutor.execute(() -> { + mHandler.post(new Runnable() { + @Override + public void run() { if (DEBUG) { Log.v(TAG + "[" + mName + "]", "onDrained"); } mListener.onDrained(); + } }); } } diff --git a/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java b/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java index 9615450be447..f6272c9e6a66 100644 --- a/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java +++ b/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java @@ -16,8 +16,7 @@ package android.hardware.camera2.utils; import android.hardware.camera2.utils.TaskDrainer.DrainListener; - -import java.util.concurrent.Executor; +import android.os.Handler; /** * Keep track of a single concurrent task starting and finishing; @@ -39,25 +38,25 @@ public class TaskSingleDrainer { /** * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener - * via the {@code executor}. + * via the {@code handler}. * - * @param executor a non-{@code null} executor to use for listener execution + * @param handler a non-{@code null} handler to use to post runnables to * @param listener a non-{@code null} listener where {@code onDrained} will be called */ - public TaskSingleDrainer(Executor executor, DrainListener listener) { - mTaskDrainer = new TaskDrainer<>(executor, listener); + public TaskSingleDrainer(Handler handler, DrainListener listener) { + mTaskDrainer = new TaskDrainer<>(handler, listener); } /** * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener - * via the {@code executor}. + * via the {@code handler}. * - * @param executor a non-{@code null} executor to use for listener execution + * @param handler a non-{@code null} handler to use to post runnables to * @param listener a non-{@code null} listener where {@code onDrained} will be called * @param name an optional name used for debug logging */ - public TaskSingleDrainer(Executor executor, DrainListener listener, String name) { - mTaskDrainer = new TaskDrainer<>(executor, listener, name); + public TaskSingleDrainer(Handler handler, DrainListener listener, String name) { + mTaskDrainer = new TaskDrainer<>(handler, listener, name); } /** diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index f468942cc951..504f840af5bf 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -23,6 +23,7 @@ import android.util.IntArray; import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; +import android.view.SurfaceControl; /** * Display manager local system service interface. @@ -115,7 +116,7 @@ public abstract class DisplayManagerInternal { * Called by the window manager to perform traversals while holding a * surface flinger transaction. */ - public abstract void performTraversalInTransactionFromWindowManager(); + public abstract void performTraversal(SurfaceControl.Transaction t); /** * Tells the display manager about properties of the display that depend on the windows on it. diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index b3bf092aeffe..b4c8a5e504bc 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.MATCH_PARENT; 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 @@ public class InputMethodService extends AbstractInputMethodService { 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 @@ public class InputMethodService extends AbstractInputMethodService { // 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 @@ public class InputMethodService extends AbstractInputMethodService { boolean mIsInputViewShown; int mStatusIcon; + + @BackDispositionMode int mBackDisposition; /** @@ -1015,8 +1089,19 @@ public class InputMethodService extends AbstractInputMethodService { 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 @@ public class InputMethodService extends AbstractInputMethodService { 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 @@ public class InputMethodService extends AbstractInputMethodService { mInputStarted = false; mStartedInputConnection = null; mCurCompletions = null; - mBackDisposition = BACK_DISPOSITION_DEFAULT; } void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) { @@ -2096,25 +2187,31 @@ public class InputMethodService extends AbstractInputMethodService { 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/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java index 2bb43bd36be3..e84f91314386 100644 --- a/core/java/android/metrics/LogMaker.java +++ b/core/java/android/metrics/LogMaker.java @@ -103,7 +103,7 @@ public class LogMaker { * @hide // TODO Expose in the future? Too late for O. */ public LogMaker setLatency(long milliseconds) { - entries.put(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS, milliseconds); + entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_LATENCY_MILLIS, milliseconds); return this; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 29b7931bf7c7..e46a5f05c48d 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3727,7 +3727,7 @@ public final class Settings { public static final Validator SOUND_EFFECTS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; /** - * Whether the haptic feedback (long presses, ...) are enabled. The value is + * Whether haptic feedback (Vibrate on tap) is enabled. The value is * boolean (1 or 0). */ public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled"; @@ -10271,31 +10271,6 @@ public final class Settings { "battery_saver_device_specific_constants"; /** - * Battery anomaly detection specific settings - * This is encoded as a key=value list, separated by commas. - * wakeup_blacklisted_tags is a string, encoded as a set of tags, encoded via - * {@link Uri#encode(String)}, separated by colons. Ex: - * - * "anomaly_detection_enabled=true,wakelock_threshold=2000,wakeup_alarm_enabled=true," - * "wakeup_alarm_threshold=10,wakeup_blacklisted_tags=tag1:tag2:with%2Ccomma:with%3Acolon" - * - * The following keys are supported: - * - * <pre> - * anomaly_detection_enabled (boolean) - * wakelock_enabled (boolean) - * wakelock_threshold (long) - * wakeup_alarm_enabled (boolean) - * wakeup_alarm_threshold (long) - * wakeup_blacklisted_tags (string) - * bluetooth_scan_enabled (boolean) - * bluetooth_scan_threshold (long) - * </pre> - * @hide - */ - public static final String ANOMALY_DETECTION_CONSTANTS = "anomaly_detection_constants"; - - /** * Battery tip specific settings * This is encoded as a key=value list, separated by commas. Ex: * @@ -10324,6 +10299,31 @@ public final class Settings { public static final String BATTERY_TIP_CONSTANTS = "battery_tip_constants"; /** + * Battery anomaly detection specific settings + * This is encoded as a key=value list, separated by commas. + * wakeup_blacklisted_tags is a string, encoded as a set of tags, encoded via + * {@link Uri#encode(String)}, separated by colons. Ex: + * + * "anomaly_detection_enabled=true,wakelock_threshold=2000,wakeup_alarm_enabled=true," + * "wakeup_alarm_threshold=10,wakeup_blacklisted_tags=tag1:tag2:with%2Ccomma:with%3Acolon" + * + * The following keys are supported: + * + * <pre> + * anomaly_detection_enabled (boolean) + * wakelock_enabled (boolean) + * wakelock_threshold (long) + * wakeup_alarm_enabled (boolean) + * wakeup_alarm_threshold (long) + * wakeup_blacklisted_tags (string) + * bluetooth_scan_enabled (boolean) + * bluetooth_scan_threshold (long) + * </pre> + * @hide + */ + public static final String ANOMALY_DETECTION_CONSTANTS = "anomaly_detection_constants"; + + /** * An integer to show the version of the anomaly config. Ex: 1, which means * current version is 1. * @hide @@ -10378,6 +10378,17 @@ public final class Settings { 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. * @@ -10598,7 +10609,7 @@ public final class Settings { * Default: 1 * @hide */ - public static final java.lang.String APP_STANDBY_ENABLED = "app_standby_enabled"; + public static final String APP_STANDBY_ENABLED = "app_standby_enabled"; /** * Whether or not app auto restriction is enabled. When it is enabled, settings app will @@ -10609,7 +10620,7 @@ public final class Settings { * * @hide */ - public static final java.lang.String APP_AUTO_RESTRICTION_ENABLED = + public static final String APP_AUTO_RESTRICTION_ENABLED = "app_auto_restriction_enabled"; private static final Validator APP_AUTO_RESTRICTION_ENABLED_VALIDATOR = @@ -12327,6 +12338,28 @@ public final class Settings { * @hide */ public static final String SHOW_ZEN_UPGRADE_NOTIFICATION = "show_zen_upgrade_notification"; + + /** + * Backup and restore agent timeout parameters. + * These parameters are represented by a comma-delimited key-value list. + * + * The following strings are supported as keys: + * <pre> + * kv_backup_agent_timeout_millis (long) + * full_backup_agent_timeout_millis (long) + * shared_backup_agent_timeout_millis (long) + * restore_agent_timeout_millis (long) + * restore_agent_finished_timeout_millis (long) + * </pre> + * + * They map to milliseconds represented as longs. + * + * Ex: "kv_backup_agent_timeout_millis=30000,full_backup_agent_timeout_millis=300000" + * + * @hide + */ + public static final String BACKUP_AGENT_TIMEOUT_PARAMETERS = + "backup_agent_timeout_parameters"; } /** 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 4275c29ee728..000000000000 --- 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/KeyChainSnapshot.java b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java index 4580c47ac3c3..00f54e16863d 100644 --- a/core/java/android/security/keystore/recovery/KeyChainSnapshot.java +++ b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java @@ -18,12 +18,14 @@ package android.security.keystore.recovery; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.os.BadParcelableException; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.util.Preconditions; import java.security.cert.CertPath; +import java.security.cert.CertificateException; import java.util.List; /** @@ -54,7 +56,7 @@ public final class KeyChainSnapshot implements Parcelable { private long mCounterId = DEFAULT_COUNTER_ID; private byte[] mServerParams; private byte[] mPublicKey; // The raw public key bytes used - private CertPath mCertPath; // The certificate path including the intermediate certificates + private RecoveryCertPath mCertPath; // The cert path including necessary intermediate certs private List<KeyChainProtectionParams> mKeyChainProtectionParams; private List<WrappedApplicationKey> mEntryRecoveryData; private byte[] mEncryptedRecoveryKeyBlob; @@ -127,7 +129,17 @@ public final class KeyChainSnapshot implements Parcelable { */ // TODO: Change to @NonNull public CertPath getTrustedHardwareCertPath() { - return mCertPath; + if (mCertPath == null) { + return null; + } else { + try { + return mCertPath.getCertPath(); + } catch (CertificateException e) { + // Rethrow an unchecked exception as it should not happen. If such an issue exists, + // an exception should have been thrown during service initialization. + throw new BadParcelableException(e); + } + } } /** @@ -232,11 +244,17 @@ public final class KeyChainSnapshot implements Parcelable { * contain a certificate of the trusted hardware public key and any necessary intermediate * certificates. * - * @param certPath The public key + * @param certPath The certificate path + * @throws CertificateException if the given certificate path cannot be encoded properly * @return This builder. */ - public Builder setTrustedHardwareCertPath(CertPath certPath) { - mInstance.mCertPath = certPath; + public Builder setTrustedHardwareCertPath(CertPath certPath) throws CertificateException { + // TODO: Make it NonNull when the caller code is all updated + if (certPath == null) { + mInstance.mCertPath = null; + } else { + mInstance.mCertPath = RecoveryCertPath.createRecoveryCertPath(certPath); + } return this; } @@ -302,6 +320,7 @@ public final class KeyChainSnapshot implements Parcelable { out.writeLong(mCounterId); out.writeByteArray(mServerParams); out.writeByteArray(mPublicKey); + out.writeTypedObject(mCertPath, /* no flags */ 0); } /** @@ -316,6 +335,7 @@ public final class KeyChainSnapshot implements Parcelable { mCounterId = in.readLong(); mServerParams = in.createByteArray(); mPublicKey = in.createByteArray(); + mCertPath = in.readTypedObject(RecoveryCertPath.CREATOR); } @Override diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java index 18431cacbfaf..febca7ec9de1 100644 --- a/core/java/android/text/DynamicLayout.java +++ b/core/java/android/text/DynamicLayout.java @@ -704,7 +704,12 @@ public class DynamicLayout extends Layout { // Spans other than ReplacementSpan can be ignored because line top and bottom are // disjunction of all tops and bottoms, although it's not optimal. final Paint paint = getPaint(); - paint.getTextBounds(text, start, end, mTempRect); + if (text instanceof PrecomputedText) { + PrecomputedText precomputed = (PrecomputedText) text; + precomputed.getBounds(start, end, mTempRect); + } else { + paint.getTextBounds(text, start, end, mTempRect); + } final Paint.FontMetricsInt fm = paint.getFontMetricsInt(); return mTempRect.top < fm.top || mTempRect.bottom > fm.bottom; } diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java index aafcf44a73fc..801d6e7d850a 100644 --- a/core/java/android/text/MeasuredParagraph.java +++ b/core/java/android/text/MeasuredParagraph.java @@ -21,6 +21,7 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Paint; +import android.graphics.Rect; import android.text.AutoGrowArray.ByteArray; import android.text.AutoGrowArray.FloatArray; import android.text.AutoGrowArray.IntArray; @@ -297,6 +298,18 @@ public class MeasuredParagraph { } /** + * Retrieves the bounding rectangle that encloses all of the characters, with an implied origin + * at (0, 0). + * + * This is available only if the MeasuredParagraph is computed with buildForStaticLayout. + */ + public void getBounds(@NonNull Paint paint, @IntRange(from = 0) int start, + @IntRange(from = 0) int end, @NonNull Rect bounds) { + nGetBounds(mNativePtr, mCopiedBuffer, paint.getNativeInstance(), start, end, + paint.getBidiFlags(), bounds); + } + + /** * Generates new MeasuredParagraph for Bidi computation. * * If recycle is null, this returns new instance. If recycle is not null, this fills computed @@ -728,4 +741,7 @@ public class MeasuredParagraph { @CriticalNative private static native int nGetMemoryUsage(/* Non Zero */ long nativePtr); + + private static native void nGetBounds(long nativePtr, char[] buf, long paintPtr, int start, + int end, int bidiFlag, Rect rect); } diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java index b74019373f57..74b199fa738c 100644 --- a/core/java/android/text/PrecomputedText.java +++ b/core/java/android/text/PrecomputedText.java @@ -19,6 +19,8 @@ package android.text; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.graphics.Rect; +import android.text.style.MetricAffectingSpan; import android.util.IntArray; import com.android.internal.util.Preconditions; @@ -61,7 +63,7 @@ import java.util.Objects; * {@link android.widget.TextView} will be rejected internally and compute the text layout again * with the current {@link android.widget.TextView} parameters. */ -public class PrecomputedText implements Spanned { +public class PrecomputedText implements Spannable { private static final char LINE_FEED = '\n'; /** @@ -268,7 +270,7 @@ public class PrecomputedText implements Spanned { }; // The original text. - private final @NonNull SpannedString mText; + private final @NonNull SpannableString mText; // The inclusive start offset of the measuring target. private final @IntRange(from = 0) int mStart; @@ -342,7 +344,7 @@ public class PrecomputedText implements Spanned { private PrecomputedText(@NonNull CharSequence text, @IntRange(from = 0) int start, @IntRange(from = 0) int end, @NonNull Params param, @NonNull MeasuredParagraph[] measuredTexts, @NonNull int[] paragraphBreakPoints) { - mText = new SpannedString(text); + mText = new SpannableString(text); mStart = start; mEnd = end; mParams = param; @@ -448,6 +450,21 @@ public class PrecomputedText implements Spanned { return getMeasuredParagraph(paraIndex).getWidth(start - paraStart, end - paraStart); } + /** @hide */ + public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end, + @NonNull Rect bounds) { + final int paraIndex = findParaIndex(start); + final int paraStart = getParagraphStart(paraIndex); + final int paraEnd = getParagraphEnd(paraIndex); + if (start < paraStart || paraEnd < end) { + throw new RuntimeException("Cannot measured across the paragraph:" + + "para: (" + paraStart + ", " + paraEnd + "), " + + "request: (" + start + ", " + end + ")"); + } + getMeasuredParagraph(paraIndex).getBounds(mParams.mPaint, + start - paraStart, end - paraStart, bounds); + } + /** * Returns the size of native PrecomputedText memory usage. * @@ -463,6 +480,35 @@ public class PrecomputedText implements Spanned { } /////////////////////////////////////////////////////////////////////////////////////////////// + // Spannable overrides + // + // Do not allow to modify MetricAffectingSpan + + /** + * @throws IllegalArgumentException if {@link MetricAffectingSpan} is specified. + */ + @Override + public void setSpan(Object what, int start, int end, int flags) { + if (what instanceof MetricAffectingSpan) { + throw new IllegalArgumentException( + "MetricAffectingSpan can not be set to PrecomputedText."); + } + mText.setSpan(what, start, end, flags); + } + + /** + * @throws IllegalArgumentException if {@link MetricAffectingSpan} is specified. + */ + @Override + public void removeSpan(Object what) { + if (what instanceof MetricAffectingSpan) { + throw new IllegalArgumentException( + "MetricAffectingSpan can not be removed from PrecomputedText."); + } + mText.removeSpan(what); + } + + /////////////////////////////////////////////////////////////////////////////////////////////// // Spanned overrides // // Just proxy for underlying mText if appropriate. diff --git a/core/java/android/util/KeyValueSettingObserver.java b/core/java/android/util/KeyValueSettingObserver.java new file mode 100644 index 000000000000..9fca8b2cfab2 --- /dev/null +++ b/core/java/android/util/KeyValueSettingObserver.java @@ -0,0 +1,97 @@ +/* + * 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.util; + +import android.content.ContentResolver; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; + +/** + * Abstract class for observing changes to a specified setting stored as a comma-separated key value + * list of parameters. Registers and unregisters a {@link ContentObserver} and handles updates when + * the setting changes. + * + * <p>Subclasses should pass in the relevant setting's {@link Uri} in the constructor and implement + * {@link #update(KeyValueListParser)} to receive updates when the value changes. + * Calls to {@link #update(KeyValueListParser)} only trigger after calling {@link + * #start()}. + * + * <p>To get the most up-to-date parameter values, first call {@link #start()} before accessing the + * values to start observing changes, and then call {@link #stop()} once finished. + * + * @hide + */ +public abstract class KeyValueSettingObserver { + private static final String TAG = "KeyValueSettingObserver"; + + private final KeyValueListParser mParser = new KeyValueListParser(','); + + private final ContentObserver mObserver; + private final ContentResolver mResolver; + private final Uri mSettingUri; + + public KeyValueSettingObserver(Handler handler, ContentResolver resolver, + Uri uri) { + mObserver = new SettingObserver(handler); + mResolver = resolver; + mSettingUri = uri; + } + + /** Starts observing changes for the setting. Pair with {@link #stop()}. */ + public void start() { + mResolver.registerContentObserver(mSettingUri, false, mObserver); + setParserValue(); + update(mParser); + } + + /** Stops observing changes for the setting. */ + public void stop() { + mResolver.unregisterContentObserver(mObserver); + } + + /** + * Returns the {@link String} representation of the setting. Subclasses should implement this + * for their setting. + */ + public abstract String getSettingValue(ContentResolver resolver); + + /** Updates the parser with the current setting value. */ + private void setParserValue() { + String setting = getSettingValue(mResolver); + try { + mParser.setString(setting); + } catch (IllegalArgumentException e) { + Slog.e(TAG, "Malformed setting: " + setting); + } + } + + /** Subclasses should implement this to update references to their parameters. */ + public abstract void update(KeyValueListParser parser); + + private class SettingObserver extends ContentObserver { + private SettingObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + setParserValue(); + update(mParser); + } + } +} diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java index 3350f3e164bc..789131cf87f4 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 final class StatsLog extends StatsLogInternal { */ 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 final class StatsLog extends StatsLogInternal { */ 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 final class StatsLog extends StatsLogInternal { */ 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/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index b6adee9501a6..66a9c6c01ca4 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -51,6 +51,7 @@ public final class DisplayCutout { private static final String TAG = "DisplayCutout"; private static final String BOTTOM_MARKER = "@bottom"; private static final String DP_MARKER = "@dp"; + private static final String RIGHT_MARKER = "@right"; /** * Category for overlays that allow emulating a display cutout on devices that don't have @@ -373,6 +374,13 @@ public final class DisplayCutout { } } spec = spec.trim(); + final float offsetX; + if (spec.endsWith(RIGHT_MARKER)) { + offsetX = displayWidth; + spec = spec.substring(0, spec.length() - RIGHT_MARKER.length()).trim(); + } else { + offsetX = displayWidth / 2f; + } final boolean inDp = spec.endsWith(DP_MARKER); if (inDp) { spec = spec.substring(0, spec.length() - DP_MARKER.length()); @@ -397,7 +405,7 @@ public final class DisplayCutout { if (inDp) { m.postScale(density, density); } - m.postTranslate(displayWidth / 2f, 0); + m.postTranslate(offsetX, 0); p.transform(m); if (bottomSpec != null) { diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl index 5607b1134e5b..89684ca46003 100644 --- a/core/java/android/view/IRecentsAnimationController.aidl +++ b/core/java/android/view/IRecentsAnimationController.aidl @@ -51,4 +51,12 @@ interface IRecentsAnimationController { * and then enable it mid-animation to start receiving touch events. */ void setInputConsumerEnabled(boolean enabled); + + /** + * Informs the system whether the animation targets passed into + * IRecentsAnimationRunner.onAnimationStart are currently behind the system bars. If they are, + * they can control the SystemUI flags, otherwise the SystemUI flags from home activity will be + * taken. + */ + void setAnimationTargetsBehindSystemBars(boolean behindSystemBars); } diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 77a74e260811..d172fb5cd9ad 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -181,9 +181,10 @@ interface IWindowManager 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/view/RecordingCanvas.java b/core/java/android/view/RecordingCanvas.java index fc7d828de12e..f7a41ffa67e5 100644 --- a/core/java/android/view/RecordingCanvas.java +++ b/core/java/android/view/RecordingCanvas.java @@ -474,8 +474,7 @@ public class RecordingCanvas extends Canvas { } nDrawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount, - x, y, isRtl, paint.getNativeInstance(), 0 /* measured text */, - 0 /* measured text offset */); + x, y, isRtl, paint.getNativeInstance(), 0 /* measured text */); } @Override @@ -506,19 +505,16 @@ public class RecordingCanvas extends Canvas { char[] buf = TemporaryBuffer.obtain(contextLen); TextUtils.getChars(text, contextStart, contextEnd, buf, 0); long measuredTextPtr = 0; - int measuredTextOffset = 0; if (text instanceof PrecomputedText) { PrecomputedText mt = (PrecomputedText) text; int paraIndex = mt.findParaIndex(start); if (end <= mt.getParagraphEnd(paraIndex)) { // Only support if the target is in the same paragraph. measuredTextPtr = mt.getMeasuredParagraph(paraIndex).getNativePtr(); - measuredTextOffset = start - mt.getParagraphStart(paraIndex); } } nDrawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len, - 0, contextLen, x, y, isRtl, paint.getNativeInstance(), - measuredTextPtr, measuredTextOffset); + 0, contextLen, x, y, isRtl, paint.getNativeInstance(), measuredTextPtr); TemporaryBuffer.recycle(buf); } } @@ -641,7 +637,7 @@ public class RecordingCanvas extends Canvas { @FastNative private static native void nDrawTextRun(long nativeCanvas, char[] text, int start, int count, int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint, - long nativePrecomputedText, int measuredTextOffset); + long nativePrecomputedText); @FastNative private static native void nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count, diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java index 8def43512e51..d2240e1f2775 100644 --- a/core/java/android/view/RemoteAnimationDefinition.java +++ b/core/java/android/view/RemoteAnimationDefinition.java @@ -16,10 +16,14 @@ package android.view; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; + import android.annotation.Nullable; +import android.app.WindowConfiguration; +import android.app.WindowConfiguration.ActivityType; import android.os.Parcel; import android.os.Parcelable; -import android.util.ArrayMap; +import android.util.ArraySet; import android.util.SparseArray; import android.view.WindowManager.TransitionType; @@ -30,7 +34,7 @@ import android.view.WindowManager.TransitionType; */ public class RemoteAnimationDefinition implements Parcelable { - private final SparseArray<RemoteAnimationAdapter> mTransitionAnimationMap; + private final SparseArray<RemoteAnimationAdapterEntry> mTransitionAnimationMap; public RemoteAnimationDefinition() { mTransitionAnimationMap = new SparseArray<>(); @@ -40,34 +44,70 @@ public class RemoteAnimationDefinition implements Parcelable { * Registers a remote animation for a specific transition. * * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values. + * @param activityTypeFilter The remote animation only runs if an activity with type of this + * parameter is involved in the transition. + * @param adapter The adapter that described how to run the remote animation. + */ + public void addRemoteAnimation(@TransitionType int transition, + @ActivityType int activityTypeFilter, RemoteAnimationAdapter adapter) { + mTransitionAnimationMap.put(transition, + new RemoteAnimationAdapterEntry(adapter, activityTypeFilter)); + } + + /** + * Registers a remote animation for a specific transition without defining an activity type + * filter. + * + * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values. * @param adapter The adapter that described how to run the remote animation. */ public void addRemoteAnimation(@TransitionType int transition, RemoteAnimationAdapter adapter) { - mTransitionAnimationMap.put(transition, adapter); + addRemoteAnimation(transition, ACTIVITY_TYPE_UNDEFINED, adapter); } /** * Checks whether a remote animation for specific transition is defined. * * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values. + * @param activityTypes The set of activity types of activities that are involved in the + * transition. Will be used for filtering. * @return Whether this definition has defined a remote animation for the specified transition. */ - public boolean hasTransition(@TransitionType int transition) { - return mTransitionAnimationMap.get(transition) != null; + public boolean hasTransition(@TransitionType int transition, ArraySet<Integer> activityTypes) { + return getAdapter(transition, activityTypes) != null; } /** * Retrieves the remote animation for a specific transition. * * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values. + * @param activityTypes The set of activity types of activities that are involved in the + * transition. Will be used for filtering. * @return The remote animation adapter for the specified transition. */ - public @Nullable RemoteAnimationAdapter getAdapter(@TransitionType int transition) { - return mTransitionAnimationMap.get(transition); + public @Nullable RemoteAnimationAdapter getAdapter(@TransitionType int transition, + ArraySet<Integer> activityTypes) { + final RemoteAnimationAdapterEntry entry = mTransitionAnimationMap.get(transition); + if (entry == null) { + return null; + } + if (entry.activityTypeFilter == ACTIVITY_TYPE_UNDEFINED + || activityTypes.contains(entry.activityTypeFilter)) { + return entry.adapter; + } else { + return null; + } } public RemoteAnimationDefinition(Parcel in) { - mTransitionAnimationMap = in.readSparseArray(null /* loader */); + final int size = in.readInt(); + mTransitionAnimationMap = new SparseArray<>(size); + for (int i = 0; i < size; i++) { + final int transition = in.readInt(); + final RemoteAnimationAdapterEntry entry = in.readTypedObject( + RemoteAnimationAdapterEntry.CREATOR); + mTransitionAnimationMap.put(transition, entry); + } } /** @@ -76,7 +116,7 @@ public class RemoteAnimationDefinition implements Parcelable { */ public void setCallingPid(int pid) { for (int i = mTransitionAnimationMap.size() - 1; i >= 0; i--) { - mTransitionAnimationMap.valueAt(i).setCallingPid(pid); + mTransitionAnimationMap.valueAt(i).adapter.setCallingPid(pid); } } @@ -87,7 +127,12 @@ public class RemoteAnimationDefinition implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeSparseArray((SparseArray) mTransitionAnimationMap); + final int size = mTransitionAnimationMap.size(); + dest.writeInt(size); + for (int i = 0; i < size; i++) { + dest.writeInt(mTransitionAnimationMap.keyAt(i)); + dest.writeTypedObject(mTransitionAnimationMap.valueAt(i), flags); + } } public static final Creator<RemoteAnimationDefinition> CREATOR = @@ -100,4 +145,50 @@ public class RemoteAnimationDefinition implements Parcelable { return new RemoteAnimationDefinition[size]; } }; + + private static class RemoteAnimationAdapterEntry implements Parcelable { + + final RemoteAnimationAdapter adapter; + + /** + * Only run the transition if one of the activities matches the filter. + * {@link WindowConfiguration.ACTIVITY_TYPE_UNDEFINED} means no filter + */ + @ActivityType final int activityTypeFilter; + + RemoteAnimationAdapterEntry(RemoteAnimationAdapter adapter, int activityTypeFilter) { + this.adapter = adapter; + this.activityTypeFilter = activityTypeFilter; + } + + private RemoteAnimationAdapterEntry(Parcel in) { + adapter = in.readParcelable(RemoteAnimationAdapter.class.getClassLoader()); + activityTypeFilter = in.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(adapter, flags); + dest.writeInt(activityTypeFilter); + } + + @Override + public int describeContents() { + return 0; + } + + private static final Creator<RemoteAnimationAdapterEntry> CREATOR + = new Creator<RemoteAnimationAdapterEntry>() { + + @Override + public RemoteAnimationAdapterEntry createFromParcel(Parcel in) { + return new RemoteAnimationAdapterEntry(in); + } + + @Override + public RemoteAnimationAdapterEntry[] newArray(int size) { + return new RemoteAnimationAdapterEntry[size]; + } + }; + } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index d908e7979cf7..d5216843f81e 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -29,6 +29,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; import android.Manifest; import android.animation.LayoutTransition; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.ResourcesManager; @@ -4152,9 +4153,7 @@ public final class ViewRootImpl implements ViewParent, Log.v(TAG, "Dispatching key " + msg.obj + " from Autofill to " + mView); } KeyEvent event = (KeyEvent) msg.obj; - // send InputEvent to pre IME, set FLAG_FROM_AUTOFILL so the InputEvent - // wont be dropped as app window is not focus. - enqueueInputEvent(event, null, QueuedInputEvent.FLAG_FROM_AUTOFILL, true); + enqueueInputEvent(event, null, 0, true); } break; case MSG_CHECK_FOCUS: { InputMethodManager imm = InputMethodManager.peekInstance(); @@ -4447,7 +4446,7 @@ public final class ViewRootImpl implements ViewParent, return true; } else if ((!mAttachInfo.mHasWindowFocus && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER) - && (q.mFlags & QueuedInputEvent.FLAG_FROM_AUTOFILL) == 0) || mStopped + && !isAutofillUiShowing()) || mStopped || (mIsAmbientMode && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_BUTTON)) || (mPausedForTransition && !isBack(q.mEvent))) { // This is a focus event and the window doesn't currently have input focus or @@ -4782,18 +4781,11 @@ public final class ViewRootImpl implements ViewParent, ensureTouchMode(event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); } - if (action == MotionEvent.ACTION_DOWN && mView instanceof ViewGroup) { + if (action == MotionEvent.ACTION_DOWN) { // Upon motion event within app window, close autofill ui. - ViewGroup decorView = (ViewGroup) mView; - if (decorView.getChildCount() > 0) { - // We cannot use decorView's Context for querying AutofillManager: DecorView's - // context is based on Application Context, it would allocate a different - // AutofillManager instance. - AutofillManager afm = (AutofillManager) decorView.getChildAt(0).getContext() - .getSystemService(Context.AUTOFILL_MANAGER_SERVICE); - if (afm != null) { - afm.requestHideFillUi(); - } + AutofillManager afm = getAutofillManager(); + if (afm != null) { + afm.requestHideFillUi(); } } @@ -6435,6 +6427,28 @@ public final class ViewRootImpl implements ViewParent, return mAudioManager; } + private @Nullable AutofillManager getAutofillManager() { + if (mView instanceof ViewGroup) { + ViewGroup decorView = (ViewGroup) mView; + if (decorView.getChildCount() > 0) { + // We cannot use decorView's Context for querying AutofillManager: DecorView's + // context is based on Application Context, it would allocate a different + // AutofillManager instance. + return decorView.getChildAt(0).getContext() + .getSystemService(AutofillManager.class); + } + } + return null; + } + + private boolean isAutofillUiShowing() { + AutofillManager afm = getAutofillManager(); + if (afm == null) { + return false; + } + return afm.isAutofillUiShowing(); + } + public AccessibilityInteractionController getAccessibilityInteractionController() { if (mView == null) { throw new IllegalStateException("getAccessibilityInteractionController" @@ -6840,7 +6854,6 @@ public final class ViewRootImpl implements ViewParent, public static final int FLAG_FINISHED_HANDLED = 1 << 3; public static final int FLAG_RESYNTHESIZED = 1 << 4; public static final int FLAG_UNHANDLED = 1 << 5; - public static final int FLAG_FROM_AUTOFILL = 1 << 6; public QueuedInputEvent mNext; diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 158c2ee0b2d0..c1092978cea0 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -1407,6 +1407,15 @@ public final class AutofillManager { return client; } + /** + * Check if autofill ui is showing, must be called on UI thread. + * @hide + */ + public boolean isAutofillUiShowing() { + final AutofillClient client = mContext.getAutofillClient(); + return client != null & client.autofillClientIsFillUiShowing(); + } + /** @hide */ public void onAuthenticationResult(int authenticationId, Intent data, View focusView) { if (!hasAutofillFeature()) { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index f39b73e671d4..5178a97e6b68 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -251,7 +251,7 @@ import java.util.Map; * density, or high density screens, respectively. For example: * <pre> * <link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio:1.5)" href="hdpi.css" /></pre> - * <p>The {@code hdpi.css} stylesheet is only used for devices with a screen pixel ration of 1.5, + * <p>The {@code hdpi.css} stylesheet is only used for devices with a screen pixel ratio of 1.5, * which is the high density pixel ratio. * </li> * </ul> diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java index 07593a512216..49e11b8baf51 100644 --- a/core/java/android/webkit/WebViewZygote.java +++ b/core/java/android/webkit/WebViewZygote.java @@ -19,6 +19,7 @@ package android.webkit; import android.app.LoadedApk; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.os.AsyncTask; import android.os.Build; import android.os.ChildZygoteProcess; import android.os.Process; @@ -93,11 +94,17 @@ public class WebViewZygote { synchronized (sLock) { sMultiprocessEnabled = enabled; - // When multi-process is disabled, kill the zygote. When it is enabled, - // the zygote is not explicitly started here to avoid waiting on the - // zygote launch at boot. Instead, the zygote will be started when it is - // first needed in getProcess(). - if (!enabled) { + // When toggling between multi-process being on/off, start or stop the + // zygote. If it is enabled and the zygote is not yet started, launch it. + // Otherwise, kill it. The name may be null if the package information has + // not yet been resolved. + if (enabled) { + // Run on a background thread as this waits for the zygote to start and we don't + // want to block the caller on this. It's okay if this is delayed as anyone trying + // to use the zygote will call it first anyway. + AsyncTask.THREAD_POOL_EXECUTOR.execute(WebViewZygote::getProcess); + } else { + // No need to run this in the background, it's very brief. stopZygoteLocked(); } } diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index 75fc53864101..bbdf15c871bb 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -1182,12 +1182,12 @@ public class RelativeLayout extends ViewGroup { * 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/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 6fe64a03a95c..1e2d18c3ad83 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -291,6 +291,7 @@ import java.util.Locale; * @attr ref android.R.styleable#TextView_drawableTintMode * @attr ref android.R.styleable#TextView_lineSpacingExtra * @attr ref android.R.styleable#TextView_lineSpacingMultiplier + * @attr ref android.R.styleable#TextView_justificationMode * @attr ref android.R.styleable#TextView_marqueeRepeatLimit * @attr ref android.R.styleable#TextView_inputType * @attr ref android.R.styleable#TextView_imeOptions @@ -5641,6 +5642,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener needEditableForNotification = true; } + PrecomputedText precomputed = + (text instanceof PrecomputedText) ? (PrecomputedText) text : null; if (type == BufferType.EDITABLE || getKeyListener() != null || needEditableForNotification) { createEditorIfNeeded(); @@ -5650,10 +5653,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setFilters(t, mFilters); InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null) imm.restartInput(this); - } else if (type == BufferType.SPANNABLE || mMovement != null) { - text = mSpannableFactory.newSpannable(text); - } else if (text instanceof PrecomputedText) { - PrecomputedText precomputed = (PrecomputedText) text; + } else if (precomputed != null) { if (mTextDir == null) { mTextDir = getTextDirectionHeuristic(); } @@ -5666,6 +5666,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener + "PrecomputedText: " + precomputed.getParams() + "TextView: " + getTextMetricsParams()); } + } else if (type == BufferType.SPANNABLE || mMovement != null) { + text = mSpannableFactory.newSpannable(text); } else if (!(text instanceof CharWrapper)) { text = TextUtils.stringOrSpannedString(text); } diff --git a/core/java/com/android/internal/backup/LocalTransportParameters.java b/core/java/com/android/internal/backup/LocalTransportParameters.java index 390fae96f810..154e79d4f7ef 100644 --- a/core/java/com/android/internal/backup/LocalTransportParameters.java +++ b/core/java/com/android/internal/backup/LocalTransportParameters.java @@ -16,62 +16,32 @@ package com.android.internal.backup; +import android.util.KeyValueSettingObserver; import android.content.ContentResolver; -import android.database.ContentObserver; import android.os.Handler; import android.provider.Settings; import android.util.KeyValueListParser; -import android.util.Slog; -class LocalTransportParameters { +class LocalTransportParameters extends KeyValueSettingObserver { private static final String TAG = "LocalTransportParams"; private static final String SETTING = Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS; private static final String KEY_FAKE_ENCRYPTION_FLAG = "fake_encryption_flag"; - private final KeyValueListParser mParser = new KeyValueListParser(','); - private final ContentObserver mObserver; - private final ContentResolver mResolver; private boolean mFakeEncryptionFlag; LocalTransportParameters(Handler handler, ContentResolver resolver) { - mObserver = new Observer(handler); - mResolver = resolver; - } - - /** Observes for changes in the setting. This method MUST be paired with {@link #stop()}. */ - void start() { - mResolver.registerContentObserver(Settings.Secure.getUriFor(SETTING), false, mObserver); - update(); - } - - /** Stop observing for changes in the setting. */ - void stop() { - mResolver.unregisterContentObserver(mObserver); + super(handler, resolver, Settings.Secure.getUriFor(SETTING)); } boolean isFakeEncryptionFlag() { return mFakeEncryptionFlag; } - private void update() { - String parameters = ""; - try { - parameters = Settings.Secure.getString(mResolver, SETTING); - } catch (IllegalArgumentException e) { - Slog.e(TAG, "Malformed " + SETTING + " setting: " + e.getMessage()); - } - mParser.setString(parameters); - mFakeEncryptionFlag = mParser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false); + public String getSettingValue(ContentResolver resolver) { + return Settings.Secure.getString(resolver, SETTING); } - private class Observer extends ContentObserver { - private Observer(Handler handler) { - super(handler); - } - - @Override - public void onChange(boolean selfChange) { - update(); - } + public void update(KeyValueListParser parser) { + mFakeEncryptionFlag = parser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false); } } diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java index 44adbb22eb7e..59504360f3cf 100644 --- a/core/java/com/android/internal/notification/SystemNotificationChannels.java +++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java @@ -50,6 +50,7 @@ public class SystemNotificationChannels { public static String FOREGROUND_SERVICE = "FOREGROUND_SERVICE"; public static String HEAVY_WEIGHT_APP = "HEAVY_WEIGHT_APP"; public static String SYSTEM_CHANGES = "SYSTEM_CHANGES"; + public static String DO_NOT_DISTURB = "DO_NOT_DISTURB"; public static void createAll(Context context) { final NotificationManager nm = context.getSystemService(NotificationManager.class); @@ -158,6 +159,11 @@ public class SystemNotificationChannels { NotificationManager.IMPORTANCE_LOW); channelsList.add(systemChanges); + NotificationChannel dndChanges = new NotificationChannel(DO_NOT_DISTURB, + context.getString(R.string.notification_channel_do_not_disturb), + NotificationManager.IMPORTANCE_LOW); + channelsList.add(dndChanges); + nm.createNotificationChannels(channelsList); } diff --git a/core/java/com/android/internal/os/FuseAppLoop.java b/core/java/com/android/internal/os/FuseAppLoop.java index 12405ebce057..67fbe5e76745 100644 --- a/core/java/com/android/internal/os/FuseAppLoop.java +++ b/core/java/com/android/internal/os/FuseAppLoop.java @@ -138,7 +138,7 @@ public class FuseAppLoop implements Handler.Callback { private static final int FUSE_FSYNC = 20; // Defined in FuseBuffer.h - private static final int FUSE_MAX_WRITE = 256 * 1024; + private static final int FUSE_MAX_WRITE = 128 * 1024; @Override public boolean handleMessage(Message msg) { diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index 9d012de33089..0c5ea6327dff 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -23,6 +23,7 @@ import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; +import android.content.res.Resources; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.util.Log; @@ -33,6 +34,7 @@ import android.view.LayoutInflater; import android.view.MenuItem; import android.view.SubMenu; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewDebug; import android.widget.LinearLayout; @@ -108,13 +110,6 @@ public final class MenuItemImpl implements MenuItem { private CharSequence mContentDescription; private CharSequence mTooltipText; - private static String sLanguage; - private static String sPrependShortcutLabel; - private static String sEnterShortcutLabel; - private static String sDeleteShortcutLabel; - private static String sSpaceShortcutLabel; - - /** * Instantiates this menu item. * @@ -130,20 +125,6 @@ public final class MenuItemImpl implements MenuItem { MenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering, CharSequence title, int showAsAction) { - String lang = menu.getContext().getResources().getConfiguration().locale.toString(); - if (sPrependShortcutLabel == null || !lang.equals(sLanguage)) { - sLanguage = lang; - // This is instantiated from the UI thread, so no chance of sync issues - sPrependShortcutLabel = menu.getContext().getResources().getString( - com.android.internal.R.string.prepend_shortcut_label); - sEnterShortcutLabel = menu.getContext().getResources().getString( - com.android.internal.R.string.menu_enter_shortcut_label); - sDeleteShortcutLabel = menu.getContext().getResources().getString( - com.android.internal.R.string.menu_delete_shortcut_label); - sSpaceShortcutLabel = menu.getContext().getResources().getString( - com.android.internal.R.string.menu_space_shortcut_label); - } - mMenu = menu; mId = id; mGroup = group; @@ -353,19 +334,45 @@ public final class MenuItemImpl implements MenuItem { return ""; } - StringBuilder sb = new StringBuilder(sPrependShortcutLabel); + final Resources res = mMenu.getContext().getResources(); + + StringBuilder sb = new StringBuilder(); + if (ViewConfiguration.get(mMenu.getContext()).hasPermanentMenuKey()) { + // Only prepend "Menu+" if there is a hardware menu key. + sb.append(res.getString( + com.android.internal.R.string.prepend_shortcut_label)); + } + + final int modifiers = + mMenu.isQwertyMode() ? mShortcutAlphabeticModifiers : mShortcutNumericModifiers; + appendModifier(sb, modifiers, KeyEvent.META_META_ON, res.getString( + com.android.internal.R.string.menu_meta_shortcut_label)); + appendModifier(sb, modifiers, KeyEvent.META_CTRL_ON, res.getString( + com.android.internal.R.string.menu_ctrl_shortcut_label)); + appendModifier(sb, modifiers, KeyEvent.META_ALT_ON, res.getString( + com.android.internal.R.string.menu_alt_shortcut_label)); + appendModifier(sb, modifiers, KeyEvent.META_SHIFT_ON, res.getString( + com.android.internal.R.string.menu_shift_shortcut_label)); + appendModifier(sb, modifiers, KeyEvent.META_SYM_ON, res.getString( + com.android.internal.R.string.menu_sym_shortcut_label)); + appendModifier(sb, modifiers, KeyEvent.META_FUNCTION_ON, res.getString( + com.android.internal.R.string.menu_function_shortcut_label)); + switch (shortcut) { case '\n': - sb.append(sEnterShortcutLabel); + sb.append(res.getString( + com.android.internal.R.string.menu_enter_shortcut_label)); break; case '\b': - sb.append(sDeleteShortcutLabel); + sb.append(res.getString( + com.android.internal.R.string.menu_delete_shortcut_label)); break; case ' ': - sb.append(sSpaceShortcutLabel); + sb.append(res.getString( + com.android.internal.R.string.menu_space_shortcut_label)); break; default: @@ -376,6 +383,12 @@ public final class MenuItemImpl implements MenuItem { return sb.toString(); } + private static void appendModifier(StringBuilder sb, int mask, int modifier, String label) { + if ((mask & modifier) == modifier) { + sb.append(label); + } + } + /** * @return Whether this menu item should be showing shortcuts (depends on * whether the menu should show shortcuts and whether this item has diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp index 3b081eff110a..f831c051182e 100644 --- a/core/jni/android/graphics/BitmapRegionDecoder.cpp +++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp @@ -155,12 +155,6 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in 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 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in 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 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in 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/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index 2c05d0b976fc..bd14d45325a7 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -309,7 +309,7 @@ namespace PaintGlue { jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) { minikin::Layout layout = MinikinUtils::doLayout( paint, static_cast<minikin::Bidi>(bidiFlags), typeface, text, 0, count, count, - nullptr, 0); + nullptr); size_t nGlyphs = layout.nGlyphs(); uint16_t* glyphs = new uint16_t[nGlyphs]; SkPoint* pos = new SkPoint[nGlyphs]; @@ -351,8 +351,7 @@ namespace PaintGlue { SkIRect ir; minikin::Layout layout = MinikinUtils::doLayout(&paint, - static_cast<minikin::Bidi>(bidiFlags), typeface, text, 0, count, count, nullptr, - 0); + static_cast<minikin::Bidi>(bidiFlags), typeface, text, 0, count, count, nullptr); minikin::MinikinRect rect; layout.getBounds(&rect); r.fLeft = rect.mLeft; @@ -468,7 +467,7 @@ namespace PaintGlue { } minikin::Layout layout = MinikinUtils::doLayout(paint, static_cast<minikin::Bidi>(bidiFlags), typeface, str.get(), 0, str.size(), - str.size(), nullptr, 0); + str.size(), nullptr); size_t nGlyphs = countNonSpaceGlyphs(layout); if (nGlyphs != 1 && nChars > 1) { // multiple-character input, and was not a ligature @@ -489,7 +488,7 @@ namespace PaintGlue { static const jchar ZZ_FLAG_STR[] = { 0xD83C, 0xDDFF, 0xD83C, 0xDDFF }; minikin::Layout zzLayout = MinikinUtils::doLayout(paint, static_cast<minikin::Bidi>(bidiFlags), typeface, ZZ_FLAG_STR, 0, 4, 4, - nullptr, 0); + nullptr); if (zzLayout.nGlyphs() != 1 || layoutContainsNotdef(zzLayout)) { // The font collection doesn't have a glyph for unknown flag. Just return true. return true; diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp index 06de5daab7d2..0017f6cd8a41 100644 --- a/core/jni/android_graphics_Canvas.cpp +++ b/core/jni/android_graphics_Canvas.cpp @@ -484,7 +484,7 @@ static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray t const Typeface* typeface = paint->getAndroidTypeface(); jchar* jchars = env->GetCharArrayElements(text, NULL); get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y, - static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr, 0); + static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr); env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); } @@ -496,13 +496,13 @@ static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring tex const int count = end - start; const jchar* jchars = env->GetStringChars(text, NULL); get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y, - static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr, 0); + static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr); env->ReleaseStringChars(text, jchars); } static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index, jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y, - jboolean isRtl, jlong paintHandle, jlong mtHandle, jint mtOffset) { + jboolean isRtl, jlong paintHandle, jlong mtHandle) { Paint* paint = reinterpret_cast<Paint*>(paintHandle); minikin::MeasuredText* mt = reinterpret_cast<minikin::MeasuredText*>(mtHandle); const Typeface* typeface = paint->getAndroidTypeface(); @@ -510,8 +510,7 @@ static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArra const minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR; jchar* jchars = env->GetCharArrayElements(text, NULL); get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count, - contextCount, x, y, bidiFlags, *paint, typeface, mt, - mtOffset); + contextCount, x, y, bidiFlags, *paint, typeface, mt); env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); } @@ -526,7 +525,7 @@ static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstr jint contextCount = contextEnd - contextStart; const jchar* jchars = env->GetStringChars(text, NULL); get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count, - contextCount, x, y, bidiFlags, *paint, typeface, nullptr, 0); + contextCount, x, y, bidiFlags, *paint, typeface, nullptr); env->ReleaseStringChars(text, jchars); } @@ -640,7 +639,7 @@ static const JNINativeMethod gDrawMethods[] = { {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray}, {"nDrawText","(J[CIIFFIJ)V", (void*) CanvasJNI::drawTextChars}, {"nDrawText","(JLjava/lang/String;IIFFIJ)V", (void*) CanvasJNI::drawTextString}, - {"nDrawTextRun","(J[CIIIIFFZJJI)V", (void*) CanvasJNI::drawTextRunChars}, + {"nDrawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars}, {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJ)V", (void*) CanvasJNI::drawTextRunString}, {"nDrawTextOnPath","(J[CIIJFFIJ)V", (void*) CanvasJNI::drawTextOnPathChars}, {"nDrawTextOnPath","(JLjava/lang/String;JFFIJ)V", (void*) CanvasJNI::drawTextOnPathString}, diff --git a/core/jni/android_text_MeasuredParagraph.cpp b/core/jni/android_text_MeasuredParagraph.cpp index d33337dabae0..9d794175de18 100644 --- a/core/jni/android_text_MeasuredParagraph.cpp +++ b/core/jni/android_text_MeasuredParagraph.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "MeasuredParagraph" +#include "GraphicsJNI.h" #include "ScopedIcuLocale.h" #include "unicode/locid.h" #include "unicode/brkiter.h" @@ -109,6 +110,33 @@ static jfloat nGetWidth(jlong ptr, jint start, jint end) { return r; } +// Regular JNI +static void nGetBounds(JNIEnv* env, jobject, jlong ptr, jcharArray javaText, jlong paintPtr, + jint start, jint end, jint bidiFlags, jobject bounds) { + ScopedCharArrayRO text(env, javaText); + const minikin::U16StringPiece textBuffer(text.get(), text.size()); + + minikin::MeasuredText* mt = toMeasuredParagraph(ptr); + Paint* paint = toPaint(paintPtr); + const Typeface* typeface = Typeface::resolveDefault(paint->getAndroidTypeface()); + minikin::Layout layout = MinikinUtils::doLayout(paint, + static_cast<minikin::Bidi>(bidiFlags), typeface, textBuffer.data(), start, end - start, + textBuffer.size(), mt); + + minikin::MinikinRect rect; + layout.getBounds(&rect); + + SkRect r; + r.fLeft = rect.mLeft; + r.fTop = rect.mTop; + r.fRight = rect.mRight; + r.fBottom = rect.mBottom; + + SkIRect ir; + r.roundOut(&ir); + GraphicsJNI::irect_to_jrect(ir, env, bounds); +} + // CriticalNative static jlong nGetReleaseFunc() { return toJLong(&releaseMeasuredParagraph); @@ -128,6 +156,7 @@ static const JNINativeMethod gMethods[] = { // MeasuredParagraph native functions. {"nGetWidth", "(JII)F", (void*) nGetWidth}, // Critical Natives + {"nGetBounds", "(J[CJIIILandroid/graphics/Rect;)V", (void*) nGetBounds}, // Regular JNI {"nGetReleaseFunc", "()J", (void*) nGetReleaseFunc}, // Critical Natives {"nGetMemoryUsage", "(J)I", (void*) nGetMemoryUsage}, // Critical Native }; diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 8ca506254f74..a30b2ade0e57 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -36,8 +36,9 @@ #include <stdio.h> #include <system/graphics.h> #include <ui/DisplayInfo.h> -#include <ui/HdrCapabilities.h> #include <ui/FrameStats.h> +#include <ui/GraphicsTypes.h> +#include <ui/HdrCapabilities.h> #include <ui/Rect.h> #include <ui/Region.h> #include <utils/Log.h> @@ -290,7 +291,7 @@ static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandl } sp<GraphicBuffer> buffer; - status_t res = ScreenshotClient::captureLayers(layerHandle, sourceCrop, frameScale, &buffer); + status_t res = ScreenshotClient::captureChildLayers(layerHandle, sourceCrop, frameScale, &buffer); if (res != NO_ERROR) { return NULL; } @@ -593,7 +594,7 @@ static jboolean nativeSetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenOb static jintArray nativeGetDisplayColorModes(JNIEnv* env, jclass, jobject tokenObj) { sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); if (token == NULL) return NULL; - Vector<android_color_mode_t> colorModes; + Vector<ColorMode> colorModes; if (SurfaceComposerClient::getDisplayColorModes(token, &colorModes) != NO_ERROR || colorModes.isEmpty()) { return NULL; @@ -623,7 +624,7 @@ static jboolean nativeSetActiveColorMode(JNIEnv* env, jclass, sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); if (token == NULL) return JNI_FALSE; status_t err = SurfaceComposerClient::setActiveColorMode(token, - static_cast<android_color_mode_t>(colorMode)); + static_cast<ColorMode>(colorMode)); return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; } diff --git a/core/jni/com_android_internal_os_FuseAppLoop.cpp b/core/jni/com_android_internal_os_FuseAppLoop.cpp index 8837df5b2da7..fdc088eee6b3 100644 --- a/core/jni/com_android_internal_os_FuseAppLoop.cpp +++ b/core/jni/com_android_internal_os_FuseAppLoop.cpp @@ -166,8 +166,8 @@ void com_android_internal_os_FuseAppLoop_replyWrite( void com_android_internal_os_FuseAppLoop_replyRead( JNIEnv* env, jobject self, jlong ptr, jlong unique, jint size, jbyteArray data) { ScopedByteArrayRO array(env, data); - CHECK(size >= 0); - CHECK(static_cast<size_t>(size) < array.size()); + CHECK_GE(size, 0); + CHECK_LE(static_cast<size_t>(size), array.size()); if (!reinterpret_cast<fuse::FuseAppLoop*>(ptr)->ReplyRead(unique, size, array.get())) { reinterpret_cast<fuse::FuseAppLoop*>(ptr)->Break(); } diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index d05be2ca787b..7c8a52d1432b 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -71,6 +71,9 @@ using android::String8; using android::base::StringPrintf; using android::base::WriteStringToFile; +#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \ + append(StringPrintf(__VA_ARGS__)) + static pid_t gSystemServerPid = 0; static const char kZygoteClassName[] = "com/android/internal/os/Zygote"; @@ -186,30 +189,32 @@ static void UnsetChldSignalHandler() { // Calls POSIX setgroups() using the int[] object as an argument. // A NULL argument is tolerated. -static void SetGids(JNIEnv* env, jintArray javaGids) { +static bool SetGids(JNIEnv* env, jintArray javaGids, std::string* error_msg) { if (javaGids == NULL) { - return; + return true; } ScopedIntArrayRO gids(env, javaGids); if (gids.get() == NULL) { - RuntimeAbort(env, __LINE__, "Getting gids int array failed"); + *error_msg = CREATE_ERROR("Getting gids int array failed"); + return false; } int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0])); if (rc == -1) { - std::ostringstream oss; - oss << "setgroups failed: " << strerror(errno) << ", gids.size=" << gids.size(); - RuntimeAbort(env, __LINE__, oss.str().c_str()); + *error_msg = CREATE_ERROR("setgroups failed: %s, gids.size=%zu", strerror(errno), gids.size()); + return false; } + + return true; } // Sets the resource limits via setrlimit(2) for the values in the // two-dimensional array of integers that's passed in. The second dimension // contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is // treated as an empty array. -static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) { +static bool SetRLimits(JNIEnv* env, jobjectArray javaRlimits, std::string* error_msg) { if (javaRlimits == NULL) { - return; + return true; } rlimit rlim; @@ -219,7 +224,8 @@ static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) { ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i)); ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get())); if (javaRlimit.size() != 3) { - RuntimeAbort(env, __LINE__, "rlimits array must have a second dimension of size 3"); + *error_msg = CREATE_ERROR("rlimits array must have a second dimension of size 3"); + return false; } rlim.rlim_cur = javaRlimit[1]; @@ -227,11 +233,13 @@ static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) { int rc = setrlimit(javaRlimit[0], &rlim); if (rc == -1) { - ALOGE("setrlimit(%d, {%ld, %ld}) failed", javaRlimit[0], rlim.rlim_cur, + *error_msg = CREATE_ERROR("setrlimit(%d, {%ld, %ld}) failed", javaRlimit[0], rlim.rlim_cur, rlim.rlim_max); - RuntimeAbort(env, __LINE__, "setrlimit failed"); + return false; } } + + return true; } // The debug malloc library needs to know whether it's the zygote or a child. @@ -259,14 +267,16 @@ static void SetUpSeccompFilter(uid_t uid) { } } -static void EnableKeepCapabilities(JNIEnv* env) { +static bool EnableKeepCapabilities(std::string* error_msg) { int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); if (rc == -1) { - RuntimeAbort(env, __LINE__, "prctl(PR_SET_KEEPCAPS) failed"); + *error_msg = CREATE_ERROR("prctl(PR_SET_KEEPCAPS) failed: %s", strerror(errno)); + return false; } + return true; } -static void DropCapabilitiesBoundingSet(JNIEnv* env) { +static bool DropCapabilitiesBoundingSet(std::string* error_msg) { for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) { int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); if (rc == -1) { @@ -274,14 +284,15 @@ static void DropCapabilitiesBoundingSet(JNIEnv* env) { ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify " "your kernel is compiled with file capabilities support"); } else { - ALOGE("prctl(PR_CAPBSET_DROP, %d) failed: %s", i, strerror(errno)); - RuntimeAbort(env, __LINE__, "prctl(PR_CAPBSET_DROP) failed"); + *error_msg = CREATE_ERROR("prctl(PR_CAPBSET_DROP, %d) failed: %s", i, strerror(errno)); + return false; } } } + return true; } -static void SetInheritable(JNIEnv* env, uint64_t inheritable) { +static bool SetInheritable(uint64_t inheritable, std::string* error_msg) { __user_cap_header_struct capheader; memset(&capheader, 0, sizeof(capheader)); capheader.version = _LINUX_CAPABILITY_VERSION_3; @@ -289,21 +300,23 @@ static void SetInheritable(JNIEnv* env, uint64_t inheritable) { __user_cap_data_struct capdata[2]; if (capget(&capheader, &capdata[0]) == -1) { - ALOGE("capget failed: %s", strerror(errno)); - RuntimeAbort(env, __LINE__, "capget failed"); + *error_msg = CREATE_ERROR("capget failed: %s", strerror(errno)); + return false; } capdata[0].inheritable = inheritable; capdata[1].inheritable = inheritable >> 32; if (capset(&capheader, &capdata[0]) == -1) { - ALOGE("capset(inh=%" PRIx64 ") failed: %s", inheritable, strerror(errno)); - RuntimeAbort(env, __LINE__, "capset failed"); + *error_msg = CREATE_ERROR("capset(inh=%" PRIx64 ") failed: %s", inheritable, strerror(errno)); + return false; } + + return true; } -static void SetCapabilities(JNIEnv* env, uint64_t permitted, uint64_t effective, - uint64_t inheritable) { +static bool SetCapabilities(uint64_t permitted, uint64_t effective, uint64_t inheritable, + std::string* error_msg) { __user_cap_header_struct capheader; memset(&capheader, 0, sizeof(capheader)); capheader.version = _LINUX_CAPABILITY_VERSION_3; @@ -319,18 +332,20 @@ static void SetCapabilities(JNIEnv* env, uint64_t permitted, uint64_t effective, capdata[1].inheritable = inheritable >> 32; if (capset(&capheader, &capdata[0]) == -1) { - ALOGE("capset(perm=%" PRIx64 ", eff=%" PRIx64 ", inh=%" PRIx64 ") failed: %s", permitted, - effective, inheritable, strerror(errno)); - RuntimeAbort(env, __LINE__, "capset failed"); + *error_msg = CREATE_ERROR("capset(perm=%" PRIx64 ", eff=%" PRIx64 ", inh=%" PRIx64 ") " + "failed: %s", permitted, effective, inheritable, strerror(errno)); + return false; } + return true; } -static void SetSchedulerPolicy(JNIEnv* env) { +static bool SetSchedulerPolicy(std::string* error_msg) { errno = -set_sched_policy(0, SP_DEFAULT); if (errno != 0) { - ALOGE("set_sched_policy(0, SP_DEFAULT) failed"); - RuntimeAbort(env, __LINE__, "set_sched_policy(0, SP_DEFAULT) failed"); + *error_msg = CREATE_ERROR("set_sched_policy(0, SP_DEFAULT) failed: %s", strerror(errno)); + return false; } + return true; } static int UnmountTree(const char* path) { @@ -364,7 +379,7 @@ static int UnmountTree(const char* path) { // Create a private mount namespace and bind mount appropriate emulated // storage for the given user. static bool MountEmulatedStorage(uid_t uid, jint mount_mode, - bool force_mount_namespace) { + bool force_mount_namespace, std::string* error_msg) { // See storage config details at http://source.android.com/tech/storage/ String8 storageSource; @@ -381,7 +396,7 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode, // Create a second private mount namespace for our process if (unshare(CLONE_NEWNS) == -1) { - ALOGW("Failed to unshare(): %s", strerror(errno)); + *error_msg = CREATE_ERROR("Failed to unshare(): %s", strerror(errno)); return false; } @@ -392,7 +407,9 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode, if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage", NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) { - ALOGW("Failed to mount %s to /storage: %s", storageSource.string(), strerror(errno)); + *error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s", + storageSource.string(), + strerror(errno)); return false; } @@ -400,11 +417,14 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode, userid_t user_id = multiuser_get_user_id(uid); const String8 userSource(String8::format("/mnt/user/%d", user_id)); if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) { + *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", userSource.string()); return false; } if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self", NULL, MS_BIND, NULL)) == -1) { - ALOGW("Failed to mount %s to /storage/self: %s", userSource.string(), strerror(errno)); + *error_msg = CREATE_ERROR("Failed to mount %s to /storage/self: %s", + userSource.string(), + strerror(errno)); return false; } @@ -436,31 +456,32 @@ static bool NeedsNoRandomizeWorkaround() { // descriptor (if any) is closed via dup2(), replacing it with a valid // (open) descriptor to /dev/null. -static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) { +static bool DetachDescriptors(JNIEnv* env, jintArray fdsToClose, std::string* error_msg) { if (!fdsToClose) { - return; + return true; } jsize count = env->GetArrayLength(fdsToClose); ScopedIntArrayRO ar(env, fdsToClose); if (ar.get() == NULL) { - RuntimeAbort(env, __LINE__, "Bad fd array"); + *error_msg = "Bad fd array"; + return false; } jsize i; int devnull; for (i = 0; i < count; i++) { devnull = open("/dev/null", O_RDWR); if (devnull < 0) { - ALOGE("Failed to open /dev/null: %s", strerror(errno)); - RuntimeAbort(env, __LINE__, "Failed to open /dev/null"); - continue; + *error_msg = std::string("Failed to open /dev/null: ").append(strerror(errno)); + return false; } ALOGV("Switching descriptor %d to /dev/null: %s", ar[i], strerror(errno)); if (dup2(devnull, ar[i]) < 0) { - ALOGE("Failed dup2() on descriptor %d: %s", ar[i], strerror(errno)); - RuntimeAbort(env, __LINE__, "Failed dup2()"); + *error_msg = StringPrintf("Failed dup2() on descriptor %d: %s", ar[i], strerror(errno)); + return false; } close(devnull); } + return true; } void SetThreadName(const char* thread_name) { @@ -495,20 +516,23 @@ void SetThreadName(const char* thread_name) { // The list of open zygote file descriptors. static FileDescriptorTable* gOpenFdTable = NULL; -static void FillFileDescriptorVector(JNIEnv* env, +static bool FillFileDescriptorVector(JNIEnv* env, jintArray java_fds, - std::vector<int>* fds) { + std::vector<int>* fds, + std::string* error_msg) { CHECK(fds != nullptr); if (java_fds != nullptr) { ScopedIntArrayRO ar(env, java_fds); if (ar.get() == nullptr) { - RuntimeAbort(env, __LINE__, "Bad fd array"); + *error_msg = "Bad fd array"; + return false; } fds->reserve(ar.size()); for (size_t i = 0; i < ar.size(); ++i) { fds->push_back(ar[i]); } } + return true; } // Utility routine to fork zygote and specialize the child process. @@ -526,32 +550,53 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra sigemptyset(&sigchld); sigaddset(&sigchld, SIGCHLD); + auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg) + __attribute__ ((noreturn)) { + const char* se_name_c_str = nullptr; + std::unique_ptr<ScopedUtfChars> se_name; + if (java_se_name != nullptr) { + se_name.reset(new ScopedUtfChars(env, java_se_name)); + se_name_c_str = se_name->c_str(); + } + if (se_name_c_str == nullptr && is_system_server) { + se_name_c_str = "system_server"; + } + const std::string& error_msg = (se_name_c_str == nullptr) + ? msg + : StringPrintf("(%s) %s", se_name_c_str, msg.c_str()); + env->FatalError(error_msg.c_str()); + __builtin_unreachable(); + }; + // Temporarily block SIGCHLD during forks. The SIGCHLD handler might // log, which would result in the logging FDs we close being reopened. // This would cause failures because the FDs are not whitelisted. // // Note that the zygote process is single threaded at this point. if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) { - ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)); - RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_BLOCK, { SIGCHLD }) failed."); + fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } // Close any logging related FDs before we start evaluating the list of // file descriptors. __android_log_close(); + std::string error_msg; + // If this is the first fork for this zygote, create the open FD table. // If it isn't, we just need to check whether the list of open files has // changed (and it shouldn't in the normal case). std::vector<int> fds_to_ignore; - FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore); + if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) { + fail_fn(error_msg); + } if (gOpenFdTable == NULL) { - gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore); + gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg); if (gOpenFdTable == NULL) { - RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table."); + fail_fn(error_msg); } - } else if (!gOpenFdTable->Restat(fds_to_ignore)) { - RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table."); + } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) { + fail_fn(error_msg); } pid_t pid = fork(); @@ -560,17 +605,18 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra PreApplicationInit(); // Clean up any descriptors which must be closed immediately - DetachDescriptors(env, fdsToClose); + if (!DetachDescriptors(env, fdsToClose, &error_msg)) { + fail_fn(error_msg); + } // Re-open all remaining open file descriptors so that they aren't shared // with the zygote across a fork. - if (!gOpenFdTable->ReopenOrDetach()) { - RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors."); + if (!gOpenFdTable->ReopenOrDetach(&error_msg)) { + fail_fn(error_msg); } if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) { - ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)); - RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed."); + fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } // Must be called when the new process still has CAP_SYS_ADMIN. The other alternative is to @@ -580,11 +626,17 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { - EnableKeepCapabilities(env); + if (!EnableKeepCapabilities(&error_msg)) { + fail_fn(error_msg); + } } - SetInheritable(env, permittedCapabilities); - DropCapabilitiesBoundingSet(env); + if (!SetInheritable(permittedCapabilities, &error_msg)) { + fail_fn(error_msg); + } + if (!DropCapabilitiesBoundingSet(&error_msg)) { + fail_fn(error_msg); + } bool use_native_bridge = !is_system_server && (instructionSet != NULL) && android::NativeBridgeAvailable(); @@ -601,8 +653,8 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra ALOGW("Native bridge will not be used because dataDir == NULL."); } - if (!MountEmulatedStorage(uid, mount_external, use_native_bridge)) { - ALOGW("Failed to mount emulated storage: %s", strerror(errno)); + if (!MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg)) { + ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno)); if (errno == ENOTCONN || errno == EROFS) { // When device is actively encrypting, we get ENOTCONN here // since FUSE was mounted before the framework restarted. @@ -610,7 +662,7 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra // FUSE hasn't been created yet by init. // In either case, continue without external storage. } else { - RuntimeAbort(env, __LINE__, "Cannot continue without emulated storage"); + fail_fn(error_msg); } } @@ -625,9 +677,14 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra } } - SetGids(env, javaGids); + std::string error_msg; + if (!SetGids(env, javaGids, &error_msg)) { + fail_fn(error_msg); + } - SetRLimits(env, javaRlimits); + if (!SetRLimits(env, javaRlimits, &error_msg)) { + fail_fn(error_msg); + } if (use_native_bridge) { ScopedUtfChars isa_string(env, instructionSet); @@ -637,14 +694,12 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra int rc = setresgid(gid, gid, gid); if (rc == -1) { - ALOGE("setresgid(%d) failed: %s", gid, strerror(errno)); - RuntimeAbort(env, __LINE__, "setresgid failed"); + fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno))); } rc = setresuid(uid, uid, uid); if (rc == -1) { - ALOGE("setresuid(%d) failed: %s", uid, strerror(errno)); - RuntimeAbort(env, __LINE__, "setresuid failed"); + fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno))); } if (NeedsNoRandomizeWorkaround()) { @@ -656,9 +711,14 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra } } - SetCapabilities(env, permittedCapabilities, effectiveCapabilities, permittedCapabilities); + if (!SetCapabilities(permittedCapabilities, effectiveCapabilities, permittedCapabilities, + &error_msg)) { + fail_fn(error_msg); + } - SetSchedulerPolicy(env); + if (!SetSchedulerPolicy(&error_msg)) { + fail_fn(error_msg); + } const char* se_info_c_str = NULL; ScopedUtfChars* se_info = NULL; @@ -666,7 +726,7 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra se_info = new ScopedUtfChars(env, java_se_info); se_info_c_str = se_info->c_str(); if (se_info_c_str == NULL) { - RuntimeAbort(env, __LINE__, "se_info_c_str == NULL"); + fail_fn("se_info_c_str == NULL"); } } const char* se_name_c_str = NULL; @@ -675,14 +735,13 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra se_name = new ScopedUtfChars(env, java_se_name); se_name_c_str = se_name->c_str(); if (se_name_c_str == NULL) { - RuntimeAbort(env, __LINE__, "se_name_c_str == NULL"); + fail_fn("se_name_c_str == NULL"); } } rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str); if (rc == -1) { - ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid, - is_system_server, se_info_c_str, se_name_c_str); - RuntimeAbort(env, __LINE__, "selinux_android_setcontext failed"); + fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid, + is_system_server, se_info_c_str, se_name_c_str)); } // Make it easier to debug audit logs by setting the main thread's name to the @@ -703,15 +762,14 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, is_system_server, is_child_zygote, instructionSet); if (env->ExceptionCheck()) { - RuntimeAbort(env, __LINE__, "Error calling post fork hooks."); + fail_fn("Error calling post fork hooks."); } } else if (pid > 0) { // the parent process // We blocked SIGCHLD prior to a fork, we unblock it here. if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) { - ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)); - RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed."); + fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } } return pid; diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp index 2e6058268115..c5904e0e9e5e 100644 --- a/core/jni/fd_utils.cpp +++ b/core/jni/fd_utils.cpp @@ -123,14 +123,57 @@ FileDescriptorWhitelist::FileDescriptorWhitelist() FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr; +// Keeps track of all relevant information (flags, offset etc.) of an +// open zygote file descriptor. +class FileDescriptorInfo { + public: + // Create a FileDescriptorInfo for a given file descriptor. Returns + // |NULL| if an error occurred. + static FileDescriptorInfo* CreateFromFd(int fd, std::string* error_msg); + + // Checks whether the file descriptor associated with this object + // refers to the same description. + bool Restat() const; + + bool ReopenOrDetach(std::string* error_msg) const; + + const int fd; + const struct stat stat; + const std::string file_path; + const int open_flags; + const int fd_flags; + const int fs_flags; + const off_t offset; + const bool is_sock; + + private: + FileDescriptorInfo(int fd); + + FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags, + int fd_flags, int fs_flags, off_t offset); + + // Returns the locally-bound name of the socket |fd|. Returns true + // iff. all of the following hold : + // + // - the socket's sa_family is AF_UNIX. + // - the length of the path is greater than zero (i.e, not an unnamed socket). + // - the first byte of the path isn't zero (i.e, not a socket with an abstract + // address). + static bool GetSocketName(const int fd, std::string* result); + + bool DetachSocket(std::string* error_msg) const; + + DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo); +}; + // static -FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { +FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, std::string* error_msg) { struct stat f_stat; // This should never happen; the zygote should always have the right set // of permissions required to stat all its open files. if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { - PLOG(ERROR) << "Unable to stat fd " << fd; - return NULL; + *error_msg = android::base::StringPrintf("Unable to stat %d", fd); + return nullptr; } const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get(); @@ -138,13 +181,15 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { if (S_ISSOCK(f_stat.st_mode)) { std::string socket_name; if (!GetSocketName(fd, &socket_name)) { - return NULL; + *error_msg = "Unable to get socket name"; + return nullptr; } if (!whitelist->IsAllowed(socket_name)) { - LOG(ERROR) << "Socket name not whitelisted : " << socket_name - << " (fd=" << fd << ")"; - return NULL; + *error_msg = android::base::StringPrintf("Socket name not whitelisted : %s (fd=%d)", + socket_name.c_str(), + fd); + return nullptr; } return new FileDescriptorInfo(fd); @@ -161,19 +206,22 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { // with the child process across forks but those should have been closed // before we got to this point. if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) { - LOG(ERROR) << "Unsupported st_mode " << f_stat.st_mode; - return NULL; + *error_msg = android::base::StringPrintf("Unsupported st_mode %u", f_stat.st_mode); + return nullptr; } std::string file_path; const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd); if (!android::base::Readlink(fd_path, &file_path)) { - return NULL; + *error_msg = android::base::StringPrintf("Could not read fd link %s: %s", + fd_path.c_str(), + strerror(errno)); + return nullptr; } if (!whitelist->IsAllowed(file_path)) { - LOG(ERROR) << "Not whitelisted : " << file_path; - return NULL; + *error_msg = std::string("Not whitelisted : ").append(file_path); + return nullptr; } // File descriptor flags : currently on FD_CLOEXEC. We can set these @@ -181,8 +229,11 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { // there won't be any races. const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)); if (fd_flags == -1) { - PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFD)"; - return NULL; + *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_GETFD) (%s): %s", + fd, + file_path.c_str(), + strerror(errno)); + return nullptr; } // File status flags : @@ -199,8 +250,11 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) { // their presence and pass them in to open(). int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)); if (fs_flags == -1) { - PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFL)"; - return NULL; + *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_GETFL) (%s): %s", + fd, + file_path.c_str(), + strerror(errno)); + return nullptr; } // File offset : Ignore the offset for non seekable files. @@ -225,9 +279,9 @@ bool FileDescriptorInfo::Restat() const { return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev; } -bool FileDescriptorInfo::ReopenOrDetach() const { +bool FileDescriptorInfo::ReopenOrDetach(std::string* error_msg) const { if (is_sock) { - return DetachSocket(); + return DetachSocket(error_msg); } // NOTE: This might happen if the file was unlinked after being opened. @@ -236,31 +290,49 @@ bool FileDescriptorInfo::ReopenOrDetach() const { const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags)); if (new_fd == -1) { - PLOG(ERROR) << "Failed open(" << file_path << ", " << open_flags << ")"; + *error_msg = android::base::StringPrintf("Failed open(%s, %i): %s", + file_path.c_str(), + open_flags, + strerror(errno)); return false; } if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) { close(new_fd); - PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFD, " << fd_flags << ")"; + *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_SETFD, %d) (%s): %s", + new_fd, + fd_flags, + file_path.c_str(), + strerror(errno)); return false; } if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) { close(new_fd); - PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFL, " << fs_flags << ")"; + *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_SETFL, %d) (%s): %s", + new_fd, + fs_flags, + file_path.c_str(), + strerror(errno)); return false; } if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) { close(new_fd); - PLOG(ERROR) << "Failed lseek64(" << new_fd << ", SEEK_SET)"; + *error_msg = android::base::StringPrintf("Failed lseek64(%d, SEEK_SET) (%s): %s", + new_fd, + file_path.c_str(), + strerror(errno)); return false; } if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) { close(new_fd); - PLOG(ERROR) << "Failed dup2(" << fd << ", " << new_fd << ")"; + *error_msg = android::base::StringPrintf("Failed dup2(%d, %d) (%s): %s", + fd, + new_fd, + file_path.c_str(), + strerror(errno)); return false; } @@ -336,20 +408,22 @@ bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) { return true; } -bool FileDescriptorInfo::DetachSocket() const { +bool FileDescriptorInfo::DetachSocket(std::string* error_msg) const { const int dev_null_fd = open("/dev/null", O_RDWR); if (dev_null_fd < 0) { - PLOG(ERROR) << "Failed to open /dev/null"; + *error_msg = std::string("Failed to open /dev/null: ").append(strerror(errno)); return false; } if (dup2(dev_null_fd, fd) == -1) { - PLOG(ERROR) << "Failed dup2 on socket descriptor " << fd; + *error_msg = android::base::StringPrintf("Failed dup2 on socket descriptor %d: %s", + fd, + strerror(errno)); return false; } if (close(dev_null_fd) == -1) { - PLOG(ERROR) << "Failed close(" << dev_null_fd << ")"; + *error_msg = android::base::StringPrintf("Failed close(%d): %s", dev_null_fd, strerror(errno)); return false; } @@ -357,11 +431,12 @@ bool FileDescriptorInfo::DetachSocket() const { } // static -FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore) { +FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore, + std::string* error_msg) { DIR* d = opendir(kFdPath); - if (d == NULL) { - PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath); - return NULL; + if (d == nullptr) { + *error_msg = std::string("Unable to open directory ").append(kFdPath); + return nullptr; } int dir_fd = dirfd(d); dirent* e; @@ -377,7 +452,7 @@ FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ continue; } - FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd); + FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd, error_msg); if (info == NULL) { if (closedir(d) == -1) { PLOG(ERROR) << "Unable to close directory"; @@ -388,19 +463,21 @@ FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ } if (closedir(d) == -1) { - PLOG(ERROR) << "Unable to close directory"; - return NULL; + *error_msg = "Unable to close directory"; + return nullptr; } return new FileDescriptorTable(open_fd_map); } -bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) { +bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, std::string* error_msg) { std::set<int> open_fds; // First get the list of open descriptors. DIR* d = opendir(kFdPath); if (d == NULL) { - PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath); + *error_msg = android::base::StringPrintf("Unable to open directory %s: %s", + kFdPath, + strerror(errno)); return false; } @@ -420,21 +497,21 @@ bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) { } if (closedir(d) == -1) { - PLOG(ERROR) << "Unable to close directory"; + *error_msg = android::base::StringPrintf("Unable to close directory: %s", strerror(errno)); return false; } - return RestatInternal(open_fds); + return RestatInternal(open_fds, error_msg); } // Reopens all file descriptors that are contained in the table. Returns true // if all descriptors were successfully re-opened or detached, and false if an // error occurred. -bool FileDescriptorTable::ReopenOrDetach() { +bool FileDescriptorTable::ReopenOrDetach(std::string* error_msg) { std::unordered_map<int, FileDescriptorInfo*>::const_iterator it; for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) { const FileDescriptorInfo* info = it->second; - if (info == NULL || !info->ReopenOrDetach()) { + if (info == NULL || !info->ReopenOrDetach(error_msg)) { return false; } } @@ -447,7 +524,7 @@ FileDescriptorTable::FileDescriptorTable( : open_fd_map_(map) { } -bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds) { +bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds, std::string* error_msg) { bool error = false; // Iterate through the list of file descriptors we've already recorded @@ -455,6 +532,8 @@ bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds) { // // (a) they continue to be open. // (b) they refer to the same file. + // + // We'll only store the last error message. std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin(); while (it != open_fd_map_.end()) { std::set<int>::const_iterator element = open_fds.find(it->first); @@ -475,7 +554,7 @@ bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds) { // The file descriptor refers to a different description. We must // update our entry in the table. delete it->second; - it->second = FileDescriptorInfo::CreateFromFd(*element); + it->second = FileDescriptorInfo::CreateFromFd(*element, error_msg); if (it->second == NULL) { // The descriptor no longer no longer refers to a whitelisted file. // We flag an error and remove it from the list of files we're @@ -510,7 +589,7 @@ bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds) { std::set<int>::const_iterator it; for (it = open_fds.begin(); it != open_fds.end(); ++it) { const int fd = (*it); - FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd); + FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd, error_msg); if (info == NULL) { // A newly opened file is not on the whitelist. Flag an error and // continue. diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h index a39e387fde6c..a3570d7ed1fb 100644 --- a/core/jni/fd_utils.h +++ b/core/jni/fd_utils.h @@ -28,6 +28,8 @@ #include <android-base/macros.h> +class FileDescriptorInfo; + // Whitelist of open paths that the zygote is allowed to keep open. // // In addition to the paths listed in kPathWhitelist in file_utils.cpp, and @@ -66,49 +68,6 @@ class FileDescriptorWhitelist { DISALLOW_COPY_AND_ASSIGN(FileDescriptorWhitelist); }; -// Keeps track of all relevant information (flags, offset etc.) of an -// open zygote file descriptor. -class FileDescriptorInfo { - public: - // Create a FileDescriptorInfo for a given file descriptor. Returns - // |NULL| if an error occurred. - static FileDescriptorInfo* CreateFromFd(int fd); - - // Checks whether the file descriptor associated with this object - // refers to the same description. - bool Restat() const; - - bool ReopenOrDetach() const; - - const int fd; - const struct stat stat; - const std::string file_path; - const int open_flags; - const int fd_flags; - const int fs_flags; - const off_t offset; - const bool is_sock; - - private: - FileDescriptorInfo(int fd); - - FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags, - int fd_flags, int fs_flags, off_t offset); - - // Returns the locally-bound name of the socket |fd|. Returns true - // iff. all of the following hold : - // - // - the socket's sa_family is AF_UNIX. - // - the length of the path is greater than zero (i.e, not an unnamed socket). - // - the first byte of the path isn't zero (i.e, not a socket with an abstract - // address). - static bool GetSocketName(const int fd, std::string* result); - - bool DetachSocket() const; - - DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo); -}; - // A FileDescriptorTable is a collection of FileDescriptorInfo objects // keyed by their FDs. class FileDescriptorTable { @@ -116,19 +75,20 @@ class FileDescriptorTable { // Creates a new FileDescriptorTable. This function scans // /proc/self/fd for the list of open file descriptors and collects // information about them. Returns NULL if an error occurs. - static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore); + static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore, + std::string* error_msg); - bool Restat(const std::vector<int>& fds_to_ignore); + bool Restat(const std::vector<int>& fds_to_ignore, std::string* error_msg); // Reopens all file descriptors that are contained in the table. Returns true // if all descriptors were successfully re-opened or detached, and false if an // error occurred. - bool ReopenOrDetach(); + bool ReopenOrDetach(std::string* error_msg); private: FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map); - bool RestatInternal(std::set<int>& open_fds); + bool RestatInternal(std::set<int>& open_fds, std::string* error_msg); static int ParseFd(dirent* e, int dir_fd); diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto index 914a7db56f1d..a818e2095ca3 100644 --- a/core/proto/android/providers/settings.proto +++ b/core/proto/android/providers/settings.proto @@ -56,388 +56,456 @@ message GlobalSettingsProto { optional SettingProto enable_accessibility_global_gesture_enabled = 3 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto airplane_mode_on = 4 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto theater_mode_on = 5 [ (android.privacy).dest = DEST_AUTOMATIC ]; - reserved 6,7,8,9,10; // Accidentally used. They are currently free to be reused. // A comma-separated list of radios that need to be disabled when airplane // mode is on. This overrides wifi_on and bluetooth_on if wifi and bluetooth // are included in the comma-separated list. - optional SettingProto airplane_mode_radios = 11 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto airplane_mode_toggleable_radios = 12 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_class_of_device = 293 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_disabled_profiles = 13; - optional SettingProto bluetooth_interoperability_list = 14; - optional SettingProto wifi_sleep_policy = 15 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto auto_time = 16 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto auto_time_zone = 17 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto car_dock_sound = 18; - optional SettingProto car_undock_sound = 19; - optional SettingProto desk_dock_sound = 20; - optional SettingProto desk_undock_sound = 21; - optional SettingProto dock_sounds_enabled = 22 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dock_sounds_enabled_when_accessibility = 23 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto lock_sound = 24; - optional SettingProto unlock_sound = 25; - optional SettingProto trusted_sound = 26; - optional SettingProto low_battery_sound = 27; - optional SettingProto power_sounds_enabled = 28 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wireless_charging_started_sound = 29; - optional SettingProto charging_sounds_enabled = 30 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto stay_on_while_plugged_in = 31 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bugreport_in_power_menu = 32 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto adb_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto airplane_mode_radios = 6 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto airplane_mode_toggleable_radios = 7 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto bluetooth_class_of_device = 8 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto bluetooth_disabled_profiles = 9; + optional SettingProto bluetooth_interoperability_list = 10; + optional SettingProto wifi_sleep_policy = 11 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto auto_time = 12 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto auto_time_zone = 13 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto car_dock_sound = 14; + optional SettingProto car_undock_sound = 15; + optional SettingProto desk_dock_sound = 16; + optional SettingProto desk_undock_sound = 17; + optional SettingProto dock_sounds_enabled = 18 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dock_sounds_enabled_when_accessibility = 19 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lock_sound = 20; + optional SettingProto unlock_sound = 21; + optional SettingProto trusted_sound = 22; + optional SettingProto low_battery_sound = 23; + optional SettingProto power_sounds_enabled = 24 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wireless_charging_started_sound = 25; + optional SettingProto charging_sounds_enabled = 26 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto stay_on_while_plugged_in = 27 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto bugreport_in_power_menu = 28 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto adb_enabled = 29 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Whether views are allowed to save their attribute data. - optional SettingProto debug_view_attributes = 34 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto assisted_gps_enabled = 35 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_on = 36 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto cdma_cell_broadcast_sms = 37 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto cdma_roaming_mode = 38 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto cdma_subscription_mode = 39 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto data_activity_timeout_mobile = 40 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto data_activity_timeout_wifi = 41 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto data_roaming = 42 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto mdc_initial_max_retry = 43 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto force_allow_on_external = 44 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto euicc_provisioned = 294 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto development_force_resizable_activities = 45 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto development_enable_freeform_windows_support = 46 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto development_settings_enabled = 47 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto device_provisioned = 48 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto device_provisioning_mobile_data_enabled = 49 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto display_size_forced = 50 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto display_scaling_force = 51 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto download_max_bytes_over_mobile = 52 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto download_recommended_max_bytes_over_mobile = 53 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto hdmi_control_enabled = 54 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto hdmi_system_audio_control_enabled = 55 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto hdmi_control_auto_wakeup_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto hdmi_control_auto_device_off_enabled = 57 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto location_background_throttle_interval_ms = 295 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto location_background_throttle_proximity_alert_interval_ms = 296 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto debug_view_attributes = 30 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto assisted_gps_enabled = 31 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto bluetooth_on = 32 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto cdma_cell_broadcast_sms = 33 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto cdma_roaming_mode = 34 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto cdma_subscription_mode = 35 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto data_activity_timeout_mobile = 36 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto data_activity_timeout_wifi = 37 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto data_roaming = 38 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mdc_initial_max_retry = 39 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto force_allow_on_external = 40 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto euicc_provisioned = 41 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto development_force_resizable_activities = 42 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto development_enable_freeform_windows_support = 43 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto development_settings_enabled = 44 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto device_provisioned = 45 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto device_provisioning_mobile_data_enabled = 46 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto display_size_forced = 47 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto display_scaling_force = 48 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto download_max_bytes_over_mobile = 49 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto download_recommended_max_bytes_over_mobile = 50 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto hdmi_control_enabled = 51 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto hdmi_system_audio_control_enabled = 52 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto hdmi_control_auto_wakeup_enabled = 53 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto hdmi_control_auto_device_off_enabled = 54 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // If true, out-of-the-box execution for priv apps is enabled. + optional SettingProto priv_app_oob_enabled = 55 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto location_background_throttle_interval_ms = 56 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto location_background_throttle_proximity_alert_interval_ms = 57 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Packages that are whitelisted for background throttling (throttling will // not be applied). - optional SettingProto location_background_throttle_package_whitelist = 297 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_scan_background_throttle_interval_ms = 298 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_scan_background_throttle_package_whitelist = 299 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto mhl_input_switching_enabled = 58 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto mhl_power_charge_enabled = 59 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto mobile_data = 60 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto mobile_data_always_on = 61 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto connectivity_metrics_buffer_size = 62 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_enabled = 63 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_poll_interval = 64 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_time_cache_max_age = 65 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_global_alert_bytes = 66 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_sample_enabled = 67 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_augment_enabled = 300 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_dev_bucket_duration = 68 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_dev_persist_bytes = 69 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_dev_rotate_age = 70 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_dev_delete_age = 71 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_uid_bucket_duration = 72 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_uid_persist_bytes = 73 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_uid_rotate_age = 74 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_uid_delete_age = 75 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_uid_tag_bucket_duration = 76 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_uid_tag_persist_bytes = 77 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_uid_tag_rotate_age = 78 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto netstats_uid_tag_delete_age = 79 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto location_background_throttle_package_whitelist = 58 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_scan_background_throttle_interval_ms = 59 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_scan_background_throttle_package_whitelist = 60 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mhl_input_switching_enabled = 61 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mhl_power_charge_enabled = 62 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mobile_data = 63 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mobile_data_always_on = 64 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto connectivity_metrics_buffer_size = 65 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_enabled = 66 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_poll_interval = 67 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_time_cache_max_age = 68 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_global_alert_bytes = 69 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_sample_enabled = 70 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_augment_enabled = 71 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_dev_bucket_duration = 72 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_dev_persist_bytes = 73 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_dev_rotate_age = 74 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_dev_delete_age = 75 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_uid_bucket_duration = 76 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_uid_persist_bytes = 77 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_uid_rotate_age = 78 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_uid_delete_age = 79 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_uid_tag_bucket_duration = 80 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_uid_tag_persist_bytes = 81 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_uid_tag_rotate_age = 82 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto netstats_uid_tag_delete_age = 83 [ (android.privacy).dest = DEST_AUTOMATIC ]; // User preference for which network(s) should be used. - optional SettingProto network_preference = 80; - optional SettingProto network_scorer_app = 81 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto nitz_update_diff = 82 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto nitz_update_spacing = 83 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto ntp_server = 84; - optional SettingProto ntp_timeout = 85 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto storage_benchmark_interval = 86 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dns_resolver_sample_validity_seconds = 87 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dns_resolver_success_threshold_percent = 88 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dns_resolver_min_samples = 89 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dns_resolver_max_samples = 90 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_preference = 84; + optional SettingProto network_scorer_app = 85 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto night_display_forced_auto_mode_available = 86 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto nitz_update_diff = 87 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto nitz_update_spacing = 88 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ntp_server = 89; + optional SettingProto ntp_timeout = 90 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto storage_benchmark_interval = 91 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dns_resolver_sample_validity_seconds = 92 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dns_resolver_success_threshold_percent = 93 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dns_resolver_min_samples = 94 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dns_resolver_max_samples = 95 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Whether to disable the automatic scheduling of system updates. - optional SettingProto ota_disable_automatic_update = 91 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto package_verifier_enable = 92 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto package_verifier_timeout = 93 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto package_verifier_default_response = 94; - optional SettingProto package_verifier_setting_visible = 95 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto package_verifier_include_adb = 96 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto fstrim_mandatory_interval = 97 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto pdp_watchdog_poll_interval_ms = 98 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto pdp_watchdog_long_poll_interval_ms = 99 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto pdp_watchdog_error_poll_interval_ms = 100 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto pdp_watchdog_trigger_packet_count = 101 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto pdp_watchdog_error_poll_count = 102 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto pdp_watchdog_max_pdp_reset_fail_count = 103 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto setup_prepaid_data_service_url = 105; - optional SettingProto setup_prepaid_detection_target_url = 106; - optional SettingProto setup_prepaid_detection_redir_host = 107; - optional SettingProto sms_outgoing_check_interval_ms = 108 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sms_outgoing_check_max_count = 109 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ota_disable_automatic_update = 96 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto package_verifier_enable = 97 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto package_verifier_timeout = 98 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto package_verifier_default_response = 99; + optional SettingProto package_verifier_setting_visible = 100 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto package_verifier_include_adb = 101 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto fstrim_mandatory_interval = 102 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto pdp_watchdog_poll_interval_ms = 103 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto pdp_watchdog_long_poll_interval_ms = 104 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto pdp_watchdog_error_poll_interval_ms = 105 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto pdp_watchdog_trigger_packet_count = 106 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto pdp_watchdog_error_poll_count = 107 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto pdp_watchdog_max_pdp_reset_fail_count = 108 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto setup_prepaid_data_service_url = 109; + optional SettingProto setup_prepaid_detection_target_url = 110; + optional SettingProto setup_prepaid_detection_redir_host = 111; + optional SettingProto sms_outgoing_check_interval_ms = 112 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sms_outgoing_check_max_count = 113 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Used to disable SMS short code confirmation. Defaults to true. - optional SettingProto sms_short_code_confirmation = 110 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sms_short_code_rule = 111 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tcp_default_init_rwnd = 112 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tether_supported = 113 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tether_dun_required = 114 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tether_dun_apn = 115; - optional SettingProto tether_offload_disabled = 301 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sms_short_code_confirmation = 114 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sms_short_code_rule = 115 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tcp_default_init_rwnd = 116 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tether_supported = 117 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tether_dun_required = 118 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tether_dun_apn = 119; + optional SettingProto tether_offload_disabled = 120 [ (android.privacy).dest = DEST_AUTOMATIC ]; // List of carrier app certificate mapped to carrier app package id which are whitelisted to // prompt the user for install when a SIM card with matching UICC carrier privilege rules is // inserted. - optional SettingProto carrier_app_whitelist = 116 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto carrier_app_names = 358 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto usb_mass_storage_enabled = 117 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto use_google_mail = 118 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto webview_data_reduction_proxy_key = 119; - optional SettingProto webview_fallback_logic_enabled = 120 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto carrier_app_whitelist = 121 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto carrier_app_names = 122 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto usb_mass_storage_enabled = 123 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto use_google_mail = 124 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto webview_data_reduction_proxy_key = 125; + optional SettingProto webview_fallback_logic_enabled = 126 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Name of the package used as WebView provider. - optional SettingProto webview_provider = 121 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto webview_multiprocess = 122 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto network_switch_notification_daily_limit = 123 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto network_switch_notification_rate_limit_millis = 124 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto network_avoid_bad_wifi = 125 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto network_metered_multipath_preference = 302 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto network_watchlist_last_report_time = 303 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_badging_thresholds = 304 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_display_on = 126 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_display_certification_on = 127 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_display_wps_config = 128 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_networks_available_notification_on = 129 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wimax_networks_available_notification_on = 130 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_networks_available_repeat_delay = 131 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_country_code = 132; - optional SettingProto wifi_framework_scan_interval_ms = 133 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_idle_ms = 134 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_num_open_networks_kept = 135 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_on = 136 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_scan_always_available = 137 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_wakeup_enabled = 138 [ (android.privacy).dest = DEST_AUTOMATIC ]; - reserved 305; // Removed wifi_wakeup_available - optional SettingProto network_scoring_ui_enabled = 306 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto speed_label_cache_eviction_age_millis = 307 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto recommended_network_evaluator_cache_expiry_ms = 308 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto network_recommendations_enabled = 139 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto network_recommendations_package = 286 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto use_open_wifi_package = 309 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto network_recommendation_request_timeout_ms = 310 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto ble_scan_always_available = 140 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_saved_state = 141 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_supplicant_scan_interval_ms = 142 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_enhanced_auto_join = 143 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_network_show_rssi = 144 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_scan_interval_when_p2p_connected_ms = 145 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_watchdog_on = 146 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_watchdog_poor_network_test_enabled = 147 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_suspend_optimizations_enabled = 148 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_verbose_logging_enabled = 149 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_connected_mac_randomization_enabled = 350 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_max_dhcp_retry_count = 150 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_mobile_data_transition_wakelock_timeout_ms = 151 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_device_owner_configs_lockdown = 152 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_frequency_band = 153 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_p2p_device_name = 154; - optional SettingProto wifi_reenable_delay_ms = 155 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_ephemeral_out_of_range_timeout_ms = 156 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto data_stall_alarm_non_aggressive_delay_in_ms = 157 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto data_stall_alarm_aggressive_delay_in_ms = 158 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto provisioning_apn_alarm_delay_in_ms = 159 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto gprs_register_check_period_ms = 160 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wtf_is_fatal = 161 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto webview_provider = 127 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto webview_multiprocess = 128 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_switch_notification_daily_limit = 129 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_switch_notification_rate_limit_millis = 130 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_avoid_bad_wifi = 131 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_metered_multipath_preference = 132 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_watchlist_last_report_time = 133 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_badging_thresholds = 134 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_display_on = 135 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_display_certification_on = 136 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_display_wps_config = 137 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_networks_available_notification_on = 138 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_carrier_networks_available_notification_on = 139 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wimax_networks_available_notification_on = 140 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_networks_available_repeat_delay = 141 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_country_code = 142; + optional SettingProto wifi_framework_scan_interval_ms = 143 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_idle_ms = 144 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_num_open_networks_kept = 145 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_on = 146 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_scan_always_available = 147 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto soft_ap_timeout_enabled = 148 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_wakeup_enabled = 149 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_scoring_ui_enabled = 150 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto speed_label_cache_eviction_age_millis = 151 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto recommended_network_evaluator_cache_expiry_ms = 152 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_recommendations_enabled = 153 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_recommendations_package = 154 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto use_open_wifi_package = 155 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_recommendation_request_timeout_ms = 156 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ble_scan_always_available = 157 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ble_scan_low_power_window_ms = 158 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ble_scan_balanced_window_ms = 159 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ble_scan_low_latency_window_ms = 160 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ble_scan_low_power_interval_ms = 161 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ble_scan_balanced_interval_ms = 162 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ble_scan_low_latency_interval_ms = 163 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_saved_state = 164 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_supplicant_scan_interval_ms = 165 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_enhanced_auto_join = 166 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_network_show_rssi = 167 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_scan_interval_when_p2p_connected_ms = 168 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_watchdog_on = 169 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_watchdog_poor_network_test_enabled = 170 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_suspend_optimizations_enabled = 171 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_verbose_logging_enabled = 172 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_connected_mac_randomization_enabled = 173 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_max_dhcp_retry_count = 174 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_mobile_data_transition_wakelock_timeout_ms = 175 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_device_owner_configs_lockdown = 176 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_frequency_band = 177 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_p2p_device_name = 178; + optional SettingProto wifi_reenable_delay_ms = 179 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_ephemeral_out_of_range_timeout_ms = 180 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto data_stall_alarm_non_aggressive_delay_in_ms = 181 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto data_stall_alarm_aggressive_delay_in_ms = 182 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto provisioning_apn_alarm_delay_in_ms = 183 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto gprs_register_check_period_ms = 184 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wtf_is_fatal = 185 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Ringer mode. A change in this value will not reflect as a change in the // ringer mode. - optional SettingProto mode_ringer = 162 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mode_ringer = 186 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Overlay display devices setting. // The value is a specially formatted string that describes the size and // density of simulated secondary devices. // Format: {width}x{height}/dpi;... - optional SettingProto overlay_display_devices = 163 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto battery_discharge_duration_threshold = 164 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto battery_discharge_threshold = 165 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto send_action_app_error = 166 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dropbox_age_seconds = 167 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dropbox_max_files = 168 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dropbox_quota_kb = 169 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dropbox_quota_percent = 170 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dropbox_reserve_percent = 171 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dropbox_tag_prefix = 172 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto error_logcat_prefix = 173 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sys_free_storage_log_interval = 174 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto disk_free_change_reporting_threshold = 175 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sys_storage_threshold_percentage = 176 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sys_storage_threshold_max_bytes = 177 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sys_storage_full_threshold_bytes = 178 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sys_storage_cache_percentage = 311 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sys_storage_cache_max_bytes = 312 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sync_max_retry_delay_in_seconds = 179 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto connectivity_change_delay = 180 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto connectivity_sampling_interval_in_seconds = 181 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto pac_change_delay = 182 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto captive_portal_mode = 183 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto captive_portal_detection_enabled = 313 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto captive_portal_server = 184; - optional SettingProto captive_portal_https_url = 185; - optional SettingProto captive_portal_http_url = 186; - optional SettingProto captive_portal_fallback_url = 187; - optional SettingProto captive_portal_other_fallback_urls = 314; - optional SettingProto captive_portal_use_https = 188 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto captive_portal_user_agent = 189; - optional SettingProto nsd_on = 190 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto overlay_display_devices = 187 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto battery_discharge_duration_threshold = 188 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto battery_discharge_threshold = 189 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto send_action_app_error = 190 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dropbox_age_seconds = 191 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dropbox_max_files = 192 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dropbox_quota_kb = 193 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dropbox_quota_percent = 194 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dropbox_reserve_percent = 195 [ (android.privacy).dest = DEST_AUTOMATIC ]; + repeated SettingProto dropbox_settings = 196; + repeated SettingProto error_logcat_lines = 197; + optional SettingProto sys_free_storage_log_interval = 198 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto disk_free_change_reporting_threshold = 199 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sys_storage_threshold_percentage = 200 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sys_storage_threshold_max_bytes = 201 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sys_storage_full_threshold_bytes = 202 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sys_storage_cache_percentage = 203 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sys_storage_cache_max_bytes = 204 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sync_max_retry_delay_in_seconds = 205 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto connectivity_change_delay = 206 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto connectivity_sampling_interval_in_seconds = 207 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto pac_change_delay = 208 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto captive_portal_mode = 209 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto captive_portal_detection_enabled = 210 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto captive_portal_server = 211; + optional SettingProto captive_portal_https_url = 212; + optional SettingProto captive_portal_http_url = 213; + optional SettingProto captive_portal_fallback_url = 214; + optional SettingProto captive_portal_other_fallback_urls = 215; + optional SettingProto captive_portal_use_https = 216 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto captive_portal_user_agent = 217; + optional SettingProto nsd_on = 218 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Let user pick default install location. - optional SettingProto set_install_location = 191 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto default_install_location = 192 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto inet_condition_debounce_up_delay = 193 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto inet_condition_debounce_down_delay = 194 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto read_external_storage_enforced_default = 195 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto http_proxy = 196; - optional SettingProto global_http_proxy_host = 197; - optional SettingProto global_http_proxy_port = 198; - optional SettingProto global_http_proxy_exclusion_list = 199; - optional SettingProto global_http_proxy_pac = 200; + optional SettingProto set_install_location = 219 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto default_install_location = 220 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto inet_condition_debounce_up_delay = 221 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto inet_condition_debounce_down_delay = 222 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto read_external_storage_enforced_default = 223 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto http_proxy = 224; + optional SettingProto global_http_proxy_host = 225; + optional SettingProto global_http_proxy_port = 226; + optional SettingProto global_http_proxy_exclusion_list = 227; + optional SettingProto global_http_proxy_pac = 228; // Enables the UI setting to allow the user to specify the global HTTP proxy // and associated exclusion list. - optional SettingProto set_global_http_proxy = 201 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto default_dns_server = 202; + optional SettingProto set_global_http_proxy = 229 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto default_dns_server = 230; // The requested Private DNS mode and an accompanying specifier. - optional SettingProto private_dns_mode = 315; - optional SettingProto private_dns_specifier = 316; - optional SettingProto bluetooth_headset_priority_prefix = 203 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_a2dp_sink_priority_prefix = 204 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_a2dp_src_priority_prefix = 205 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_a2dp_supports_optional_codecs_prefix = 287 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_a2dp_optional_codecs_enabled_prefix = 288 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_input_device_priority_prefix = 206 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_map_priority_prefix = 207 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_map_client_priority_prefix = 208 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_pbap_client_priority_prefix = 209 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_sap_priority_prefix = 210 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_pan_priority_prefix = 211 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_hearing_aid_priority_prefix = 345 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto activity_manager_constants = 317; - optional SettingProto device_idle_constants = 212; - optional SettingProto device_idle_constants_watch = 213; - optional SettingProto battery_saver_constants = 318; - optional SettingProto anomaly_detection_constants = 319; - optional SettingProto always_on_display_constants = 320; - optional SettingProto app_idle_constants = 214; - optional SettingProto power_manager_constants = 321; - optional SettingProto alarm_manager_constants = 215; - optional SettingProto job_scheduler_constants = 216; - optional SettingProto shortcut_manager_constants = 217; - optional SettingProto device_policy_constants = 322; - optional SettingProto text_classifier_constants = 323; - optional SettingProto window_animation_scale = 218 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto transition_animation_scale = 219 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto animator_duration_scale = 220 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto fancy_ime_animations = 221 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto compatibility_mode = 222 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto emergency_tone = 223 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto call_auto_retry = 224 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto emergency_affordance_needed = 225 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto preferred_network_mode = 226 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto private_dns_mode = 231; + optional SettingProto private_dns_specifier = 232; + repeated SettingProto bluetooth_headset_priorities = 233; + repeated SettingProto bluetooth_a2dp_sink_priorities = 234; + repeated SettingProto bluetooth_a2dp_src_priorities = 235; + repeated SettingProto bluetooth_a2dp_supports_optional_codecs = 236; + repeated SettingProto bluetooth_a2dp_optional_codecs_enabled = 237; + repeated SettingProto bluetooth_input_device_priorities = 238; + repeated SettingProto bluetooth_map_priorities = 239; + repeated SettingProto bluetooth_map_client_priorities = 240; + repeated SettingProto bluetooth_pbap_client_priorities = 241; + repeated SettingProto bluetooth_sap_priorities = 242; + repeated SettingProto bluetooth_pan_priorities = 243; + repeated SettingProto bluetooth_hearing_aid_priorities = 244; + // These are key=value lists, separated by commas. + optional SettingProto activity_manager_constants = 245; + optional SettingProto device_idle_constants = 246; + optional SettingProto battery_saver_constants = 247; + optional SettingProto battery_saver_device_specific_constants = 248; + optional SettingProto battery_tip_constants = 249; + optional SettingProto anomaly_detection_constants = 250; + // Version of the anomaly config. + optional SettingProto anomaly_config_version = 251 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // A base64-encoded string represents anomaly stats config. + optional SettingProto anomaly_config = 252; + // This is a key=value list, separated by commas. + optional SettingProto always_on_display_constants = 253; + // System VDSO global setting. This links to the "sys.vdso" system property. + // The following values are supported: + // false -> both 32 and 64 bit vdso disabled + // 32 -> 32 bit vdso enabled + // 64 -> 64 bit vdso enabled + // Any other value defaults to both 32 bit and 64 bit true. + optional SettingProto sys_vdso = 254 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // UidCpuPower global setting. This links the sys.uidcpupower system property. + // The following values are supported: + // 0 -> /proc/uid_cpupower/* are disabled + // 1 -> /proc/uid_cpupower/* are enabled + // Any other value defaults to enabled. + optional SettingProto sys_uidcpupower = 255 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // An integer to reduce the FPS by this factor. Only for experiments. + optional SettingProto fps_divisor = 256 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Flag to enable or disable display panel low power mode (lpm) + // false -> Display panel power saving mode is disabled. + // true -> Display panel power saving mode is enabled. + optional SettingProto display_panel_lpm = 257 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // These are key=value lists, separated by commas. + optional SettingProto app_idle_constants = 258; + optional SettingProto power_manager_constants = 259; + optional SettingProto alarm_manager_constants = 260; + optional SettingProto job_scheduler_constants = 261; + optional SettingProto shortcut_manager_constants = 262; + optional SettingProto device_policy_constants = 263; + optional SettingProto text_classifier_constants = 264; + optional SettingProto battery_stats_constants = 265; + optional SettingProto sync_manager_constants = 266; + optional SettingProto app_standby_enabled = 267 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto app_auto_restriction_enabled = 268 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto forced_app_standby_enabled = 269 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto forced_app_standby_for_small_battery_enabled = 270 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto off_body_radios_off_for_small_battery_enabled = 271 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto off_body_radios_off_delay_ms = 272 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_on_when_proxy_disconnected = 273 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto time_only_mode_enabled = 274 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_watchlist_enabled = 275 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto keep_profile_in_background = 276 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto window_animation_scale = 277 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto transition_animation_scale = 278 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto animator_duration_scale = 279 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto fancy_ime_animations = 280 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto compatibility_mode = 281 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto emergency_tone = 282 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto call_auto_retry = 283 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto emergency_affordance_needed = 284 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto preferred_network_mode = 285 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Name of an application package to be debugged. - optional SettingProto debug_app = 227; - optional SettingProto wait_for_debugger = 228 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enable_gpu_debug_layers = 342 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto debug_app = 286; + optional SettingProto wait_for_debugger = 287 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enable_gpu_debug_layers = 288 [ (android.privacy).dest = DEST_AUTOMATIC ]; // App allowed to load GPU debug layers. - optional SettingProto gpu_debug_app = 343; - optional SettingProto gpu_debug_layers = 344 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto low_power_mode = 229 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto low_power_mode_trigger_level = 230 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto always_finish_activities = 231 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dock_audio_media_enabled = 232 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto encoded_surround_output = 233 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto audio_safe_volume_state = 234 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tzinfo_update_content_url = 235; - optional SettingProto tzinfo_update_metadata_url = 236; - optional SettingProto selinux_update_content_url = 237; - optional SettingProto selinux_update_metadata_url = 238; - optional SettingProto sms_short_codes_update_content_url = 239; - optional SettingProto sms_short_codes_update_metadata_url = 240; - optional SettingProto apn_db_update_content_url = 241; - optional SettingProto apn_db_update_metadata_url = 242; - optional SettingProto cert_pin_update_content_url = 243; - optional SettingProto cert_pin_update_metadata_url = 244; - optional SettingProto intent_firewall_update_content_url = 245; - optional SettingProto intent_firewall_update_metadata_url = 246; - optional SettingProto lang_id_update_content_url = 324; - optional SettingProto lang_id_update_metadata_url = 325; - optional SettingProto smart_selection_update_content_url = 326; - optional SettingProto smart_selection_update_metadata_url = 327; - optional SettingProto selinux_status = 247 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto development_force_rtl = 248 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto low_battery_sound_timeout = 249 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wifi_bounce_delay_override_ms = 250 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto policy_control = 251 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto zen_mode = 252 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto zen_mode_ringer_level = 253 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto zen_mode_config_etag = 254; - optional SettingProto heads_up_notifications_enabled = 255 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto device_name = 256; - optional SettingProto network_scoring_provisioned = 257 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto require_password_to_decrypt = 258 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enhanced_4g_mode_enabled = 259 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto vt_ims_enabled = 260 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wfc_ims_enabled = 261 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wfc_ims_mode = 262 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wfc_ims_roaming_mode = 263 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wfc_ims_roaming_enabled = 264 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto lte_service_forced = 265 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto ephemeral_cookie_max_size_bytes = 266 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enable_ephemeral_feature = 267 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto instant_app_dexopt_enabled = 328 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto installed_instant_app_min_cache_period = 268 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto installed_instant_app_max_cache_period = 289 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto uninstalled_instant_app_min_cache_period = 290 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto uninstalled_instant_app_max_cache_period = 291 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto unused_static_shared_lib_min_cache_period = 292 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto allow_user_switching_when_system_user_locked = 269 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto boot_count = 270 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto safe_boot_disallowed = 271 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto device_demo_mode = 272 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto network_access_timeout_ms = 329 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto database_downgrade_reason = 274; - optional SettingProto database_creation_buildid = 330 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto contacts_database_wal_enabled = 275 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto location_settings_link_to_permissions_enabled = 331 [ (android.privacy).dest = DEST_AUTOMATIC ]; - reserved 332; // Removed backup_refactored_service_disabled - optional SettingProto euicc_factory_reset_timeout_millis = 333 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto storage_settings_clobber_threshold = 334 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto chained_battery_attribution_enabled = 353 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto hidden_api_blacklist_exemptions = 355 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto gpu_debug_app = 289; + optional SettingProto gpu_debug_layers = 290 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto low_power_mode = 291 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Battery level [1-100] at which low power mode automatically turns on. If + // 0, it will not automatically turn on. + optional SettingProto low_power_mode_trigger_level = 292 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting + // is not set or the value is 0, the default max will be used. + optional SettingProto low_power_mode_trigger_level_max = 293 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto always_finish_activities = 294 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dock_audio_media_enabled = 295 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto encoded_surround_output = 296 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto audio_safe_volume_state = 297 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tzinfo_update_content_url = 298; + optional SettingProto tzinfo_update_metadata_url = 299; + optional SettingProto selinux_update_content_url = 300; + optional SettingProto selinux_update_metadata_url = 301; + optional SettingProto sms_short_codes_update_content_url = 302; + optional SettingProto sms_short_codes_update_metadata_url = 303; + optional SettingProto apn_db_update_content_url = 304; + optional SettingProto apn_db_update_metadata_url = 305; + optional SettingProto cert_pin_update_content_url = 306; + optional SettingProto cert_pin_update_metadata_url = 307; + optional SettingProto intent_firewall_update_content_url = 308; + optional SettingProto intent_firewall_update_metadata_url = 309; + optional SettingProto lang_id_update_content_url = 310; + optional SettingProto lang_id_update_metadata_url = 311; + optional SettingProto smart_selection_update_content_url = 312; + optional SettingProto smart_selection_update_metadata_url = 313; + optional SettingProto selinux_status = 314 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto development_force_rtl = 315 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto low_battery_sound_timeout = 316 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wifi_bounce_delay_override_ms = 317 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto policy_control = 318 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto emulate_display_cutout = 319 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto zen_mode = 320 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto zen_mode_ringer_level = 321 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto zen_mode_config_etag = 322; + // If 0, turning on dnd manually will last indefinitely. Else if + // non-negative, turning on dnd manually will last for this many minutes. + // Else (if negative), turning on dnd manually will surface a dialog that + // prompts user to specify a duration. + optional SettingProto zen_duration = 323 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto heads_up_notifications_enabled = 324 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto device_name = 325; + optional SettingProto network_scoring_provisioned = 326 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto require_password_to_decrypt = 327 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enhanced_4g_mode_enabled = 328 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto vt_ims_enabled = 329 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wfc_ims_enabled = 330 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wfc_ims_mode = 331 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wfc_ims_roaming_mode = 332 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wfc_ims_roaming_enabled = 333 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lte_service_forced = 334 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ephemeral_cookie_max_size_bytes = 335 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enable_ephemeral_feature = 336 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto instant_app_dexopt_enabled = 337 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto installed_instant_app_min_cache_period = 338 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto installed_instant_app_max_cache_period = 339 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto uninstalled_instant_app_min_cache_period = 340 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto uninstalled_instant_app_max_cache_period = 341 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto unused_static_shared_lib_min_cache_period = 342 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto allow_user_switching_when_system_user_locked = 343 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto boot_count = 344 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto safe_boot_disallowed = 345 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto device_demo_mode = 346 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto network_access_timeout_ms = 347 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto database_downgrade_reason = 348; + optional SettingProto database_creation_buildid = 349 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto contacts_database_wal_enabled = 350 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto location_settings_link_to_permissions_enabled = 351 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto euicc_factory_reset_timeout_millis = 352 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto storage_settings_clobber_threshold = 353 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // If set to 1, {@link Secure#LOCATION_MODE} will be set to {@link + // Secure#LOCATION_MODE_OFF} temporarily for all users. + optional SettingProto location_global_kill_switch = 354 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // If set to 1, SettingsProvider's restoreAnyVersion="true" attribute will + // be ignored and restoring to lower version of platform API will be + // skipped. + optional SettingProto override_settings_provider_restore_any_version = 355 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto chained_battery_attribution_enabled = 356 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto autofill_compat_allowed_packages = 357 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto hidden_api_blacklist_exemptions = 358 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Subscription to be used for voice call on a multi sim device. The // supported values are 0 = SUB1, 1 = SUB2 and etc. - optional SettingProto multi_sim_voice_call_subscription = 276 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto multi_sim_voice_prompt = 277 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto multi_sim_data_call_subscription = 278 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto multi_sim_sms_subscription = 279 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto multi_sim_sms_prompt = 280 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto multi_sim_voice_call_subscription = 359 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto multi_sim_voice_prompt = 360 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto multi_sim_data_call_subscription = 361 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto multi_sim_sms_subscription = 362 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto multi_sim_sms_prompt = 363 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Whether to enable new contacts aggregator or not. // 1 = enable, 0 = disable. - optional SettingProto new_contact_aggregator = 281 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto contact_metadata_sync_enabled = 282 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enable_cellular_on_boot = 283 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto max_notification_enqueue_rate = 284 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto show_notification_channel_warnings = 335 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto cell_on = 285 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto show_temperature_warning = 336 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto warning_temperature = 337 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enable_diskstats_logging = 338 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enable_cache_quota_calculation = 339 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enable_deletion_helper_no_threshold_toggle = 340 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto notification_snooze_options = 341 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enable_gnss_raw_meas_full_tracking = 346 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto install_carrier_app_notification_persistent = 356 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto install_carrier_app_notification_sleep_millis = 357 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto zram_enabled = 347 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto smart_replies_in_notifications_flags = 348 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto show_first_crash_dialog = 349 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto show_restart_in_crash_dialog = 351 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto show_mute_in_crash_dialog = 352 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingsProto show_zen_upgrade_notification = 354 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingsProto app_auto_restriction_enabled = 359 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingsProto zen_duration = 360 [ (android.privacy).dest = DEST_AUTOMATIC ]; - + optional SettingProto new_contact_aggregator = 364 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto contact_metadata_sync_enabled = 365 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enable_cellular_on_boot = 366 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto max_notification_enqueue_rate = 367 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_notification_channel_warnings = 368 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto cell_on = 369 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_temperature_warning = 370 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto warning_temperature = 371 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enable_diskstats_logging = 372 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enable_cache_quota_calculation = 373 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enable_deletion_helper_no_threshold_toggle = 374 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto notification_snooze_options = 375 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Configuration flags for SQLite Compatibility WAL. Encoded as a key-value + // list, separated by commas. + // E.g.: compatibility_wal_supported=true, wal_syncmode=OFF + optional SettingProto sqlite_compatibility_wal_flags = 376 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enable_gnss_raw_meas_full_tracking = 377 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto install_carrier_app_notification_persistent = 378 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto install_carrier_app_notification_sleep_millis = 379 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto zram_enabled = 380 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto smart_replies_in_notifications_flags = 381 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_first_crash_dialog = 382 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_restart_in_crash_dialog = 383 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_mute_in_crash_dialog = 384 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingsProto show_zen_upgrade_notification = 385 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingsProto backup_agent_timeout_parameters = 386; // Please insert fields in the same order as in // frameworks/base/core/java/android/provider/Settings.java. - // Next tag = 361; + // Next tag = 387; } message SecureSettingsProto { @@ -454,227 +522,229 @@ message SecureSettingsProto { optional SettingProto voice_interaction_service = 7 [ (android.privacy).dest = DEST_AUTOMATIC ]; // The currently selected autofill service flattened ComponentName. optional SettingProto autofill_service = 8 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_hci_log = 9; - optional SettingProto user_setup_complete = 10 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Boolean indicating if Autofill supports field classification. + optional SettingProto autofill_feature_field_classification = 9 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto autofill_user_data_max_user_data_size = 10 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto autofill_user_data_max_field_classification_ids_size = 11 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto autofill_user_data_max_category_count = 12 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto autofill_user_data_max_value_length = 13 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto autofill_user_data_min_value_length = 14 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto user_setup_complete = 15 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Whether the current user has been set up via setup wizard (0 = false, // 1 = true). This value differs from USER_SETUP_COMPLETE in that it can be // reset back to 0 in case SetupWizard has been re-enabled on TV devices. - optional SettingProto tv_user_setup_complete = 170 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto completed_category_prefix = 11 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enabled_input_methods = 12 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto disabled_system_input_methods = 13 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto show_ime_with_hard_keyboard = 14 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto always_on_vpn_app = 15; - optional SettingProto always_on_vpn_lockdown = 16 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto install_non_market_apps = 17 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto unknown_sources_default_reversed = 171 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tv_user_setup_complete = 16 [ (android.privacy).dest = DEST_AUTOMATIC ]; + repeated SettingProto completed_categories = 17; + optional SettingProto enabled_input_methods = 18 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto disabled_system_input_methods = 19 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_ime_with_hard_keyboard = 20 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto always_on_vpn_app = 21; + optional SettingProto always_on_vpn_lockdown = 22 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto install_non_market_apps = 23 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto unknown_sources_default_reversed = 24 [ (android.privacy).dest = DEST_AUTOMATIC ]; // The degree of location access enabled by the user. - optional SettingProto location_mode = 18 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto location_previous_mode = 19; + optional SettingProto location_mode = 25 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // The App or module that changes the location mode. + optional SettingProto location_changer = 26 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Whether lock-to-app will lock the keyguard when exiting. - optional SettingProto lock_to_app_exit_locked = 20 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto lock_screen_lock_after_timeout = 21 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto lock_screen_allow_private_notifications = 172 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto lock_screen_allow_remote_input = 22 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto show_note_about_notification_hiding = 23 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto trust_agents_initialized = 24 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto parental_control_enabled = 25 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto parental_control_last_update = 26 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto parental_control_redirect_url = 27 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto settings_classname = 28 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_enabled = 29 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_shortcut_enabled = 173 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_shortcut_on_lock_screen = 174 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_shortcut_dialog_shown = 175 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_shortcut_target_service = 176 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lock_to_app_exit_locked = 27 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lock_screen_lock_after_timeout = 28 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lock_screen_allow_private_notifications = 29 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lock_screen_allow_remote_input = 30 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_note_about_notification_hiding = 31 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto trust_agents_initialized = 32 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto parental_control_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto parental_control_last_update = 34 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto parental_control_redirect_url = 35 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto settings_classname = 36 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_enabled = 37 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_shortcut_enabled = 38 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_shortcut_on_lock_screen = 39 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_shortcut_dialog_shown = 40 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_shortcut_target_service = 41 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Setting specifying the accessibility service or feature to be toggled via // the accessibility button in the navigation bar. This is either a // flattened ComponentName or the class name of a system class implementing // a supported accessibility feature. - optional SettingProto accessibility_button_target_component = 177 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto touch_exploration_enabled = 30 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_button_target_component = 42 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto touch_exploration_enabled = 43 [ (android.privacy).dest = DEST_AUTOMATIC ]; // List of the enabled accessibility providers. - optional SettingProto enabled_accessibility_services = 31; + optional SettingProto enabled_accessibility_services = 44; // List of the accessibility services to which the user has granted // permission to put the device into touch exploration mode. - optional SettingProto touch_exploration_granted_accessibility_services = 32; + optional SettingProto touch_exploration_granted_accessibility_services = 45; + // Uri of the slice that's presented on the keyguard. Defaults to a slice + // with the date and next alarm. + optional SettingProto keyguard_slice_uri = 46; // Whether to speak passwords while in accessibility mode. - optional SettingProto accessibility_speak_password = 33 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_high_text_contrast_enabled = 34 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_script_injection = 35; - optional SettingProto accessibility_screen_reader_url = 36; - optional SettingProto accessibility_web_content_key_bindings = 37; - optional SettingProto accessibility_display_magnification_enabled = 38 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_display_magnification_navbar_enabled = 178 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_display_magnification_scale = 39 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_display_magnification_auto_update = 179 [deprecated = true]; - optional SettingProto accessibility_soft_keyboard_mode = 40 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_captioning_enabled = 41 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_captioning_locale = 42 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_captioning_preset = 43 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_captioning_background_color = 44 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_captioning_foreground_color = 45 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_captioning_edge_type = 46 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_captioning_edge_color = 47 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_captioning_window_color = 48 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_captioning_typeface = 49 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_captioning_font_scale = 50 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_display_inversion_enabled = 51 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_display_daltonizer_enabled = 52 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_display_daltonizer = 53 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_autoclick_enabled = 54 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_autoclick_delay = 55 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accessibility_large_pointer_icon = 56 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto long_press_timeout = 57 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto multi_press_timeout = 58 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enabled_print_services = 59; - optional SettingProto disabled_print_services = 60; - optional SettingProto display_density_forced = 61 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tts_default_rate = 62 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tts_default_pitch = 63 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tts_default_synth = 64 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tts_default_locale = 65 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tts_enabled_plugins = 66; - optional SettingProto connectivity_release_pending_intent_delay_ms = 67 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto allowed_geolocation_origins = 68; - optional SettingProto preferred_tty_mode = 69 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enhanced_voice_privacy_enabled = 70 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tty_mode_enabled = 71 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto backup_enabled = 72 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto backup_auto_restore = 73 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto backup_provisioned = 74 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto backup_transport = 75 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto last_setup_shown = 76 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_global_search_activity = 77 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_num_promoted_sources = 78 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_max_results_to_display = 79 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_max_results_per_source = 80 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_web_results_override_limit = 81 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_promoted_source_deadline_millis = 82 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_source_timeout_millis = 83 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_prefill_millis = 84 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_max_stat_age_millis = 85 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_max_source_event_age_millis = 86 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_min_impressions_for_source_ranking = 87 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_min_clicks_for_source_ranking = 88 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_max_shortcuts_returned = 89 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_query_thread_core_pool_size = 90 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_query_thread_max_pool_size = 91 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_shortcut_refresh_core_pool_size = 92 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_shortcut_refresh_max_pool_size = 93 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_thread_keepalive_seconds = 94 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto search_per_source_concurrent_query_limit = 95 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_speak_password = 47 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_high_text_contrast_enabled = 48 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_display_magnification_enabled = 49 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_display_magnification_navbar_enabled = 50 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_display_magnification_scale = 51 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_soft_keyboard_mode = 52 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_captioning_enabled = 53 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_captioning_locale = 54 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_captioning_preset = 55 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_captioning_background_color = 56 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_captioning_foreground_color = 57 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_captioning_edge_type = 58 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_captioning_edge_color = 59 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_captioning_window_color = 60 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_captioning_typeface = 61 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_captioning_font_scale = 62 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_display_inversion_enabled = 63 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_display_daltonizer_enabled = 64 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Integer property that specifies the type of color space adjustment to perform. + optional SettingProto accessibility_display_daltonizer = 65 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_autoclick_enabled = 66 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_autoclick_delay = 67 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accessibility_large_pointer_icon = 68 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto long_press_timeout = 69 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto multi_press_timeout = 70 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enabled_print_services = 71; + optional SettingProto disabled_print_services = 72; + optional SettingProto display_density_forced = 73 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tts_default_rate = 74 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tts_default_pitch = 75 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tts_default_synth = 76 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tts_default_locale = 77 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tts_enabled_plugins = 78; + optional SettingProto connectivity_release_pending_intent_delay_ms = 79 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto allowed_geolocation_origins = 80; + optional SettingProto preferred_tty_mode = 81 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enhanced_voice_privacy_enabled = 82 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tty_mode_enabled = 83 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto backup_enabled = 84 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto backup_auto_restore = 85 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto backup_provisioned = 86 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto backup_transport = 87 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto last_setup_shown = 88 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_global_search_activity = 89 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_num_promoted_sources = 90 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_max_results_to_display = 91 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_max_results_per_source = 92 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_web_results_override_limit = 93 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_promoted_source_deadline_millis = 94 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_source_timeout_millis = 95 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_prefill_millis = 96 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_max_stat_age_millis = 97 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_max_source_event_age_millis = 98 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_min_impressions_for_source_ranking = 99 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_min_clicks_for_source_ranking = 100 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_max_shortcuts_returned = 101 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_query_thread_core_pool_size = 102 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_query_thread_max_pool_size = 103 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_shortcut_refresh_core_pool_size = 104 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_shortcut_refresh_max_pool_size = 105 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_thread_keepalive_seconds = 106 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto search_per_source_concurrent_query_limit = 107 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Whether or not alert sounds are played on StorageManagerService events. - optional SettingProto mount_play_notification_snd = 96 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto mount_ums_autostart = 97 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto mount_ums_prompt = 98 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto mount_ums_notify_enabled = 99 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto anr_show_background = 100 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mount_play_notification_snd = 108 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mount_ums_autostart = 109 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mount_ums_prompt = 110 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mount_ums_notify_enabled = 111 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto anr_show_background = 112 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_first_crash_dialog_dev_option = 113 [ (android.privacy).dest = DEST_AUTOMATIC ]; // The ComponentName string of the service to be used as the voice // recognition service. - optional SettingProto voice_recognition_service = 101 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto package_verifier_user_consent = 102 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto selected_spell_checker = 103 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto selected_spell_checker_subtype = 104 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto spell_checker_enabled = 105 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto incall_power_button_behavior = 106 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto incall_back_button_behavior = 107 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto wake_gesture_enabled = 108 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto doze_enabled = 109 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto doze_always_on = 110 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto doze_pulse_on_pick_up = 111 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto doze_pulse_on_long_press = 180 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto doze_pulse_on_double_tap = 112 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto ui_night_mode = 113 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto screensaver_enabled = 114 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto screensaver_components = 115 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto screensaver_activate_on_dock = 116 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto screensaver_activate_on_sleep = 117 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto screensaver_default_component = 118 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto nfc_payment_default_component = 119 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto nfc_payment_foreground = 120 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sms_default_application = 121 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dialer_default_application = 122 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto emergency_assistance_application = 123 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto assist_structure_enabled = 124 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto assist_screenshot_enabled = 125 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto assist_disclosure_enabled = 126 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto voice_recognition_service = 114 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto package_verifier_user_consent = 115 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto selected_spell_checker = 116 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto selected_spell_checker_subtype = 117 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto spell_checker_enabled = 118 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto incall_power_button_behavior = 119 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto incall_back_button_behavior = 120 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto wake_gesture_enabled = 121 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto doze_enabled = 122 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto doze_always_on = 123 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto doze_pulse_on_pick_up = 124 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto doze_pulse_on_long_press = 125 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto doze_pulse_on_double_tap = 126 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ui_night_mode = 127 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto screensaver_enabled = 128 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto screensaver_components = 129 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto screensaver_activate_on_dock = 130 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto screensaver_activate_on_sleep = 131 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto screensaver_default_component = 132 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto nfc_payment_default_component = 133 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto nfc_payment_foreground = 134 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sms_default_application = 135 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dialer_default_application = 136 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto emergency_assistance_application = 137 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto assist_structure_enabled = 138 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto assist_screenshot_enabled = 139 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto assist_disclosure_enabled = 140 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_rotation_suggestions = 141 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto num_rotation_suggestions_accepted = 142 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Read only list of the service components that the current user has // explicitly allowed to see and assist with all of the user's // notifications. - optional SettingProto enabled_notification_assistant = 127 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enabled_notification_listeners = 128 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto enabled_notification_policy_access_packages = 129 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enabled_notification_assistant = 143 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enabled_notification_listeners = 144 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enabled_notification_policy_access_packages = 145 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Defines whether managed profile ringtones should be synced from its // parent profile. - optional SettingProto sync_parent_sounds = 130 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto immersive_mode_confirmations = 131 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sync_parent_sounds = 146 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto immersive_mode_confirmations = 147 [ (android.privacy).dest = DEST_AUTOMATIC ]; // The query URI to find a print service to install. - optional SettingProto print_service_search_uri = 132 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto print_service_search_uri = 148 [ (android.privacy).dest = DEST_AUTOMATIC ]; // The query URI to find an NFC service to install. - optional SettingProto payment_service_search_uri = 133 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto payment_service_search_uri = 149 [ (android.privacy).dest = DEST_AUTOMATIC ]; // The query URI to find an auto fill service to install. - optional SettingProto autofill_service_search_uri = 181 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto skip_first_use_hints = 134 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto unsafe_volume_music_active_ms = 135 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto lock_screen_show_notifications = 136 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tv_input_hidden_inputs = 137; - optional SettingProto tv_input_custom_labels = 138; - optional SettingProto usb_audio_automatic_routing_disabled = 139 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sleep_timeout = 140 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto double_tap_to_wake = 141 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto autofill_service_search_uri = 150 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto skip_first_use_hints = 151 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto unsafe_volume_music_active_ms = 152 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lock_screen_show_notifications = 153 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tv_input_hidden_inputs = 154; + optional SettingProto tv_input_custom_labels = 155; + optional SettingProto usb_audio_automatic_routing_disabled = 156 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sleep_timeout = 157 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto double_tap_to_wake = 158 [ (android.privacy).dest = DEST_AUTOMATIC ]; // The current assistant component. It could be a voice interaction service, // or an activity that handles ACTION_ASSIST, or empty, which means using // the default handling. - optional SettingProto assistant = 142 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto camera_gesture_disabled = 143 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto camera_double_tap_power_gesture_disabled = 144 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto camera_double_twist_to_flip_enabled = 145 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto camera_lift_trigger_enabled = 182 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto assist_gesture_enabled = 183 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto assist_gesture_sensitivity = 184 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto assist_gesture_silence_alerts_enabled = 185 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto assist_gesture_wake_enabled = 186 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto assist_gesture_setup_complete = 187 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto night_display_activated = 146 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto night_display_auto_mode = 147 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto night_display_color_temperature = 188 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto night_display_custom_start_time = 148 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto night_display_custom_end_time = 149 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto night_display_last_activated_time = 189 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto brightness_use_twilight = 150; - optional SettingProto enabled_vr_listeners = 151 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto vr_display_mode = 152 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto carrier_apps_handled = 153 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto managed_profile_contact_remote_search = 154 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto automatic_storage_manager_enabled = 155 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto automatic_storage_manager_days_to_retain = 156 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto automatic_storage_manager_bytes_cleared = 157 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto automatic_storage_manager_last_run = 158 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto automatic_storage_manager_turned_off_by_policy = 190 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto system_navigation_keys_enabled = 159 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto downloads_backup_enabled = 160; - optional SettingProto downloads_backup_allow_metered = 161; - optional SettingProto downloads_backup_charging_only = 162; - optional SettingProto automatic_storage_manager_downloads_days_to_retain = 163; + optional SettingProto assistant = 159 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto camera_gesture_disabled = 160 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto camera_double_tap_power_gesture_disabled = 161 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto camera_double_twist_to_flip_enabled = 162 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto camera_lift_trigger_enabled = 163 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto assist_gesture_enabled = 164 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto assist_gesture_sensitivity = 165 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto assist_gesture_silence_alerts_enabled = 166 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto assist_gesture_wake_enabled = 167 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto assist_gesture_setup_complete = 168 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto night_display_activated = 169 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto night_display_auto_mode = 170 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto night_display_color_temperature = 171 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto night_display_custom_start_time = 172 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto night_display_custom_end_time = 173 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto night_display_last_activated_time = 174 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto enabled_vr_listeners = 175 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto vr_display_mode = 176 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto carrier_apps_handled = 177 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto managed_profile_contact_remote_search = 178 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto automatic_storage_manager_enabled = 179 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto automatic_storage_manager_days_to_retain = 180 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto automatic_storage_manager_bytes_cleared = 181 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto automatic_storage_manager_last_run = 182 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto automatic_storage_manager_turned_off_by_policy = 183 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto system_navigation_keys_enabled = 184 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Holds comma-separated list of ordering of QuickSettings tiles. - optional SettingProto qs_tiles = 164 [ (android.privacy).dest = DEST_AUTOMATIC ]; - reserved 165; // Removed demo_user_setup_complete - optional SettingProto instant_apps_enabled = 166 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto device_paired = 167 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto package_verifier_state = 191 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto cmas_additional_broadcast_pkg = 192 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto notification_badging = 168 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto qs_auto_added_tiles = 193 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto lockdown_in_power_menu = 194 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto backup_manager_constants = 169; - optional SettingProto show_first_crash_dialog_dev_option = 195 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto bluetooth_on_while_driving = 196 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto backup_local_transport_parameters = 197; - + optional SettingProto qs_tiles = 185 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto instant_apps_enabled = 186 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto device_paired = 187 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto package_verifier_state = 188 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto cmas_additional_broadcast_pkg = 189 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto notification_badging = 190 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto qs_auto_added_tiles = 191 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lockdown_in_power_menu = 192 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto backup_manager_constants = 193; + optional SettingProto backup_local_transport_parameters = 194; + optional SettingProto bluetooth_on_while_driving = 195 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Please insert fields in the same order as in // frameworks/base/core/java/android/provider/Settings.java. - // Next tag = 198 + // Next tag = 196 } message SystemSettingsProto { @@ -688,29 +758,31 @@ message SystemSettingsProto { optional SettingProto bluetooth_discoverability_timeout = 5 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto font_scale = 6 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto system_locales = 7 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto display_color_mode = 67 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto screen_off_timeout = 8 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto screen_brightness = 9 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto screen_brightness_for_vr = 10 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto screen_brightness_mode = 11 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto screen_auto_brightness_adj = 12 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto display_color_mode = 8 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto screen_off_timeout = 9 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto screen_brightness = 10 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto screen_brightness_for_vr = 11 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto screen_brightness_mode = 12 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto screen_auto_brightness_adj = 13 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Determines which streams are affected by ringer mode changes. The stream // type's bit will be set to 1 if it should be muted when going into an // inaudible ringer mode. - optional SettingProto mode_ringer_streams_affected = 13 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto mute_streams_affected = 14 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto vibrate_on = 15 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto vibrate_input_devices = 16 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto volume_ring = 17 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto volume_system = 18 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto volume_voice = 19 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto volume_music = 20 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto volume_alarm = 21 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto volume_notification = 22 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto volume_bluetooth_sco = 23 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto volume_accessibility = 68 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto volume_master = 24 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto master_mono = 25 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mode_ringer_streams_affected = 14 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto mute_streams_affected = 15 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto vibrate_on = 16 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto vibrate_input_devices = 17 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto notification_vibration_intensity = 18 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto haptic_feedback_intensity = 19 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto volume_ring = 20 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto volume_system = 21 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto volume_voice = 22 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto volume_music = 23 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto volume_alarm = 24 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto volume_notification = 25 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto volume_bluetooth_sco = 26 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto volume_accessibility = 27 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto volume_master = 28 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto master_mono = 29 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Whether silent mode should allow vibration feedback. This is used // internally in AudioService and the Sound settings activity to coordinate // decoupling of vibrate and silent modes. This setting will likely be @@ -719,59 +791,63 @@ message SystemSettingsProto { // Not used anymore. On devices with vibrator, the user explicitly selects // silent or vibrate mode. Kept for use by legacy database upgrade code in // DatabaseHelper. - optional SettingProto vibrate_in_silent = 26 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto vibrate_in_silent = 30 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Appended to various volume related settings to record the previous values // before the settings were affected by a silent/vibrate ringer mode change. - optional SettingProto append_for_last_audible = 27 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto ringtone = 28; - optional SettingProto ringtone_cache = 29; - optional SettingProto notification_sound = 30; - optional SettingProto notification_sound_cache = 31; - optional SettingProto alarm_alert = 32; - optional SettingProto alarm_alert_cache = 33; - optional SettingProto media_button_receiver = 34; - optional SettingProto text_auto_replace = 35 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto text_auto_caps = 36 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto text_auto_punctuate = 37 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto text_show_password = 38 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto show_gtalk_service_status = 39 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto time_12_24 = 40 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto date_format = 41 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto setup_wizard_has_run = 42 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto accelerometer_rotation = 43 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto user_rotation = 44 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto hide_rotation_lock_toggle_for_accessibility = 45 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto vibrate_when_ringing = 46 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dtmf_tone_when_dialing = 47 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto dtmf_tone_type_when_dialing = 48 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto hearing_aid = 49 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto tty_mode = 50 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sound_effects_enabled = 51 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto haptic_feedback_enabled = 52 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto notification_light_pulse = 53 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto append_for_last_audible = 31 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto ringtone = 32; + optional SettingProto ringtone_cache = 33; + optional SettingProto notification_sound = 34; + optional SettingProto notification_sound_cache = 35; + optional SettingProto alarm_alert = 36; + optional SettingProto alarm_alert_cache = 37; + optional SettingProto media_button_receiver = 38; + optional SettingProto text_auto_replace = 39 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto text_auto_caps = 40 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto text_auto_punctuate = 41 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto text_show_password = 42 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_gtalk_service_status = 43 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto time_12_24 = 44 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto date_format = 45 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto setup_wizard_has_run = 46 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto accelerometer_rotation = 47 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto user_rotation = 48 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto hide_rotation_lock_toggle_for_accessibility = 49 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto vibrate_when_ringing = 50 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dtmf_tone_when_dialing = 51 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto dtmf_tone_type_when_dialing = 52 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto hearing_aid = 53 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto tty_mode = 54 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // User-selected RTT mode. When on, outgoing and incoming calls will be + // answered as RTT calls when supported by the device and carrier. Boolean + // value. + optional SettingProto rtt_calling_mode = 55 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sound_effects_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto haptic_feedback_enabled = 57 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto notification_light_pulse = 58 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Show pointer location on screen? 0 = no, 1 = yes. - optional SettingProto pointer_location = 54 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto show_touches = 55 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto pointer_location = 59 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_touches = 60 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Log raw orientation data from {@link // com.android.server.policy.WindowOrientationListener} for use with the // orientationplot.py tool. // 0 = no, 1 = yes - optional SettingProto window_orientation_listener_log = 56 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto lockscreen_sounds_enabled = 57 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto lockscreen_disabled = 58 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sip_receive_calls = 59 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sip_call_options = 60 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sip_always = 61 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto sip_address_only = 62 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto pointer_speed = 63 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto lock_to_app_enabled = 64 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto egg_mode = 65 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto show_battery_percent = 69 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto when_to_make_wifi_calls = 66 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto window_orientation_listener_log = 61 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lockscreen_sounds_enabled = 62 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lockscreen_disabled = 63 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sip_receive_calls = 64 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sip_call_options = 65 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sip_always = 66 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto sip_address_only = 67 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto pointer_speed = 68 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto lock_to_app_enabled = 69 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto egg_mode = 70 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_battery_percent = 71 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto when_to_make_wifi_calls = 72 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Please insert fields in the same order as in // frameworks/base/core/java/android/provider/Settings.java. - // Next tag = 70; + // Next tag = 73; } message SettingProto { diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto index 64aa98b1136e..c58de563692b 100644 --- a/core/proto/android/server/powermanagerservice.proto +++ b/core/proto/android/server/powermanagerservice.proto @@ -198,7 +198,7 @@ message WakeLockProto { } optional .android.os.WakeLockLevelEnum lock_level = 1; - optional string tag = 2 [ (.android.privacy).dest = DEST_EXPLICIT ]; + optional string tag = 2; optional WakeLockFlagsProto flags = 3; optional bool is_disabled = 4; // Acquire time in ms diff --git a/core/proto/android/service/diskstats.proto b/core/proto/android/service/diskstats.proto index 3d7ee914074e..e5bdc8bd16f6 100644 --- a/core/proto/android/service/diskstats.proto +++ b/core/proto/android/service/diskstats.proto @@ -55,25 +55,25 @@ message DiskStatsCachedValuesProto { 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 @@ message DiskStatsAppSizesProto { // 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 @@ message DiskStatsFreeSpaceProto { // 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 f42206562fc4..c2fedf5a5722 100644 --- a/core/proto/android/service/graphicsstats.proto +++ b/core/proto/android/service/graphicsstats.proto @@ -56,7 +56,7 @@ message GraphicsStatsJankSummaryProto { // 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 @@ message GraphicsStatsJankSummaryProto { // 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/AndroidManifest.xml b/core/res/AndroidManifest.xml index a4c0c54322e3..9b11a33593bd 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2552,6 +2552,12 @@ <permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS" android:protectionLevel="signature|installer" /> + <!-- Allows an application to update the user app op modes. + Not for use by third party apps. + @hide --> + <permission android:name="android.permission.MANAGE_APP_OPS_MODES" + android:protectionLevel="signature|installer|verifier" /> + <!-- @SystemApi Allows an application to open windows that are for use by parts of the system user interface. <p>Not for use by third-party applications. diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 88dfe4233771..daad866b92b8 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 > Network & internet > Mobile networks > 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> @@ -2444,6 +2444,18 @@ <string name="more_item_label">More</string> <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the MENU button together with the shortcut to invoke the item. For example, if the shortcut to open a new tab in browser is MENU and B together, then this would be prepended to the letter "B" --> <string name="prepend_shortcut_label">Menu+</string> + <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the META key together with the shortcut to invoke the item. --> + <string name="menu_meta_shortcut_label">Meta+</string> + <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the CTRL key together with the shortcut to invoke the item. --> + <string name="menu_ctrl_shortcut_label">Ctrl+</string> + <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the ALT key together with the shortcut to invoke the item. --> + <string name="menu_alt_shortcut_label">Alt+</string> + <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the SHIFT key together with the shortcut to invoke the item. --> + <string name="menu_shift_shortcut_label">Shift+</string> + <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the SYM key together with the shortcut to invoke the item. --> + <string name="menu_sym_shortcut_label">Sym+</string> + <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the FUNCTION key together with the shortcut to invoke the item. --> + <string name="menu_function_shortcut_label">Function+</string> <!-- Displayed in place of the regular shortcut letter when a menu item has Menu+space for the shortcut. --> <string name="menu_space_shortcut_label">space</string> <!-- Displayed in place of the regular shortcut letter when a menu item has Menu+enter for the shortcut. --> @@ -3267,7 +3279,7 @@ <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MIDI mode. This is the title --> <string name="usb_midi_notification_title">MIDI via USB turned on</string> <!-- USB_PREFERENCES: Notification for when a USB accessory is attached. This is the title --> - <string name="usb_accessory_notification_title">USB accessory mode turned on</string> + <string name="usb_accessory_notification_title">USB accessory connected</string> <!-- See USB_PREFERENCES. This is the message. --> <string name="usb_notification_message">Tap for more options.</string> <!-- See USB_PREFERENCES. This is the message when a data mode is turned on (mtp, ptp, midi) and the device is supplying power.. --> @@ -3281,7 +3293,7 @@ <!-- Title of notification shown when ADB is actively connected to the phone. --> <string name="adb_active_notification_title">USB debugging connected</string> <!-- Message of notification shown when ADB is actively connected to the phone. --> - <string name="adb_active_notification_message">Tap to disable USB debugging.</string> + <string name="adb_active_notification_message">Tap to turn off USB debugging</string> <string name="adb_active_notification_message" product="tv">Select to disable USB debugging.</string> <!-- Title of notification shown to indicate that bug report is being collected. --> @@ -4877,10 +4889,16 @@ <!-- Notification action for editing a screenshot (drawing on it, cropping it, etc) --> <string name="screenshot_edit">Edit</string> - <!-- Title for the notification channel notifying user of settings system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] --> + <!-- Title for the notification channel notifying user of settings system changes. [CHAR LIMIT=NONE] --> <string name="notification_channel_system_changes">System changes</string> + <!-- Title for the notification channel notifying user of do not disturb system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] --> + <string name="notification_channel_do_not_disturb">Do Not Disturb</string> + <!-- Title of notification indicating do not disturb visual interruption settings have changed when upgrading to P --> + <string name="zen_upgrade_notification_visd_title">Do Not Disturb is hiding notifications to help you focus</string> + <!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings --> + <string name="zen_upgrade_notification_visd_content">This is new behavior. Tap to change.</string> <!-- Title of notification indicating do not disturb settings have changed when upgrading to P --> - <string name="zen_upgrade_notification_title">Do Not Disturb is hiding notifications to help you focus</string> + <string name="zen_upgrade_notification_title">Do Not Disturb has changed</string> <!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings --> - <string name="zen_upgrade_notification_content">This is a new feature from the latest system update. Tap to change.</string> + <string name="zen_upgrade_notification_content">Tap to check what\'s blocked.</string> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 97116f54e7c9..55e91571c8c0 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -528,9 +528,15 @@ <java-symbol type="string" name="delete" /> <java-symbol type="string" name="deleteText" /> <java-symbol type="string" name="grant_permissions_header_text" /> + <java-symbol type="string" name="menu_alt_shortcut_label" /> + <java-symbol type="string" name="menu_ctrl_shortcut_label" /> <java-symbol type="string" name="menu_delete_shortcut_label" /> <java-symbol type="string" name="menu_enter_shortcut_label" /> + <java-symbol type="string" name="menu_function_shortcut_label" /> + <java-symbol type="string" name="menu_meta_shortcut_label" /> <java-symbol type="string" name="menu_space_shortcut_label" /> + <java-symbol type="string" name="menu_shift_shortcut_label" /> + <java-symbol type="string" name="menu_sym_shortcut_label" /> <java-symbol type="string" name="notification_title" /> <java-symbol type="string" name="permission_request_notification_with_subtitle" /> <java-symbol type="string" name="prepend_shortcut_label" /> @@ -3123,6 +3129,7 @@ <java-symbol type="string" name="notification_channel_usb" /> <java-symbol type="string" name="notification_channel_heavy_weight_app" /> <java-symbol type="string" name="notification_channel_system_changes" /> + <java-symbol type="string" name="notification_channel_do_not_disturb" /> <java-symbol type="string" name="config_defaultAutofillService" /> <java-symbol type="string" name="config_defaultTextClassifierPackage" /> @@ -3289,6 +3296,8 @@ <java-symbol type="string" name="zen_upgrade_notification_title" /> <java-symbol type="string" name="zen_upgrade_notification_content" /> + <java-symbol type="string" name="zen_upgrade_notification_visd_title" /> + <java-symbol type="string" name="zen_upgrade_notification_visd_content" /> <java-symbol type="string" name="config_managed_provisioning_package" /> diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml index 970a0f00bf5e..7b5ad9a42d00 100644 --- a/core/tests/coretests/AndroidTest.xml +++ b/core/tests/coretests/AndroidTest.xml @@ -14,15 +14,16 @@ limitations under the License. --> <configuration description="Runs Frameworks Core 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="FrameworksCoreTests.apk" /> <option name="test-file-name" value="BstatsTestApp.apk" /> </target_preparer> - - <option name="test-suite-tag" value="apct" /> <option name="test-tag" value="FrameworksCoreTests" /> <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="com.android.frameworks.coretests" /> - <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" /> </test> </configuration> diff --git a/core/tests/coretests/BinderProxyCountingTestApp/Android.mk b/core/tests/coretests/BinderProxyCountingTestApp/Android.mk index c3af6bd123b8..4642694d7b67 100644 --- a/core/tests/coretests/BinderProxyCountingTestApp/Android.mk +++ b/core/tests/coretests/BinderProxyCountingTestApp/Android.mk @@ -24,5 +24,6 @@ LOCAL_PACKAGE_NAME := BinderProxyCountingTestApp 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 34016ed633b1..f852c7afeacd 100644 --- a/core/tests/coretests/BinderProxyCountingTestService/Android.mk +++ b/core/tests/coretests/BinderProxyCountingTestService/Android.mk @@ -24,5 +24,6 @@ LOCAL_PACKAGE_NAME := BinderProxyCountingTestService 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 e04536ba7499..a5872a5e5be9 100644 --- a/core/tests/coretests/BstatsTestApp/Android.mk +++ b/core/tests/coretests/BstatsTestApp/Android.mk @@ -30,4 +30,5 @@ LOCAL_CERTIFICATE := platform 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 22a261e35453..a08eae94b3f6 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -383,6 +383,7 @@ public class SettingsBackupTest { 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, @@ -462,8 +463,8 @@ public class SettingsBackupTest { Settings.Global.ZRAM_ENABLED, Settings.Global.OVERRIDE_SETTINGS_PROVIDER_RESTORE_ANY_VERSION, Settings.Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED, - Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS); - + Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS, + Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS); private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS = newHashSet( Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, diff --git a/core/tests/featureflagtests/AndroidTest.xml b/core/tests/featureflagtests/AndroidTest.xml index 44f9c3e37853..38c048ab061e 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 f06983559830..6507839a4288 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 a43f48eb6e68..8098c1497865 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 65bb8decc332..270d7731a974 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 78cfa462beeb..4c50b7df3368 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 c51de6a7897e..e18a7e0df175 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_CFLAGS := $(MY_CFLAGS) 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_CFLAGS := $(MY_CFLAGS) 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/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml index fd1027c218d8..be0372deb14e 100644 --- a/data/etc/hiddenapi-package-whitelist.xml +++ b/data/etc/hiddenapi-package-whitelist.xml @@ -67,6 +67,7 @@ which apps should be allowed to access the entire private API. <hidden-api-whitelisted-app package="com.android.pacprocessor" /> <hidden-api-whitelisted-app package="com.android.phone" /> <hidden-api-whitelisted-app package="com.android.pmc" /> + <hidden-api-whitelisted-app package="com.android.printservice.recommendation" /> <hidden-api-whitelisted-app package="com.android.printspooler" /> <hidden-api-whitelisted-app package="com.android.providers.blockednumber" /> <hidden-api-whitelisted-app package="com.android.providers.contacts" /> diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java index 07df0454362c..5dc446391ec6 100644 --- a/graphics/java/android/graphics/BaseCanvas.java +++ b/graphics/java/android/graphics/BaseCanvas.java @@ -454,8 +454,7 @@ public abstract class BaseCanvas { throwIfHasHwBitmapInSwMode(paint); nDrawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount, - x, y, isRtl, paint.getNativeInstance(), 0 /* measured text */, - 0 /* measured text offset */); + x, y, isRtl, paint.getNativeInstance(), 0 /* measured text */); } public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart, @@ -486,19 +485,16 @@ public abstract class BaseCanvas { char[] buf = TemporaryBuffer.obtain(contextLen); TextUtils.getChars(text, contextStart, contextEnd, buf, 0); long measuredTextPtr = 0; - int measuredTextOffset = 0; if (text instanceof PrecomputedText) { PrecomputedText mt = (PrecomputedText) text; int paraIndex = mt.findParaIndex(start); if (end <= mt.getParagraphEnd(paraIndex)) { - // Only suppor the same paragraph. + // Only suppor the text in the same paragraph. measuredTextPtr = mt.getMeasuredParagraph(paraIndex).getNativePtr(); - measuredTextOffset = start - mt.getParagraphStart(paraIndex); } } nDrawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len, - 0, contextLen, x, y, isRtl, paint.getNativeInstance(), - measuredTextPtr, measuredTextOffset); + 0, contextLen, x, y, isRtl, paint.getNativeInstance(), measuredTextPtr); TemporaryBuffer.recycle(buf); } } @@ -647,7 +643,7 @@ public abstract class BaseCanvas { private static native void nDrawTextRun(long nativeCanvas, char[] text, int start, int count, int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint, - long nativePrecomputedText, int measuredTextOffset); + long nativePrecomputedText); private static native void nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count, long nativePath, float hOffset, float vOffset, int bidiFlags, long nativePaint); diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 44e7066c5c66..52d29e32e464 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -461,6 +461,11 @@ public final class Bitmap implements Parcelable { * * This configuration may be useful when using opaque bitmaps * that do not require high color fidelity. + * + * <p>Use this formula to pack into 16 bits:</p> + * <pre class="prettyprint"> + * short color = (R & 0x1f) << 11 | (G & 0x3f) << 5 | (B & 0x1f); + * </pre> */ RGB_565 (3), @@ -493,6 +498,11 @@ public final class Bitmap implements Parcelable { * * This configuration is very flexible and offers the best * quality. It should be used whenever possible. + * + * <p>Use this formula to pack into 32 bits:</p> + * <pre class="prettyprint"> + * int color = (A & 0xff) << 24 | (B & 0xff) << 16 | (G & 0xff) << 8 | (R & 0xff); + * </pre> */ ARGB_8888 (5), @@ -503,6 +513,11 @@ public final class Bitmap implements Parcelable { * * This configuration is particularly suited for wide-gamut and * HDR content. + * + * <p>Use this formula to pack into 64 bits:</p> + * <pre class="prettyprint"> + * long color = (A & 0xffff) << 48 | (B & 0xffff) << 32 | (G & 0xffff) << 16 | (R & 0xffff); + * </pre> */ RGBA_F16 (6), diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index f27c11dbf735..20c22b720717 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -167,10 +167,8 @@ public class Typeface { nativeSetDefault(t.native_instance); } - // TODO: Make this public API. (b/64852739) - /** @hide */ - @VisibleForTesting - public int getWeight() { + /** Returns the typeface's weight value */ + public @IntRange(from = 0, to = 1000) int getWeight() { return mWeight; } @@ -883,6 +881,15 @@ public class Typeface { } /** + * This method is used by supportlib-v27. + * TODO: Remove private API use in supportlib: http://b/72665240 + */ + private static Typeface createFromFamiliesWithDefault(FontFamily[] families, int weight, + int italic) { + return createFromFamiliesWithDefault(families, DEFAULT_FAMILY, weight, italic); + } + + /** * Create a new typeface from an array of font families, including * also the font families in the fallback list. * @param fallbackName the family name. If given families don't support characters, the diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp index cf29e434a351..8110664ad44b 100644 --- a/libs/hwui/JankTracker.cpp +++ b/libs/hwui/JankTracker.cpp @@ -129,22 +129,42 @@ void JankTracker::finishFrame(const FrameInfo& frame) { 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)) { + // Only things like Surface.lockHardwareCanvas() are exempt from tracking + if (CC_UNLIKELY(frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS)) { return; } - // Only things like Surface.lockHardwareCanvas() are exempt from tracking - if (frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS) { + 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->reportJank(); - (*mGlobalData)->reportJank(); + 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 dc6a7ff5ddb7..110211eda23a 100644 --- a/libs/hwui/JankTracker.h +++ b/libs/hwui/JankTracker.h @@ -75,6 +75,7 @@ private: 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 b392ecdde18f..f9cf54998032 100644 --- a/libs/hwui/ProfileData.cpp +++ b/libs/hwui/ProfileData.cpp @@ -23,8 +23,7 @@ namespace uirenderer { 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 1e688ab6fa68..564920b60328 100644 --- a/libs/hwui/ProfileData.h +++ b/libs/hwui/ProfileData.h @@ -33,6 +33,7 @@ enum JankType { kSlowUI, kSlowSync, kSlowRT, + kMissedDeadline, // must be last NUM_BUCKETS, diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 2b0b22df7edf..40b811d813fd 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -764,6 +764,13 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& p void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset, const SkPaint& paint, const SkPath& path, size_t start, size_t end) { + // Set align to left for drawing, as we don't want individual + // glyphs centered or right-aligned; the offsets take care of + // that portion of the alignment. + SkPaint paintCopy(paint); + paintCopy.setTextAlign(SkPaint::kLeft_Align); + SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); + const int N = end - start; SkAutoSTMalloc<1024, uint8_t> storage(N * (sizeof(uint16_t) + sizeof(SkRSXform))); SkRSXform* xform = (SkRSXform*)storage.get(); @@ -788,7 +795,7 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, xform[i - start].fTy = pos.y() + tan.x() * y - halfWidth * tan.y(); } - this->asSkCanvas()->drawTextRSXform(glyphs, sizeof(uint16_t) * N, xform, nullptr, paint); + this->asSkCanvas()->drawTextRSXform(glyphs, sizeof(uint16_t) * N, xform, nullptr, paintCopy); } // ---------------------------------------------------------------------------- diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp index ad4c8be74d75..20543df85068 100644 --- a/libs/hwui/hwui/Canvas.cpp +++ b/libs/hwui/hwui/Canvas.cpp @@ -158,13 +158,13 @@ private: void Canvas::drawText(const uint16_t* text, int start, int count, int contextCount, float x, float y, minikin::Bidi bidiFlags, const Paint& origPaint, - const Typeface* typeface, minikin::MeasuredText* mt, int mtOffset) { + const Typeface* typeface, minikin::MeasuredText* mt) { // minikin may modify the original paint Paint paint(origPaint); minikin::Layout layout = MinikinUtils::doLayout(&paint, bidiFlags, typeface, text, start, count, contextCount, - mt, mtOffset); + mt); x += MinikinUtils::xOffsetForTextAlign(&paint, layout); @@ -212,8 +212,7 @@ void Canvas::drawTextOnPath(const uint16_t* text, int count, minikin::Bidi bidiF const Typeface* typeface) { Paint paintCopy(paint); minikin::Layout layout = - MinikinUtils::doLayout(&paintCopy, bidiFlags, typeface, text, 0, count, count, nullptr, - 0); + MinikinUtils::doLayout(&paintCopy, bidiFlags, typeface, text, 0, count, count, nullptr); hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path); // Set align to left for drawing, as we don't want individual diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index fabb8d2e4549..d04bb2e5ad03 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -270,7 +270,7 @@ public: */ void drawText(const uint16_t* text, int start, int count, int contextCount, float x, float y, minikin::Bidi bidiFlags, const Paint& origPaint, const Typeface* typeface, - minikin::MeasuredText* mt, int mtOffset); + minikin::MeasuredText* mt); void drawTextOnPath(const uint16_t* text, int count, minikin::Bidi bidiFlags, const SkPath& path, float hOffset, float vOffset, const Paint& paint, diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp index a0d000dd2179..5b69bb78101f 100644 --- a/libs/hwui/hwui/MinikinUtils.cpp +++ b/libs/hwui/hwui/MinikinUtils.cpp @@ -49,8 +49,7 @@ minikin::MinikinPaint MinikinUtils::prepareMinikinPaint(const Paint* paint, minikin::Layout MinikinUtils::doLayout(const Paint* paint, minikin::Bidi bidiFlags, const Typeface* typeface, const uint16_t* buf, size_t start, - size_t count, size_t bufSize, minikin::MeasuredText* mt, - int mtOffset) { + size_t count, size_t bufSize, minikin::MeasuredText* mt) { minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface); minikin::Layout layout; @@ -62,15 +61,9 @@ minikin::Layout MinikinUtils::doLayout(const Paint* paint, minikin::Bidi bidiFla if (mt == nullptr) { layout.doLayout(textBuf,range, bidiFlags, minikinPaint, startHyphen, endHyphen); - return layout; + } else { + mt->buildLayout(textBuf, range, minikinPaint, bidiFlags, startHyphen, endHyphen, &layout); } - - if (mt->buildLayout(textBuf, range, minikinPaint, bidiFlags, mtOffset, startHyphen, endHyphen, - &layout)) { - return layout; - } - - layout.doLayout(textBuf, range, bidiFlags, minikinPaint, startHyphen, endHyphen); return layout; } @@ -85,7 +78,8 @@ float MinikinUtils::measureText(const Paint* paint, minikin::Bidi bidiFlags, const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit); return minikin::Layout::measureText(textBuf, range, bidiFlags, minikinPaint, startHyphen, - endHyphen, advances, nullptr /* extent */); + endHyphen, advances, nullptr /* extent */, + nullptr /* layout pieces */); } bool MinikinUtils::hasVariationSelector(const Typeface* typeface, uint32_t codepoint, uint32_t vs) { diff --git a/libs/hwui/hwui/MinikinUtils.h b/libs/hwui/hwui/MinikinUtils.h index 124fe4f81fbe..77dfbb21f7b5 100644 --- a/libs/hwui/hwui/MinikinUtils.h +++ b/libs/hwui/hwui/MinikinUtils.h @@ -45,7 +45,7 @@ public: ANDROID_API static minikin::Layout doLayout(const Paint* paint, minikin::Bidi bidiFlags, const Typeface* typeface, const uint16_t* buf, size_t start, size_t count, size_t bufSize, - minikin::MeasuredText* mt, int mtOffset); + minikin::MeasuredText* mt); ANDROID_API static float measureText(const Paint* paint, minikin::Bidi bidiFlags, const Typeface* typeface, const uint16_t* buf, diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 25c76eb4db3e..62d78e73ccc0 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -148,31 +148,6 @@ void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { // 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 0e5dbdbab078..93807a5476e6 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h @@ -88,6 +88,45 @@ private: * @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 e0303a8a62d5..599226bebe84 100644 --- a/libs/hwui/service/GraphicsStatsService.cpp +++ b/libs/hwui/service/GraphicsStatsService.cpp @@ -176,6 +176,8 @@ bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::st 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 @@ void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) { 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/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp index 51cf772e8691..b99854e5af07 100644 --- a/libs/hwui/tests/common/TestUtils.cpp +++ b/libs/hwui/tests/common/TestUtils.cpp @@ -125,7 +125,7 @@ void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint SkPaint glyphPaint(paint); glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); canvas->drawText(utf16.get(), 0, strlen(text), strlen(text), x, y, minikin::Bidi::LTR, - glyphPaint, nullptr, nullptr /* measured text */, 0 /* measured text offset */); + glyphPaint, nullptr, nullptr /* measured text */); } void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint, diff --git a/libs/hwui/tests/common/scenes/JankyScene.cpp b/libs/hwui/tests/common/scenes/JankyScene.cpp new file mode 100644 index 000000000000..f5e6b317529a --- /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 7590b22486c5..f29f57f1c197 100644 --- a/libs/incident/proto/android/privacy.proto +++ b/libs/incident/proto/android/privacy.proto @@ -23,13 +23,10 @@ import "google/protobuf/descriptor.proto"; 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 @@ enum Destination { 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 f198f4324fc8..182f661fcfff 100644 --- a/media/OWNERS +++ b/media/OWNERS @@ -4,3 +4,6 @@ lajos@google.com 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 3d5f6bc9ac71..8a742b75cdf8 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -1602,7 +1602,9 @@ final public class MediaCodec { 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 @@ final public class MediaCodec { */ @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 3dd6879e4482..2a601f9b4cdb 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -829,14 +829,24 @@ public final class MediaCodecInfo { /** @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 @@ public final class MediaCodecInfo { 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 @@ public final class MediaCodecInfo { 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 @@ public final class MediaCodecInfo { } /** @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 @@ public final class MediaCodecInfo { 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 @@ public final class MediaCodecInfo { 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 @@ public final class MediaCodecInfo { } /** @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 b51c662539cf..20c320947f45 100644 --- a/media/java/android/media/MediaController2.java +++ b/media/java/android/media/MediaController2.java @@ -28,7 +28,6 @@ import android.media.MediaSession2.CommandButton; import android.media.MediaSession2.CommandGroup; import android.media.MediaSession2.ControllerInfo; import android.media.MediaSession2.ErrorCode; -import android.media.MediaSession2.PlaylistParams; import android.media.session.MediaSessionManager; import android.media.update.ApiLoader; import android.media.update.MediaController2Provider; @@ -139,23 +138,6 @@ public class MediaController2 implements AutoCloseable { @Nullable ResultReceiver receiver) { } /** - * Called when the playlist is changed. - * <p> - * If the previously playing media item is gone, you should invalidate previous playback - * information and wait for later callbacks. - * - * @param controller the controller for this event - * @param playlist A new playlist set by the session. - * @see #onPositionChanged(MediaController2, long, long) - * @see #onBufferedPositionChanged(MediaController2, long) - * @see #onCurrentMediaItemChanged(MediaController2, MediaItem2) - * @hide - */ - // TODO(jaewan): Remove (b/74174728) - public void onPlaylistChanged(@NonNull MediaController2 controller, - @NonNull List<MediaItem2> playlist) { } - - /** * Called when the player state is changed. * * @param controller the controller for this event @@ -266,17 +248,6 @@ public class MediaController2 implements AutoCloseable { public void onRepeatModeChanged(@NonNull MediaController2 controller, @NonNull MediaPlaylistAgent playlistAgent, @MediaPlaylistAgent.RepeatMode int repeatMode) { } - - /** - * Called when the playlist parameters are changed. - * - * @param controller the controller for this event - * @param params The new play list parameters. - * @hide - */ - // TODO(jaewan): Remove (b/74116823) - public void onPlaylistParamsChanged(@NonNull MediaController2 controller, - @NonNull PlaylistParams params) { } } /** @@ -478,19 +449,6 @@ public class MediaController2 implements AutoCloseable { } /** - * Sets the {@link PlaylistParams} for the current play list. Repeat/shuffle mode and metadata - * for the list can be set by calling this method. - * - * @param params A {@link PlaylistParams} object to set. - * @throws IllegalArgumentException if given {@param param} is null. - * @hide - */ - // TODO(jaewan): Remove (b/74116823) - public void setPlaylistParams(@NonNull PlaylistParams params) { - mProvider.setPlaylistParams_impl(params); - } - - /** * @hide */ public void skipForward() { @@ -778,17 +736,6 @@ public class MediaController2 implements AutoCloseable { } /** - * Returns the {@link PlaylistParams} for the current play list. - * Can return {@code null} if the controller doesn't have enough permission, or if the session - * has not set the parameters. - * @hide - */ - // TODO(jaewan): Remove (b/74116823) - public @Nullable PlaylistParams getPlaylistParams() { - return mProvider.getPlaylistParams_impl(); - } - - /** * Inserts the media item to the playlist at position index. * <p> * This will not change the currently playing media item. @@ -836,39 +783,83 @@ public class MediaController2 implements AutoCloseable { } /** - * Sets the index of current DataSourceDesc in the play list to be played. - * - * @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 + * Skips to the previous item in the playlist. + * <p> + * This calls {@link MediaPlaylistAgent#skipToPreviousItem()}. */ - public void skipToPlaylistItem(@NonNull MediaItem2 item) { - mProvider.skipToPlaylistItem_impl(item); - } - - public void skipToPreviousItem() { - mProvider.skipToPreviousItem_impl(); - } + 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(); } + /** + * Skips to the item in the playlist. + * <p> + * This calls {@link MediaPlaylistAgent#skipToPlaylistItem(MediaItem2)}. + * + * @param item The item in the playlist you want to play + */ + public void skipToPlaylistItem(@NonNull MediaItem2 item) { + mProvider.skipToPlaylistItem_impl(item); + } + + /** + * Gets the cached repeat mode from the {@link ControllerCallback#onRepeatModeChanged( + * MediaController2, MediaPlaylistAgent, int)}. + * + * @return repeat mode + * @see MediaPlaylistAgent#REPEAT_MODE_NONE + * @see MediaPlaylistAgent#REPEAT_MODE_ONE + * @see MediaPlaylistAgent#REPEAT_MODE_ALL + * @see MediaPlaylistAgent#REPEAT_MODE_GROUP + */ public @RepeatMode int getRepeatMode() { - // TODO(jaewan): Implement (b/74118768) - return 0; + return mProvider.getRepeatMode_impl(); } + /** + * Sets the repeat mode. + * + * @param repeatMode repeat mode + * @see MediaPlaylistAgent#REPEAT_MODE_NONE + * @see MediaPlaylistAgent#REPEAT_MODE_ONE + * @see MediaPlaylistAgent#REPEAT_MODE_ALL + * @see MediaPlaylistAgent#REPEAT_MODE_GROUP + */ public void setRepeatMode(@RepeatMode int repeatMode) { - // TODO(jaewan): Implement (b/74118768) + mProvider.setRepeatMode_impl(repeatMode); } + /** + * Gets the cached shuffle mode from the {@link ControllerCallback#onShuffleModeChanged( + * MediaController2, MediaPlaylistAgent, int)}. + * + * @return The shuffle mode + * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE + * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL + * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP + */ public @ShuffleMode int getShuffleMode() { - // TODO(jaewan): Implement (b/74118768) - return 0; + return mProvider.getShuffleMode_impl(); } + /** + * Sets the shuffle mode. + * + * @param shuffleMode The shuffle mode + * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE + * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL + * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP + */ public void setShuffleMode(@ShuffleMode int shuffleMode) { - // TODO(jaewan): Implement (b/74118768) + mProvider.setShuffleMode_impl(shuffleMode); } } diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index 1c4d898acb4f..56423fda0404 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -82,7 +82,6 @@ import java.util.Vector; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; - /** * @hide */ @@ -116,8 +115,9 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { 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 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { addTask(new Task(CALL_COMPLETED_SET_PLAYER_VOLUME, false) { @Override void process() { + mVolume = volume; _setVolume(volume, volume); } }); @@ -567,8 +568,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { */ @Override public float getPlayerVolume() { - // TODO: get real volume - return 1.0f; + return mVolume; } /** @@ -3227,9 +3227,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public void clearMediaPlayer2EventCallback() { synchronized (mEventCbLock) { - for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) { - mEventCallbackRecords.remove(cb); - } + mEventCallbackRecords.clear(); } } @@ -3300,9 +3298,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public void clearDrmEventCallback() { synchronized (mDrmEventCbLock) { - for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) { - mDrmEventCallbackRecords.remove(cb); - } + mDrmEventCallbackRecords.clear(); } } diff --git a/media/java/android/media/MediaPlayerBase.java b/media/java/android/media/MediaPlayerBase.java index 70a36bf201dd..f18e347e56bd 100644 --- a/media/java/android/media/MediaPlayerBase.java +++ b/media/java/android/media/MediaPlayerBase.java @@ -132,8 +132,8 @@ public abstract class MediaPlayerBase implements AutoCloseable { public static final long UNKNOWN_TIME = -1; /** - * Returns the current playback head position. - * @return the current play position in ms, or {@link #UNKNOWN_TIME} if unknown. + * Gets the current playback head position. + * @return the current playback position in ms, or {@link #UNKNOWN_TIME} if unknown. */ public long getCurrentPosition() { return UNKNOWN_TIME; } @@ -144,8 +144,8 @@ public abstract class MediaPlayerBase implements AutoCloseable { public long getDuration() { return UNKNOWN_TIME; } /** - * Returns the duration of the current data source, or {@link #UNKNOWN_TIME} if unknown. - * @return the duration in ms, or {@link #UNKNOWN_TIME}. + * Gets the buffered position of current playback, or {@link #UNKNOWN_TIME} if unknown. + * @return the buffered position in ms, or {@link #UNKNOWN_TIME}. */ public long getBufferedPosition() { return UNKNOWN_TIME; } diff --git a/media/java/android/media/MediaPlaylistAgent.java b/media/java/android/media/MediaPlaylistAgent.java index 1d7520ff9f0d..6b3620b62dc3 100644 --- a/media/java/android/media/MediaPlaylistAgent.java +++ b/media/java/android/media/MediaPlaylistAgent.java @@ -46,7 +46,7 @@ public abstract class MediaPlaylistAgent { @IntDef({REPEAT_MODE_NONE, REPEAT_MODE_ONE, REPEAT_MODE_ALL, REPEAT_MODE_GROUP}) @Retention(RetentionPolicy.SOURCE) - @interface RepeatMode {} + public @interface RepeatMode {} /** * Playback will be stopped at the end of the playing media list. @@ -75,7 +75,7 @@ public abstract class MediaPlaylistAgent { */ @IntDef({SHUFFLE_MODE_NONE, SHUFFLE_MODE_ALL, SHUFFLE_MODE_GROUP}) @Retention(RetentionPolicy.SOURCE) - @interface ShuffleMode {} + public @interface ShuffleMode {} /** * Media list will be played in order. @@ -266,16 +266,22 @@ public abstract class MediaPlaylistAgent { 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(); } /** - * Get repeat mode + * Gets the repeat mode * * @return repeat mode * @see #REPEAT_MODE_NONE @@ -288,7 +294,7 @@ public abstract class MediaPlaylistAgent { } /** - * Set repeat mode + * Sets the repeat mode * * @param repeatMode repeat mode * @see #REPEAT_MODE_NONE @@ -301,9 +307,9 @@ public abstract class MediaPlaylistAgent { } /** - * Get shuffle mode + * Gets the shuffle mode * - * @return shuffle mode + * @return The shuffle mode * @see #SHUFFLE_MODE_NONE * @see #SHUFFLE_MODE_ALL * @see #SHUFFLE_MODE_GROUP @@ -313,9 +319,9 @@ public abstract class MediaPlaylistAgent { } /** - * Set shuffle mode + * Sets the shuffle mode * - * @param shuffleMode shuffle mode + * @param shuffleMode The shuffle mode * @see #SHUFFLE_MODE_NONE * @see #SHUFFLE_MODE_ALL * @see #SHUFFLE_MODE_GROUP @@ -323,4 +329,19 @@ public abstract class MediaPlaylistAgent { 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 e60c5f9b3b8c..60714df09a52 100644 --- a/media/java/android/media/MediaSession2.java +++ b/media/java/android/media/MediaSession2.java @@ -28,8 +28,8 @@ import android.content.Intent; import android.media.MediaPlayerBase.BuffState; import android.media.MediaPlayerBase.PlayerEventCallback; import android.media.MediaPlayerBase.PlayerState; -import android.media.MediaSession2.PlaylistParams.RepeatMode; -import android.media.MediaSession2.PlaylistParams.ShuffleMode; +import android.media.MediaPlaylistAgent.RepeatMode; +import android.media.MediaPlaylistAgent.ShuffleMode; import android.media.update.ApiLoader; import android.media.update.MediaSession2Provider; import android.media.update.MediaSession2Provider.BuilderBaseProvider; @@ -40,7 +40,6 @@ import android.media.update.MediaSession2Provider.ControllerInfoProvider; import android.media.update.ProviderCreator; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; import android.os.IInterface; import android.os.ResultReceiver; @@ -182,16 +181,6 @@ public class MediaSession2 implements AutoCloseable { public static final int COMMAND_CODE_PLAYBACK_ADJUST_VOLUME = 11; /** - * Command code for {@link MediaController2#setPlaylistParams(PlaylistParams)}. - * <p> - * Command would be sent directly to the player if the session doesn't reject the request - * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}. - * @hide - */ - // TODO(jaewan): Remove (b/74116823) - public static final int COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS = 12; - - /** * Command code for {@link MediaController2#skipToPlaylistItem(MediaItem2)}. * <p> * Command would be sent directly to the playlist agent if the session doesn't reject the @@ -314,6 +303,13 @@ public class MediaSession2 implements AutoCloseable { public static final int COMMAND_CODE_PREPARE_FROM_SEARCH = 27; /** + * Command code for {@link MediaController2#setRating(String, Rating2)}. + * @hide + */ + // TODO(jaewan): Unhide + public static final int COMMAND_CODE_SET_RATING = 29; + + /** * Command code for {@link MediaBrowser2} specific functions that allows navigation and search * from the {@link MediaLibraryService2}. This would be ignored for a {@link MediaSession2}, * not {@link android.media.MediaLibraryService2.MediaLibrarySession}. @@ -325,11 +321,6 @@ public class MediaSession2 implements AutoCloseable { /** * @hide */ - public static final int COMMAND_CODE_MAX = 28; - - /** - * @hide - */ @IntDef({ERROR_CODE_UNKNOWN_ERROR, ERROR_CODE_APP_ERROR, ERROR_CODE_NOT_SUPPORTED, ERROR_CODE_AUTHENTICATION_EXPIRED, ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED, ERROR_CODE_CONCURRENT_STREAM_LIMIT, ERROR_CODE_PARENTAL_CONTROL_RESTRICTED, @@ -452,6 +443,13 @@ public class MediaSession2 implements AutoCloseable { .createMediaSession2Command(this, COMMAND_CODE_CUSTOM, action, extras); } + /** + * @hide + */ + public CommandProvider getProvider() { + return mProvider; + } + public int getCommandCode() { return mProvider.getCommandCode_impl(); } @@ -510,6 +508,13 @@ public class MediaSession2 implements AutoCloseable { .createMediaSession2CommandGroup(context, this, others); } + /** + * @hide + */ + public CommandGroup(@NonNull CommandGroupProvider provider) { + mProvider = provider; + } + public void addCommand(@NonNull Command command) { mProvider.addCommand_impl(command); } @@ -622,7 +627,6 @@ public class MediaSession2 implements AutoCloseable { * @see #COMMAND_CODE_PLAYBACK_REWIND * @see #COMMAND_CODE_PLAYBACK_SEEK_TO * @see #COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM - * @see #COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS * @see #COMMAND_CODE_PLAYLIST_ADD_ITEM * @see #COMMAND_CODE_PLAYLIST_REMOVE_ITEM * @see #COMMAND_CODE_PLAYLIST_GET_LIST @@ -1219,134 +1223,6 @@ public class MediaSession2 implements AutoCloseable { } /** - * Parameter for the playlist. - * @hide - */ - // TODO(jaewan): Remove (b/74116823) - public final static class PlaylistParams { - /** - * @hide - */ - @IntDef({REPEAT_MODE_NONE, REPEAT_MODE_ONE, REPEAT_MODE_ALL, - REPEAT_MODE_GROUP}) - @Retention(RetentionPolicy.SOURCE) - public @interface RepeatMode {} - - /** - * Playback will be stopped at the end of the playing media list. - */ - public static final int REPEAT_MODE_NONE = 0; - - /** - * Playback of the current playing media item will be repeated. - */ - public static final int REPEAT_MODE_ONE = 1; - - /** - * Playing media list will be repeated. - */ - public static final int REPEAT_MODE_ALL = 2; - - /** - * Playback of the playing media group will be repeated. - * A group is a logical block of media items which is specified in the section 5.7 of the - * Bluetooth AVRCP 1.6. - */ - public static final int REPEAT_MODE_GROUP = 3; - - /** - * @hide - */ - @IntDef({SHUFFLE_MODE_NONE, SHUFFLE_MODE_ALL, SHUFFLE_MODE_GROUP}) - @Retention(RetentionPolicy.SOURCE) - public @interface ShuffleMode {} - - /** - * Media list will be played in order. - */ - public static final int SHUFFLE_MODE_NONE = 0; - - /** - * Media list will be played in shuffled order. - */ - public static final int SHUFFLE_MODE_ALL = 1; - - /** - * Media group will be played in shuffled order. - * A group is a logical block of media items which is specified in the section 5.7 of the - * Bluetooth AVRCP 1.6. - */ - public static final int SHUFFLE_MODE_GROUP = 2; - - - private final MediaSession2Provider.PlaylistParamsProvider mProvider; - - /** - * Instantiate {@link PlaylistParams} - * - * @param context context - * @param repeatMode repeat mode - * @param shuffleMode shuffle mode - * @param playlistMetadata metadata for the list - */ - public PlaylistParams(@NonNull Context context, @RepeatMode int repeatMode, - @ShuffleMode int shuffleMode, @Nullable MediaMetadata2 playlistMetadata) { - mProvider = ApiLoader.getProvider(context).createMediaSession2PlaylistParams( - context, this, repeatMode, shuffleMode, playlistMetadata); - } - - /** - * Create a new bundle for this object. - * - * @return - */ - public @NonNull Bundle toBundle() { - return mProvider.toBundle_impl(); - } - - /** - * Create a new playlist params from the bundle that was previously returned by - * {@link #toBundle}. - * - * @param context context - * @return a new playlist params. Can be {@code null} for error. - */ - public static @Nullable PlaylistParams fromBundle( - @NonNull Context context, @Nullable Bundle bundle) { - return ApiLoader.getProvider(context).fromBundle_PlaylistParams(context, bundle); - } - - /** - * Get repeat mode - * - * @return repeat mode - * @see #REPEAT_MODE_NONE, #REPEAT_MODE_ONE, #REPEAT_MODE_ALL, #REPEAT_MODE_GROUP - */ - public @RepeatMode int getRepeatMode() { - return mProvider.getRepeatMode_impl(); - } - - /** - * Get shuffle mode - * - * @return shuffle mode - * @see #SHUFFLE_MODE_NONE, #SHUFFLE_MODE_ALL, #SHUFFLE_MODE_GROUP - */ - public @ShuffleMode int getShuffleMode() { - return mProvider.getShuffleMode_impl(); - } - - /** - * Get metadata for the playlist - * - * @return metadata. Can be {@code null} - */ - public @Nullable MediaMetadata2 getPlaylistMetadata() { - return mProvider.getPlaylistMetadata_impl(); - } - } - - /** * Constructor is hidden and apps can only instantiate indirectly through {@link Builder}. * <p> * This intended behavior and here's the reasons. @@ -1579,29 +1455,6 @@ public class MediaSession2 implements AutoCloseable { } /** - * Sets the {@link PlaylistParams} for the current play list. Repeat/shuffle mode and metadata - * for the list can be set by calling this method. - * - * @param params A {@link PlaylistParams} object to set. - * @throws IllegalArgumentException if given {@param param} is null. - * @hide - */ - // TODO(jaewan): Remove (b/74116823) - public void setPlaylistParams(PlaylistParams params) { - mProvider.setPlaylistParams_impl(params); - } - - /** - * Returns the {@link PlaylistParams} for the current play list. - * Returns {@code null} if not set. - * @hide - */ - // TODO(jaewan): Remove (b/74116823) - public PlaylistParams getPlaylistParams() { - return mProvider.getPlaylistParams_impl(); - } - - /** * Notify errors to the connected controllers * * @param errorCode error code @@ -1612,65 +1465,37 @@ public class MediaSession2 implements AutoCloseable { } /** - * Register {@link PlayerEventCallback} to listen changes in the underlying - * {@link MediaPlayerBase}, regardless of the change in the underlying player. - * <p> - * Registered callbacks will be also called when the underlying player is changed. - * - * @param executor a callback Executor - * @param callback a EventCallback - * @throws IllegalArgumentException if executor or callback is {@code null}. - * @hide - */ - // TODO(jaewan): Remove (b/74157064) - public void registerPlayerEventCallback(@NonNull @CallbackExecutor Executor executor, - @NonNull PlayerEventCallback callback) { - mProvider.registerPlayerEventCallback_impl(executor, callback); - } - - /** - * Unregister the previously registered {@link PlayerEventCallback}. - * - * @param callback the callback to be removed - * @throws IllegalArgumentException if the callback is {@code null}. - * @hide - */ - // TODO(jaewan): Remove (b/74157064) - public void unregisterPlayerEventCallback(@NonNull PlayerEventCallback callback) { - mProvider.unregisterPlayerEventCallback_impl(callback); - } - - /** - * Get the player state. + * Gets the current player state. * - * @return player state + * @return the current player state * @hide */ + // TODO(jaewan): Unhide (b/74578458) public @PlayerState int getPlayerState() { - // TODO(jaewan): implement this (b/74578458) - return PLAYER_STATE_IDLE; + return mProvider.getPlayerState_impl(); } /** - * Get the current position. + * Gets the current position. * - * @return position + * @return the current playback position in ms, or {@link MediaPlayerBase#UNKNOWN_TIME} if + * unknown. * @hide */ - public long getCurrentPosition() { - // TODO(jaewan): implement this (b/74578458) - return -1; + // TODO(jaewan): Unhide (b/74578458) + public long getPosition() { + return mProvider.getPosition_impl(); } /** - * Get the buffered position. + * Gets the buffered position, or {@link MediaPlayerBase#UNKNOWN_TIME} if unknown. * - * @return buffered position + * @return the buffered position in ms, or {@link MediaPlayerBase#UNKNOWN_TIME}. * @hide */ + // TODO(jaewan): Unhide (b/74578458) public long getBufferedPosition() { - // TODO(jaewan): implement this (b/74578458) - return -1; + return mProvider.getBufferedPosition_impl(); } /** @@ -1774,20 +1599,41 @@ public class MediaSession2 implements AutoCloseable { } /** - * 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(); } @@ -1857,21 +1703,53 @@ public class MediaSession2 implements AutoCloseable { mProvider.updatePlaylistMetadata_impl(metadata); } + /** + * Gets the repeat mode from the {@link MediaPlaylistAgent}. + * + * @return repeat mode + * @see MediaPlaylistAgent#REPEAT_MODE_NONE + * @see MediaPlaylistAgent#REPEAT_MODE_ONE + * @see MediaPlaylistAgent#REPEAT_MODE_ALL + * @see MediaPlaylistAgent#REPEAT_MODE_GROUP + */ public @RepeatMode int getRepeatMode() { - // TODO(jaewan): Implement (b/74118768) - return 0; + return mProvider.getRepeatMode_impl(); } + /** + * Sets the repeat mode to the {@link MediaPlaylistAgent}. + * + * @param repeatMode repeat mode + * @see MediaPlaylistAgent#REPEAT_MODE_NONE + * @see MediaPlaylistAgent#REPEAT_MODE_ONE + * @see MediaPlaylistAgent#REPEAT_MODE_ALL + * @see MediaPlaylistAgent#REPEAT_MODE_GROUP + */ public void setRepeatMode(@RepeatMode int repeatMode) { - // TODO(jaewan): Implement (b/74118768) + mProvider.setRepeatMode_impl(repeatMode); } + /** + * Gets the shuffle mode from the {@link MediaPlaylistAgent}. + * + * @return The shuffle mode + * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE + * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL + * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP + */ public @ShuffleMode int getShuffleMode() { - // TODO(jaewan): Implement (b/74118768) - return 0; + return mProvider.getShuffleMode_impl(); } + /** + * Sets the shuffle mode to the {@link MediaPlaylistAgent}. + * + * @param shuffleMode The shuffle mode + * @see MediaPlaylistAgent#SHUFFLE_MODE_NONE + * @see MediaPlaylistAgent#SHUFFLE_MODE_ALL + * @see MediaPlaylistAgent#SHUFFLE_MODE_GROUP + */ public void setShuffleMode(@ShuffleMode int shuffleMode) { - // TODO(jaewan): Implement (b/74118768) + mProvider.setShuffleMode_impl(shuffleMode); } } diff --git a/media/java/android/media/update/MediaController2Provider.java b/media/java/android/media/update/MediaController2Provider.java index 55672b68de7a..22e5b181228b 100644 --- a/media/java/android/media/update/MediaController2Provider.java +++ b/media/java/android/media/update/MediaController2Provider.java @@ -22,7 +22,6 @@ import android.media.MediaController2.PlaybackInfo; import android.media.MediaItem2; import android.media.MediaMetadata2; import android.media.MediaSession2.Command; -import android.media.MediaSession2.PlaylistParams; import android.media.Rating2; import android.media.SessionToken2; import android.net.Uri; @@ -65,8 +64,6 @@ public interface MediaController2Provider extends TransportControlProvider { void replacePlaylistItem_impl(int index, MediaItem2 item); void removePlaylistItem_impl(MediaItem2 item); - PlaylistParams getPlaylistParams_impl(); - void setPlaylistParams_impl(PlaylistParams params); int getPlayerState_impl(); long getPosition_impl(); float getPlaybackSpeed_impl(); diff --git a/media/java/android/media/update/MediaPlaylistAgentProvider.java b/media/java/android/media/update/MediaPlaylistAgentProvider.java index b27d5a1e7b62..e1522cf5b619 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 @@ public interface MediaPlaylistAgentProvider { void setRepeatMode_impl(int repeatMode); int getShuffleMode_impl(); void setShuffleMode_impl(int shuffleMode); + MediaItem2 getMediaItem_impl(DataSourceDesc dsd); } diff --git a/media/java/android/media/update/MediaSession2Provider.java b/media/java/android/media/update/MediaSession2Provider.java index 84ea369336d7..e5ea38667983 100644 --- a/media/java/android/media/update/MediaSession2Provider.java +++ b/media/java/android/media/update/MediaSession2Provider.java @@ -29,7 +29,6 @@ import android.media.MediaSession2.CommandButton; import android.media.MediaSession2.CommandButton.Builder; import android.media.MediaSession2.CommandGroup; import android.media.MediaSession2.ControllerInfo; -import android.media.MediaSession2.PlaylistParams; import android.media.MediaSession2.SessionCallback; import android.media.SessionToken2; import android.media.VolumeProvider2; @@ -65,11 +64,10 @@ public interface MediaSession2Provider extends TransportControlProvider { List<MediaItem2> getPlaylist_impl(); void setPlaylist_impl(List<MediaItem2> list, MediaMetadata2 metadata); MediaItem2 getCurrentPlaylistItem_impl(); - void setPlaylistParams_impl(PlaylistParams params); - PlaylistParams getPlaylistParams_impl(); void notifyError_impl(int errorCode, Bundle extras); - void registerPlayerEventCallback_impl(Executor executor, PlayerEventCallback callback); - void unregisterPlayerEventCallback_impl(PlayerEventCallback callback); + int getPlayerState_impl(); + long getPosition_impl(); + long getBufferedPosition_impl(); interface CommandProvider { int getCommandCode_impl(); @@ -117,13 +115,6 @@ public interface MediaSession2Provider extends TransportControlProvider { String toString_impl(); } - interface PlaylistParamsProvider { - int getRepeatMode_impl(); - int getShuffleMode_impl(); - MediaMetadata2 getPlaylistMetadata_impl(); - Bundle toBundle_impl(); - } - interface BuilderBaseProvider<T extends MediaSession2, C extends SessionCallback> { void setPlayer_impl(MediaPlayerBase player); void setPlaylistAgent_impl(MediaPlaylistAgent playlistAgent); diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java index f78d4a48f1ac..1c0e2556f12d 100644 --- a/media/java/android/media/update/StaticProvider.java +++ b/media/java/android/media/update/StaticProvider.java @@ -31,7 +31,6 @@ import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessio import android.media.MediaMetadata2; import android.media.MediaPlaylistAgent; import android.media.MediaSession2; -import android.media.MediaSession2.PlaylistParams; import android.media.MediaSession2.SessionCallback; import android.media.MediaSessionService2; import android.media.MediaSessionService2.MediaNotification; @@ -44,7 +43,6 @@ import android.media.update.MediaSession2Provider.CommandButtonProvider; import android.media.update.MediaSession2Provider.CommandGroupProvider; import android.media.update.MediaSession2Provider.CommandProvider; import android.media.update.MediaSession2Provider.ControllerInfoProvider; -import android.media.update.MediaSession2Provider.PlaylistParamsProvider; import android.media.update.MediaSessionService2Provider.MediaNotificationProvider; import android.os.Bundle; import android.os.IInterface; @@ -78,10 +76,6 @@ public interface StaticProvider { ControllerInfoProvider createMediaSession2ControllerInfo(Context context, MediaSession2.ControllerInfo instance, int uid, int pid, String packageName, IInterface callback); - PlaylistParamsProvider createMediaSession2PlaylistParams(Context context, - PlaylistParams playlistParams, int repeatMode, int shuffleMode, - MediaMetadata2 playlistMetadata); - PlaylistParams fromBundle_PlaylistParams(Context context, Bundle bundle); CommandButtonProvider.BuilderProvider createMediaSession2CommandButtonBuilder(Context context, MediaSession2.CommandButton.Builder instance); BuilderBaseProvider<MediaSession2, SessionCallback> createMediaSession2Builder( diff --git a/media/java/android/media/update/TransportControlProvider.java b/media/java/android/media/update/TransportControlProvider.java index eb03ca7fc0e5..03944d243dc8 100644 --- a/media/java/android/media/update/TransportControlProvider.java +++ b/media/java/android/media/update/TransportControlProvider.java @@ -33,4 +33,9 @@ public interface TransportControlProvider { void rewind_impl(); void seekTo_impl(long pos); void skipToPlaylistItem_impl(MediaItem2 item); + + int getRepeatMode_impl(); + void setRepeatMode_impl(int repeatMode); + int getShuffleMode_impl(); + void setShuffleMode_impl(int shuffleMode); } diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 44e5d61361cd..0ba45f1391c5 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -128,7 +128,6 @@ cc_library_shared { "libcutils", "libdexfile", "liblzma", - "libmedia", "libmedia_helper", "libmedia_player2_util", "libmediadrm", @@ -149,7 +148,6 @@ cc_library_shared { "libstagefright_timedtext", "libunwindstack", "libutilscallstack", - "libvndksupport", "libz", "libziparchive", ], diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index a1022c082909..000317e688da 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 @@ static struct { 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 @@ status_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const { 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 @@ static jobject android_media_MediaCodec_getName( 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 @@ static void android_media_MediaCodec_native_init(JNIEnv *env) { 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 @@ static const JNINativeMethod gMethods[] = { { "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 2ec8703adc83..985f55a89254 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -120,6 +120,8 @@ struct JMediaCodec : public AHandler { 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> ¶ms); diff --git a/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java b/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java index 4709d35018c2..9ba7e092f34b 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 @@ import java.util.List; 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 @@ public class AutofillFieldClassificationServiceImpl extends AutofillFieldClassif 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"); - } - - 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); + + DEFAULT_ALGORITHM + " instead"); } - 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 d2e804af1b43..302b16022c26 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"; + + // TODO(b/70291841): STOPSHIP - set to false before launching + private static final boolean DEBUG = true; - public static final String NAME = "EDIT_DISTANCE"; + static final String DEFAULT_ALGORITHM = "EDIT_DISTANCE"; /** - * Gets the singleton instance. + * Gets the field classification score of 2 values based on the edit distance between them. + * + * <p>The score is defined as: @(max_length - edit_distance) / max_length */ - public static EditDistanceScorer getInstance() { - return sInstance; + @VisibleForTesting + static float getScore(@Nullable AutofillValue actualValue, @Nullable String userDataValue) { + if (actualValue == null || !actualValue.isText() || userDataValue == null) return 0; + + 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; } - private EditDistanceScorer() { + /** + * 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); } /** - * Returns the classification score between an actual {@link AutofillValue} filled - * by the user and the expected value predicted by an autofill service. + * 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>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>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 */ - public float getScore(@NonNull AutofillValue actualValue, @NonNull 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++; + // 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 000000000000..48c076e67e78 --- /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 cc1571920e86..afe223641d37 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 android.ext.services.autofill.EditDistanceScorer.getScore; +import static android.ext.services.autofill.EditDistanceScorer.getScores; +import static android.view.autofill.AutofillValue.forText; + import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; -import android.support.test.runner.AndroidJUnit4; import android.view.autofill.AutofillValue; import org.junit.Test; -import org.junit.runner.RunWith; -@RunWith(AndroidJUnit4.class) -public class EditDistanceScorerTest { +import java.util.Arrays; +import java.util.List; - private final EditDistanceScorer mScorer = EditDistanceScorer.getInstance(); +public class EditDistanceScorerTest { @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/SettingsLib/common.mk b/packages/SettingsLib/common.mk index 15b50d719291..28f97d1948bd 100644 --- a/packages/SettingsLib/common.mk +++ b/packages/SettingsLib/common.mk @@ -16,11 +16,11 @@ ifeq ($(LOCAL_USE_AAPT2),true) LOCAL_STATIC_JAVA_LIBRARIES += \ android-support-annotations \ - apptoolkit-lifecycle-common + android-arch-lifecycle-common LOCAL_STATIC_ANDROID_LIBRARIES += \ android-support-v4 \ - apptoolkit-lifecycle-runtime \ + android-arch-lifecycle-runtime \ android-support-v7-recyclerview \ android-support-v7-preference \ android-support-v7-appcompat \ diff --git a/packages/SettingsLib/res/layout/preference_access_point.xml b/packages/SettingsLib/res/layout/preference_access_point.xml new file mode 100644 index 000000000000..62173da5b7eb --- /dev/null +++ b/packages/SettingsLib/res/layout/preference_access_point.xml @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<!-- Based off preference_two_target.xml with Material ripple moved to parent for full ripple. --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:settings="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:gravity="center_vertical" + android:background="?android:attr/selectableItemBackground" + android:clipToPadding="false"> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:gravity="start|center_vertical" + android:clipToPadding="false" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> + + <LinearLayout + android:id="@+id/icon_frame" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="start|center_vertical" + android:minWidth="56dp" + android:orientation="horizontal" + android:clipToPadding="false" + android:paddingTop="4dp" + android:paddingBottom="4dp"> + <android.support.v7.internal.widget.PreferenceImageView + android:id="@android:id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + settings:maxWidth="48dp" + settings:maxHeight="48dp" /> + </LinearLayout> + + <RelativeLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1" + android:paddingTop="16dp" + android:paddingBottom="16dp"> + + <TextView + android:id="@android:id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceListItem" + android:ellipsize="marquee" /> + + <TextView + android:id="@android:id/summary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@android:id/title" + android:layout_alignStart="@android:id/title" + android:textAppearance="?android:attr/textAppearanceListItemSecondary" + android:textColor="?android:attr/textColorSecondary" + android:maxLines="10" /> + + </RelativeLayout> + + </LinearLayout> + + <include layout="@layout/preference_two_target_divider" /> + + <!-- Preference should place its actual preference widget here. --> + <LinearLayout + android:id="@android:id/widget_frame" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:minWidth="64dp" + android:gravity="center" + android:orientation="vertical" /> + +</LinearLayout> diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java index 2b6d09f9b72e..70816782541d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java +++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java @@ -19,6 +19,7 @@ package com.android.settingslib.fuelgauge; import android.os.IDeviceIdleController; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.support.annotation.VisibleForTesting; import android.util.ArraySet; import android.util.Log; @@ -37,6 +38,7 @@ public class PowerWhitelistBackend { private final IDeviceIdleController mDeviceIdleService; private final ArraySet<String> mWhitelistedApps = new ArraySet<>(); private final ArraySet<String> mSysWhitelistedApps = new ArraySet<>(); + private final ArraySet<String> mSysWhitelistedAppsExceptIdle = new ArraySet<>(); public PowerWhitelistBackend() { mDeviceIdleService = IDeviceIdleController.Stub.asInterface( @@ -62,6 +64,10 @@ public class PowerWhitelistBackend { return mWhitelistedApps.contains(pkg); } + public boolean isSysWhitelistedExceptIdle(String pkg) { + return mSysWhitelistedAppsExceptIdle.contains(pkg); + } + public void addApp(String pkg) { try { mDeviceIdleService.addPowerSaveWhitelistApp(pkg); @@ -83,6 +89,7 @@ public class PowerWhitelistBackend { @VisibleForTesting public void refreshList() { mSysWhitelistedApps.clear(); + mSysWhitelistedAppsExceptIdle.clear(); mWhitelistedApps.clear(); try { String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist(); @@ -93,6 +100,11 @@ public class PowerWhitelistBackend { for (String app : sysWhitelistedApps) { mSysWhitelistedApps.add(app); } + String[] sysWhitelistedAppsExceptIdle = + mDeviceIdleService.getSystemPowerWhitelistExceptIdle(); + for (String app : sysWhitelistedAppsExceptIdle) { + mSysWhitelistedAppsExceptIdle.add(app); + } } catch (RemoteException e) { Log.w(TAG, "Unable to reach IDeviceIdleController", e); } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java index 8115ede2729e..26f3683f92b4 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java @@ -68,6 +68,7 @@ public class AccessPointPreference extends Preference { private final UserBadgeCache mBadgeCache; private final IconInjector mIconInjector; private TextView mTitleView; + private boolean mShowDivider; private boolean mForSavedNetworks = false; private AccessPoint mAccessPoint; @@ -115,7 +116,8 @@ public class AccessPointPreference extends Preference { int iconResId, boolean forSavedNetworks, StateListDrawable frictionSld, int level, IconInjector iconInjector) { super(context); - setWidgetLayoutResource(R.layout.access_point_friction_widget); + setLayoutResource(R.layout.preference_access_point); + setWidgetLayoutResource(getWidgetLayoutResourceId()); mBadgeCache = cache; mAccessPoint = accessPoint; mForSavedNetworks = forSavedNetworks; @@ -128,6 +130,10 @@ public class AccessPointPreference extends Preference { .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding); } + protected int getWidgetLayoutResourceId() { + return R.layout.access_point_friction_widget; + } + public AccessPoint getAccessPoint() { return mAccessPoint; } @@ -154,6 +160,18 @@ public class AccessPointPreference extends Preference { ImageView frictionImageView = (ImageView) view.findViewById(R.id.friction_icon); bindFrictionImage(frictionImageView); + + final View divider = view.findViewById(R.id.two_target_divider); + divider.setVisibility(shouldShowDivider() ? View.VISIBLE : View.INVISIBLE); + } + + public boolean shouldShowDivider() { + return mShowDivider; + } + + public void setShowDivider(boolean showDivider) { + mShowDivider = showDivider; + notifyChanged(); } protected void updateIcon(int level, Context context) { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java index c6a1428fa34e..5a123af02ca4 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java @@ -48,6 +48,7 @@ public class PowerWhitelistBackendTest { MockitoAnnotations.initMocks(this); doReturn(new String[] {}).when(mDeviceIdleService).getFullPowerWhitelist(); doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelist(); + doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelistExceptIdle(); doNothing().when(mDeviceIdleService).addPowerSaveWhitelistApp(anyString()); doNothing().when(mDeviceIdleService).removePowerSaveWhitelistApp(anyString()); mPowerWhitelistBackend = new PowerWhitelistBackend(mDeviceIdleService); @@ -88,6 +89,15 @@ public class PowerWhitelistBackendTest { assertThat(mPowerWhitelistBackend.isSysWhitelisted(PACKAGE_ONE)).isTrue(); assertThat(mPowerWhitelistBackend.isSysWhitelisted(PACKAGE_TWO)).isFalse(); assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isFalse(); + } + + @Test + public void testIsSystemWhitelistedExceptIdle() throws Exception { + doReturn(new String[]{PACKAGE_TWO}).when( + mDeviceIdleService).getSystemPowerWhitelistExceptIdle(); + mPowerWhitelistBackend.refreshList(); + assertThat(mPowerWhitelistBackend.isSysWhitelistedExceptIdle(PACKAGE_ONE)).isFalse(); + assertThat(mPowerWhitelistBackend.isSysWhitelistedExceptIdle(PACKAGE_TWO)).isTrue(); } } diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index 1cd02f418352..ecda53a15f48 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -207,4 +207,7 @@ Else (if negative), turning on dnd manually will surface a dialog that prompts user to specify a duration.--> <integer name="def_zen_duration">0</integer> + + <!-- Default for Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS --> + <string name="def_backup_agent_timeout_parameters"></string> </resources> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index cfcfb95b0f88..4530f8062f0d 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -40,6 +40,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Global; import android.provider.Settings.Secure; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; @@ -2594,15 +2595,26 @@ class DatabaseHelper extends SQLiteOpenHelper { loadSetting(stmt, Settings.Global.CALL_AUTO_RETRY, 0); // Set the preferred network mode to target desired value or Default - // value defined in RILConstants - int type; - type = RILConstants.PREFERRED_NETWORK_MODE; - loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, type); + // value defined in system property + String val = ""; + String mode; + for (int phoneId = 0; + phoneId < TelephonyManager.getDefault().getPhoneCount(); phoneId++) { + mode = TelephonyManager.getTelephonyProperty(phoneId, + "ro.telephony.default_network", + Integer.toString(RILConstants.PREFERRED_NETWORK_MODE)); + if (phoneId == 0) { + val = mode; + } else { + val = val + "," + mode; + } + } + loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, val); // Set the preferred cdma subscription source to target desired value or default // value defined in Phone - type = SystemProperties.getInt("ro.telephony.default_cdma_sub", - Phone.PREFERRED_CDMA_SUBSCRIPTION); + int type = SystemProperties.getInt("ro.telephony.default_cdma_sub", + Phone.PREFERRED_CDMA_SUBSCRIPTION); loadSetting(stmt, Settings.Global.CDMA_SUBSCRIPTION_MODE, type); loadIntegerSetting(stmt, Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index ccb4d8c866da..9a438398127d 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -39,19 +39,15 @@ class SettingsProtoDumpUtil { SettingsState globalSettings = settingsRegistry.getSettingsLocked( SettingsProvider.SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); if (globalSettings != null) { - long globalSettingsToken = proto.start(SettingsServiceDumpProto.GLOBAL_SETTINGS); - dumpProtoGlobalSettingsLocked(globalSettings, proto); - proto.end(globalSettingsToken); + dumpProtoGlobalSettingsLocked(proto, SettingsServiceDumpProto.GLOBAL_SETTINGS, globalSettings); } // Per-user settings SparseBooleanArray users = settingsRegistry.getKnownUsersLocked(); final int userCount = users.size(); for (int i = 0; i < userCount; i++) { - long userSettingsToken = proto.start(SettingsServiceDumpProto.USER_SETTINGS); - dumpProtoUserSettingsLocked( - settingsRegistry, UserHandle.of(users.keyAt(i)), proto); - proto.end(userSettingsToken); + dumpProtoUserSettingsLocked(proto, SettingsServiceDumpProto.USER_SETTINGS, + settingsRegistry, UserHandle.of(users.keyAt(i))); } } @@ -63,30 +59,33 @@ class SettingsProtoDumpUtil { * @param proto The proto buf stream to dump to */ private static void dumpProtoUserSettingsLocked( + @NonNull ProtoOutputStream proto, + long fieldId, SettingsProvider.SettingsRegistry settingsRegistry, - @NonNull UserHandle user, - @NonNull ProtoOutputStream proto) { + @NonNull UserHandle user) { + final long token = proto.start(fieldId); + proto.write(UserSettingsProto.USER_ID, user.getIdentifier()); SettingsState secureSettings = settingsRegistry.getSettingsLocked( SettingsProvider.SETTINGS_TYPE_SECURE, user.getIdentifier()); if (secureSettings != null) { - long secureSettingsToken = proto.start(UserSettingsProto.SECURE_SETTINGS); - dumpProtoSecureSettingsLocked(secureSettings, proto); - proto.end(secureSettingsToken); + dumpProtoSecureSettingsLocked(proto, UserSettingsProto.SECURE_SETTINGS, secureSettings); } SettingsState systemSettings = settingsRegistry.getSettingsLocked( SettingsProvider.SETTINGS_TYPE_SYSTEM, user.getIdentifier()); if (systemSettings != null) { - long systemSettingsToken = proto.start(UserSettingsProto.SYSTEM_SETTINGS); - dumpProtoSystemSettingsLocked(systemSettings, proto); - proto.end(systemSettingsToken); + dumpProtoSystemSettingsLocked(proto, UserSettingsProto.SYSTEM_SETTINGS, systemSettings); } + + proto.end(token); } private static void dumpProtoGlobalSettingsLocked( - @NonNull SettingsState s, @NonNull ProtoOutputStream p) { + @NonNull ProtoOutputStream p, long fieldId, @NonNull SettingsState s) { + final long token = p.start(fieldId); + s.dumpHistoricalOperations(p, GlobalSettingsProto.HISTORICAL_OPERATIONS); // This uses the same order as in Settings.Global. @@ -102,6 +101,11 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.THEATER_MODE_ON, GlobalSettingsProto.THEATER_MODE_ON); + // RADIO_BLUETOOTH is just a constant and not an actual setting. + // RADIO_WIFI is just a constant and not an actual setting. + // RADIO_WIMAX is just a constant and not an actual setting. + // RADIO_CELL is just a constant and not an actual setting. + // RADIO_NFC is just a constant and not an actual setting. dumpSetting(s, p, Settings.Global.AIRPLANE_MODE_RADIOS, GlobalSettingsProto.AIRPLANE_MODE_RADIOS); @@ -253,6 +257,9 @@ class SettingsProtoDumpUtil { Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, GlobalSettingsProto.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED); dumpSetting(s, p, + Settings.Global.PRIV_APP_OOB_ENABLED, + GlobalSettingsProto.PRIV_APP_OOB_ENABLED); + dumpSetting(s, p, Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, GlobalSettingsProto.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS); dumpSetting(s, p, @@ -343,6 +350,9 @@ class SettingsProtoDumpUtil { Settings.Global.NETWORK_SCORER_APP, GlobalSettingsProto.NETWORK_SCORER_APP); dumpSetting(s, p, + Settings.Global.NIGHT_DISPLAY_FORCED_AUTO_MODE_AVAILABLE, + GlobalSettingsProto.NIGHT_DISPLAY_FORCED_AUTO_MODE_AVAILABLE); + dumpSetting(s, p, Settings.Global.NITZ_UPDATE_DIFF, GlobalSettingsProto.NITZ_UPDATE_DIFF); dumpSetting(s, p, @@ -499,6 +509,9 @@ class SettingsProtoDumpUtil { Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, GlobalSettingsProto.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON); dumpSetting(s, p, + Settings.Global.WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON, + GlobalSettingsProto.WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON); + dumpSetting(s, p, Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON, GlobalSettingsProto.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON); dumpSetting(s, p, @@ -523,6 +536,9 @@ class SettingsProtoDumpUtil { Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, GlobalSettingsProto.WIFI_SCAN_ALWAYS_AVAILABLE); dumpSetting(s, p, + Settings.Global.SOFT_AP_TIMEOUT_ENABLED, + GlobalSettingsProto.SOFT_AP_TIMEOUT_ENABLED); + dumpSetting(s, p, Settings.Global.WIFI_WAKEUP_ENABLED, GlobalSettingsProto.WIFI_WAKEUP_ENABLED); dumpSetting(s, p, @@ -532,6 +548,9 @@ class SettingsProtoDumpUtil { Settings.Global.SPEED_LABEL_CACHE_EVICTION_AGE_MILLIS, GlobalSettingsProto.SPEED_LABEL_CACHE_EVICTION_AGE_MILLIS); dumpSetting(s, p, + Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS, + GlobalSettingsProto.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS); + dumpSetting(s, p, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, GlobalSettingsProto.NETWORK_RECOMMENDATIONS_ENABLED); dumpSetting(s, p, @@ -544,12 +563,27 @@ class SettingsProtoDumpUtil { Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, GlobalSettingsProto.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS); dumpSetting(s, p, - Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS, - GlobalSettingsProto.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS); - dumpSetting(s, p, Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, GlobalSettingsProto.BLE_SCAN_ALWAYS_AVAILABLE); dumpSetting(s, p, + Settings.Global.BLE_SCAN_LOW_POWER_WINDOW_MS, + GlobalSettingsProto.BLE_SCAN_LOW_POWER_WINDOW_MS); + dumpSetting(s, p, + Settings.Global.BLE_SCAN_BALANCED_WINDOW_MS, + GlobalSettingsProto.BLE_SCAN_BALANCED_WINDOW_MS); + dumpSetting(s, p, + Settings.Global.BLE_SCAN_LOW_LATENCY_WINDOW_MS, + GlobalSettingsProto.BLE_SCAN_LOW_LATENCY_WINDOW_MS); + dumpSetting(s, p, + Settings.Global.BLE_SCAN_LOW_POWER_INTERVAL_MS, + GlobalSettingsProto.BLE_SCAN_LOW_POWER_INTERVAL_MS); + dumpSetting(s, p, + Settings.Global.BLE_SCAN_BALANCED_INTERVAL_MS, + GlobalSettingsProto.BLE_SCAN_BALANCED_INTERVAL_MS); + dumpSetting(s, p, + Settings.Global.BLE_SCAN_LOW_LATENCY_INTERVAL_MS, + GlobalSettingsProto.BLE_SCAN_LOW_LATENCY_INTERVAL_MS); + dumpSetting(s, p, Settings.Global.WIFI_SAVED_STATE, GlobalSettingsProto.WIFI_SAVED_STATE); dumpSetting(s, p, @@ -645,12 +679,12 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.DROPBOX_RESERVE_PERCENT, GlobalSettingsProto.DROPBOX_RESERVE_PERCENT); - dumpSetting(s, p, + dumpRepeatedSetting(s, p, Settings.Global.DROPBOX_TAG_PREFIX, - GlobalSettingsProto.DROPBOX_TAG_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.DROPBOX_SETTINGS); + dumpRepeatedSetting(s, p, Settings.Global.ERROR_LOGCAT_PREFIX, - GlobalSettingsProto.ERROR_LOGCAT_PREFIX); + GlobalSettingsProto.ERROR_LOGCAT_LINES); dumpSetting(s, p, Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL, GlobalSettingsProto.SYS_FREE_STORAGE_LOG_INTERVAL); @@ -756,42 +790,42 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.PRIVATE_DNS_SPECIFIER, GlobalSettingsProto.PRIVATE_DNS_SPECIFIER); - dumpSetting(s, p, + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_HEADSET_PRIORITY_PREFIX, - GlobalSettingsProto.BLUETOOTH_HEADSET_PRIORITY_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_HEADSET_PRIORITIES); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX, - GlobalSettingsProto.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_A2DP_SINK_PRIORITIES); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX, - GlobalSettingsProto.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_A2DP_SRC_PRIORITIES); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX, - GlobalSettingsProto.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX, - GlobalSettingsProto.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX, - GlobalSettingsProto.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_INPUT_DEVICE_PRIORITIES); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_MAP_PRIORITY_PREFIX, - GlobalSettingsProto.BLUETOOTH_MAP_PRIORITY_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_MAP_PRIORITIES); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX, - GlobalSettingsProto.BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_MAP_CLIENT_PRIORITIES); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_PBAP_CLIENT_PRIORITY_PREFIX, - GlobalSettingsProto.BLUETOOTH_PBAP_CLIENT_PRIORITY_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_PBAP_CLIENT_PRIORITIES); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_SAP_PRIORITY_PREFIX, - GlobalSettingsProto.BLUETOOTH_SAP_PRIORITY_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_SAP_PRIORITIES); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_PAN_PRIORITY_PREFIX, - GlobalSettingsProto.BLUETOOTH_PAN_PRIORITY_PREFIX); - dumpSetting(s, p, + GlobalSettingsProto.BLUETOOTH_PAN_PRIORITIES); + dumpRepeatedSetting(s, p, Settings.Global.BLUETOOTH_HEARING_AID_PRIORITY_PREFIX, - GlobalSettingsProto.BLUETOOTH_HEARING_AID_PRIORITY_PREFIX); + GlobalSettingsProto.BLUETOOTH_HEARING_AID_PRIORITIES); dumpSetting(s, p, Settings.Global.ACTIVITY_MANAGER_CONSTANTS, GlobalSettingsProto.ACTIVITY_MANAGER_CONSTANTS); @@ -802,12 +836,36 @@ class SettingsProtoDumpUtil { Settings.Global.BATTERY_SAVER_CONSTANTS, GlobalSettingsProto.BATTERY_SAVER_CONSTANTS); dumpSetting(s, p, + Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS, + GlobalSettingsProto.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS); + dumpSetting(s, p, + Settings.Global.BATTERY_TIP_CONSTANTS, + GlobalSettingsProto.BATTERY_TIP_CONSTANTS); + dumpSetting(s, p, Settings.Global.ANOMALY_DETECTION_CONSTANTS, GlobalSettingsProto.ANOMALY_DETECTION_CONSTANTS); dumpSetting(s, p, + Settings.Global.ANOMALY_CONFIG_VERSION, + GlobalSettingsProto.ANOMALY_CONFIG_VERSION); + dumpSetting(s, p, + Settings.Global.ANOMALY_CONFIG, + GlobalSettingsProto.ANOMALY_CONFIG); + dumpSetting(s, p, Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS, GlobalSettingsProto.ALWAYS_ON_DISPLAY_CONSTANTS); dumpSetting(s, p, + Settings.Global.SYS_VDSO, + GlobalSettingsProto.SYS_VDSO); + dumpSetting(s, p, + Settings.Global.SYS_UIDCPUPOWER, + GlobalSettingsProto.SYS_UIDCPUPOWER); + dumpSetting(s, p, + Settings.Global.FPS_DEVISOR, + GlobalSettingsProto.FPS_DIVISOR); + dumpSetting(s, p, + Settings.Global.DISPLAY_PANEL_LPM, + GlobalSettingsProto.DISPLAY_PANEL_LPM); + dumpSetting(s, p, Settings.Global.APP_IDLE_CONSTANTS, GlobalSettingsProto.APP_IDLE_CONSTANTS); dumpSetting(s, p, @@ -829,6 +887,42 @@ class SettingsProtoDumpUtil { Settings.Global.TEXT_CLASSIFIER_CONSTANTS, GlobalSettingsProto.TEXT_CLASSIFIER_CONSTANTS); dumpSetting(s, p, + Settings.Global.BATTERY_STATS_CONSTANTS, + GlobalSettingsProto.BATTERY_STATS_CONSTANTS); + dumpSetting(s, p, + Settings.Global.SYNC_MANAGER_CONSTANTS, + GlobalSettingsProto.SYNC_MANAGER_CONSTANTS); + dumpSetting(s, p, + Settings.Global.APP_STANDBY_ENABLED, + GlobalSettingsProto.APP_STANDBY_ENABLED); + dumpSetting(s, p, + Settings.Global.APP_AUTO_RESTRICTION_ENABLED, + GlobalSettingsProto.APP_AUTO_RESTRICTION_ENABLED); + dumpSetting(s, p, + Settings.Global.FORCED_APP_STANDBY_ENABLED, + GlobalSettingsProto.FORCED_APP_STANDBY_ENABLED); + dumpSetting(s, p, + Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, + GlobalSettingsProto.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED); + dumpSetting(s, p, + Settings.Global.OFF_BODY_RADIOS_OFF_FOR_SMALL_BATTERY_ENABLED, + GlobalSettingsProto.OFF_BODY_RADIOS_OFF_FOR_SMALL_BATTERY_ENABLED); + dumpSetting(s, p, + Settings.Global.OFF_BODY_RADIOS_OFF_DELAY_MS, + GlobalSettingsProto.OFF_BODY_RADIOS_OFF_DELAY_MS); + dumpSetting(s, p, + Settings.Global.WIFI_ON_WHEN_PROXY_DISCONNECTED, + GlobalSettingsProto.WIFI_ON_WHEN_PROXY_DISCONNECTED); + dumpSetting(s, p, + Settings.Global.TIME_ONLY_MODE_ENABLED, + GlobalSettingsProto.TIME_ONLY_MODE_ENABLED); + dumpSetting(s, p, + Settings.Global.NETWORK_WATCHLIST_ENABLED, + GlobalSettingsProto.NETWORK_WATCHLIST_ENABLED); + dumpSetting(s, p, + Settings.Global.KEEP_PROFILE_IN_BACKGROUND, + GlobalSettingsProto.KEEP_PROFILE_IN_BACKGROUND); + dumpSetting(s, p, Settings.Global.WINDOW_ANIMATION_SCALE, GlobalSettingsProto.WINDOW_ANIMATION_SCALE); dumpSetting(s, p, @@ -870,15 +964,6 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.GPU_DEBUG_LAYERS, GlobalSettingsProto.GPU_DEBUG_LAYERS); - dumpSetting(s, p, - Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, - GlobalSettingsProto.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING); - dumpSetting(s, p, - Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT, - GlobalSettingsProto.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT); - dumpSetting(s, p, - Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS, - GlobalSettingsProto.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS); // Settings.Global.SHOW_PROCESSES intentionally excluded since it's deprecated. dumpSetting(s, p, Settings.Global.LOW_POWER_MODE, @@ -887,6 +972,9 @@ class SettingsProtoDumpUtil { Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, GlobalSettingsProto.LOW_POWER_MODE_TRIGGER_LEVEL); dumpSetting(s, p, + Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, + GlobalSettingsProto.LOW_POWER_MODE_TRIGGER_LEVEL_MAX); + dumpSetting(s, p, Settings.Global.ALWAYS_FINISH_ACTIVITIES, GlobalSettingsProto.ALWAYS_FINISH_ACTIVITIES); dumpSetting(s, p, @@ -962,6 +1050,9 @@ class SettingsProtoDumpUtil { Settings.Global.POLICY_CONTROL, GlobalSettingsProto.POLICY_CONTROL); dumpSetting(s, p, + Settings.Global.EMULATE_DISPLAY_CUTOUT, + GlobalSettingsProto.EMULATE_DISPLAY_CUTOUT); + dumpSetting(s, p, Settings.Global.ZEN_MODE, GlobalSettingsProto.ZEN_MODE); dumpSetting(s, p, @@ -971,6 +1062,9 @@ class SettingsProtoDumpUtil { Settings.Global.ZEN_MODE_CONFIG_ETAG, GlobalSettingsProto.ZEN_MODE_CONFIG_ETAG); dumpSetting(s, p, + Settings.Global.ZEN_DURATION, + GlobalSettingsProto.ZEN_DURATION); + dumpSetting(s, p, Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, GlobalSettingsProto.HEADS_UP_NOTIFICATIONS_ENABLED); dumpSetting(s, p, @@ -1061,9 +1155,18 @@ class SettingsProtoDumpUtil { Settings.Global.STORAGE_SETTINGS_CLOBBER_THRESHOLD, GlobalSettingsProto.STORAGE_SETTINGS_CLOBBER_THRESHOLD); dumpSetting(s, p, + Settings.Global.LOCATION_GLOBAL_KILL_SWITCH, + GlobalSettingsProto.LOCATION_GLOBAL_KILL_SWITCH); + dumpSetting(s, p, + Settings.Global.OVERRIDE_SETTINGS_PROVIDER_RESTORE_ANY_VERSION, + GlobalSettingsProto.OVERRIDE_SETTINGS_PROVIDER_RESTORE_ANY_VERSION); + dumpSetting(s, p, Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED, GlobalSettingsProto.CHAINED_BATTERY_ATTRIBUTION_ENABLED); dumpSetting(s, p, + Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES, + GlobalSettingsProto.AUTOFILL_COMPAT_ALLOWED_PACKAGES); + dumpSetting(s, p, Global.HIDDEN_API_BLACKLIST_EXEMPTIONS, GlobalSettingsProto.HIDDEN_API_BLACKLIST_EXEMPTIONS); dumpSetting(s, p, @@ -1121,6 +1224,18 @@ class SettingsProtoDumpUtil { Settings.Global.NOTIFICATION_SNOOZE_OPTIONS, GlobalSettingsProto.NOTIFICATION_SNOOZE_OPTIONS); dumpSetting(s, p, + Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, + GlobalSettingsProto.SQLITE_COMPATIBILITY_WAL_FLAGS); + dumpSetting(s, p, + Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, + GlobalSettingsProto.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING); + dumpSetting(s, p, + Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT, + GlobalSettingsProto.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT); + dumpSetting(s, p, + Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS, + GlobalSettingsProto.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS); + dumpSetting(s, p, Settings.Global.ZRAM_ENABLED, GlobalSettingsProto.ZRAM_ENABLED); dumpSetting(s, p, @@ -1139,13 +1254,21 @@ class SettingsProtoDumpUtil { Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, GlobalSettingsProto.SHOW_ZEN_UPGRADE_NOTIFICATION); dumpSetting(s, p, - Settings.Global.APP_AUTO_RESTRICTION_ENABLED, - GlobalSettingsProto.APP_AUTO_RESTRICTION_ENABLED); - dumpSetting(s, p, - Settings.Global.ZEN_DURATION, - GlobalSettingsProto.ZEN_DURATION); - + Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS, + GlobalSettingsProto.BACKUP_AGENT_TIMEOUT_PARAMETERS); // Please insert new settings using the same order as in Settings.Global. + + p.end(token); + } + + /** Dumps settings that use a common prefix into a repeated field. */ + private static void dumpRepeatedSetting(@NonNull SettingsState settings, + @NonNull ProtoOutputStream proto, String settingPrefix, long fieldId) { + for (String s : settings.getSettingNamesLocked()) { + if (s.startsWith(settingPrefix)) { + dumpSetting(settings, proto, s, fieldId); + } + } } /** Dump a single {@link SettingsState.Setting} to a proto buf */ @@ -1167,7 +1290,9 @@ class SettingsProtoDumpUtil { } static void dumpProtoSecureSettingsLocked( - @NonNull SettingsState s, @NonNull ProtoOutputStream p) { + @NonNull ProtoOutputStream p, long fieldId, @NonNull SettingsState s) { + final long token = p.start(fieldId); + s.dumpHistoricalOperations(p, SecureSettingsProto.HISTORICAL_OPERATIONS); // This uses the same order as in Settings.Secure. @@ -1199,6 +1324,24 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Secure.AUTOFILL_SERVICE, SecureSettingsProto.AUTOFILL_SERVICE); + dumpSetting(s, p, + Settings.Secure.AUTOFILL_FEATURE_FIELD_CLASSIFICATION, + SecureSettingsProto.AUTOFILL_FEATURE_FIELD_CLASSIFICATION); + dumpSetting(s, p, + Settings.Secure.AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE, + SecureSettingsProto.AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE); + dumpSetting(s, p, + Settings.Secure.AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE, + SecureSettingsProto.AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE); + dumpSetting(s, p, + Settings.Secure.AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT, + SecureSettingsProto.AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT); + dumpSetting(s, p, + Settings.Secure.AUTOFILL_USER_DATA_MAX_VALUE_LENGTH, + SecureSettingsProto.AUTOFILL_USER_DATA_MAX_VALUE_LENGTH); + dumpSetting(s, p, + Settings.Secure.AUTOFILL_USER_DATA_MIN_VALUE_LENGTH, + SecureSettingsProto.AUTOFILL_USER_DATA_MIN_VALUE_LENGTH); // Settings.Secure.DEVICE_PROVISIONED intentionally excluded since it's deprecated. dumpSetting(s, p, Settings.Secure.USER_SETUP_COMPLETE, @@ -1209,9 +1352,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Secure.TV_USER_SETUP_COMPLETE, SecureSettingsProto.TV_USER_SETUP_COMPLETE); - dumpSetting(s, p, + dumpRepeatedSetting(s, p, Settings.Secure.COMPLETED_CATEGORY_PREFIX, - SecureSettingsProto.COMPLETED_CATEGORY_PREFIX); + SecureSettingsProto.COMPLETED_CATEGORIES); dumpSetting(s, p, Settings.Secure.ENABLED_INPUT_METHODS, SecureSettingsProto.ENABLED_INPUT_METHODS); @@ -1238,6 +1381,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Secure.LOCATION_MODE, SecureSettingsProto.LOCATION_MODE); + dumpSetting(s, p, + Settings.Secure.LOCATION_CHANGER, + SecureSettingsProto.LOCATION_CHANGER); // Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS intentionally excluded since it's deprecated. dumpSetting(s, p, Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, @@ -1309,6 +1455,9 @@ class SettingsProtoDumpUtil { Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, SecureSettingsProto.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); dumpSetting(s, p, + Settings.Secure.KEYGUARD_SLICE_URI, + SecureSettingsProto.KEYGUARD_SLICE_URI); + dumpSetting(s, p, Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, SecureSettingsProto.ACCESSIBILITY_SPEAK_PASSWORD); dumpSetting(s, p, @@ -1324,9 +1473,6 @@ class SettingsProtoDumpUtil { Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, SecureSettingsProto.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE); dumpSetting(s, p, - Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE, - SecureSettingsProto.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE); - dumpSetting(s, p, Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SecureSettingsProto.ACCESSIBILITY_SOFT_KEYBOARD_MODE); dumpSetting(s, p, @@ -1618,6 +1764,12 @@ class SettingsProtoDumpUtil { Settings.Secure.ASSIST_DISCLOSURE_ENABLED, SecureSettingsProto.ASSIST_DISCLOSURE_ENABLED); dumpSetting(s, p, + Settings.Secure.SHOW_ROTATION_SUGGESTIONS, + SecureSettingsProto.SHOW_ROTATION_SUGGESTIONS); + dumpSetting(s, p, + Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED, + SecureSettingsProto.NUM_ROTATION_SUGGESTIONS_ACCEPTED); + dumpSetting(s, p, Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT, SecureSettingsProto.ENABLED_NOTIFICATION_ASSISTANT); dumpSetting(s, p, @@ -1776,12 +1928,15 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING, SecureSettingsProto.BLUETOOTH_ON_WHILE_DRIVING); - // Please insert new settings using the same order as in Settings.Secure. + + p.end(token); } private static void dumpProtoSystemSettingsLocked( - @NonNull SettingsState s, @NonNull ProtoOutputStream p) { + @NonNull ProtoOutputStream p, long fieldId, @NonNull SettingsState s) { + final long token = p.start(fieldId); + s.dumpHistoricalOperations(p, SystemSettingsProto.HISTORICAL_OPERATIONS); // This uses the same order as in Settings.System. @@ -1794,11 +1949,11 @@ class SettingsProtoDumpUtil { Settings.System.ADVANCED_SETTINGS, SystemSettingsProto.ADVANCED_SETTINGS); // Settings.System.AIRPLANE_MODE_ON intentionally excluded since it's deprecated. - // Settings.System.RADIO_BLUETOOTH intentionally excluded since it's deprecated. - // Settings.System.RADIO_WIFI intentionally excluded since it's deprecated. - // Settings.System.RADIO_WIMAX intentionally excluded since it's deprecated. - // Settings.System.RADIO_CELL intentionally excluded since it's deprecated. - // Settings.System.RADIO_NFC intentionally excluded since it's deprecated. + // Settings.System.RADIO_BLUETOOTH intentionally excluded since it's just a constant. + // Settings.System.RADIO_WIFI intentionally excluded since it's just a constant. + // Settings.System.RADIO_WIMAX intentionally excluded since it's just a constant. + // Settings.System.RADIO_CELL intentionally excluded since it's just a constant. + // Settings.System.RADIO_NFC intentionally excluded since it's just a constant. // Settings.System.AIRPLANE_MODE_RADIOS intentionally excluded since it's deprecated. // Settings.System.AIRPLANE_MODE_TOGGLABLE_RADIOS intentionally excluded since it's deprecated. // Settings.System.WIFI_SLEEP_POLICY intentionally excluded since it's deprecated. @@ -1861,6 +2016,12 @@ class SettingsProtoDumpUtil { Settings.System.VIBRATE_INPUT_DEVICES, SystemSettingsProto.VIBRATE_INPUT_DEVICES); dumpSetting(s, p, + Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + SystemSettingsProto.NOTIFICATION_VIBRATION_INTENSITY); + dumpSetting(s, p, + Settings.System.HAPTIC_FEEDBACK_INTENSITY, + SystemSettingsProto.HAPTIC_FEEDBACK_INTENSITY); + dumpSetting(s, p, Settings.System.VOLUME_RING, SystemSettingsProto.VOLUME_RING); dumpSetting(s, p, @@ -1973,6 +2134,9 @@ class SettingsProtoDumpUtil { Settings.System.TTY_MODE, SystemSettingsProto.TTY_MODE); dumpSetting(s, p, + Settings.System.RTT_CALLING_MODE, + SystemSettingsProto.RTT_CALLING_MODE); + dumpSetting(s, p, Settings.System.SOUND_EFFECTS_ENABLED, SystemSettingsProto.SOUND_EFFECTS_ENABLED); dumpSetting(s, p, @@ -2038,5 +2202,7 @@ class SettingsProtoDumpUtil { // they're deprecated from Settings.System. // Please insert new settings using the same order as in Settings.System. + + p.end(token); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 639885847907..da62d94f9c63 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -2938,7 +2938,7 @@ public class SettingsProvider extends ContentProvider { } private final class UpgradeController { - private static final int SETTINGS_VERSION = 157; + private static final int SETTINGS_VERSION = 158; private final int mUserId; @@ -3584,7 +3584,7 @@ public class SettingsProvider extends ContentProvider { } if (currentVersion == 155) { - // Version 155: Set the default value for CHARGING_STARTED_SOUND. + // Version 156: Set the default value for CHARGING_STARTED_SOUND. final SettingsState globalSettings = getGlobalSettingsLocked(); final String oldValue = globalSettings.getSettingLocked( Global.CHARGING_STARTED_SOUND).getValue(); @@ -3605,7 +3605,7 @@ public class SettingsProvider extends ContentProvider { } if (currentVersion == 156) { - // Version 156: Set a default value for zen duration + // Version 157: Set a default value for zen duration final SettingsState globalSettings = getGlobalSettingsLocked(); final Setting currentSetting = globalSettings.getSettingLocked( Global.ZEN_DURATION); @@ -3616,9 +3616,26 @@ public class SettingsProvider extends ContentProvider { Global.ZEN_DURATION, defaultZenDuration, null, true, SettingsState.SYSTEM_PACKAGE_NAME); } - currentVersion = 157; } + + if (currentVersion == 157) { + // Version 158: Set default value for BACKUP_AGENT_TIMEOUT_PARAMETERS. + final SettingsState globalSettings = getGlobalSettingsLocked(); + final String oldValue = globalSettings.getSettingLocked( + Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS).getValue(); + if (TextUtils.equals(null, oldValue)) { + final String defaultValue = getContext().getResources().getString( + R.string.def_backup_agent_timeout_parameters); + if (!TextUtils.isEmpty(defaultValue)) { + globalSettings.insertSettingLocked( + Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS, defaultValue, + null, true, + SettingsState.SYSTEM_PACKAGE_NAME); + } + } + currentVersion = 158; + } // vXXX: Add new settings above this point. if (currentVersion != newVersion) { diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 937b9397a9a5..589ae2a1193f 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -118,6 +118,7 @@ <uses-permission android:name="android.permission.REGISTER_CONNECTION_MANAGER" /> <uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION" /> <uses-permission android:name="android.permission.GET_APP_OPS_STATS" /> + <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" /> <uses-permission android:name="android.permission.ACTIVITY_EMBEDDING" /> diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java index 6131acc91ca5..aa2fb32f13a8 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java @@ -16,6 +16,7 @@ package com.android.systemui.plugins.statusbar.phone; import android.graphics.Canvas; import android.view.MotionEvent; +import android.view.View; import com.android.systemui.plugins.Plugin; import com.android.systemui.plugins.annotations.ProvidesInterface; @@ -42,6 +43,8 @@ public interface NavGesture extends Plugin { public void onLayout(boolean changed, int left, int top, int right, int bottom); + public void onNavigationButtonLongPress(View v); + public default void destroy() { } } diff --git a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml index 93df340f59d4..461d62e5f79d 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 113282b8d3fe..85a325a0e4cb 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-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 12fccd4c4fdf..4d6509de9c5d 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -401,9 +401,9 @@ <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Aucune\ninterruption"</string> <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priorité\nuniquement"</string> <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmes\nuniquement"</string> - <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement… (rechargé à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string> - <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement rapide… (à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string> - <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement lent… (à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string> + <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement… (rechargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string> + <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement rapide… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string> + <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement lent… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string> <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string> <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string> <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 814b3efb74ef..1db9050a3ae1 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -88,13 +88,13 @@ support charging on it. That is, a charger that fits into the USB port and goes into a wall socket, not into a computer. (This happens because some devices require more current than the USB spec allows. [CHAR LIMIT=NONE] --> - <string name="invalid_charger">USB charging not supported.\nUse only the supplied charger.</string> + <string name="invalid_charger">Can\'t charge via USB. Use the charger that came with your device.</string> <!-- First line of invalid_charger, used in the notification form. [CHAR LIMIT=NONE]--> - <string name="invalid_charger_title">USB charging not supported.</string> + <string name="invalid_charger_title">Can\'t charge via USB</string> <!-- Second line of invalid_charger, used in the notification form. [CHAR LIMIT=NONE]--> - <string name="invalid_charger_text">Use only the supplied charger.</string> + <string name="invalid_charger_text">Use the charger that came with your device</string> <!-- When the battery is low, this is the label of the button to go to the power usage activity to find out what drained the battery. [CHAR LIMIT=30] --> @@ -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] --> @@ -1062,6 +1062,9 @@ <!-- The text to clear all notifications. [CHAR LIMIT=60] --> <string name="clear_all_notifications_text">Clear all</string> + <!-- The text to show in the notifications shade when dnd is suppressing notifications. [CHAR LIMIT=100] --> + <string name="dnd_suppressing_shade_text">Do Not disturb is hiding notifications</string> + <!-- Media projection permission dialog action text. [CHAR LIMIT=60] --> <string name="media_projection_action_text">Start now</string> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl index ef36610b48c6..861244539725 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl @@ -80,4 +80,17 @@ oneway interface IOverviewProxy { * Sent when overview is to be hidden. */ void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); + + /** + * Sent when a user swipes up over the navigation bar to launch overview. Swipe up is determined + * by passing the touch slop in the direction towards launcher from navigation bar. During and + * after this event is sent the caller will continue to send motion events. The motion + * {@param event} passed after the touch slop was exceeded will also be passed after by + * {@link onMotionEvent}. Since motion events will be sent, motion up or cancel can still be + * sent to cancel overview regardless the current state of launcher (eg. if overview is already + * visible, this event will still be sent if user swipes up). When this signal is sent, + * navigation bar will not handle any gestures such as quick scrub or switch and the home button + * will cancel (long) press. + */ + void onQuickStep(in MotionEvent event); } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl index 846aaddf74de..4799f398fb7a 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl @@ -36,11 +36,6 @@ interface ISystemUiProxy { void startScreenPinning(int taskId) = 1; /** - * Called when the overview service has started the recents animation. - */ - void onRecentsAnimationStarted() = 2; - - /** * Specifies the text to be shown for onboarding the new swipe-up gesture to access recents. */ void setRecentsOnboardingText(CharSequence text) = 3; diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java index 9a7abf82c56c..940c9ef522a3 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java @@ -51,6 +51,14 @@ public class RecentsAnimationControllerCompat { } } + public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) { + try { + mAnimationController.setAnimationTargetsBehindSystemBars(behindSystemBars); + } catch (RemoteException e) { + Log.e(TAG, "Failed to set whether animation targets are behind system bars", e); + } + } + public void finish(boolean toHome) { try { mAnimationController.finish(toHome); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java index 5fff5febec85..098698aa1c5c 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java @@ -29,6 +29,11 @@ public class RemoteAnimationDefinitionCompat { mWrapped.addRemoteAnimation(transition, adapter.getWrapped()); } + public void addRemoteAnimation(int transition, int activityTypeFilter, + RemoteAnimationAdapterCompat adapter) { + mWrapped.addRemoteAnimation(transition, activityTypeFilter, adapter.getWrapped()); + } + RemoteAnimationDefinition getWrapped() { return mWrapped; } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java index a9c80c62e998..2de3ae2bd9e4 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java @@ -18,6 +18,7 @@ package com.android.systemui.shared.system; import static android.view.Display.DEFAULT_DISPLAY; +import android.app.WindowConfiguration; import android.graphics.Rect; import android.os.Handler; import android.os.RemoteException; @@ -58,6 +59,8 @@ public class WindowManagerWrapper { public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_KEYGUARD_OCCLUDE; public static final int TRANSIT_KEYGUARD_UNOCCLUDE = WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; + public static final int ACTIVITY_TYPE_STANDARD = WindowConfiguration.ACTIVITY_TYPE_STANDARD; + private static final WindowManagerWrapper sInstance = new WindowManagerWrapper(); public static WindowManagerWrapper getInstance() { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java index b8a07cdbdc41..63b7ae2d856a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java @@ -60,7 +60,7 @@ class KeyguardEsimArea extends Button implements View.OnClickListener { .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/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java index f0952f9641f2..10ba7f6704de 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java @@ -47,12 +47,12 @@ import java.util.HashMap; import java.util.List; import java.util.function.Consumer; -import androidx.app.slice.Slice; -import androidx.app.slice.SliceItem; -import androidx.app.slice.core.SliceQuery; -import androidx.app.slice.widget.ListContent; -import androidx.app.slice.widget.RowContent; -import androidx.app.slice.widget.SliceLiveData; +import androidx.slice.Slice; +import androidx.slice.SliceItem; +import androidx.slice.core.SliceQuery; +import androidx.slice.widget.ListContent; +import androidx.slice.widget.RowContent; +import androidx.slice.widget.SliceLiveData; /** * View visible under the clock on the lock screen and AoD. @@ -117,7 +117,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe private void showSlice(Slice slice) { - ListContent lc = new ListContent(slice); + ListContent lc = new ListContent(getContext(), slice); mHasHeader = lc.hasHeader(); List<SliceItem> subItems = lc.getRowItems(); if (!mHasHeader) { @@ -125,7 +125,8 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe } else { mTitle.setVisibility(VISIBLE); // If there's a header it'll be the first subitem - RowContent header = new RowContent(subItems.get(0), true /* showStartItem */); + RowContent header = new RowContent(getContext(), subItems.get(0), + true /* showStartItem */); SliceItem mainTitle = header.getTitleItem(); CharSequence title = mainTitle != null ? mainTitle.getText() : null; mTitle.setText(title); @@ -149,7 +150,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe final int startIndex = mHasHeader ? 1 : 0; // First item is header; skip it for (int i = startIndex; i < subItemsCount; i++) { SliceItem item = subItems.get(i); - RowContent rc = new RowContent(item, true /* showStartItem */); + RowContent rc = new RowContent(getContext(), item, true /* showStartItem */); final Uri itemTag = item.getSlice().getUri(); // Try to reuse the view if already exists in the layout KeyguardSliceButton button = mRow.findViewWithTag(itemTag); @@ -182,6 +183,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe } button.setCompoundDrawables(iconDrawable, null, null, null); button.setOnClickListener(this); + button.setClickable(pendingIntent != null); } // Removing old views diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java index 041af0e47119..a4af6b26a854 100644 --- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java @@ -102,15 +102,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis } } - public void onRecentsAnimationStarted() { - long token = Binder.clearCallingIdentity(); - try { - mHandler.post(OverviewProxyService.this::notifyRecentsAnimationStarted); - } finally { - Binder.restoreCallingIdentity(token); - } - } - public void onSplitScreenInvoked() { long token = Binder.clearCallingIdentity(); try { @@ -283,9 +274,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis } } - private void notifyRecentsAnimationStarted() { + public void notifyQuickStepStarted() { for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) { - mConnectionCallbacks.get(i).onRecentsAnimationStarted(); + mConnectionCallbacks.get(i).onQuickStepStarted(); } } @@ -300,7 +291,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis public interface OverviewProxyListener { default void onConnectionChanged(boolean isConnected) {} - default void onRecentsAnimationStarted() {} + default void onQuickStepStarted() {} default void onInteractionFlagsChanged(@InteractionType int flags) {} } } diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index ec2390fbcfc6..9a20c81c4919 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -33,6 +33,7 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Region; import android.hardware.display.DisplayManager; +import android.os.SystemProperties; import android.provider.Settings.Secure; import android.support.annotation.VisibleForTesting; import android.util.DisplayMetrics; @@ -65,6 +66,8 @@ import com.android.systemui.tuner.TunerService.Tunable; public class ScreenDecorations extends SystemUI implements Tunable { public static final String SIZE = "sysui_rounded_size"; public static final String PADDING = "sysui_rounded_content_padding"; + private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS = + SystemProperties.getBoolean("debug.screenshot_rounded_corners", false); private int mRoundedDefault; private View mOverlay; @@ -237,7 +240,12 @@ public class ScreenDecorations extends SystemUI implements Tunable { | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, PixelFormat.TRANSLUCENT); lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS - | WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; + | WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; + + if (!DEBUG_SCREENSHOT_ROUNDED_CORNERS) { + lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; + } + lp.setTitle("ScreenDecorOverlay"); lp.gravity = Gravity.TOP | Gravity.LEFT; lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; @@ -380,6 +388,7 @@ public class ScreenDecorations extends SystemUI implements Tunable { 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 8f87d647a0e3..988753372130 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 @@ public class WirelessChargingLayout extends FrameLayout { // 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 @@ public class WirelessChargingLayout extends FrameLayout { 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/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java index 26618bff4db7..d81b32b162b7 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java @@ -40,10 +40,10 @@ import java.util.Date; import java.util.Locale; import java.util.concurrent.TimeUnit; -import androidx.app.slice.Slice; -import androidx.app.slice.SliceProvider; -import androidx.app.slice.builders.ListBuilder; -import androidx.app.slice.builders.ListBuilder.RowBuilder; +import androidx.slice.Slice; +import androidx.slice.SliceProvider; +import androidx.slice.builders.ListBuilder; +import androidx.slice.builders.ListBuilder.RowBuilder; /** * Simple Slice provider that shows the current date. diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java index 0486a9dcca74..a4927b7704c5 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java @@ -63,7 +63,6 @@ import android.util.Pair; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.View.OnTouchListener; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.WindowManager.LayoutParams; @@ -551,7 +550,6 @@ public class PipMenuActivity extends Activity { alpha = (int) (interpolatedAlpha * 255); } else { if (mMenuState == MENU_STATE_CLOSE) { - mSettingsButton.setAlpha(menuAlpha); mDismissButton.setAlpha(menuAlpha); } alpha = (int) (fraction * DISMISS_BACKGROUND_ALPHA * 255); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index a48dcc69ae9f..9792e4102d79 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -33,7 +33,9 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.util.AttributeSet; import android.util.Log; +import android.util.Pair; import android.view.View; +import android.view.WindowInsets; import android.widget.RelativeLayout; import android.widget.TextView; @@ -47,6 +49,7 @@ import com.android.systemui.SysUiServiceProvider; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.qs.QSDetail.Callback; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager; import com.android.systemui.statusbar.policy.DarkIconDispatcher; @@ -260,6 +263,19 @@ public class QuickStatusBarHeader extends RelativeLayout implements CommandQueue public void onAttachedToWindow() { SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this); Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager); + requestApplyInsets(); + } + + @Override + public WindowInsets onApplyWindowInsets(WindowInsets insets) { + Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins( + insets.getDisplayCutout(), getDisplay()); + if (padding == null) { + setPadding(0, 0, 0, 0); + } else { + setPadding(padding.first, 0, padding.second, 0); + } + return super.onApplyWindowInsets(insets); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index f3a2ae3770b6..8427e3229441 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 @@ public class DndTile extends QSTileImpl<BooleanState> { 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/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java index d9359a43d8a8..c348187115f0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java @@ -189,7 +189,7 @@ public class RecentsOnboarding { } } - public void onRecentsAnimationStarted() { + public void onQuickStepStarted() { boolean alreadySeenRecentsOnboarding = Prefs.getBoolean(mContext, Prefs.Key.HAS_SEEN_RECENTS_ONBOARDING, false); if (!alreadySeenRecentsOnboarding) { diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java index 406eef82f737..f2a7adf680f8 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java +++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java @@ -368,7 +368,9 @@ public class BrightnessController implements ToggleSlider.Listener { } else { final int val = value + mMinimumBacklight; if (stopTracking) { - MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val); + final int metric = mAutomatic ? + MetricsEvent.ACTION_BRIGHTNESS_AUTO : MetricsEvent.ACTION_BRIGHTNESS; + MetricsLogger.action(mContext, metric, val); } setBrightness(val); if (!tracking) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java index 58adde269758..3698c3a0038d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar; import android.annotation.ColorInt; +import android.annotation.StringRes; import android.content.Context; import android.content.res.Configuration; import android.util.AttributeSet; @@ -30,6 +31,7 @@ import com.android.systemui.statusbar.stack.StackScrollState; public class EmptyShadeView extends StackScrollerDecorView { private TextView mEmptyText; + private @StringRes int mText = R.string.empty_shade_text; public EmptyShadeView(Context context, AttributeSet attrs) { super(context, attrs); @@ -38,7 +40,7 @@ public class EmptyShadeView extends StackScrollerDecorView { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - mEmptyText.setText(R.string.empty_shade_text); + mEmptyText.setText(mText); } @Override @@ -50,6 +52,11 @@ public class EmptyShadeView extends StackScrollerDecorView { mEmptyText.setTextColor(color); } + public void setText(@StringRes int text) { + mText = text; + mEmptyText.setText(mText); + } + @Override protected void onFinishInflate() { super.onFinishInflate(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java index 5c21fd1167e4..6560f8f9c420 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 @@ package com.android.systemui.statusbar; 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 @@ public class VibratorHelper { 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 class VibratorHelper { 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/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 110995505444..010b1651a0d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -157,7 +157,7 @@ public class KeyguardBouncer { public void onFullyHidden() { if (!mShowingSoon) { cancelShowRunnable(); - inflateView(); + mRoot.setVisibility(View.INVISIBLE); mFalsingManager.onBouncerHidden(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index bb929dd16310..994c0abcf70b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -26,6 +26,7 @@ import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.util.Pair; import android.util.TypedValue; import android.view.DisplayCutout; import android.view.Gravity; @@ -43,7 +44,6 @@ import com.android.systemui.BatteryMeterView; import com.android.systemui.Dependency; import com.android.systemui.Interpolators; import com.android.systemui.R; -import com.android.systemui.ScreenDecorations; import com.android.systemui.qs.QSPanel; import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager; import com.android.systemui.statusbar.policy.BatteryController; @@ -213,6 +213,7 @@ public class KeyguardStatusBarView extends RelativeLayout @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { + mLayoutState = LAYOUT_NONE; if (updateLayoutConsideringCutout()) { requestLayout(); } @@ -221,13 +222,24 @@ public class KeyguardStatusBarView extends RelativeLayout private boolean updateLayoutConsideringCutout() { DisplayCutout dc = getRootWindowInsets().getDisplayCutout(); - if (dc == null) { + Pair<Integer, Integer> cornerCutoutMargins = + PhoneStatusBarView.cornerCutoutMargins(dc, getDisplay()); + updateCornerCutoutPadding(cornerCutoutMargins); + if (dc == null || cornerCutoutMargins != null) { return updateLayoutParamsNoCutout(); } else { return updateLayoutParamsForCutout(dc); } } + private void updateCornerCutoutPadding(Pair<Integer, Integer> cornerCutoutMargins) { + if (cornerCutoutMargins != null) { + setPadding(cornerCutoutMargins.first, 0, cornerCutoutMargins.second, 0); + } else { + setPadding(0, 0, 0, 0); + } + } + private boolean updateLayoutParamsNoCutout() { if (mLayoutState == LAYOUT_NO_CUTOUT) { return false; 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 9fa06f77fe9e..91483bcd358c 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 class NavigationBarFragment extends Fragment implements Callbacks { 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; @@ -175,8 +176,8 @@ public class NavigationBarFragment extends Fragment implements Callbacks { } @Override - public void onRecentsAnimationStarted() { - mNavigationBarView.setRecentsAnimationStarted(true); + public void onQuickStepStarted() { + mNavigationBarView.onQuickStepStarted(); // Use navbar dragging as a signal to hide the rotate button setRotateSuggestionButtonState(false); @@ -343,10 +344,19 @@ public class NavigationBarFragment extends Fragment implements Callbacks { 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 @@ public class NavigationBarFragment extends Fragment implements Callbacks { @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 @@ public class NavigationBarFragment extends Fragment implements Callbacks { } // If window rotation matches suggested rotation, remove any current suggestions - final int winRotation = mWindowManager.getDefaultDisplay().getRotation(); if (rotation == winRotation) { getView().removeCallbacks(mRemoveRotationProposal); setRotateSuggestionButtonState(false); @@ -751,6 +770,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks { if (shouldDisableNavbarGestures()) { return false; } + mNavigationBarView.onNavigationButtonLongPress(v); mMetricsLogger.action(MetricsEvent.ACTION_ASSIST_LONG_PRESS); mAssistManager.startAssist(new Bundle() /* args */); mStatusBar.awakenDreams(); @@ -787,10 +807,12 @@ public class NavigationBarFragment extends Fragment implements Callbacks { } private boolean onLongPressBackHome(View v) { + mNavigationBarView.onNavigationButtonLongPress(v); return onLongPressNavigationButtons(v, R.id.back, R.id.home); } private boolean onLongPressBackRecents(View v) { + mNavigationBarView.onNavigationButtonLongPress(v); return onLongPressNavigationButtons(v, R.id.back, R.id.recent_apps); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java index 6a1ed51e85b4..cd000fe4ba70 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java @@ -19,31 +19,22 @@ package com.android.systemui.statusbar.phone; import static android.view.WindowManager.DOCKED_INVALID; import static android.view.WindowManager.DOCKED_LEFT; import static android.view.WindowManager.DOCKED_TOP; -import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY; -import static com.android.systemui.OverviewProxyService.TAG_OPS; import android.app.ActivityManager; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; -import android.graphics.Matrix; import android.graphics.Rect; -import android.os.RemoteException; -import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget; import com.android.systemui.Dependency; -import com.android.systemui.OverviewProxyService; -import com.android.systemui.OverviewProxyService.OverviewProxyListener; import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.SysUiServiceProvider; import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper; -import com.android.systemui.shared.recents.IOverviewProxy; -import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.stackdivider.Divider; import com.android.systemui.tuner.TunerService; @@ -75,25 +66,14 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture private NavigationBarView mNavigationBarView; private boolean mIsVertical; - private final QuickScrubController mQuickScrubController; + private final QuickStepController mQuickStepController; private final int mScrollTouchSlop; - private final Matrix mTransformGlobalMatrix = new Matrix(); - private final Matrix mTransformLocalMatrix = new Matrix(); private final StatusBar mStatusBar; private int mTouchDownX; private int mTouchDownY; private boolean mDownOnRecents; private VelocityTracker mVelocityTracker; - private OverviewProxyService mOverviewProxyService = Dependency.get(OverviewProxyService.class); - private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() { - @Override - public void onRecentsAnimationStarted() { - mRecentsAnimationStarted = true; - mQuickScrubController.setRecentsAnimationStarted(true /* started */); - } - }; - private boolean mRecentsAnimationStarted; private boolean mDockWindowEnabled; private boolean mDockWindowTouchSlopExceeded; private int mDragMode; @@ -103,14 +83,12 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture mStatusBar = SysUiServiceProvider.getComponent(context, StatusBar.class); Resources r = context.getResources(); mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance); - mQuickScrubController = new QuickScrubController(context); + mQuickStepController = new QuickStepController(context); Dependency.get(TunerService.class).addTunable(this, KEY_DOCK_WINDOW_GESTURE); - mOverviewProxyService.addCallback(mOverviewProxyListener); } public void destroy() { Dependency.get(TunerService.class).removeTunable(this); - mOverviewProxyService.removeCallback(mOverviewProxyListener); } public void setComponents(RecentsComponent recentsComponent, Divider divider, @@ -118,65 +96,19 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture mRecentsComponent = recentsComponent; mDivider = divider; mNavigationBarView = navigationBarView; - mQuickScrubController.setComponents(mNavigationBarView); + mQuickStepController.setComponents(mNavigationBarView); } public void setBarState(boolean isVertical, boolean isRTL) { mIsVertical = isVertical; - mQuickScrubController.setBarState(isVertical, isRTL); - } - - private boolean proxyMotionEvents(MotionEvent event) { - final IOverviewProxy overviewProxy = mOverviewProxyService.getProxy(); - if (overviewProxy != null && mNavigationBarView.isQuickStepSwipeUpEnabled()) { - mNavigationBarView.requestUnbufferedDispatch(event); - event.transform(mTransformGlobalMatrix); - try { - if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { - overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget()); - } - overviewProxy.onMotionEvent(event); - if (DEBUG_OVERVIEW_PROXY) { - Log.d(TAG_OPS, "Send MotionEvent: " + event.toString()); - } - return true; - } catch (RemoteException e) { - Log.e(TAG, "Callback failed", e); - } finally { - event.transform(mTransformLocalMatrix); - } - } - return false; + mQuickStepController.setBarState(isVertical, isRTL); } public boolean onInterceptTouchEvent(MotionEvent event) { - if (mNavigationBarView.inScreenPinning() || mStatusBar.isKeyguardShowing() - || !mStatusBar.isPresenterFullyCollapsed()) { + if (!canHandleGestures()) { return false; } - - int action = event.getActionMasked(); - switch (action) { - case MotionEvent.ACTION_DOWN: { - mTouchDownX = (int) event.getX(); - mTouchDownY = (int) event.getY(); - mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX); - mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX); - mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix); - mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix); - mRecentsAnimationStarted = false; - mQuickScrubController.setRecentsAnimationStarted(false /* started */); - break; - } - } - boolean handledByQuickscrub = mQuickScrubController.onInterceptTouchEvent(event); - if (!handledByQuickscrub) { - // Proxy motion events until we start intercepting for quickscrub - proxyMotionEvents(event); - } - - boolean result = handledByQuickscrub; - result |= mRecentsAnimationStarted; + boolean result = mQuickStepController.onInterceptTouchEvent(event); if (mDockWindowEnabled) { result |= interceptDockWindowEvent(event); } @@ -184,18 +116,10 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture } public boolean onTouchEvent(MotionEvent event) { - if (mNavigationBarView.inScreenPinning() || mStatusBar.isKeyguardShowing() - || !mStatusBar.isPresenterFullyCollapsed()) { + if (!canHandleGestures()) { return false; } - - // The same down event was just sent on intercept and therefore can be ignored here - boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN - && mOverviewProxyService.getProxy() != null; - boolean result = mQuickScrubController.onTouchEvent(event) - || ignoreProxyDownEvent - || proxyMotionEvents(event); - result |= mRecentsAnimationStarted; + boolean result = mQuickStepController.onTouchEvent(event); if (mDockWindowEnabled) { result |= handleDockWindowEvent(event); } @@ -203,17 +127,19 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture } public void onDraw(Canvas canvas) { - if (mNavigationBarView.isQuickScrubEnabled()) { - mQuickScrubController.onDraw(canvas); - } + mQuickStepController.onDraw(canvas); } public void onLayout(boolean changed, int left, int top, int right, int bottom) { - mQuickScrubController.onLayout(changed, left, top, right, bottom); + mQuickStepController.onLayout(changed, left, top, right, bottom); } public void onDarkIntensityChange(float intensity) { - mQuickScrubController.onDarkIntensityChange(intensity); + mQuickStepController.onDarkIntensityChange(intensity); + } + + public void onNavigationButtonLongPress(View v) { + mQuickStepController.onNavigationButtonLongPress(v); } private boolean interceptDockWindowEvent(MotionEvent event) { @@ -342,6 +268,11 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture mVelocityTracker = null; } + private boolean canHandleGestures() { + return !mNavigationBarView.inScreenPinning() && !mStatusBar.isKeyguardShowing() + && mStatusBar.isPresenterFullyCollapsed(); + } + private int calculateDragMode() { if (mIsVertical && !mDivider.getView().isHorizontalDivision()) { return DRAG_MODE_DIVIDER; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index e97fa855e5e7..fcbd37c50f73 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -290,18 +290,12 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav notifyVerticalChangedListener(mVertical); } - public void setRecentsAnimationStarted(boolean started) { + public void onQuickStepStarted() { if (mRecentsOnboarding != null) { - mRecentsOnboarding.onRecentsAnimationStarted(); + mRecentsOnboarding.onQuickStepStarted(); } } - public void onConnectionChanged(boolean isConnected) { - updateSlippery(); - updateNavButtonIcons(); - setUpSwipeUpOnboarding(isConnected); - } - @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getActionMasked()) { @@ -675,6 +669,10 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } } + public void onNavigationButtonLongPress(View v) { + mGestureHelper.onNavigationButtonLongPress(v); + } + public void onPanelExpandedChange(boolean expanded) { updateSlippery(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 5076404a5e4e..0fd0a05e98ab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -23,9 +23,12 @@ import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFro import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; +import android.graphics.Point; import android.graphics.Rect; import android.util.AttributeSet; import android.util.EventLog; +import android.util.Pair; +import android.view.Display; import android.view.DisplayCutout; import android.view.Gravity; import android.view.MotionEvent; @@ -33,9 +36,9 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; import android.view.accessibility.AccessibilityEvent; - import android.widget.FrameLayout; import android.widget.LinearLayout; + import com.android.systemui.Dependency; import com.android.systemui.EventLogTags; import com.android.systemui.R; @@ -284,18 +287,20 @@ public class PhoneStatusBarView extends PanelBar { } private void updateLayoutForCutout() { - updateCutoutLocation(); - updateSafeInsets(); + Pair<Integer, Integer> cornerCutoutMargins = cornerCutoutMargins(mDisplayCutout, + getDisplay()); + updateCutoutLocation(cornerCutoutMargins); + updateSafeInsets(cornerCutoutMargins); } - private void updateCutoutLocation() { + private void updateCutoutLocation(Pair<Integer, Integer> cornerCutoutMargins) { // Not all layouts have a cutout (e.g., Car) if (mCutoutSpace == null) { return; } if (mDisplayCutout == null || mDisplayCutout.isEmpty() - || mLastOrientation != ORIENTATION_PORTRAIT) { + || mLastOrientation != ORIENTATION_PORTRAIT || cornerCutoutMargins != null) { mCutoutSpace.setVisibility(View.GONE); return; } @@ -310,7 +315,7 @@ public class PhoneStatusBarView extends PanelBar { lp.height = bounds.height(); } - private void updateSafeInsets() { + private void updateSafeInsets(Pair<Integer, Integer> cornerCutoutMargins) { // Depending on our rotation, we may have to work around a cutout in the middle of the view, // or letterboxing from the right or left sides. @@ -323,5 +328,30 @@ public class PhoneStatusBarView extends PanelBar { lp.leftMargin = mDisplayCutout.getSafeInsetLeft(); lp.rightMargin = mDisplayCutout.getSafeInsetRight(); + + if (cornerCutoutMargins != null) { + lp.leftMargin = Math.max(lp.leftMargin, cornerCutoutMargins.first); + lp.rightMargin = Math.max(lp.rightMargin, cornerCutoutMargins.second); + } + } + + public static Pair<Integer, Integer> cornerCutoutMargins(DisplayCutout cutout, + Display display) { + if (cutout == null) { + return null; + } + Point size = new Point(); + display.getRealSize(size); + + Rect bounds = new Rect(); + boundsFromDirection(cutout, Gravity.TOP, bounds); + + if (bounds.left <= 0) { + return new Pair<>(bounds.right, 0); + } + if (bounds.right >= size.x) { + return new Pair<>(0, size.x - bounds.left); + } + return null; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java index 00aff53595ff..19544b170d1f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java @@ -25,6 +25,7 @@ import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; import android.os.Handler; @@ -55,10 +56,10 @@ import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ /** * Class to detect gestures on the navigation bar and implement quick scrub and switch. */ -public class QuickScrubController extends GestureDetector.SimpleOnGestureListener implements +public class QuickStepController extends GestureDetector.SimpleOnGestureListener implements GestureHelper { - private static final String TAG = "QuickScrubController"; + private static final String TAG = "QuickStepController"; private static final int QUICK_SWITCH_FLING_VELOCITY = 0; private static final int ANIM_DURATION_MS = 200; private static final long LONG_PRESS_DELAY_MS = 225; @@ -75,7 +76,8 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene private boolean mDraggingActive; private boolean mQuickScrubActive; private boolean mAllowQuickSwitch; - private boolean mRecentsAnimationStarted; + private boolean mAllowGestureDetection; + private boolean mQuickStepStarted; private float mDownOffset; private float mTranslation; private int mTouchDownX; @@ -101,6 +103,8 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene private final ValueAnimator mButtonAnimator; private final AnimatorSet mQuickScrubEndAnimator; private final Context mContext; + private final Matrix mTransformGlobalMatrix = new Matrix(); + private final Matrix mTransformLocalMatrix = new Matrix(); private final ArgbEvaluator mTrackColorEvaluator = new ArgbEvaluator(); private final AnimatorUpdateListener mTrackAnimatorListener = valueAnimator -> { @@ -123,7 +127,6 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene private AnimatorListenerAdapter mQuickScrubEndListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mNavigationBarView.getHomeButton().setClickable(true); mQuickScrubActive = false; mTranslation = 0; mQuickScrubEndAnimator.setCurrentPlayTime(mQuickScrubEndAnimator.getDuration()); @@ -165,7 +168,7 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene } }; - public QuickScrubController(Context context) { + public QuickStepController(Context context) { mContext = context; mScrollTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mOverviewEventSender = Dependency.get(OverviewProxyService.class); @@ -197,31 +200,35 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene */ @Override public boolean onInterceptTouchEvent(MotionEvent event) { - final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton(); - if (!mNavigationBarView.isQuickScrubEnabled()) { - homeButton.setDelayTouchFeedback(false); - return false; - } - return handleTouchEvent(event); } /** - * @return true if we want to handle touch events for quick scrub/switch and prevent proxying - * the event to the overview service. + * @return true if we want to handle touch events for quick scrub/switch or if down event (that + * will get consumed and ignored). No events will be proxied to the overview service. */ @Override public boolean onTouchEvent(MotionEvent event) { - return handleTouchEvent(event); + // The same down event was just sent on intercept and therefore can be ignored here + final boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN + && mOverviewEventSender.getProxy() != null; + return ignoreProxyDownEvent || handleTouchEvent(event); } private boolean handleTouchEvent(MotionEvent event) { - final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy(); + if (!mNavigationBarView.isQuickScrubEnabled() + && !mNavigationBarView.isQuickStepSwipeUpEnabled()) { + mNavigationBarView.getHomeButton().setDelayTouchFeedback(false /* delay */); + return false; + } + mNavigationBarView.requestUnbufferedDispatch(event); + final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton(); if (mGestureDetector.onTouchEvent(event)) { // If the fling has been handled on UP, then skip proxying the UP return true; } + final boolean homePressed = mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME; int action = event.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { @@ -232,89 +239,99 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene mQuickScrubEndAnimator.end(); } mHomeButtonView = homeButton.getCurrentView(); - if (mNavigationBarView.isQuickScrubEnabled() - && mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME) { - mTouchDownX = x; - mTouchDownY = y; - homeButton.setDelayTouchFeedback(true); + homeButton.setDelayTouchFeedback(true /* delay */); + mTouchDownX = x; + mTouchDownY = y; + if (homePressed) { mHandler.postDelayed(mLongPressRunnable, LONG_PRESS_DELAY_MS); - } else { - homeButton.setDelayTouchFeedback(false); - mTouchDownX = mTouchDownY = -1; } + mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX); + mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX); + mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix); + mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix); + mQuickStepStarted = false; mAllowQuickSwitch = true; + mAllowGestureDetection = true; break; } case MotionEvent.ACTION_MOVE: { - if (mTouchDownX != -1) { - int x = (int) event.getX(); - int y = (int) event.getY(); - int xDiff = Math.abs(x - mTouchDownX); - int yDiff = Math.abs(y - mTouchDownY); - boolean exceededTouchSlopX = xDiff > mScrollTouchSlop && xDiff > yDiff; - boolean exceededTouchSlopY = yDiff > mScrollTouchSlop && yDiff > xDiff; - boolean exceededTouchSlop, exceededPerpendicularTouchSlop; - int pos, touchDown, offset, trackSize; - - if (mIsVertical) { - exceededTouchSlop = exceededTouchSlopY; - exceededPerpendicularTouchSlop = exceededTouchSlopX; - pos = y; - touchDown = mTouchDownY; - offset = pos - mTrackRect.top; - trackSize = mTrackRect.height(); - } else { - exceededTouchSlop = exceededTouchSlopX; - exceededPerpendicularTouchSlop = exceededTouchSlopY; - pos = x; - touchDown = mTouchDownX; - offset = pos - mTrackRect.left; - trackSize = mTrackRect.width(); - } - // Do not start scrubbing when dragging in the perpendicular direction if we - // haven't already started quickscrub - if (!mDraggingActive && !mQuickScrubActive && exceededPerpendicularTouchSlop) { - mHandler.removeCallbacksAndMessages(null); - return false; - } - if (!mDragPositive) { - offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width(); + if (mQuickStepStarted || !mAllowGestureDetection){ + break; + } + int x = (int) event.getX(); + int y = (int) event.getY(); + int xDiff = Math.abs(x - mTouchDownX); + int yDiff = Math.abs(y - mTouchDownY); + boolean exceededTouchSlopX = xDiff > mScrollTouchSlop && xDiff > yDiff; + boolean exceededTouchSlopY = yDiff > mScrollTouchSlop && yDiff > xDiff; + boolean exceededTouchSlop, exceededPerpendicularTouchSlop; + int pos, touchDown, offset, trackSize; + + if (mIsVertical) { + exceededTouchSlop = exceededTouchSlopY; + exceededPerpendicularTouchSlop = exceededTouchSlopX; + pos = y; + touchDown = mTouchDownY; + offset = pos - mTrackRect.top; + trackSize = mTrackRect.height(); + } else { + exceededTouchSlop = exceededTouchSlopX; + exceededPerpendicularTouchSlop = exceededTouchSlopY; + pos = x; + touchDown = mTouchDownX; + offset = pos - mTrackRect.left; + trackSize = mTrackRect.width(); + } + // Decide to start quickstep if dragging away from the navigation bar, otherwise in + // the parallel direction, decide to start quickscrub. Only one may run. + if (!mDraggingActive && !mQuickScrubActive && exceededPerpendicularTouchSlop) { + if (mNavigationBarView.isQuickStepSwipeUpEnabled()) { + startQuickStep(event); } + break; + } - // Control the button movement - if (!mDraggingActive && exceededTouchSlop && !mRecentsAnimationStarted) { - boolean allowDrag = !mDragPositive - ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown; - if (allowDrag) { - mDownOffset = offset; - homeButton.setClickable(false); - mDraggingActive = true; - } + // Do not handle quick scrub/switch if disabled or hit target is not home button + if (!homePressed || !mNavigationBarView.isQuickScrubEnabled()) { + break; + } + + if (!mDragPositive) { + offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width(); + } + + // Control the button movement + if (!mDraggingActive && exceededTouchSlop) { + boolean allowDrag = !mDragPositive + ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown; + if (allowDrag) { + mDownOffset = offset; + homeButton.abortCurrentGesture(); + mDraggingActive = true; } - if (mDraggingActive && (mDragPositive && offset >= 0 - || !mDragPositive && offset <= 0)) { - float scrubFraction = - Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1); - mTranslation = !mDragPositive - ? Utilities.clamp(offset - mDownOffset, -trackSize, 0) - : Utilities.clamp(offset - mDownOffset, 0, trackSize); - if (mQuickScrubActive) { - try { - mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction); - if (DEBUG_OVERVIEW_PROXY) { - Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to send progress of quick scrub.", e); + } + if (mDraggingActive && (mDragPositive && offset >= 0 + || !mDragPositive && offset <= 0)) { + float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1); + mTranslation = !mDragPositive + ? Utilities.clamp(offset - mDownOffset, -trackSize, 0) + : Utilities.clamp(offset - mDownOffset, 0, trackSize); + if (mQuickScrubActive) { + try { + mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction); + if (DEBUG_OVERVIEW_PROXY) { + Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction); } - } else { - mTranslation /= SWITCH_STICKINESS; - } - if (mIsVertical) { - mHomeButtonView.setTranslationY(mTranslation); - } else { - mHomeButtonView.setTranslationX(mTranslation); + } catch (RemoteException e) { + Log.e(TAG, "Failed to send progress of quick scrub.", e); } + } else { + mTranslation /= SWITCH_STICKINESS; + } + if (mIsVertical) { + mHomeButtonView.setTranslationY(mTranslation); + } else { + mHomeButtonView.setTranslationX(mTranslation); } } break; @@ -324,11 +341,20 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene endQuickScrub(true /* animate */); break; } - return mDraggingActive || mQuickScrubActive; + + // Proxy motion events to launcher if not handled by quick scrub/switch + boolean handled = mDraggingActive || mQuickScrubActive; + if (!handled && mAllowGestureDetection) { + proxyMotionEvents(event); + } + return handled || mQuickStepStarted; } @Override public void onDraw(Canvas canvas) { + if (mNavigationBarView.isQuickScrubEnabled()) { + return; + } int color = (int) mTrackColorEvaluator.evaluate(mDarkIntensity, mLightTrackColor, mDarkTrackColor); mTrackPaint.setColor(color); @@ -381,6 +407,31 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene } } + @Override + public void onNavigationButtonLongPress(View v) { + mAllowGestureDetection = false; + mHandler.removeCallbacksAndMessages(null); + } + + private void startQuickStep(MotionEvent event) { + mQuickStepStarted = true; + event.transform(mTransformGlobalMatrix); + try { + mOverviewEventSender.getProxy().onQuickStep(event); + if (DEBUG_OVERVIEW_PROXY) { + Log.d(TAG_OPS, "Quick Step Start"); + } + } catch (RemoteException e) { + Log.e(TAG, "Failed to send quick step started.", e); + } finally { + event.transform(mTransformLocalMatrix); + } + mOverviewEventSender.notifyQuickStepStarted(); + mNavigationBarView.getHomeButton().abortCurrentGesture(); + cancelQuickSwitch(); + mHandler.removeCallbacksAndMessages(null); + } + private void startQuickScrub() { if (!mQuickScrubActive && mDraggingActive) { mQuickScrubActive = true; @@ -396,9 +447,6 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene } catch (RemoteException e) { Log.e(TAG, "Failed to send start of quick scrub.", e); } - } else { - // After long press do not allow quick scrub/switch - mTouchDownX = -1; } } @@ -421,11 +469,24 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene mDraggingActive = false; } - public void setRecentsAnimationStarted(boolean started) { - mRecentsAnimationStarted = started; - if (started) { - cancelQuickSwitch(); + private boolean proxyMotionEvents(MotionEvent event) { + final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy(); + event.transform(mTransformGlobalMatrix); + try { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget()); + } + overviewProxy.onMotionEvent(event); + if (DEBUG_OVERVIEW_PROXY) { + Log.d(TAG_OPS, "Send MotionEvent: " + event.toString()); + } + return true; + } catch (RemoteException e) { + Log.e(TAG, "Callback failed", e); + } finally { + event.transform(mTransformLocalMatrix); } + return false; } public void cancelQuickSwitch() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index e4f142a992e9..2e45b120a75f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -232,6 +232,7 @@ import com.android.systemui.statusbar.policy.PreviewInflater; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserInfoControllerImpl; import com.android.systemui.statusbar.policy.UserSwitcherController; +import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import com.android.systemui.util.NotificationChannels; import com.android.systemui.volume.VolumeComponent; @@ -407,6 +408,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected NotificationEntryManager mEntryManager; protected NotificationViewHierarchyManager mViewHierarchyManager; protected AppOpsListener mAppOpsListener; + private ZenModeController mZenController; /** * Helper that is responsible for showing the right toast when a disallowed activity operation @@ -626,6 +628,7 @@ public class StatusBar extends SystemUI implements DemoMode, mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class); mAppOpsListener = Dependency.get(AppOpsListener.class); mAppOpsListener.setUpWithPresenter(this, mEntryManager); + mZenController = Dependency.get(ZenModeController.class); mColorExtractor = Dependency.get(SysuiColorExtractor.class); mColorExtractor.addOnColorsChangedListener(this); @@ -1166,6 +1169,7 @@ public class StatusBar extends SystemUI implements DemoMode, } mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate( R.layout.status_bar_no_notifications, mStackScroller, false); + mEmptyShadeView.setText(R.string.empty_shade_text); mStackScroller.setEmptyShadeView(mEmptyShadeView); } @@ -1498,6 +1502,9 @@ public class StatusBar extends SystemUI implements DemoMode, return entry.row.getParent() instanceof NotificationStackScrollLayout; } + public boolean areNotificationsHidden() { + return mZenController.areNotificationsHiddenInShade(); + } public void requestNotificationUpdate() { mEntryManager.updateNotifications(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index 3bcfd4b7f381..e5fefd34ffb7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -224,8 +224,10 @@ public class KeyButtonView extends ImageView implements ButtonInterface { case MotionEvent.ACTION_DOWN: mDownTime = SystemClock.uptimeMillis(); mLongClicked = false; - mTouchDownX = (int) ev.getX(); - mTouchDownY = (int) ev.getY(); + + // Use raw X and Y to detect gestures in case a parent changes the x and y values + mTouchDownX = (int) ev.getRawX(); + mTouchDownY = (int) ev.getRawY(); if (mCode != 0) { sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime); } else { @@ -241,8 +243,8 @@ public class KeyButtonView extends ImageView implements ButtonInterface { postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout()); break; case MotionEvent.ACTION_MOVE: - x = (int)ev.getX(); - y = (int)ev.getY(); + x = (int)ev.getRawX(); + y = (int)ev.getRawY(); boolean exceededTouchSlopX = Math.abs(x - mTouchDownX) > mTouchSlop; boolean exceededTouchSlopY = Math.abs(y - mTouchDownY) > mTouchSlop; if (exceededTouchSlopX || exceededTouchSlopY) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java index 8777aa6454bc..4ee805934522 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java @@ -35,6 +35,7 @@ public interface ZenModeController extends CallbackController<Callback> { boolean isCountdownConditionSupported(); int getCurrentUser(); boolean isVolumeRestricted(); + boolean areNotificationsHiddenInShade(); public static interface Callback { default void onZenChanged(int zen) {} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java index 0fd244527540..a9da239ada9d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java @@ -33,13 +33,11 @@ import android.os.UserManager; import android.provider.Settings.Global; import android.provider.Settings.Secure; import android.service.notification.Condition; -import android.service.notification.IConditionListener; import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig.ZenRule; -import android.support.annotation.VisibleForTesting; import android.util.Log; -import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.qs.GlobalSetting; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.util.Utils; @@ -64,9 +62,9 @@ public class ZenModeControllerImpl extends CurrentUserTracker implements ZenMode private final UserManager mUserManager; private int mUserId; - private boolean mRequesting; private boolean mRegistered; private ZenModeConfig mConfig; + private int mZenMode; public ZenModeControllerImpl(Context context, Handler handler) { super(context); @@ -74,6 +72,7 @@ public class ZenModeControllerImpl extends CurrentUserTracker implements ZenMode mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) { @Override protected void handleValueChanged(int value) { + updateZenMode(value); fireZenChanged(value); } }; @@ -86,7 +85,9 @@ public class ZenModeControllerImpl extends CurrentUserTracker implements ZenMode mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); mConfig = mNoMan.getZenModeConfig(); mModeSetting.setListening(true); + updateZenMode(mModeSetting.getValue()); mConfigSetting.setListening(true); + updateZenModeConfig(); mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); mSetupObserver = new SetupObserver(handler); mSetupObserver.register(); @@ -101,6 +102,15 @@ public class ZenModeControllerImpl extends CurrentUserTracker implements ZenMode } @Override + public boolean areNotificationsHiddenInShade() { + if (mZenMode != Global.ZEN_MODE_OFF) { + return (mConfig.suppressedVisualEffects & NotificationManager.Policy + .SUPPRESSED_EFFECT_NOTIFICATION_LIST) != 0; + } + return false; + } + + @Override public void addCallback(Callback callback) { mCallbacks.add(callback); } @@ -186,10 +196,6 @@ public class ZenModeControllerImpl extends CurrentUserTracker implements ZenMode Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available)); } - private void fireConditionsChanged(Condition[] conditions) { - Utils.safeForeach(mCallbacks, c -> c.onConditionsChanged(conditions)); - } - private void fireManualRuleChanged(ZenRule rule) { Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule)); } @@ -199,17 +205,13 @@ public class ZenModeControllerImpl extends CurrentUserTracker implements ZenMode Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config)); } - private void updateConditions(Condition[] conditions) { - if (conditions == null || conditions.length == 0) return; - for (Condition c : conditions) { - if ((c.flags & Condition.FLAG_RELEVANT_NOW) == 0) continue; - mConditions.put(c.id, c); - } - fireConditionsChanged( - mConditions.values().toArray(new Condition[mConditions.values().size()])); + @VisibleForTesting + protected void updateZenMode(int mode) { + mZenMode = mode; } - private void updateZenModeConfig() { + @VisibleForTesting + protected void updateZenModeConfig() { final ZenModeConfig config = mNoMan.getZenModeConfig(); if (Objects.equals(config, mConfig)) return; final ZenRule oldRule = mConfig != null ? mConfig.manualRule : null; @@ -220,16 +222,6 @@ public class ZenModeControllerImpl extends CurrentUserTracker implements ZenMode fireManualRuleChanged(newRule); } - private final IConditionListener mListener = new IConditionListener.Stub() { - @Override - public void onConditionsReceived(Condition[] conditions) { - if (DEBUG) Slog.d(TAG, "onConditionsReceived " - + (conditions == null ? 0 : conditions.length) + " mRequesting=" + mRequesting); - if (!mRequesting) return; - updateConditions(conditions); - } - }; - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 66fde7986b00..a85f4e2b53a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -104,7 +104,6 @@ import android.support.v4.graphics.ColorUtils; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; @@ -3985,6 +3984,11 @@ public class NotificationStackScrollLayout extends ViewGroup } else { mEmptyShadeView.setInvisible(); } + if (mStatusBar.areNotificationsHidden()) { + mEmptyShadeView.setText(R.string.dnd_suppressing_shade_text); + } else { + mEmptyShadeView.setText(R.string.empty_shade_text); + } mEmptyShadeView.setVisibility(newVisibility); mEmptyShadeView.setWillBeGone(false); updateContentHeight(); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index 89e7dd146045..ee6748eee2f8 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.ApplicationInfo; 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.HandlerThread; 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 com.android.systemui.statusbar.phone.StatusBar; 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 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa 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 class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa 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 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa } 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 22bf98378ccb..e94d6bd5ee99 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -479,6 +479,7 @@ public class VolumeDialogImpl implements VolumeDialog { if (mShowing) return; mShowing = true; + initSettingsH(); mDialog.show(); Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked()); mController.notifyVisible(true); @@ -896,6 +897,9 @@ public class VolumeDialogImpl implements VolumeDialog { } private String getStreamLabelH(StreamState ss) { + if (ss == null) { + return ""; + } if (ss.remoteLabel != null) { return ss.remoteLabel; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java index b6116e00bac1..5812da29b2ab 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java @@ -21,7 +21,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; -import androidx.app.slice.Slice; +import androidx.slice.Slice; import android.app.AlarmManager; import android.content.ContentResolver; @@ -45,10 +45,10 @@ import org.mockito.MockitoAnnotations; import java.util.Arrays; import java.util.concurrent.TimeUnit; -import androidx.app.slice.SliceItem; -import androidx.app.slice.SliceProvider; -import androidx.app.slice.SliceSpecs; -import androidx.app.slice.core.SliceQuery; +import androidx.slice.SliceItem; +import androidx.slice.SliceProvider; +import androidx.slice.SliceSpecs; +import androidx.slice.core.SliceQuery; @SmallTest @RunWith(AndroidTestingRunner.class) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java index ec994a1a5650..5c347301bd8c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java @@ -17,7 +17,7 @@ package com.android.systemui.statusbar.policy; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_NUM_STATUS_ICONS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_ICONS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent - .NOTIFICATION_SINCE_CREATE_MILLIS; + .RESERVED_FOR_LOGBUILDER_LATENCY_MILLIS; import static org.junit.Assert.*; import static org.mockito.ArgumentMatchers.any; @@ -119,9 +119,9 @@ public class IconLoggerImplTest extends SysuiTestCase { verify(mMetricsLogger).write(argThat(maker -> { if (IconLoggerImpl.MIN_LOG_INTERVAL > - (long) maker.getTaggedData(NOTIFICATION_SINCE_CREATE_MILLIS)) { + (long) maker.getTaggedData(RESERVED_FOR_LOGBUILDER_LATENCY_MILLIS)) { Log.e("IconLoggerImplTest", "Invalid latency " - + maker.getTaggedData(NOTIFICATION_SINCE_CREATE_MILLIS)); + + maker.getTaggedData(RESERVED_FOR_LOGBUILDER_LATENCY_MILLIS)); return false; } if (1 != (int) maker.getTaggedData(FIELD_NUM_STATUS_ICONS)) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java index 8124bf39328b..da8017e25525 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java @@ -14,11 +14,17 @@ package com.android.systemui.statusbar.policy; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.app.NotificationManager; import android.os.Handler; +import android.provider.Settings; import android.service.notification.ZenModeConfig; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; @@ -27,8 +33,11 @@ import android.testing.TestableLooper.RunWithLooper; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.policy.ZenModeController.Callback; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) @@ -36,21 +45,64 @@ import org.junit.runner.RunWith; public class ZenModeControllerImplTest extends SysuiTestCase { private Callback mCallback; + @Mock + NotificationManager mNm; + @Mock + ZenModeConfig mConfig; + + private ZenModeControllerImpl mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext.addMockSystemService(NotificationManager.class, mNm); + when(mNm.getZenModeConfig()).thenReturn(mConfig); + + mController = new ZenModeControllerImpl(mContext, new Handler()); + } @Test public void testRemoveDuringCallback() { - ZenModeControllerImpl controller = new ZenModeControllerImpl(mContext, new Handler()); mCallback = new Callback() { @Override public void onConfigChanged(ZenModeConfig config) { - controller.removeCallback(mCallback); + mController.removeCallback(mCallback); } }; - controller.addCallback(mCallback); + mController.addCallback(mCallback); Callback mockCallback = mock(Callback.class); - controller.addCallback(mockCallback); - controller.fireConfigChanged(null); + mController.addCallback(mockCallback); + mController.fireConfigChanged(null); verify(mockCallback).onConfigChanged(eq(null)); } + @Test + public void testAreNotificationsHiddenInShade_zenOffShadeSuppressed() { + mConfig.suppressedVisualEffects = + NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; + mController.updateZenMode(Settings.Global.ZEN_MODE_OFF); + mController.updateZenModeConfig(); + + assertFalse(mController.areNotificationsHiddenInShade()); + } + + @Test + public void testAreNotificationsHiddenInShade_zenOnShadeNotSuppressed() { + mConfig.suppressedVisualEffects = + NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; + mController.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); + mController.updateZenModeConfig(); + + assertFalse(mController.areNotificationsHiddenInShade()); + } + + @Test + public void testAreNotificationsHiddenInShade_zenOnShadeSuppressed() { + mConfig.suppressedVisualEffects = + NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; + mController.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); + mController.updateZenModeConfig(); + + assertTrue(mController.areNotificationsHiddenInShade()); + } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java index d9673d3552d8..6fa91ff07850 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java @@ -17,17 +17,16 @@ package com.android.systemui.statusbar.stack; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.annotation.UiThread; import android.support.test.annotation.UiThreadTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; -import android.view.NotificationHeaderView; -import android.view.View; +import com.android.systemui.R; import com.android.systemui.SysuiTestCase; -import com.android.systemui.statusbar.NotificationTestHelper; +import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBar; @@ -72,4 +71,27 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { 0.01 /* delta */); } + @Test + public void updateEmptyView_dndSuppressing() { + EmptyShadeView view = mock(EmptyShadeView.class); + mStackScroller.setEmptyShadeView(view); + when(view.willBeGone()).thenReturn(true); + when(mBar.areNotificationsHidden()).thenReturn(true); + + mStackScroller.updateEmptyShadeView(true); + + verify(view).setText(R.string.dnd_suppressing_shade_text); + } + + @Test + public void updateEmptyView_dndNotSuppressing() { + EmptyShadeView view = mock(EmptyShadeView.class); + mStackScroller.setEmptyShadeView(view); + when(view.willBeGone()).thenReturn(true); + when(mBar.areNotificationsHidden()).thenReturn(false); + + mStackScroller.updateEmptyShadeView(true); + + verify(view).setText(R.string.empty_shade_text); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java index fb9bf7a15f60..86c43c998877 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java @@ -77,4 +77,9 @@ public class FakeZenModeController extends BaseLeakChecker<Callback> implements public boolean isVolumeRestricted() { return false; } + + @Override + public boolean areNotificationsHiddenInShade() { + return false; + } } diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.mk new file mode 100644 index 000000000000..74c43b40616f --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := DisplayCutoutEmulationCorner +LOCAL_CERTIFICATE := platform + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := DisplayCutoutEmulationCornerOverlay +LOCAL_SDK_VERSION := current + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..5f7f7c9bd3e4 --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/AndroidManifest.xml @@ -0,0 +1,26 @@ +<!-- + ~ 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.internal.display.cutout.emulation.corner" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="android" + android:category="com.android.internal.display_cutout_emulation" + android:priority="1"/> + + <application android:label="@string/display_cutout_emulation_overlay" android:hasCode="false"/> +</manifest> diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml new file mode 100644 index 000000000000..80d8066959af --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml @@ -0,0 +1,55 @@ +<!-- + ~ 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. + --> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- The bounding path of the cutout region of the main built-in display. + Must either be empty if there is no cutout region, or a string that is parsable by + {@link android.util.PathParser}. + + The path is assumed to be specified in display coordinates with pixel units and in + the display's native orientation, with the origin of the coordinate system at the + center top of the display. + + To facilitate writing device-independent emulation overlays, the marker `@dp` can be + appended after the path string to interpret coordinates in dp instead of px units. + Note that a physical cutout should be configured in pixels for the best results. + --> + <string translatable="false" name="config_mainBuiltInDisplayCutout"> + M 0,0 + L -48, 0 + C -48,48 -48,48 0,48 + Z + @dp + @right + </string> + + <!-- Whether the display cutout region of the main built-in display should be forced to + black in software (to avoid aliasing or emulate a cutout that is not physically existent). + --> + <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> + <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) --> + <dimen name="quick_qs_offset_height">48dp</dimen> + <!-- Total height of QQS (quick_qs_offset_height + 128) --> + <dimen name="quick_qs_total_height">176dp</dimen> + +</resources> + + diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml new file mode 100644 index 000000000000..754ba722d081 --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <string name="display_cutout_emulation_overlay">Corner display cutout</string> + +</resources> + diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index d89cc966bf29..e3be5d43a327 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -5503,6 +5503,10 @@ message MetricsEvent { // OS: P ACTION_MANAGE_NOTIFICATIONS = 1358; + // This value should never appear in log outputs - it is reserved for + // internal platform metrics use. + RESERVED_FOR_LOGBUILDER_LATENCY_MILLIS = 1359; + // ---- End P Constants, all P constants go above this line ---- // Add new aosp constants above this line. // END OF AOSP CONSTANTS diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto index 74efec93f201..0763fa129f65 100644 --- a/proto/src/wifi.proto +++ b/proto/src/wifi.proto @@ -926,6 +926,34 @@ message WifiAwareLog { // 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/BackupAgentTimeoutParameters.java b/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java new file mode 100644 index 000000000000..4de2c9b8e79f --- /dev/null +++ b/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java @@ -0,0 +1,150 @@ +/* + * 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.backup; + +import android.content.ContentResolver; +import android.os.Handler; +import android.provider.Settings; +import android.util.KeyValueListParser; +import android.util.KeyValueSettingObserver; +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; + +/** + * Configure backup and restore agent timeouts. + * + * <p>These timeout parameters are stored in Settings.Global to be configurable flags with P/H. They + * are represented as a comma-delimited key value list. + */ +public class BackupAgentTimeoutParameters extends KeyValueSettingObserver { + @VisibleForTesting + public static final String SETTING = Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS; + + @VisibleForTesting + public static final String SETTING_KV_BACKUP_AGENT_TIMEOUT_MILLIS = + "kv_backup_agent_timeout_millis"; + + @VisibleForTesting + public static final String SETTING_FULL_BACKUP_AGENT_TIMEOUT_MILLIS = + "full_backup_agent_timeout_millis"; + + @VisibleForTesting + public static final String SETTING_SHARED_BACKUP_AGENT_TIMEOUT_MILLIS = + "shared_backup_agent_timeout_millis"; + + @VisibleForTesting + public static final String SETTING_RESTORE_AGENT_TIMEOUT_MILLIS = + "restore_agent_timeout_millis"; + + @VisibleForTesting + public static final String SETTING_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS = + "restore_agent_finished_timeout_millis"; + + // Default values + @VisibleForTesting public static final long DEFAULT_KV_BACKUP_AGENT_TIMEOUT_MILLIS = 30 * 1000; + + @VisibleForTesting + public static final long DEFAULT_FULL_BACKUP_AGENT_TIMEOUT_MILLIS = 5 * 60 * 1000; + + @VisibleForTesting + public static final long DEFAULT_SHARED_BACKUP_AGENT_TIMEOUT_MILLIS = 30 * 60 * 1000; + + @VisibleForTesting public static final long DEFAULT_RESTORE_AGENT_TIMEOUT_MILLIS = 60 * 1000; + + @VisibleForTesting + public static final long DEFAULT_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS = 30 * 1000; + + @GuardedBy("mLock") + private long mKvBackupAgentTimeoutMillis; + + @GuardedBy("mLock") + private long mFullBackupAgentTimeoutMillis; + + @GuardedBy("mLock") + private long mSharedBackupAgentTimeoutMillis; + + @GuardedBy("mLock") + private long mRestoreAgentTimeoutMillis; + + @GuardedBy("mLock") + private long mRestoreAgentFinishedTimeoutMillis; + + private final Object mLock = new Object(); + + public BackupAgentTimeoutParameters(Handler handler, ContentResolver resolver) { + super(handler, resolver, Settings.Global.getUriFor(SETTING)); + } + + public String getSettingValue(ContentResolver resolver) { + return Settings.Global.getString(resolver, SETTING); + } + + public void update(KeyValueListParser parser) { + synchronized (mLock) { + mKvBackupAgentTimeoutMillis = + parser.getLong( + SETTING_KV_BACKUP_AGENT_TIMEOUT_MILLIS, + DEFAULT_KV_BACKUP_AGENT_TIMEOUT_MILLIS); + mFullBackupAgentTimeoutMillis = + parser.getLong( + SETTING_FULL_BACKUP_AGENT_TIMEOUT_MILLIS, + DEFAULT_FULL_BACKUP_AGENT_TIMEOUT_MILLIS); + mSharedBackupAgentTimeoutMillis = + parser.getLong( + SETTING_SHARED_BACKUP_AGENT_TIMEOUT_MILLIS, + DEFAULT_SHARED_BACKUP_AGENT_TIMEOUT_MILLIS); + mRestoreAgentTimeoutMillis = + parser.getLong( + SETTING_RESTORE_AGENT_TIMEOUT_MILLIS, + DEFAULT_RESTORE_AGENT_TIMEOUT_MILLIS); + mRestoreAgentFinishedTimeoutMillis = + parser.getLong( + SETTING_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS, + DEFAULT_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS); + } + } + + public long getKvBackupAgentTimeoutMillis() { + synchronized (mLock) { + return mKvBackupAgentTimeoutMillis; + } + } + + public long getFullBackupAgentTimeoutMillis() { + synchronized (mLock) { + return mFullBackupAgentTimeoutMillis; + } + } + + public long getSharedBackupAgentTimeoutMillis() { + synchronized (mLock) { + return mSharedBackupAgentTimeoutMillis; + } + } + + public long getRestoreAgentTimeoutMillis() { + synchronized (mLock) { + return mRestoreAgentTimeoutMillis; + } + } + + public long getRestoreAgentFinishedTimeoutMillis() { + synchronized (mLock) { + return mRestoreAgentFinishedTimeoutMillis; + } + } +} diff --git a/services/backup/java/com/android/server/backup/BackupManagerConstants.java b/services/backup/java/com/android/server/backup/BackupManagerConstants.java index 99160c24d3b4..dd6e6ab2ece1 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerConstants.java +++ b/services/backup/java/com/android/server/backup/BackupManagerConstants.java @@ -18,53 +18,76 @@ package com.android.server.backup; import android.app.AlarmManager; import android.content.ContentResolver; -import android.database.ContentObserver; -import android.net.Uri; import android.os.Handler; import android.provider.Settings; import android.text.TextUtils; import android.util.KeyValueListParser; +import android.util.KeyValueSettingObserver; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; /** * Class to access backup manager constants. * - * The backup manager constants are encoded as a key value list separated by commas - * and stored as a Settings.Secure. + * <p>The backup manager constants are encoded as a key value list separated by commas and stored as + * a Settings.Secure. */ -class BackupManagerConstants extends ContentObserver { +class BackupManagerConstants extends KeyValueSettingObserver { private static final String TAG = "BackupManagerConstants"; + private static final String SETTING = Settings.Secure.BACKUP_MANAGER_CONSTANTS; // Key names stored in the secure settings value. - private static final String KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS = + @VisibleForTesting + public static final String KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS = "key_value_backup_interval_milliseconds"; - private static final String KEY_VALUE_BACKUP_FUZZ_MILLISECONDS = + + @VisibleForTesting + public static final String KEY_VALUE_BACKUP_FUZZ_MILLISECONDS = "key_value_backup_fuzz_milliseconds"; - private static final String KEY_VALUE_BACKUP_REQUIRE_CHARGING = + + @VisibleForTesting + public static final String KEY_VALUE_BACKUP_REQUIRE_CHARGING = "key_value_backup_require_charging"; - private static final String KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE = + + @VisibleForTesting + public static final String KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE = "key_value_backup_required_network_type"; - private static final String FULL_BACKUP_INTERVAL_MILLISECONDS = + + @VisibleForTesting + public static final String FULL_BACKUP_INTERVAL_MILLISECONDS = "full_backup_interval_milliseconds"; - private static final String FULL_BACKUP_REQUIRE_CHARGING = - "full_backup_require_charging"; - private static final String FULL_BACKUP_REQUIRED_NETWORK_TYPE = + + @VisibleForTesting + public static final String FULL_BACKUP_REQUIRE_CHARGING = "full_backup_require_charging"; + + @VisibleForTesting + public static final String FULL_BACKUP_REQUIRED_NETWORK_TYPE = "full_backup_required_network_type"; - private static final String BACKUP_FINISHED_NOTIFICATION_RECEIVERS = + + @VisibleForTesting + public static final String BACKUP_FINISHED_NOTIFICATION_RECEIVERS = "backup_finished_notification_receivers"; // Hard coded default values. - private static final long DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS = + @VisibleForTesting + public static final long DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS = 4 * AlarmManager.INTERVAL_HOUR; - private static final long DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS = - 10 * 60 * 1000; - private static final boolean DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING = true; - private static final int DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE = 1; - private static final long DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS = + + @VisibleForTesting + public static final long DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS = 10 * 60 * 1000; + + @VisibleForTesting public static final boolean DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING = true; + @VisibleForTesting public static final int DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE = 1; + + @VisibleForTesting + public static final long DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS = 24 * AlarmManager.INTERVAL_HOUR; - private static final boolean DEFAULT_FULL_BACKUP_REQUIRE_CHARGING = true; - private static final int DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE = 2; - private static final String DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS = ""; + + @VisibleForTesting public static final boolean DEFAULT_FULL_BACKUP_REQUIRE_CHARGING = true; + @VisibleForTesting public static final int DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE = 2; + + @VisibleForTesting + public static final String DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS = ""; // Backup manager constants. private long mKeyValueBackupIntervalMilliseconds; @@ -76,49 +99,46 @@ class BackupManagerConstants extends ContentObserver { private int mFullBackupRequiredNetworkType; private String[] mBackupFinishedNotificationReceivers; - private ContentResolver mResolver; - private final KeyValueListParser mParser = new KeyValueListParser(','); - public BackupManagerConstants(Handler handler, ContentResolver resolver) { - super(handler); - mResolver = resolver; - updateSettings(); - mResolver.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.BACKUP_MANAGER_CONSTANTS), false, this); + super(handler, resolver, Settings.Secure.getUriFor(SETTING)); } - @Override - public void onChange(boolean selfChange, Uri uri) { - updateSettings(); + public String getSettingValue(ContentResolver resolver) { + return Settings.Secure.getString(resolver, SETTING); } - private synchronized void updateSettings() { - try { - mParser.setString(Settings.Secure.getString(mResolver, - Settings.Secure.BACKUP_MANAGER_CONSTANTS)); - } catch (IllegalArgumentException e) { - // Failed to parse the settings string. Use defaults. - Slog.e(TAG, "Bad backup manager constants: " + e.getMessage()); - } - - mKeyValueBackupIntervalMilliseconds = mParser.getLong( - KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS, - DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS); - mKeyValueBackupFuzzMilliseconds = mParser.getLong(KEY_VALUE_BACKUP_FUZZ_MILLISECONDS, - DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS); - mKeyValueBackupRequireCharging = mParser.getBoolean(KEY_VALUE_BACKUP_REQUIRE_CHARGING, - DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING); - mKeyValueBackupRequiredNetworkType = mParser.getInt(KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE, - DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE); - mFullBackupIntervalMilliseconds = mParser.getLong(FULL_BACKUP_INTERVAL_MILLISECONDS, - DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS); - mFullBackupRequireCharging = mParser.getBoolean(FULL_BACKUP_REQUIRE_CHARGING, - DEFAULT_FULL_BACKUP_REQUIRE_CHARGING); - mFullBackupRequiredNetworkType = mParser.getInt(FULL_BACKUP_REQUIRED_NETWORK_TYPE, - DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE); - String backupFinishedNotificationReceivers = mParser.getString( - BACKUP_FINISHED_NOTIFICATION_RECEIVERS, - DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS); + public synchronized void update(KeyValueListParser parser) { + mKeyValueBackupIntervalMilliseconds = + parser.getLong( + KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS, + DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS); + mKeyValueBackupFuzzMilliseconds = + parser.getLong( + KEY_VALUE_BACKUP_FUZZ_MILLISECONDS, + DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS); + mKeyValueBackupRequireCharging = + parser.getBoolean( + KEY_VALUE_BACKUP_REQUIRE_CHARGING, + DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING); + mKeyValueBackupRequiredNetworkType = + parser.getInt( + KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE, + DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE); + mFullBackupIntervalMilliseconds = + parser.getLong( + FULL_BACKUP_INTERVAL_MILLISECONDS, + DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS); + mFullBackupRequireCharging = + parser.getBoolean( + FULL_BACKUP_REQUIRE_CHARGING, DEFAULT_FULL_BACKUP_REQUIRE_CHARGING); + mFullBackupRequiredNetworkType = + parser.getInt( + FULL_BACKUP_REQUIRED_NETWORK_TYPE, + DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE); + String backupFinishedNotificationReceivers = + parser.getString( + BACKUP_FINISHED_NOTIFICATION_RECEIVERS, + DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS); if (backupFinishedNotificationReceivers.isEmpty()) { mBackupFinishedNotificationReceivers = new String[] {}; } else { @@ -132,40 +152,50 @@ class BackupManagerConstants extends ContentObserver { // a reference of this object. public synchronized long getKeyValueBackupIntervalMilliseconds() { if (BackupManagerService.DEBUG_SCHEDULING) { - Slog.v(TAG, "getKeyValueBackupIntervalMilliseconds(...) returns " - + mKeyValueBackupIntervalMilliseconds); + Slog.v( + TAG, + "getKeyValueBackupIntervalMilliseconds(...) returns " + + mKeyValueBackupIntervalMilliseconds); } return mKeyValueBackupIntervalMilliseconds; } public synchronized long getKeyValueBackupFuzzMilliseconds() { if (BackupManagerService.DEBUG_SCHEDULING) { - Slog.v(TAG, "getKeyValueBackupFuzzMilliseconds(...) returns " - + mKeyValueBackupFuzzMilliseconds); + Slog.v( + TAG, + "getKeyValueBackupFuzzMilliseconds(...) returns " + + mKeyValueBackupFuzzMilliseconds); } return mKeyValueBackupFuzzMilliseconds; } public synchronized boolean getKeyValueBackupRequireCharging() { if (BackupManagerService.DEBUG_SCHEDULING) { - Slog.v(TAG, "getKeyValueBackupRequireCharging(...) returns " - + mKeyValueBackupRequireCharging); + Slog.v( + TAG, + "getKeyValueBackupRequireCharging(...) returns " + + mKeyValueBackupRequireCharging); } return mKeyValueBackupRequireCharging; } public synchronized int getKeyValueBackupRequiredNetworkType() { if (BackupManagerService.DEBUG_SCHEDULING) { - Slog.v(TAG, "getKeyValueBackupRequiredNetworkType(...) returns " - + mKeyValueBackupRequiredNetworkType); + Slog.v( + TAG, + "getKeyValueBackupRequiredNetworkType(...) returns " + + mKeyValueBackupRequiredNetworkType); } return mKeyValueBackupRequiredNetworkType; } public synchronized long getFullBackupIntervalMilliseconds() { if (BackupManagerService.DEBUG_SCHEDULING) { - Slog.v(TAG, "getFullBackupIntervalMilliseconds(...) returns " - + mFullBackupIntervalMilliseconds); + Slog.v( + TAG, + "getFullBackupIntervalMilliseconds(...) returns " + + mFullBackupIntervalMilliseconds); } return mFullBackupIntervalMilliseconds; } @@ -179,19 +209,21 @@ class BackupManagerConstants extends ContentObserver { public synchronized int getFullBackupRequiredNetworkType() { if (BackupManagerService.DEBUG_SCHEDULING) { - Slog.v(TAG, "getFullBackupRequiredNetworkType(...) returns " - + mFullBackupRequiredNetworkType); + Slog.v( + TAG, + "getFullBackupRequiredNetworkType(...) returns " + + mFullBackupRequiredNetworkType); } return mFullBackupRequiredNetworkType; } - /** - * Returns an array of package names that should be notified whenever a backup finishes. - */ + /** Returns an array of package names that should be notified whenever a backup finishes. */ public synchronized String[] getBackupFinishedNotificationReceivers() { if (BackupManagerService.DEBUG_SCHEDULING) { - Slog.v(TAG, "getBackupFinishedNotificationReceivers(...) returns " - + TextUtils.join(", ", mBackupFinishedNotificationReceivers)); + Slog.v( + TAG, + "getBackupFinishedNotificationReceivers(...) returns " + + TextUtils.join(", ", mBackupFinishedNotificationReceivers)); } return mBackupFinishedNotificationReceivers; } diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 646909177e72..d6f6c6cf1fc3 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -851,6 +851,10 @@ public class BackupManagerService implements BackupManagerServiceInterface { mJournal = null; // will be created on first use mConstants = new BackupManagerConstants(mBackupHandler, mContext.getContentResolver()); + // We are observing changes to the constants throughout the lifecycle of BMS. This is + // because we reference the constants in multiple areas of BMS, which otherwise would + // require frequent starting and stopping. + mConstants.start(); // Set up the various sorts of package tracking we do mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule"); @@ -1394,7 +1398,7 @@ public class BackupManagerService implements BackupManagerServiceInterface { // 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--) { @@ -1639,7 +1643,7 @@ public class BackupManagerService implements BackupManagerServiceInterface { } try { PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, - PackageManager.GET_SIGNATURES); + PackageManager.GET_SIGNING_CERTIFICATES); if (!AppBackupUtils.appIsEligibleForBackup(packageInfo.applicationInfo, mPackageManager)) { BackupObserverUtils.sendBackupOnPackageResult(observer, packageName, @@ -2349,7 +2353,8 @@ public class BackupManagerService implements BackupManagerServiceInterface { 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 3cf374faada4..dc28cd179bcb 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.ComponentName; 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.Build; 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 class PackageManagerBackupAgent extends BackupAgent { 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 @@ public class PackageManagerBackupAgent extends BackupAgent { 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 @@ public class PackageManagerBackupAgent extends BackupAgent { // 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 @@ public class PackageManagerBackupAgent extends BackupAgent { 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 @@ public class PackageManagerBackupAgent extends BackupAgent { 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 @@ public class PackageManagerBackupAgent extends BackupAgent { } 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 2e2d3eb4ad21..821cca16bf60 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 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor 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 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor // 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 f9c366998ad2..2c2dd8528cb1 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 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba 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 0ba83cfeb361..11394e66a0f0 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 @@ public class PerformBackupTask implements BackupRestoreTask { // 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 0ca4f25093ce..c1a1c1dc10e7 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.app.backup.IFullBackupRestoreObserver; 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 @@ public class FullRestoreEngine extends RestoreEngine { 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 e576b3c32859..dacde0b9af68 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.app.backup.IFullBackupRestoreObserver; 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.os.RemoteException; 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 @@ public class PerformAdbRestoreTask implements Runnable { 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 3caa1e7fab79..4b467e5a0399 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.app.backup.RestoreDescription; 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 android.util.Slog; 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 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { 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 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { } 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 6780563120e3..5518374ebdbc 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.app.backup.BackupTransport; 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 @@ import com.android.server.backup.transport.TransportClient; * 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 class AppBackupUtils { 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 @@ public class AppBackupUtils { * * <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 @@ public class AppBackupUtils { 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)) { + return false; } - // Don't allow unsigned apps on either end - if (ArrayUtils.isEmpty(storedSigs) || ArrayUtils.isEmpty(deviceSigs)) { + 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; } - // 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; - - 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 d2ab09996d68..994d5a967298 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 @@ public class FullBackupUtils { 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 10f06954f17f..df7e6d45ba0f 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; 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.os.Process; 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 @@ public class RestoreUtils { 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 @@ public class RestoreUtils { } 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 cc26ff8b5090..6dd5284879f0 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.app.backup.IBackupManagerMonitor; 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 @@ public class TarBackupReader { * @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 @@ public class TarBackupReader { // 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 @@ public class TarBackupReader { // 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 15f3a2362043..9756d17f662e 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -610,7 +610,7 @@ public class AppOpsService extends IAppOpsService.Stub { @Override public void setUidMode(int code, int uid, int mode) { if (Binder.getCallingPid() != Process.myPid()) { - mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, + mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES, Binder.getCallingPid(), Binder.getCallingUid(), null); } verifyIncomingOp(code); @@ -714,7 +714,7 @@ public class AppOpsService extends IAppOpsService.Stub { @Override public void setMode(int code, int uid, String packageName, int mode) { if (Binder.getCallingPid() != Process.myPid()) { - mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, + mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES, Binder.getCallingPid(), Binder.getCallingUid(), null); } verifyIncomingOp(code); @@ -832,7 +832,7 @@ public class AppOpsService extends IAppOpsService.Stub { public void resetAllModes(int reqUserId, String reqPackageName) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); - mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, + mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES, callingPid, callingUid, null); reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId, true, true, "resetAllModes", null); @@ -1087,6 +1087,8 @@ public class AppOpsService extends IAppOpsService.Stub { String[] exceptionPackages) { verifyIncomingUid(uid); verifyIncomingOp(code); + mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES, + Binder.getCallingPid(), Binder.getCallingUid(), null); synchronized (this) { SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code); if (usageRestrictions == null) { @@ -1344,8 +1346,9 @@ public class AppOpsService extends IAppOpsService.Stub { 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) { @@ -2330,7 +2333,7 @@ public class AppOpsService extends IAppOpsService.Stub { } case "write-settings": { shell.mInternal.mContext.enforcePermission( - android.Manifest.permission.UPDATE_APP_OPS_STATS, + android.Manifest.permission.MANAGE_APP_OPS_MODES, Binder.getCallingPid(), Binder.getCallingUid(), null); long token = Binder.clearCallingIdentity(); try { @@ -2346,7 +2349,7 @@ public class AppOpsService extends IAppOpsService.Stub { } case "read-settings": { shell.mInternal.mContext.enforcePermission( - android.Manifest.permission.UPDATE_APP_OPS_STATS, + android.Manifest.permission.MANAGE_APP_OPS_MODES, Binder.getCallingPid(), Binder.getCallingUid(), null); long token = Binder.clearCallingIdentity(); try { diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java index e884de00c15a..8ea3dd64697e 100644 --- a/services/core/java/com/android/server/DiskStatsService.java +++ b/services/core/java/com/android/server/DiskStatsService.java @@ -171,8 +171,8 @@ public class DiskStatsService extends Binder { 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 @@ public class DiskStatsService extends Binder { 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 @@ public class DiskStatsService extends Binder { 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/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 62e82a064db2..38968712f4c8 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -65,7 +65,6 @@ import com.android.server.am.BatteryStatsService; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; @@ -164,14 +163,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private int[] mDataActivity; + // Connection state of default APN type data (i.e. internet) of phones private int[] mDataConnectionState; - private ArrayList<String>[] mConnectedApns; - - private LinkProperties[] mDataConnectionLinkProperties; - - private NetworkCapabilities[] mDataConnectionNetworkCapabilities; - private Bundle[] mCellLocation; private int[] mDataConnectionNetworkType; @@ -323,9 +317,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { mBatteryStats = BatteryStatsService.getService(); int numPhones = TelephonyManager.getDefault().getPhoneCount(); - if (DBG) log("TelephonyRegistor: ctor numPhones=" + numPhones); + if (DBG) log("TelephonyRegistry: ctor numPhones=" + numPhones); mNumPhones = numPhones; - mConnectedApns = new ArrayList[numPhones]; mCallState = new int[numPhones]; mDataActivity = new int[numPhones]; mDataConnectionState = new int[numPhones]; @@ -339,8 +332,6 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { mMessageWaiting = new boolean[numPhones]; mCallForwarding = new boolean[numPhones]; mCellLocation = new Bundle[numPhones]; - mDataConnectionLinkProperties = new LinkProperties[numPhones]; - mDataConnectionNetworkCapabilities = new NetworkCapabilities[numPhones]; mCellInfo = new ArrayList<List<CellInfo>>(); mPhysicalChannelConfigs = new ArrayList<List<PhysicalChannelConfig>>(); for (int i = 0; i < numPhones; i++) { @@ -358,7 +349,6 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { mCellLocation[i] = new Bundle(); mCellInfo.add(i, null); mPhysicalChannelConfigs.add(i, null); - mConnectedApns[i] = new ArrayList<String>(); } // Note that location can be null for non-phone builds like @@ -1219,36 +1209,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { int phoneId = SubscriptionManager.getPhoneId(subId); synchronized (mRecords) { if (validatePhoneId(phoneId)) { - boolean modified = false; - if (state == TelephonyManager.DATA_CONNECTED) { - if (!mConnectedApns[phoneId].contains(apnType)) { - mConnectedApns[phoneId].add(apnType); - if (mDataConnectionState[phoneId] != state) { - mDataConnectionState[phoneId] = state; - modified = true; - } - } - } else { - if (mConnectedApns[phoneId].remove(apnType)) { - if (mConnectedApns[phoneId].isEmpty()) { - mDataConnectionState[phoneId] = state; - modified = true; - } else { - // leave mDataConnectionState as is and - // send out the new status for the APN in question. - } - } - } - mDataConnectionLinkProperties[phoneId] = linkProperties; - mDataConnectionNetworkCapabilities[phoneId] = networkCapabilities; - if (mDataConnectionNetworkType[phoneId] != networkType) { - mDataConnectionNetworkType[phoneId] = networkType; - // need to tell registered listeners about the new network type - modified = true; - } - if (modified) { - String str = "onDataConnectionStateChanged(" + mDataConnectionState[phoneId] - + ", " + mDataConnectionNetworkType[phoneId] + ")"; + // We only call the callback when the change is for default APN type. + if (PhoneConstants.APN_TYPE_DEFAULT.equals(apnType) + && (mDataConnectionState[phoneId] != state + || mDataConnectionNetworkType[phoneId] != networkType)) { + String str = "onDataConnectionStateChanged(" + state + + ", " + networkType + ")"; log(str); mLocalLog.log(str); for (Record r : mRecords) { @@ -1259,15 +1225,16 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (DBG) { log("Notify data connection state changed on sub: " + subId); } - r.callback.onDataConnectionStateChanged( - mDataConnectionState[phoneId], - mDataConnectionNetworkType[phoneId]); + r.callback.onDataConnectionStateChanged(state, networkType); } catch (RemoteException ex) { mRemoveList.add(r.binder); } } } handleRemoveListLocked(); + + mDataConnectionState[phoneId] = state; + mDataConnectionNetworkType[phoneId] = networkType; } mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType, apnType, apn, reason, linkProperties, ""); @@ -1503,14 +1470,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mCallForwarding=" + mCallForwarding[i]); pw.println("mDataActivity=" + mDataActivity[i]); pw.println("mDataConnectionState=" + mDataConnectionState[i]); - pw.println("mDataConnectionLinkProperties=" + mDataConnectionLinkProperties[i]); - pw.println("mDataConnectionNetworkCapabilities=" + - mDataConnectionNetworkCapabilities[i]); pw.println("mCellLocation=" + mCellLocation[i]); pw.println("mCellInfo=" + mCellInfo.get(i)); pw.decreaseIndent(); } - pw.println("mConnectedApns=" + Arrays.toString(mConnectedApns)); pw.println("mPreciseDataConnectionState=" + mPreciseDataConnectionState); pw.println("mPreciseCallState=" + mPreciseCallState); pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 26f83f560c5c..eb4e32e47489 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -3390,10 +3390,15 @@ public final class ActiveServices { return; } + app = r.app; + if (app != null && app.debugging) { + // The app's being debugged; let it ride + return; + } + if (DEBUG_BACKGROUND_CHECK) { Slog.i(TAG, "Service foreground-required timeout for " + r); } - app = r.app; r.fgWaiting = false; stopServiceLocked(r); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 96633da16508..dd31a84ea93c 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.RemoteAction; 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 @@ public class ActivityManagerService extends IActivityManager.Stub } 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 @@ -25378,6 +25377,14 @@ public class ActivityManagerService extends IActivityManager.Stub } catch (IOException e) { } mProfilerInfo.profileFd = null; + + if (proc.pid == MY_PID) { + // When profiling the system server itself, avoid closing the file + // descriptor, as profilerControl will not create a copy. + // Note: it is also not correct to just set profileFd to null, as the + // whole ProfilerInfo instance is passed down! + profilerInfo = null; + } } else { stopProfilerLocked(proc, profileType); if (profilerInfo != null && profilerInfo.profileFd != null) { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index c00fc6afa653..a24f84aa85b9 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -195,8 +195,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // How long we wait for the activity to tell us it has stopped before // giving up. This is a good amount of time because we really need this - // from the application in order to get its saved state. - private static final int STOP_TIMEOUT = 10 * 1000; + // from the application in order to get its saved state. Once the stop + // is complete we may start destroying client resources triggering + // crashes if the UI thread was hung. We put this timeout one second behind + // the ANR timeout so these situations will generate ANR instead of + // Surface lost or other errors. + private static final int STOP_TIMEOUT = 11 * 1000; // How long we wait until giving up on an activity telling us it has // finished destroying itself. @@ -2707,9 +2711,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to " + lastState + ": " + next); next.setState(lastState, "resumeTopActivityInnerLocked"); - if (lastStack != null) { + + // lastResumedActivity being non-null implies there is a lastStack present. + if (lastResumedActivity != null) { lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked"); } + Slog.i(TAG, "Restarting because process died: " + next); if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; @@ -4494,11 +4501,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return hasVisibleActivities; } - private void updateTransitLocked(int transit, ActivityOptions options) { + private void updateTransitLocked(int transit, ActivityRecord starting, + ActivityOptions options) { if (options != null) { - ActivityRecord r = topRunningActivityLocked(); - if (r != null && !r.isState(RESUMED)) { - r.updateOptionsLocked(options); + if (starting != null && !starting.isState(RESUMED)) { + starting.updateOptionsLocked(options); } else { ActivityOptions.abort(options); } @@ -4535,8 +4542,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } - final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options, - AppTimeTracker timeTracker, String reason) { + final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord starting, + boolean noAnimation, ActivityOptions options, AppTimeTracker timeTracker, + String reason) { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr); final ActivityStack topStack = getDisplay().getTopStack(); @@ -4548,7 +4556,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (noAnimation) { ActivityOptions.abort(options); } else { - updateTransitLocked(TRANSIT_TASK_TO_FRONT, options); + updateTransitLocked(TRANSIT_TASK_TO_FRONT, starting, options); } return; } @@ -4586,7 +4594,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } ActivityOptions.abort(options); } else { - updateTransitLocked(TRANSIT_TASK_TO_FRONT, options); + updateTransitLocked(TRANSIT_TASK_TO_FRONT, r, options); } // If a new task is moved to the front, then mark the existing top activity as supporting // picture-in-picture while paused only if the task would not be considered an oerlay on top diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index abd24e140c01..efc0d7d87e63 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2196,7 +2196,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } final ActivityRecord r = task.getTopActivity(); - currentStack.moveTaskToFrontLocked(task, false /* noAnimation */, options, + currentStack.moveTaskToFrontLocked(task, r, false /* noAnimation */, options, r == null ? null : r.appTimeTracker, reason); if (DEBUG_STACK) Slog.d(TAG_STACK, diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index bd53eac7fee7..267023569ce0 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1815,8 +1815,9 @@ class ActivityStarter { // We only want to move to the front, if we aren't going to launch on a // different stack. If we launch on a different stack, we will put the // task on top there. - mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions, - mStartActivity.appTimeTracker, "bringingFoundTaskToFront"); + mTargetStack.moveTaskToFrontLocked(intentTask, mStartActivity, mNoAnimation, + mOptions, mStartActivity.appTimeTracker, + "bringingFoundTaskToFront"); mMovedToFront = true; } else if (launchStack.inSplitScreenWindowingMode()) { if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) { @@ -1830,7 +1831,7 @@ class ActivityStarter { // We choose to move task to front instead of launching it adjacent // when specific stack was requested explicitly and it appeared to be // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set. - mTargetStack.moveTaskToFrontLocked(intentTask, + mTargetStack.moveTaskToFrontLocked(intentTask, mStartActivity, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "bringToFrontInsteadOfAdjacentLaunch"); } @@ -2059,7 +2060,7 @@ class ActivityStarter { final TaskRecord topTask = mTargetStack.topTask(); if (topTask != sourceTask && !mAvoidMoveToFront) { - mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions, + mTargetStack.moveTaskToFrontLocked(sourceTask, mStartActivity, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "sourceTaskToFront"); } else if (mDoResume) { mTargetStack.moveToFront("sourceStackToFront"); @@ -2125,7 +2126,7 @@ class ActivityStarter { && top.userId == mStartActivity.userId) { if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) { - mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions, + mTargetStack.moveTaskToFrontLocked(mInTask, mStartActivity, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront"); if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do @@ -2138,7 +2139,7 @@ class ActivityStarter { } if (!mAddingToTask) { - mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions, + mTargetStack.moveTaskToFrontLocked(mInTask, mStartActivity, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront"); // We don't actually want to have this activity added to the task, so just // stop here but still tell the caller that we consumed the intent. @@ -2158,8 +2159,8 @@ class ActivityStarter { updateBounds(mInTask, mLaunchParams.mBounds); } - mTargetStack.moveTaskToFrontLocked( - mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront"); + mTargetStack.moveTaskToFrontLocked(mInTask, mStartActivity, mNoAnimation, mOptions, + mStartActivity.appTimeTracker, "inTaskToFront"); addOrReparentStartingActivity(mInTask, "setTaskFromInTask"); if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 4541acde14b4..3db1da59b4ea 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -103,7 +103,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub .replaceWith("?"); private ByteBuffer mUtf8BufferStat = ByteBuffer.allocateDirect(MAX_LOW_POWER_STATS_SIZE); private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE); - private static final int MAX_LOW_POWER_STATS_SIZE = 512; + private static final int MAX_LOW_POWER_STATS_SIZE = 2048; /** * Replaces the information in the given rpmStats with up-to-date information. diff --git a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java index d7d18a99b66f..690d985ef096 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 @@ class GlobalSettingsToPropertiesMapper { {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/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java index af99111e4bfa..ed39329844ef 100644 --- a/services/core/java/com/android/server/am/LockTaskController.java +++ b/services/core/java/com/android/server/am/LockTaskController.java @@ -469,6 +469,7 @@ public class LockTaskController { if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) { getStatusBarService().showPinningEnterExitToast(false /* entering */); } + mWindowManager.onLockTaskStateChanged(LOCK_TASK_MODE_NONE); } catch (RemoteException ex) { throw new RuntimeException(ex); } finally { @@ -580,6 +581,7 @@ public class LockTaskController { if (lockTaskModeState == LOCK_TASK_MODE_PINNED) { getStatusBarService().showPinningEnterExitToast(true /* entering */); } + mWindowManager.onLockTaskStateChanged(lockTaskModeState); mLockTaskModeState = lockTaskModeState; setStatusBarState(lockTaskModeState, userId); setKeyguardState(lockTaskModeState, userId); diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java index f1b3dfa5c003..3f05ecee77ef 100644 --- a/services/core/java/com/android/server/am/RecentTasks.java +++ b/services/core/java/com/android/server/am/RecentTasks.java @@ -1238,20 +1238,16 @@ class RecentTasks { * list (if any). */ private int findRemoveIndexForAddTask(TaskRecord task) { - int recentsCount = mTasks.size(); + final int recentsCount = mTasks.size(); + final int taskActivityType = task.getActivityType(); final Intent intent = task.intent; final boolean document = intent != null && intent.isDocument(); int maxRecents = task.maxRecents - 1; - final ActivityStack stack = task.getStack(); for (int i = 0; i < recentsCount; i++) { final TaskRecord tr = mTasks.get(i); - final ActivityStack trStack = tr.getStack(); - + final int trActivityType = tr.getActivityType(); if (task != tr) { - if (stack != null && trStack != null && stack != trStack) { - continue; - } - if (task.userId != tr.userId) { + if (taskActivityType != trActivityType || task.userId != tr.userId) { continue; } final Intent trIntent = tr.intent; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index f577d09cdb9f..9ef84d20004f 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -727,6 +727,36 @@ public class AudioService extends IAudioService.Stub } } + int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1); + if (maxAlarmVolume != -1) { + MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume; + } + + int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1); + if (defaultAlarmVolume != -1 && + defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) { + AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume; + } else { + // Default is 6 out of 7 (default maximum), so scale accordingly. + AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = + 6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7; + } + + int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1); + if (maxSystemVolume != -1) { + MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume; + } + + int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1); + if (defaultSystemVolume != -1 && + defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) { + AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume; + } else { + // Default is to use maximum. + AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = + MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]; + } + sSoundEffectVolumeDb = context.getResources().getInteger( com.android.internal.R.integer.config_soundEffectVolumeDb); diff --git a/services/core/java/com/android/server/backup/BackupUtils.java b/services/core/java/com/android/server/backup/BackupUtils.java index e5d564dec459..d817534551f7 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 @@ package com.android.server.backup; 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 @@ import java.util.List; 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 @@ public class BackupUtils { 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; + 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; + } - // hash each on-device signature - ArrayList<byte[]> deviceHashes = new ArrayList<byte[]>(nDevice); - for (int i = 0; i < nDevice; i++) { - deviceHashes.add(hashSignature(deviceSigs[i])); + if (DEBUG) { + Slog.v(TAG, "signaturesMatch(): stored=" + storedSigHashes + + " device=" + deviceHistorySigs); } - // 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; + 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/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java index 3a8e291f7976..240592528565 100644 --- a/services/core/java/com/android/server/display/DisplayDevice.java +++ b/services/core/java/com/android/server/display/DisplayDevice.java @@ -45,7 +45,7 @@ abstract class DisplayDevice { private Rect mCurrentDisplayRect; // The display device owns its surface, but it should only set it - // within a transaction from performTraversalInTransactionLocked. + // within a transaction from performTraversalLocked. private Surface mCurrentSurface; // DEBUG STATE: Last device info which was written to the log, or null if none. @@ -122,7 +122,7 @@ abstract class DisplayDevice { /** * Gives the display device a chance to update its properties while in a transaction. */ - public void performTraversalInTransactionLocked() { + public void performTraversalLocked(SurfaceControl.Transaction t) { } /** @@ -140,7 +140,7 @@ abstract class DisplayDevice { /** * Sets the mode, if supported. */ - public void requestDisplayModesInTransactionLocked(int colorMode, int modeId) { + public void requestDisplayModesLocked(int colorMode, int modeId) { } public void onOverlayChangedLocked() { @@ -149,10 +149,10 @@ abstract class DisplayDevice { /** * Sets the display layer stack while in a transaction. */ - public final void setLayerStackInTransactionLocked(int layerStack) { + public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack) { if (mCurrentLayerStack != layerStack) { mCurrentLayerStack = layerStack; - SurfaceControl.setDisplayLayerStack(mDisplayToken, layerStack); + t.setDisplayLayerStack(mDisplayToken, layerStack); } } @@ -166,7 +166,7 @@ abstract class DisplayDevice { * mapped to. displayRect is specified post-orientation, that is * it uses the orientation seen by the end-user */ - public final void setProjectionInTransactionLocked(int orientation, + public final void setProjectionLocked(SurfaceControl.Transaction t, int orientation, Rect layerStackRect, Rect displayRect) { if (mCurrentOrientation != orientation || mCurrentLayerStackRect == null @@ -185,7 +185,7 @@ abstract class DisplayDevice { } mCurrentDisplayRect.set(displayRect); - SurfaceControl.setDisplayProjection(mDisplayToken, + t.setDisplayProjection(mDisplayToken, orientation, layerStackRect, displayRect); } } @@ -193,10 +193,10 @@ abstract class DisplayDevice { /** * Sets the display surface while in a transaction. */ - public final void setSurfaceInTransactionLocked(Surface surface) { + public final void setSurfaceLocked(SurfaceControl.Transaction t, Surface surface) { if (mCurrentSurface != surface) { mCurrentSurface = surface; - SurfaceControl.setDisplaySurface(mDisplayToken, surface); + t.setDisplaySurface(mDisplayToken, surface); } } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index a5c1fe299e4e..9861ea735570 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -74,6 +74,7 @@ import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; +import android.view.SurfaceControl; import com.android.internal.util.Preconditions; import com.android.server.AnimationThread; @@ -457,14 +458,14 @@ public final class DisplayManagerService extends SystemService { } @VisibleForTesting - void performTraversalInTransactionFromWindowManagerInternal() { + void performTraversalInternal(SurfaceControl.Transaction t) { synchronized (mSyncRoot) { if (!mPendingTraversal) { return; } mPendingTraversal = false; - performTraversalInTransactionLocked(); + performTraversalLocked(t); } // List is self-synchronized copy-on-write. @@ -1056,7 +1057,7 @@ public final class DisplayManagerService extends SystemService { return changed; } - private void performTraversalInTransactionLocked() { + private void performTraversalLocked(SurfaceControl.Transaction t) { // Clear all viewports before configuring displays so that we can keep // track of which ones we have configured. clearViewportsLocked(); @@ -1065,8 +1066,8 @@ public final class DisplayManagerService extends SystemService { final int count = mDisplayDevices.size(); for (int i = 0; i < count; i++) { DisplayDevice device = mDisplayDevices.get(i); - configureDisplayInTransactionLocked(device); - device.performTraversalInTransactionLocked(); + configureDisplayLocked(t, device); + device.performTraversalLocked(t); } // Tell the input system about these new viewports. @@ -1150,7 +1151,7 @@ public final class DisplayManagerService extends SystemService { mVirtualTouchViewports.clear(); } - private void configureDisplayInTransactionLocked(DisplayDevice device) { + private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) { final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0; @@ -1175,7 +1176,7 @@ public final class DisplayManagerService extends SystemService { + device.getDisplayDeviceInfoLocked()); return; } - display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF); + display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF); // Update the viewports if needed. if (!mDefaultViewport.valid @@ -1233,7 +1234,7 @@ public final class DisplayManagerService extends SystemService { mHandler.sendMessage(msg); } - // Requests that performTraversalsInTransactionFromWindowManager be called at a + // Requests that performTraversals be called at a // later time to apply changes to surfaces and displays. private void scheduleTraversalLocked(boolean inTraversal) { if (!mPendingTraversal && mWindowManagerInternal != null) { @@ -2031,8 +2032,8 @@ public final class DisplayManagerService extends SystemService { } @Override - public void performTraversalInTransactionFromWindowManager() { - performTraversalInTransactionFromWindowManagerInternal(); + public void performTraversal(SurfaceControl.Transaction t) { + performTraversalInternal(t); } @Override diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 0d8ec6d23089..5ca9abc8355d 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -584,10 +584,9 @@ final class LocalDisplayAdapter extends DisplayAdapter { } @Override - public void requestDisplayModesInTransactionLocked( - int colorMode, int modeId) { - if (requestModeInTransactionLocked(modeId) || - requestColorModeInTransactionLocked(colorMode)) { + public void requestDisplayModesLocked(int colorMode, int modeId) { + if (requestModeLocked(modeId) || + requestColorModeLocked(colorMode)) { updateDeviceInfoLocked(); } } @@ -597,7 +596,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { updateDeviceInfoLocked(); } - public boolean requestModeInTransactionLocked(int modeId) { + public boolean requestModeLocked(int modeId) { if (modeId == 0) { modeId = mDefaultModeId; } else if (mSupportedModes.indexOfKey(modeId) < 0) { @@ -623,7 +622,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { return true; } - public boolean requestColorModeInTransactionLocked(int colorMode) { + public boolean requestColorModeLocked(int colorMode) { if (mActiveColorMode == colorMode) { return false; } diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index e582fdf63472..23ee56b24b19 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -21,6 +21,7 @@ import android.hardware.display.DisplayManagerInternal; import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; +import android.view.SurfaceControl; import java.io.PrintWriter; import java.util.Arrays; @@ -304,17 +305,18 @@ final class LogicalDisplay { * @param device The display device to modify. * @param isBlanked True if the device is being blanked. */ - public void configureDisplayInTransactionLocked(DisplayDevice device, + public void configureDisplayLocked(SurfaceControl.Transaction t, + DisplayDevice device, boolean isBlanked) { // Set the layer stack. - device.setLayerStackInTransactionLocked(isBlanked ? BLANK_LAYER_STACK : mLayerStack); + device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack); // Set the color mode and mode. if (device == mPrimaryDisplayDevice) { - device.requestDisplayModesInTransactionLocked( + device.requestDisplayModesLocked( mRequestedColorMode, mRequestedModeId); } else { - device.requestDisplayModesInTransactionLocked(0, 0); // Revert to default. + device.requestDisplayModesLocked(0, 0); // Revert to default. } // Only grab the display info now as it may have been changed based on the requests above. @@ -377,7 +379,7 @@ final class LogicalDisplay { mTempDisplayRect.right += mDisplayOffsetX; mTempDisplayRect.top += mDisplayOffsetY; mTempDisplayRect.bottom += mDisplayOffsetY; - device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect); + device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect); } /** diff --git a/services/core/java/com/android/server/display/OWNERS b/services/core/java/com/android/server/display/OWNERS index 83614219a3b5..98e32997e587 100644 --- a/services/core/java/com/android/server/display/OWNERS +++ b/services/core/java/com/android/server/display/OWNERS @@ -1,3 +1,5 @@ michaelwr@google.com +hackbod@google.com +ogunwale@google.com -per-file ColorDisplayService.java=christyfranks@google.com
\ No newline at end of file +per-file ColorDisplayService.java=christyfranks@google.com diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java index 27327d4eb100..e65637f04975 100644 --- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java @@ -271,12 +271,12 @@ final class OverlayDisplayAdapter extends DisplayAdapter { } @Override - public void performTraversalInTransactionLocked() { + public void performTraversalLocked(SurfaceControl.Transaction t) { if (mSurfaceTexture != null) { if (mSurface == null) { mSurface = new Surface(mSurfaceTexture); } - setSurfaceInTransactionLocked(mSurface); + setSurfaceLocked(t, mSurface); } } @@ -315,7 +315,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { } @Override - public void requestDisplayModesInTransactionLocked(int color, int id) { + public void requestDisplayModesLocked(int color, int id) { int index = -1; if (id == 0) { // Use the default. diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index f86d57634bff..6111c23f252c 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -269,12 +269,12 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } @Override - public void performTraversalInTransactionLocked() { + public void performTraversalLocked(SurfaceControl.Transaction t) { if ((mPendingChanges & PENDING_RESIZE) != 0) { - SurfaceControl.setDisplaySize(getDisplayTokenLocked(), mWidth, mHeight); + t.setDisplaySize(getDisplayTokenLocked(), mWidth, mHeight); } if ((mPendingChanges & PENDING_SURFACE_CHANGE) != 0) { - setSurfaceInTransactionLocked(mSurface); + setSurfaceLocked(t, mSurface); } mPendingChanges = 0; } diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java index 329337933956..e8d6ad455fbf 100644 --- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java @@ -620,9 +620,9 @@ final class WifiDisplayAdapter extends DisplayAdapter { } @Override - public void performTraversalInTransactionLocked() { + public void performTraversalLocked(SurfaceControl.Transaction t) { if (mSurface != null) { - setSurfaceInTransactionLocked(mSurface); + setSurfaceLocked(t, mSurface); } } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java index 8efce8602e78..5bfdf41a6654 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java @@ -45,6 +45,7 @@ import java.security.PublicKey; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.CertPath; +import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -148,6 +149,11 @@ public class KeySyncTask implements Runnable { mPlatformKeyManager.invalidatePlatformKey(mUserId, generation); return; } + if (isCustomLockScreen()) { + Log.w(TAG, "Unsupported credential type " + mCredentialType + "for user " + mUserId); + mRecoverableKeyStoreDb.invalidateKeysForUserIdOnCustomScreenLock(mUserId); + return; + } List<Integer> recoveryAgents = mRecoverableKeyStoreDb.getRecoveryAgents(mUserId); for (int uid : recoveryAgents) { @@ -158,6 +164,12 @@ public class KeySyncTask implements Runnable { } } + private boolean isCustomLockScreen() { + return mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_NONE + && mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_PATTERN + && mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; + } + private void syncKeysForAgent(int recoveryAgentUid) { boolean recreateCurrentVersion = false; if (!shoudCreateSnapshot(recoveryAgentUid)) { @@ -284,17 +296,23 @@ public class KeySyncTask implements Runnable { // If application keys are not updated, snapshot will not be created on next unlock. mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false); - mRecoverySnapshotStorage.put(recoveryAgentUid, new KeyChainSnapshot.Builder() + KeyChainSnapshot.Builder keyChainSnapshotBuilder = new KeyChainSnapshot.Builder() .setSnapshotVersion(getSnapshotVersion(recoveryAgentUid, recreateCurrentVersion)) .setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS) .setCounterId(counterId) .setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey)) - .setTrustedHardwareCertPath(certPath) .setServerParams(vaultHandle) .setKeyChainProtectionParams(metadataList) .setWrappedApplicationKeys(createApplicationKeyEntries(encryptedApplicationKeys)) - .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey) - .build()); + .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey); + try { + keyChainSnapshotBuilder.setTrustedHardwareCertPath(certPath); + } catch(CertificateException e) { + // Should not happen, as it's just deserialized from bytes stored in the db + Log.wtf(TAG, "Cannot serialize CertPath when calling setTrustedHardwareCertPath", e); + return; + } + mRecoverySnapshotStorage.put(recoveryAgentUid, keyChainSnapshotBuilder.build()); mSnapshotListenersStorage.recoverySnapshotAvailable(recoveryAgentUid); } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java index 89ddb6c9eb30..2676ee8897af 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java @@ -320,6 +320,20 @@ public class RecoverableKeyStoreDb { } /** + * Updates status of old keys to {@code RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE}. + */ + public void invalidateKeysForUserIdOnCustomScreenLock(int userId) { + SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(KeysEntry.COLUMN_NAME_RECOVERY_STATUS, + RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE); + String selection = + KeysEntry.COLUMN_NAME_USER_ID + " = ?"; + db.update(KeysEntry.TABLE_NAME, values, selection, + new String[] {String.valueOf(userId)}); + } + + /** * Returns the generation ID associated with the platform key of the user with {@code userId}. */ public int getPlatformKeyGenerationId(int userId) { diff --git a/services/core/java/com/android/server/media/OWNERS b/services/core/java/com/android/server/media/OWNERS index 755c1d6f8aff..8adea0e85d12 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 ab555532a102..efca15984e57 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 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/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index b9fb2e012e03..b911c7b85d23 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -256,6 +256,9 @@ public class NotificationManagerService extends SystemService { static final int LONG_DELAY = PhoneWindowManager.TOAST_WINDOW_TIMEOUT; static final int SHORT_DELAY = 2000; // 2 seconds + // 1 second past the ANR timeout. + static final int FINISH_TOKEN_TIMEOUT = 11 * 1000; + static final long[] DEFAULT_VIBRATE_PATTERN = {0, 250, 250, 250}; static final long SNOOZE_UNTIL_UNSPECIFIED = -1; @@ -4804,7 +4807,7 @@ public class NotificationManagerService extends SystemService { { mHandler.removeCallbacksAndMessages(token); Message m = Message.obtain(mHandler, MESSAGE_FINISH_TOKEN_TIMEOUT, token); - mHandler.sendMessageDelayed(m, 5); + mHandler.sendMessageDelayed(m, FINISH_TOKEN_TIMEOUT); } private void handleKillTokenTimeout(IBinder token) diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index c1593a7fa7e4..e86253037b08 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -893,9 +893,18 @@ public class ZenModeHelper { protected void applyRestrictions(boolean mute, int usage, int code) { final String[] exceptionPackages = null; // none (for now) - mAppOps.setRestriction(code, usage, - mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, - exceptionPackages); + // Only do this if we are executing within the system process... otherwise + // we are running as test code, so don't have access to the protected call. + if (Process.myUid() == Process.SYSTEM_UID) { + final long ident = Binder.clearCallingIdentity(); + try { + mAppOps.setRestriction(code, usage, + mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, + exceptionPackages); + } finally { + Binder.restoreCallingIdentity(ident); + } + } } @VisibleForTesting @@ -1194,15 +1203,21 @@ public class ZenModeHelper { final Bundle extras = new Bundle(); extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, mContext.getResources().getString(R.string.global_action_settings)); - return new Notification.Builder(mContext, SystemNotificationChannels.SYSTEM_CHANGES) + int title = R.string.zen_upgrade_notification_title; + int content = R.string.zen_upgrade_notification_content; + if (NotificationManager.Policy.areAllVisualEffectsSuppressed( + getNotificationPolicy().suppressedVisualEffects)) { + title = R.string.zen_upgrade_notification_visd_title; + content = R.string.zen_upgrade_notification_visd_content; + } + return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB) .setSmallIcon(R.drawable.ic_settings_24dp) - .setContentTitle(mContext.getResources().getString( - R.string.zen_upgrade_notification_title)) - .setContentText(mContext.getResources().getString( - R.string.zen_upgrade_notification_content)) + .setContentTitle(mContext.getResources().getString(title)) + .setContentText(mContext.getResources().getString(content)) .setAutoCancel(true) .setLocalOnly(true) .addExtras(extras) + .setStyle(new Notification.BigTextStyle()) .setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0, null)) .build(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 707184fcfb97..f4360e479c71 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.PackageLite; 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; @@ -2877,7 +2878,8 @@ public class PackageManagerService extends IPackageManager.Stub rescanFlags = scanFlags | SCAN_AS_SYSTEM; - } else if (FileUtils.contains(privilegedVendorAppDir, scanFile)) { + } else if (FileUtils.contains(privilegedVendorAppDir, scanFile) + || FileUtils.contains(privilegedOdmAppDir, scanFile)) { reparseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR; @@ -2886,7 +2888,8 @@ public class PackageManagerService extends IPackageManager.Stub | SCAN_AS_SYSTEM | SCAN_AS_VENDOR | SCAN_AS_PRIVILEGED; - } else if (FileUtils.contains(vendorAppDir, scanFile)) { + } else if (FileUtils.contains(vendorAppDir, scanFile) + || FileUtils.contains(odmAppDir, scanFile)) { reparseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR; @@ -4084,14 +4087,24 @@ public class PackageManagerService extends IPackageManager.Stub @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 @@ -4136,6 +4149,10 @@ public class PackageManagerService extends IPackageManager.Stub 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) { @@ -4148,7 +4165,7 @@ public class PackageManagerService extends IPackageManager.Stub 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 @@ -11788,6 +11805,8 @@ public class PackageManagerService extends IPackageManager.Stub codeRoot = Environment.getOemDirectory(); } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) { codeRoot = Environment.getVendorDirectory(); + } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) { + codeRoot = Environment.getOdmDirectory(); } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) { codeRoot = Environment.getProductDirectory(); } else { @@ -18217,9 +18236,11 @@ public class PackageManagerService extends IPackageManager.Stub try { final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app"); final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app"); + final File privilegedOdmAppDir = new File(Environment.getOdmDirectory(), "priv-app"); final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app"); return path.startsWith(privilegedAppDir.getCanonicalPath()) || path.startsWith(privilegedVendorAppDir.getCanonicalPath()) + || path.startsWith(privilegedOdmAppDir.getCanonicalPath()) || path.startsWith(privilegedProductAppDir.getCanonicalPath()); } catch (IOException e) { Slog.e(TAG, "Unable to access code path " + path); @@ -18238,7 +18259,8 @@ public class PackageManagerService extends IPackageManager.Stub static boolean locationIsVendor(String path) { try { - return path.startsWith(Environment.getVendorDirectory().getCanonicalPath()); + return path.startsWith(Environment.getVendorDirectory().getCanonicalPath()) + || path.startsWith(Environment.getOdmDirectory().getCanonicalPath()); } catch (IOException e) { Slog.e(TAG, "Unable to access code path " + path); } @@ -23376,6 +23398,36 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } @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); } @@ -23840,6 +23892,15 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } @Override + public boolean canAccessComponent(int callingUid, ComponentName component, int userId) { + synchronized (mPackages) { + final PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); + return !PackageManagerService.this.filterAppAccessLPr( + ps, callingUid, component, TYPE_UNKNOWN, userId); + } + } + + @Override public boolean hasInstantApplicationMetadata(String packageName, int userId) { synchronized (mPackages) { return mInstantAppRegistry.hasInstantApplicationMetadataLPr(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 520ed2526b17..eeaa3330dee4 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 @@ package com.android.server.pm; 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 @@ class ShortcutPackageInfo { //@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 @@ class ShortcutPackageInfo { 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 @@ class ShortcutPackageInfo { 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 @@ class ShortcutPackageInfo { 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 265cc8ebe4d3..15b461729495 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 @@ public class ShortcutService extends IShortcutService.Stub { 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/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index 4abcce16f777..bf85f30d092e 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -1240,6 +1240,10 @@ public final class DefaultPermissionGrantPolicy { if (dir.isDirectory() && dir.canRead()) { Collections.addAll(ret, dir.listFiles()); } + dir = new File(Environment.getOdmDirectory(), "etc/default-permissions"); + if (dir.isDirectory() && dir.canRead()) { + Collections.addAll(ret, dir.listFiles()); + } dir = new File(Environment.getProductDirectory(), "etc/default-permissions"); if (dir.isDirectory() && dir.canRead()) { Collections.addAll(ret, dir.listFiles()); diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java index c6ec287d9c6a..4aa24465215b 100644 --- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java +++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java @@ -16,6 +16,9 @@ package com.android.server.policy; +import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED; +import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; + import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.app.ActivityManager; @@ -78,6 +81,7 @@ public class ImmersiveModeConfirmation { // Local copy of vr mode enabled state, to avoid calling into VrManager with // the lock held. boolean mVrModeEnabled = false; + private int mLockTaskState = LOCK_TASK_MODE_NONE; public ImmersiveModeConfirmation(Context context) { mContext = ActivityThread.currentActivityThread().getSystemUiContext(); @@ -148,7 +152,8 @@ public class ImmersiveModeConfirmation { && userSetupComplete && !mVrModeEnabled && !navBarEmpty - && !UserManager.isDeviceInDemoMode(mContext)) { + && !UserManager.isDeviceInDemoMode(mContext) + && (mLockTaskState != LOCK_TASK_MODE_LOCKED)) { mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs); } } else { @@ -401,4 +406,8 @@ public class ImmersiveModeConfirmation { } } }; + + void onLockTaskModeChangedLw(int lockTaskState) { + mLockTaskState = lockTaskState; + } } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index c14beefaa555..3cd79e1642dc 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -1456,6 +1456,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { + "already in the process of turning the screen on."); return; } + Slog.d(TAG, "powerPress: eventTime=" + eventTime + " interactive=" + interactive + + " count=" + count + " beganFromNonInteractive=" + mBeganFromNonInteractive + + " mShortPressOnPowerBehavior=" + mShortPressOnPowerBehavior); if (count == 2) { powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior); @@ -8808,4 +8811,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { return Integer.toString(behavior); } } + + @Override + public void onLockTaskStateChangedLw(int lockTaskState) { + mImmersiveModeConfirmation.onLockTaskModeChangedLw(lockTaskState); + } } diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 8ec8c5b3c77e..b0d5e1a8c62a 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -66,6 +66,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.Manifest; import android.annotation.IntDef; import android.annotation.Nullable; +import android.app.ActivityManager; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.CompatibilityInfo; @@ -1731,4 +1732,15 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { * on the next user activity. */ public void requestUserActivityNotification(); + + /** + * Called when the state of lock task mode changes. This should be used to disable immersive + * mode confirmation. + * + * @param lockTaskState the new lock task mode state. One of + * {@link ActivityManager#LOCK_TASK_MODE_NONE}, + * {@link ActivityManager#LOCK_TASK_MODE_LOCKED}, + * {@link ActivityManager#LOCK_TASK_MODE_PINNED}. + */ + void onLockTaskStateChangedLw(int lockTaskState); } diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java index 16336b308dbc..483f974ab8b6 100644 --- a/services/core/java/com/android/server/power/BatterySaverPolicy.java +++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java @@ -69,6 +69,7 @@ public class BatterySaverPolicy extends ContentObserver { private static final String KEY_FORCE_BACKGROUND_CHECK = "force_background_check"; private static final String KEY_OPTIONAL_SENSORS_DISABLED = "optional_sensors_disabled"; private static final String KEY_AOD_DISABLED = "aod_disabled"; + private static final String KEY_SEND_TRON_LOG = "send_tron_log"; private static final String KEY_CPU_FREQ_INTERACTIVE = "cpufreq-i"; private static final String KEY_CPU_FREQ_NONINTERACTIVE = "cpufreq-n"; @@ -212,6 +213,12 @@ public class BatterySaverPolicy extends ContentObserver { @GuardedBy("mLock") private boolean mAodDisabled; + /** + * Whether BatterySavingStats should send tron events. + */ + @GuardedBy("mLock") + private boolean mSendTronLog; + @GuardedBy("mLock") private Context mContext; @@ -347,6 +354,7 @@ public class BatterySaverPolicy extends ContentObserver { mForceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, true); mOptionalSensorsDisabled = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED, true); mAodDisabled = parser.getBoolean(KEY_AOD_DISABLED, true); + mSendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, true); // Get default value from Settings.Secure final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE, @@ -384,10 +392,13 @@ public class BatterySaverPolicy extends ContentObserver { if (mLaunchBoostDisabled) sb.append("l"); if (mOptionalSensorsDisabled) sb.append("S"); if (mAodDisabled) sb.append("o"); + if (mSendTronLog) sb.append("t"); sb.append(mGpsMode); mEventLogKeys = sb.toString(); + + BatterySavingStats.getInstance().setSendTronLog(mSendTronLog); } /** @@ -483,7 +494,10 @@ public class BatterySaverPolicy extends ContentObserver { public void dump(PrintWriter pw) { synchronized (mLock) { pw.println(); - pw.println("Battery saver policy"); + BatterySavingStats.getInstance().dump(pw, ""); + + pw.println(); + pw.println("Battery saver policy (*NOTE* they only apply when battery saver is ON):"); pw.println(" Settings: " + Settings.Global.BATTERY_SAVER_CONSTANTS); pw.println(" value: " + mSettings); pw.println(" Settings: " + mDeviceSpecificSettingsSource); @@ -504,6 +518,7 @@ public class BatterySaverPolicy extends ContentObserver { pw.println(" " + KEY_FORCE_BACKGROUND_CHECK + "=" + mForceBackgroundCheck); pw.println(" " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + mOptionalSensorsDisabled); pw.println(" " + KEY_AOD_DISABLED + "=" + mAodDisabled); + pw.println(" " + KEY_SEND_TRON_LOG + "=" + mSendTronLog); pw.println(); pw.print(" Interactive File values:\n"); @@ -512,9 +527,6 @@ public class BatterySaverPolicy extends ContentObserver { pw.print(" Noninteractive File values:\n"); dumpMap(pw, " ", mFilesForNoninteractive); - pw.println(); - pw.println(); - BatterySavingStats.getInstance().dump(pw, " "); } } diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java index 5d76329eb8a1..4fd86860d8f9 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java @@ -20,6 +20,7 @@ import android.os.BatteryManagerInternal; import android.os.SystemClock; import android.util.ArrayMap; import android.util.Slog; +import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -31,6 +32,8 @@ import com.android.server.LocalServices; import com.android.server.power.BatterySaverPolicy; import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; /** * This class keeps track of battery drain rate. @@ -46,9 +49,6 @@ public class BatterySavingStats { private static final boolean DEBUG = BatterySaverPolicy.DEBUG; - @VisibleForTesting - static final boolean SEND_TRON_EVENTS = true; - private final Object mLock = new Object(); /** Whether battery saver is on or off. */ @@ -159,8 +159,18 @@ public class BatterySavingStats { @GuardedBy("mLock") final ArrayMap<Integer, Stat> mStats = new ArrayMap<>(); + @GuardedBy("mLock") + private int mBatterySaverEnabledCount = 0; + + @GuardedBy("mLock") + private long mLastBatterySaverEnabledTime = 0; + private final MetricsLoggerHelper mMetricsLoggerHelper = new MetricsLoggerHelper(); + @VisibleForTesting + @GuardedBy("mLock") + private boolean mSendTronLog; + /** * Don't call it directly -- use {@link #getInstance()}. Not private for testing. * @param metricsLogger @@ -178,6 +188,12 @@ public class BatterySavingStats { return sInstance; } + public void setSendTronLog(boolean send) { + synchronized (mLock) { + mSendTronLog = send; + } + } + private BatteryManagerInternal getBatteryManagerInternal() { if (mBatteryManagerInternal == null) { mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class); @@ -291,9 +307,22 @@ public class BatterySavingStats { final int batteryLevel = injectBatteryLevel(); final int batteryPercent = injectBatteryPercent(); + final boolean oldBatterySaverEnabled = + BatterySaverState.fromIndex(mCurrentState) != BatterySaverState.OFF; + final boolean newBatterySaverEnabled = + BatterySaverState.fromIndex(newState) != BatterySaverState.OFF; + if (oldBatterySaverEnabled != newBatterySaverEnabled) { + if (newBatterySaverEnabled) { + mBatterySaverEnabledCount++; + mLastBatterySaverEnabledTime = injectCurrentTime(); + } else { + mLastBatterySaverEnabledTime = 0; + } + } + endLastStateLocked(now, batteryLevel, batteryPercent); startNewStateLocked(newState, now, batteryLevel, batteryPercent); - mMetricsLoggerHelper.transitionState(newState, now, batteryLevel, batteryPercent); + mMetricsLoggerHelper.transitionStateLocked(newState, now, batteryLevel, batteryPercent); } @GuardedBy("mLock") @@ -358,12 +387,39 @@ public class BatterySavingStats { public void dump(PrintWriter pw, String indent) { synchronized (mLock) { pw.print(indent); - pw.println("Battery Saving Stats:"); + pw.println("Battery saving stats:"); indent = indent + " "; pw.print(indent); - pw.println("Battery Saver: w/Off w/On"); + pw.print("Battery Saver state: "); + if (mLastBatterySaverEnabledTime == 0) { + pw.print("OFF"); + } else { + pw.print("ON since "); + + final long now = System.currentTimeMillis(); + final long nowElapsed = injectCurrentTime(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + pw.print(sdf.format(new Date(now - nowElapsed + mLastBatterySaverEnabledTime))); + + pw.print(" "); + TimeUtils.formatDuration(mLastBatterySaverEnabledTime, nowElapsed, pw); + } + pw.println(); + + pw.print(indent); + pw.print("Times enabled: "); + pw.println(mBatterySaverEnabledCount); + + pw.println(); + + pw.print(indent); + pw.println("Drain stats:"); + + pw.print(indent); + pw.println(" Battery saver OFF ON"); dumpLineLocked(pw, indent, InteractiveState.NON_INTERACTIVE, "NonIntr", DozeState.NOT_DOZING, "NonDoze"); dumpLineLocked(pw, indent, InteractiveState.INTERACTIVE, " Intr", @@ -378,8 +434,6 @@ public class BatterySavingStats { DozeState.LIGHT, "Light "); dumpLineLocked(pw, indent, InteractiveState.INTERACTIVE, " Intr", DozeState.LIGHT, " "); - - pw.println(); } } @@ -395,7 +449,7 @@ public class BatterySavingStats { final Stat offStat = getStat(BatterySaverState.OFF, interactiveState, dozeState); final Stat onStat = getStat(BatterySaverState.ON, interactiveState, dozeState); - pw.println(String.format("%6dm %6dmA (%3d%%) %8.1fmA/h %6dm %6dmA (%3d%%) %8.1fmA/h", + pw.println(String.format("%6dm %6dmAh(%3d%%) %8.1fmAh/h %6dm %6dmAh(%3d%%) %8.1fmAh/h", offStat.totalMinutes(), offStat.totalBatteryDrain / 1000, offStat.totalBatteryDrainPercent, @@ -417,7 +471,8 @@ public class BatterySavingStats { (BatterySaverState.MASK << BatterySaverState.SHIFT) | (InteractiveState.MASK << InteractiveState.SHIFT); - public void transitionState(int newState, long now, int batteryLevel, int batteryPercent) { + public void transitionStateLocked( + int newState, long now, int batteryLevel, int batteryPercent) { final boolean stateChanging = ((mLastState >= 0) ^ (newState >= 0)) || (((mLastState ^ newState) & STATE_CHANGE_DETECT_MASK) != 0); @@ -425,7 +480,7 @@ public class BatterySavingStats { if (mLastState >= 0) { final long deltaTime = now - mStartTime; - report(mLastState, deltaTime, mStartBatteryLevel, mStartPercent, + reportLocked(mLastState, deltaTime, mStartBatteryLevel, mStartPercent, batteryLevel, batteryPercent); } mStartTime = now; @@ -435,10 +490,10 @@ public class BatterySavingStats { mLastState = newState; } - void report(int state, long deltaTimeMs, + void reportLocked(int state, long deltaTimeMs, int startBatteryLevelUa, int startBatteryLevelPercent, int endBatteryLevelUa, int endBatteryLevelPercent) { - if (!SEND_TRON_EVENTS) { + if (!mSendTronLog) { return; } final boolean batterySaverOn = diff --git a/services/core/java/com/android/server/search/Searchables.java b/services/core/java/com/android/server/search/Searchables.java index 6bacdfdafbda..8af76a17f084 100644 --- a/services/core/java/com/android/server/search/Searchables.java +++ b/services/core/java/com/android/server/search/Searchables.java @@ -26,14 +26,18 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.os.Binder; import android.os.Bundle; import android.os.RemoteException; +import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; +import com.android.server.LocalServices; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; @@ -119,7 +123,15 @@ public class Searchables { SearchableInfo result; synchronized (this) { result = mSearchablesMap.get(activity); - if (result != null) return result; + if (result != null) { + final PackageManagerInternal pm = + LocalServices.getService(PackageManagerInternal.class); + if (pm.canAccessComponent(Binder.getCallingUid(), result.getSearchActivity(), + UserHandle.getCallingUserId())) { + return result; + } + return null; + } } // Step 2. See if the current activity references a searchable. @@ -170,8 +182,16 @@ public class Searchables { result = mSearchablesMap.get(referredActivity); if (result != null) { mSearchablesMap.put(activity, result); + } + } + if (result != null) { + final PackageManagerInternal pm = + LocalServices.getService(PackageManagerInternal.class); + if (pm.canAccessComponent(Binder.getCallingUid(), result.getSearchActivity(), + UserHandle.getCallingUserId())) { return result; } + return null; } } @@ -410,7 +430,7 @@ public class Searchables { activities = mPm.queryIntentActivities(intent, intent.resolveTypeIfNeeded(mContext.getContentResolver()), - flags, mUserId).getList(); + flags | PackageManager.MATCH_INSTANT, mUserId).getList(); } catch (RemoteException re) { // Local call } @@ -421,36 +441,82 @@ public class Searchables { * Returns the list of searchable activities. */ public synchronized ArrayList<SearchableInfo> getSearchablesList() { - ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(mSearchablesList); - return result; + return createFilterdSearchableInfoList(mSearchablesList); } /** * Returns a list of the searchable activities that can be included in global search. */ public synchronized ArrayList<SearchableInfo> getSearchablesInGlobalSearchList() { - return new ArrayList<SearchableInfo>(mSearchablesInGlobalSearchList); + return createFilterdSearchableInfoList(mSearchablesInGlobalSearchList); } /** * Returns a list of activities that handle the global search intent. */ public synchronized ArrayList<ResolveInfo> getGlobalSearchActivities() { - return new ArrayList<ResolveInfo>(mGlobalSearchActivities); + return createFilterdResolveInfoList(mGlobalSearchActivities); + } + + private ArrayList<SearchableInfo> createFilterdSearchableInfoList(List<SearchableInfo> list) { + if (list == null) { + return null; + } + final ArrayList<SearchableInfo> resultList = new ArrayList<>(list.size()); + final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class); + final int callingUid = Binder.getCallingUid(); + final int callingUserId = UserHandle.getCallingUserId(); + for (SearchableInfo info : list) { + if (pm.canAccessComponent(callingUid, info.getSearchActivity(), callingUserId)) { + resultList.add(info); + } + } + return resultList; + } + + private ArrayList<ResolveInfo> createFilterdResolveInfoList(List<ResolveInfo> list) { + if (list == null) { + return null; + } + final ArrayList<ResolveInfo> resultList = new ArrayList<>(list.size()); + final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class); + final int callingUid = Binder.getCallingUid(); + final int callingUserId = UserHandle.getCallingUserId(); + for (ResolveInfo info : list) { + if (pm.canAccessComponent( + callingUid, info.activityInfo.getComponentName(), callingUserId)) { + resultList.add(info); + } + } + return resultList; } /** * Gets the name of the global search activity. */ public synchronized ComponentName getGlobalSearchActivity() { - return mCurrentGlobalSearchActivity; + final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class); + final int callingUid = Binder.getCallingUid(); + final int callingUserId = UserHandle.getCallingUserId(); + if (mCurrentGlobalSearchActivity != null + && pm.canAccessComponent(callingUid, mCurrentGlobalSearchActivity, callingUserId)) { + return mCurrentGlobalSearchActivity; + } + return null; } /** * Gets the name of the web search activity. */ public synchronized ComponentName getWebSearchActivity() { - return mWebSearchActivity; + final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class); + final int callingUid = Binder.getCallingUid(); + final int callingUserId = UserHandle.getCallingUserId(); + if (mWebSearchActivity != null + && pm.canAccessComponent(callingUid, mWebSearchActivity, callingUserId)) { + return mWebSearchActivity; + } + return null; } void dump(FileDescriptor fd, PrintWriter pw, String[] args) { diff --git a/services/core/java/com/android/server/slice/PinnedSliceState.java b/services/core/java/com/android/server/slice/PinnedSliceState.java index f9a4ea211f07..4e7fb969f398 100644 --- a/services/core/java/com/android/server/slice/PinnedSliceState.java +++ b/services/core/java/com/android/server/slice/PinnedSliceState.java @@ -14,9 +14,6 @@ package com.android.server.slice; -import static android.app.slice.SliceManager.PERMISSION_GRANTED; - -import android.app.slice.Slice; import android.app.slice.SliceProvider; import android.app.slice.SliceSpec; import android.content.ContentProviderClient; @@ -33,7 +30,6 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -54,18 +50,24 @@ public class PinnedSliceState { private final ArraySet<String> mPinnedPkgs = new ArraySet<>(); @GuardedBy("mLock") private final ArrayMap<IBinder, ListenerInfo> mListeners = new ArrayMap<>(); + private final String mPkg; @GuardedBy("mLock") private SliceSpec[] mSupportedSpecs = null; private final DeathRecipient mDeathRecipient = this::handleRecheckListeners; private boolean mSlicePinned; - public PinnedSliceState(SliceManagerService service, Uri uri) { + public PinnedSliceState(SliceManagerService service, Uri uri, String pkg) { mService = service; mUri = uri; + mPkg = pkg; mLock = mService.getLock(); } + public String getPkg() { + return mPkg; + } + public SliceSpec[] getSpecs() { return mSupportedSpecs; } diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java index 51e4709aa7c7..a7dfd35acf1b 100644 --- a/services/core/java/com/android/server/slice/SliceManagerService.java +++ b/services/core/java/com/android/server/slice/SliceManagerService.java @@ -149,11 +149,25 @@ public class SliceManagerService extends ISliceManager.Stub { /// ----- ISliceManager stuff ----- @Override + public Uri[] getPinnedSlices(String pkg) { + verifyCaller(pkg); + ArrayList<Uri> ret = new ArrayList<>(); + synchronized (mLock) { + for (PinnedSliceState state : mPinnedSlicesByUri.values()) { + if (Objects.equals(pkg, state.getPkg())) { + ret.add(state.getUri()); + } + } + } + return ret.toArray(new Uri[ret.size()]); + } + + @Override public void pinSlice(String pkg, Uri uri, SliceSpec[] specs, IBinder token) throws RemoteException { verifyCaller(pkg); enforceAccess(pkg, uri); uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier()); - getOrCreatePinnedSlice(uri).pin(pkg, specs, token); + getOrCreatePinnedSlice(uri, pkg).pin(pkg, specs, token); } @Override @@ -302,11 +316,11 @@ public class SliceManagerService extends ISliceManager.Stub { } } - private PinnedSliceState getOrCreatePinnedSlice(Uri uri) { + private PinnedSliceState getOrCreatePinnedSlice(Uri uri, String pkg) { synchronized (mLock) { PinnedSliceState manager = mPinnedSlicesByUri.get(uri); if (manager == null) { - manager = createPinnedSlice(uri); + manager = createPinnedSlice(uri, pkg); mPinnedSlicesByUri.put(uri, manager); } return manager; @@ -314,8 +328,8 @@ public class SliceManagerService extends ISliceManager.Stub { } @VisibleForTesting - protected PinnedSliceState createPinnedSlice(Uri uri) { - return new PinnedSliceState(this, uri); + protected PinnedSliceState createPinnedSlice(Uri uri, String pkg) { + return new PinnedSliceState(this, uri, pkg); } public Object getLock() { diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index 954627bfaf98..afcedcc80de2 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 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { 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/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index f0ca2ef1747b..93ca4dc48319 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -469,10 +469,16 @@ public class AppTransition implements Dump { * boost the priorities to a more important value whenever an app transition is going to happen * soon or an app transition is running. */ - private void updateBooster() { - WindowManagerService.sThreadPriorityBooster.setAppTransitionRunning( - mNextAppTransition != TRANSIT_UNSET || mAppTransitionState == APP_STATE_READY - || mAppTransitionState == APP_STATE_RUNNING); + void updateBooster() { + WindowManagerService.sThreadPriorityBooster.setAppTransitionRunning(needsBoosting()); + } + + private boolean needsBoosting() { + final boolean recentsAnimRunning = mService.getRecentsAnimationController() != null; + return mNextAppTransition != TRANSIT_UNSET + || mAppTransitionState == APP_STATE_READY + || mAppTransitionState == APP_STATE_RUNNING + || recentsAnimRunning; } void registerListenerLocked(AppTransitionListener listener) { diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index 40f772aaa529..1170148d6781 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -379,6 +379,8 @@ public class AppWindowContainerController if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + wtoken); wtoken.mAppStopped = false; + + mContainer.transferStartingWindowFromHiddenAboveTokenIfNeeded(); } // If we are preparing an app transition, then delay changing diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 267233750f55..1f71b8fa74ec 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -187,6 +187,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree StartingSurface startingSurface; boolean startingDisplayed; boolean startingMoved; + // True if the hidden state of this token was forced to false due to a transferred starting // window. private boolean mHiddenSetFromTransferredStartingWindow; @@ -449,6 +450,12 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (isReallyAnimating()) { delayed = true; + } else { + + // We aren't animating anything, but exiting windows rely on the animation finished + // callback being called in case the AppWindowToken was pretending to be animating, + // which we might have done because we were in closing/opening apps list. + onAnimationFinished(); } for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) { @@ -1091,7 +1098,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree mService.registerAppFreezeListener(this); mService.mAppsFreezingScreen++; if (mService.mAppsFreezingScreen == 1) { - mService.startFreezingDisplayLocked(false, 0, 0, getDisplayContent()); + mService.startFreezingDisplayLocked(0, 0, getDisplayContent()); mService.mH.removeMessages(H.APP_FREEZE_TIMEOUT); mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000); } @@ -1136,6 +1143,25 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree stopFreezingScreen(true, true); } + /** + * Tries to transfer the starting window from a token that's above ourselves in the task but + * not visible anymore. This is a common scenario apps use: Trampoline activity T start main + * activity M in the same task. Now, when reopening the task, T starts on top of M but then + * immediately finishes after, so we have to transfer T to M. + */ + void transferStartingWindowFromHiddenAboveTokenIfNeeded() { + final Task task = getTask(); + for (int i = task.mChildren.size() - 1; i >= 0; i--) { + final AppWindowToken fromToken = task.mChildren.get(i); + if (fromToken == this) { + return; + } + if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) { + return; + } + } + } + boolean transferStartingWindow(IBinder transferFrom) { final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom); if (fromToken == null) { diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java index f19cd0ff96f7..1977e126a8a0 100644 --- a/services/core/java/com/android/server/wm/BlackFrame.java +++ b/services/core/java/com/android/server/wm/BlackFrame.java @@ -41,7 +41,7 @@ public class BlackFrame { final int layer; final SurfaceControl surface; - BlackSurface(int layer, + BlackSurface(SurfaceControl.Transaction transaction, int layer, int l, int t, int r, int b, DisplayContent dc) throws OutOfResourcesException { left = l; top = t; @@ -56,24 +56,24 @@ public class BlackFrame { .setParent(null) // TODO: Work-around for b/69259549 .build(); - surface.setAlpha(1); - surface.setLayer(layer); - surface.show(); + transaction.setAlpha(surface, 1); + transaction.setLayer(surface, layer); + transaction.show(surface); if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM, " BLACK " + surface + ": CREATE layer=" + layer); } - void setAlpha(float alpha) { - surface.setAlpha(alpha); + void setAlpha(SurfaceControl.Transaction t, float alpha) { + t.setAlpha(surface, alpha); } - void setMatrix(Matrix matrix) { + void setMatrix(SurfaceControl.Transaction t, Matrix matrix) { mTmpMatrix.setTranslate(left, top); mTmpMatrix.postConcat(matrix); mTmpMatrix.getValues(mTmpFloats); - surface.setPosition(mTmpFloats[Matrix.MTRANS_X], + t.setPosition(surface, mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]); - surface.setMatrix( + t.setMatrix(surface, mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y], mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]); if (false) { @@ -87,8 +87,8 @@ public class BlackFrame { } } - void clearMatrix() { - surface.setMatrix(1, 0, 0, 1); + void clearMatrix(SurfaceControl.Transaction t) { + t.setMatrix(surface, 1, 0, 0, 1); } } @@ -113,7 +113,8 @@ public class BlackFrame { } } - public BlackFrame(Rect outer, Rect inner, int layer, DisplayContent dc, + public BlackFrame(SurfaceControl.Transaction t, + Rect outer, Rect inner, int layer, DisplayContent dc, boolean forceDefaultOrientation) throws OutOfResourcesException { boolean success = false; @@ -125,19 +126,19 @@ public class BlackFrame { mInnerRect = new Rect(inner); try { if (outer.top < inner.top) { - mBlackSurfaces[0] = new BlackSurface(layer, + mBlackSurfaces[0] = new BlackSurface(t, layer, outer.left, outer.top, inner.right, inner.top, dc); } if (outer.left < inner.left) { - mBlackSurfaces[1] = new BlackSurface(layer, + mBlackSurfaces[1] = new BlackSurface(t, layer, outer.left, inner.top, inner.left, outer.bottom, dc); } if (outer.bottom > inner.bottom) { - mBlackSurfaces[2] = new BlackSurface(layer, + mBlackSurfaces[2] = new BlackSurface(t, layer, inner.left, inner.bottom, outer.right, outer.bottom, dc); } if (outer.right > inner.right) { - mBlackSurfaces[3] = new BlackSurface(layer, + mBlackSurfaces[3] = new BlackSurface(t, layer, inner.right, outer.top, outer.right, inner.bottom, dc); } success = true; @@ -161,36 +162,36 @@ public class BlackFrame { } } - public void hide() { + public void hide(SurfaceControl.Transaction t) { if (mBlackSurfaces != null) { for (int i=0; i<mBlackSurfaces.length; i++) { if (mBlackSurfaces[i] != null) { - mBlackSurfaces[i].surface.hide(); + t.hide(mBlackSurfaces[i].surface); } } } } - public void setAlpha(float alpha) { + public void setAlpha(SurfaceControl.Transaction t, float alpha) { for (int i=0; i<mBlackSurfaces.length; i++) { if (mBlackSurfaces[i] != null) { - mBlackSurfaces[i].setAlpha(alpha); + mBlackSurfaces[i].setAlpha(t, alpha); } } } - public void setMatrix(Matrix matrix) { + public void setMatrix(SurfaceControl.Transaction t, Matrix matrix) { for (int i=0; i<mBlackSurfaces.length; i++) { if (mBlackSurfaces[i] != null) { - mBlackSurfaces[i].setMatrix(matrix); + mBlackSurfaces[i].setMatrix(t, matrix); } } } - public void clearMatrix() { + public void clearMatrix(SurfaceControl.Transaction t) { for (int i=0; i<mBlackSurfaces.length; i++) { if (mBlackSurfaces[i] != null) { - mBlackSurfaces[i].clearMatrix(); + mBlackSurfaces[i].clearMatrix(t); } } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 2dce9133d094..59babcfe0371 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -258,7 +258,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * Current rotation of the display. * Constants as per {@link android.view.Surface.Rotation}. * - * @see #updateRotationUnchecked(boolean) + * @see #updateRotationUnchecked() */ private int mRotation = 0; @@ -274,7 +274,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * Flag indicating that the application is receiving an orientation that has different metrics * than it expected. E.g. Portrait instead of Landscape. * - * @see #updateRotationUnchecked(boolean) + * @see #updateRotationUnchecked() */ private boolean mAltOrientation = false; @@ -926,7 +926,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * Returns true if the rotation has been changed. In this case YOU MUST CALL * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN. */ - boolean updateRotationUnchecked(boolean inTransaction) { + boolean updateRotationUnchecked() { if (mService.mDeferredRotationPauseCount > 0) { // Rotation updates have been paused temporarily. Defer the update until // updates have been resumed. @@ -1030,7 +1030,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mService.mPolicy.selectRotationAnimationLw(anim); if (!rotateSeamlessly) { - mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1], this); + mService.startFreezingDisplayLocked(anim[0], anim[1], this); // startFreezingDisplayLocked can reset the ScreenRotationAnimation. screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked( mDisplayId); @@ -1041,9 +1041,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // to their rotated state independently and without a freeze required. screenRotationAnimation = null; - // We have to reset this in case a window was removed before it - // finished seamless rotation. - mService.mSeamlessRotationCount = 0; + mService.startSeamlessRotation(); } // We need to update our screen size information to match the new rotation. If the rotation @@ -1053,40 +1051,27 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // #computeScreenConfiguration() later. updateDisplayAndOrientation(getConfiguration().uiMode); - if (!inTransaction) { - if (SHOW_TRANSACTIONS) { - Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked"); + // NOTE: We disable the rotation in the emulator because + // it doesn't support hardware OpenGL emulation yet. + if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null + && screenRotationAnimation.hasScreenshot()) { + if (screenRotationAnimation.setRotation(getPendingTransaction(), rotation, + MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(), + mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) { + mService.scheduleAnimationLocked(); } - mService.openSurfaceTransaction(); } - try { - // NOTE: We disable the rotation in the emulator because - // it doesn't support hardware OpenGL emulation yet. - if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null - && screenRotationAnimation.hasScreenshot()) { - if (screenRotationAnimation.setRotationInTransaction(rotation, - MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(), - mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) { - mService.scheduleAnimationLocked(); - } - } - if (rotateSeamlessly) { - forAllWindows(w -> { - w.mWinAnimator.seamlesslyRotateWindow(oldRotation, rotation); - }, true /* traverseTopToBottom */); - } - - mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); - } finally { - if (!inTransaction) { - mService.closeSurfaceTransaction("setRotationUnchecked"); - if (SHOW_LIGHT_TRANSACTIONS) { - Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked"); - } - } + if (rotateSeamlessly) { + forAllWindows(w -> { + w.mWinAnimator.seamlesslyRotateWindow(getPendingTransaction(), + oldRotation, rotation); + }, true /* traverseTopToBottom */); } + mService.mDisplayManagerInternal.performTraversal(getPendingTransaction()); + scheduleAnimation(); + forAllWindows(w -> { if (w.mHasSurface && !rotateSeamlessly) { if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w); @@ -2808,7 +2793,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); - if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) { + if (mService.updateOrientationFromAppTokensLocked(mDisplayId)) { setLayoutNeeded(); mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget(); } diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 59bec74d5265..0b0df6ff588d 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -141,6 +141,22 @@ public class RecentsAnimationController { } @Override + public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) + throws RemoteException { + long token = Binder.clearCallingIdentity(); + try { + synchronized (mService.getWindowManagerLock()) { + for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { + mPendingAnimations.get(i).mTask.setCanAffectSystemUiFlags(behindSystemBars); + } + mService.mWindowPlacerLocked.requestTraversal(); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override public void setInputConsumerEnabled(boolean enabled) { if (DEBUG) Log.d(TAG, "setInputConsumerEnabled(" + enabled + "): mCanceled=" + mCanceled); @@ -240,11 +256,16 @@ public class RecentsAnimationController { return; } try { - final RemoteAnimationTarget[] appAnimations = - new RemoteAnimationTarget[mPendingAnimations.size()]; + final ArrayList<RemoteAnimationTarget> appAnimations = new ArrayList<>(); for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { - appAnimations[i] = mPendingAnimations.get(i).createRemoteAnimationApp(); + final RemoteAnimationTarget target = + mPendingAnimations.get(i).createRemoteAnimationApp(); + if (target != null) { + appAnimations.add(target); + } } + final RemoteAnimationTarget[] appTargets = appAnimations.toArray( + new RemoteAnimationTarget[appAnimations.size()]); mPendingStart = false; final Rect minimizedHomeBounds = @@ -253,7 +274,7 @@ public class RecentsAnimationController { final Rect contentInsets = mHomeAppToken != null && mHomeAppToken.findMainWindow() != null ? mHomeAppToken.findMainWindow().mContentInsets : null; - mRunner.onAnimationStart_New(mController, appAnimations, contentInsets, + mRunner.onAnimationStart_New(mController, appTargets, contentInsets, minimizedHomeBounds); } catch (RemoteException e) { Slog.e(TAG, "Failed to start recents animation", e); @@ -284,6 +305,7 @@ public class RecentsAnimationController { + mPendingAnimations.size()); for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { final TaskAnimationAdapter adapter = mPendingAnimations.get(i); + adapter.mTask.setCanAffectSystemUiFlags(true); adapter.mCapturedFinishCallback.onAnimationFinished(adapter); } mPendingAnimations.clear(); @@ -367,6 +389,9 @@ public class RecentsAnimationController { container.getRelativePosition(position); container.getBounds(bounds); final WindowState mainWindow = mTask.getTopVisibleAppMainWindow(); + if (mainWindow == null) { + return null; + } mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash, !mTask.fillsParent(), mainWindow.mWinAnimator.mLastClipRect, mainWindow.mContentInsets, mTask.getPrefixOrderIndex(), position, bounds, diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index f32c275b61f1..32ae52375fd5 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -37,6 +37,7 @@ import android.util.SparseIntArray; import android.util.proto.ProtoOutputStream; import android.view.Display; import android.view.DisplayInfo; +import android.view.SurfaceControl; import android.view.WindowManager; import com.android.internal.util.ArrayUtils; @@ -128,6 +129,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { private final Handler mHandler; private String mCloseSystemDialogsReason; + + // Only a seperate transaction until we seperate the apply surface changes + // transaction from the global transaction. + private final SurfaceControl.Transaction mDisplayTransaction = new SurfaceControl.Transaction(); + private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> { if (w.mHasSurface) { try { @@ -725,7 +731,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); // TODO(multi-display): Update rotation for different displays separately. final int displayId = defaultDisplay.getDisplayId(); - if (defaultDisplay.updateRotationUnchecked(false /* inTransaction */)) { + if (defaultDisplay.updateRotationUnchecked()) { mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget(); } else { mUpdateRotation = false; @@ -735,7 +741,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { // PhoneWindowManager. final DisplayContent vrDisplay = mService.mVr2dDisplayId != INVALID_DISPLAY ? getDisplayContent(mService.mVr2dDisplayId) : null; - if (vrDisplay != null && vrDisplay.updateRotationUnchecked(false /* inTransaction */)) { + if (vrDisplay != null && vrDisplay.updateRotationUnchecked()) { mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mService.mVr2dDisplayId) .sendToTarget(); } @@ -835,7 +841,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { // Give the display manager a chance to adjust properties like display rotation if it needs // to. - mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); + mService.mDisplayManagerInternal.performTraversal(mDisplayTransaction); + SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction); } /** diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 5a39de5c3242..ad2fabb70299 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -224,8 +224,7 @@ class ScreenRotationAnimation { } public ScreenRotationAnimation(Context context, DisplayContent displayContent, - boolean inTransaction, boolean forceDefaultOrientation, - boolean isSecure, WindowManagerService service) { + boolean forceDefaultOrientation, boolean isSecure, WindowManagerService service) { mService = service; mContext = context; mDisplayContent = displayContent; @@ -260,52 +259,39 @@ class ScreenRotationAnimation { mOriginalWidth = originalWidth; mOriginalHeight = originalHeight; - if (!inTransaction) { - if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, - ">>> OPEN TRANSACTION ScreenRotationAnimation"); - mService.openSurfaceTransaction(); - } - + final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); try { - try { - mSurfaceControl = displayContent.makeOverlay() - .setName("ScreenshotSurface") - .setSize(mWidth, mHeight) - .setSecure(isSecure) - .build(); - - // capture a screenshot into the surface we just created - Surface sur = new Surface(); - sur.copyFrom(mSurfaceControl); - // TODO(multidisplay): we should use the proper display - SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay( - SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur); - mSurfaceControl.setLayer(SCREEN_FREEZE_LAYER_SCREENSHOT); - mSurfaceControl.setAlpha(0); - mSurfaceControl.show(); - sur.destroy(); - } catch (OutOfResourcesException e) { - Slog.w(TAG, "Unable to allocate freeze surface", e); - } - - if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM, - " FREEZE " + mSurfaceControl + ": CREATE"); - - setRotationInTransaction(originalRotation); - } finally { - if (!inTransaction) { - mService.closeSurfaceTransaction("ScreenRotationAnimation"); - if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, - "<<< CLOSE TRANSACTION ScreenRotationAnimation"); - } - } + mSurfaceControl = displayContent.makeOverlay() + .setName("ScreenshotSurface") + .setSize(mWidth, mHeight) + .setSecure(isSecure) + .build(); + + // capture a screenshot into the surface we just created + Surface sur = new Surface(); + sur.copyFrom(mSurfaceControl); + // TODO(multidisplay): we should use the proper display + SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay( + SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur); + t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT); + t.setAlpha(mSurfaceControl, 0); + t.show(mSurfaceControl); + sur.destroy(); + } catch (OutOfResourcesException e) { + Slog.w(TAG, "Unable to allocate freeze surface", e); + } + + if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM, + " FREEZE " + mSurfaceControl + ": CREATE"); + setRotation(t, originalRotation); + t.apply(); } boolean hasScreenshot() { return mSurfaceControl != null; } - private void setSnapshotTransformInTransaction(Matrix matrix, float alpha) { + private void setSnapshotTransform(SurfaceControl.Transaction t, Matrix matrix, float alpha) { if (mSurfaceControl != null) { matrix.getValues(mTmpFloats); float x = mTmpFloats[Matrix.MTRANS_X]; @@ -315,11 +301,11 @@ class ScreenRotationAnimation { x -= mCurrentDisplayRect.left; y -= mCurrentDisplayRect.top; } - mSurfaceControl.setPosition(x, y); - mSurfaceControl.setMatrix( + t.setPosition(mSurfaceControl, x, y); + t.setMatrix(mSurfaceControl, mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y], mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]); - mSurfaceControl.setAlpha(alpha); + t.setAlpha(mSurfaceControl, alpha); if (DEBUG_TRANSFORMS) { float[] srcPnts = new float[] { 0, 0, mWidth, mHeight }; float[] dstPnts = new float[4]; @@ -353,8 +339,7 @@ class ScreenRotationAnimation { } } - // Must be called while in a transaction. - private void setRotationInTransaction(int rotation) { + private void setRotation(SurfaceControl.Transaction t, int rotation) { mCurRotation = rotation; // Compute the transformation matrix that must be applied @@ -364,15 +349,14 @@ class ScreenRotationAnimation { createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix); if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta); - setSnapshotTransformInTransaction(mSnapshotInitialMatrix, 1.0f); + setSnapshotTransform(t, mSnapshotInitialMatrix, 1.0f); } - // Must be called while in a transaction. - public boolean setRotationInTransaction(int rotation, + public boolean setRotation(SurfaceControl.Transaction t, int rotation, long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) { - setRotationInTransaction(rotation); + setRotation(t, rotation); if (TWO_PHASE_ANIMATION) { - return startAnimation(maxAnimationDuration, animationScale, + return startAnimation(t, maxAnimationDuration, animationScale, finalWidth, finalHeight, false, 0, 0); } @@ -383,7 +367,7 @@ class ScreenRotationAnimation { /** * Returns true if animating. */ - private boolean startAnimation(long maxAnimationDuration, + private boolean startAnimation(SurfaceControl.Transaction t, long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight, boolean dismissing, int exitAnim, int enterAnim) { if (mSurfaceControl == null) { @@ -542,11 +526,6 @@ class ScreenRotationAnimation { final int layerStack = mDisplayContent.getDisplay().getLayerStack(); if (USE_CUSTOM_BLACK_FRAME && mCustomBlackFrame == null) { - if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( - TAG_WM, - ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation"); - mService.openSurfaceTransaction(); - // Compute the transformation matrix that must be applied // the the black frame to make it stay in the initial position // before the new screen rotation. This is different than the @@ -559,24 +538,15 @@ class ScreenRotationAnimation { Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1, mOriginalWidth*2, mOriginalHeight*2); Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight); - mCustomBlackFrame = new BlackFrame(outer, inner, + mCustomBlackFrame = new BlackFrame(t, outer, inner, SCREEN_FREEZE_LAYER_CUSTOM, mDisplayContent, false); - mCustomBlackFrame.setMatrix(mFrameInitialMatrix); + mCustomBlackFrame.setMatrix(t, mFrameInitialMatrix); } catch (OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate black surface", e); - } finally { - mService.closeSurfaceTransaction("ScreenRotationAnimation.startAnimation"); - if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( - TAG_WM, - "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation"); } } if (!customAnim && mExitingBlackFrame == null) { - if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( - TAG_WM, - ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation"); - mService.openSurfaceTransaction(); try { // Compute the transformation matrix that must be applied // the the black frame to make it stay in the initial position @@ -599,38 +569,23 @@ class ScreenRotationAnimation { mOriginalWidth*2, mOriginalHeight*2); inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight); } - mExitingBlackFrame = new BlackFrame(outer, inner, + mExitingBlackFrame = new BlackFrame(t, outer, inner, SCREEN_FREEZE_LAYER_EXIT, mDisplayContent, mForceDefaultOrientation); - mExitingBlackFrame.setMatrix(mFrameInitialMatrix); + mExitingBlackFrame.setMatrix(t, mFrameInitialMatrix); } catch (OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate black surface", e); - } finally { - mService.closeSurfaceTransaction("ScreenRotationAnimation.startAnimation"); - if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( - TAG_WM, - "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation"); } } if (customAnim && mEnteringBlackFrame == null) { - if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( - TAG_WM, - ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation"); - mService.openSurfaceTransaction(); - try { Rect outer = new Rect(-finalWidth*1, -finalHeight*1, finalWidth*2, finalHeight*2); Rect inner = new Rect(0, 0, finalWidth, finalHeight); - mEnteringBlackFrame = new BlackFrame(outer, inner, + mEnteringBlackFrame = new BlackFrame(t, outer, inner, SCREEN_FREEZE_LAYER_ENTER, mDisplayContent, false); } catch (OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate black surface", e); - } finally { - mService.closeSurfaceTransaction("ScreenRotationAnimation.startAnimation"); - if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( - TAG_WM, - "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation"); } } @@ -640,7 +595,7 @@ class ScreenRotationAnimation { /** * Returns true if animating. */ - public boolean dismiss(long maxAnimationDuration, + public boolean dismiss(SurfaceControl.Transaction t, long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight, int exitAnim, int enterAnim) { if (DEBUG_STATE) Slog.v(TAG, "Dismiss!"); if (mSurfaceControl == null) { @@ -648,7 +603,7 @@ class ScreenRotationAnimation { return false; } if (!mStarted) { - startAnimation(maxAnimationDuration, animationScale, finalWidth, finalHeight, + startAnimation(t, maxAnimationDuration, animationScale, finalWidth, finalHeight, true, exitAnim, enterAnim); } if (!mStarted) { @@ -919,7 +874,7 @@ class ScreenRotationAnimation { return more; } - void updateSurfacesInTransaction() { + void updateSurfaces(SurfaceControl.Transaction t) { if (!mStarted) { return; } @@ -927,28 +882,28 @@ class ScreenRotationAnimation { if (mSurfaceControl != null) { if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) { if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface"); - mSurfaceControl.hide(); + t.hide(mSurfaceControl); } } if (mCustomBlackFrame != null) { if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) { if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame"); - mCustomBlackFrame.hide(); + mCustomBlackFrame.hide(t); } else { - mCustomBlackFrame.setMatrix(mFrameTransformation.getMatrix()); + mCustomBlackFrame.setMatrix(t, mFrameTransformation.getMatrix()); } } if (mExitingBlackFrame != null) { if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) { if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding exiting frame"); - mExitingBlackFrame.hide(); + mExitingBlackFrame.hide(t); } else { mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix); - mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix); + mExitingBlackFrame.setMatrix(t, mExitFrameFinalMatrix); if (mForceDefaultOrientation) { - mExitingBlackFrame.setAlpha(mExitTransformation.getAlpha()); + mExitingBlackFrame.setAlpha(t, mExitTransformation.getAlpha()); } } } @@ -956,13 +911,13 @@ class ScreenRotationAnimation { if (mEnteringBlackFrame != null) { if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) { if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding entering frame"); - mEnteringBlackFrame.hide(); + mEnteringBlackFrame.hide(t); } else { - mEnteringBlackFrame.setMatrix(mEnterTransformation.getMatrix()); + mEnteringBlackFrame.setMatrix(t, mEnterTransformation.getMatrix()); } } - setSnapshotTransformInTransaction(mSnapshotFinalMatrix, mExitTransformation.getAlpha()); + setSnapshotTransform(t, mSnapshotFinalMatrix, mExitTransformation.getAlpha()); } public boolean stepAnimationLocked(long now) { diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 2e86351ee4c2..a403e6f2a212 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -96,6 +96,9 @@ class Task extends WindowContainer<AppWindowToken> { private Dimmer mDimmer = new Dimmer(this); private final Rect mTmpDimBoundsRect = new Rect(); + /** @see #setCanAffectSystemUiFlags */ + private boolean mCanAffectSystemUiFlags = true; + Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode, boolean supportsPictureInPicture, TaskDescription taskDescription, TaskWindowContainerController controller) { @@ -627,6 +630,21 @@ class Task extends WindowContainer<AppWindowToken> { callback.accept(this); } + /** + * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI + * flags. See {@link WindowState#canAffectSystemUiFlags()}. + */ + void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) { + mCanAffectSystemUiFlags = canAffectSystemUiFlags; + } + + /** + * @see #setCanAffectSystemUiFlags + */ + boolean canAffectSystemUiFlags() { + return mCanAffectSystemUiFlags; + } + @Override public String toString() { return "{taskId=" + mTaskId + " appTokens=" + mChildren + " mdr=" + mDeferRemoval + "}"; diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index ab1019779b0b..793ffce2466e 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -30,6 +30,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.view.Choreographer; +import android.view.SurfaceControl; import com.android.server.AnimationThread; import com.android.server.policy.WindowManagerPolicy; @@ -94,6 +95,8 @@ public class WindowAnimator { private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>(); private boolean mInExecuteAfterPrepareSurfacesRunnables; + private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); + WindowAnimator(final WindowManagerService service) { mService = service; mContext = service.mContext; @@ -203,7 +206,7 @@ public class WindowAnimator { final ScreenRotationAnimation screenRotationAnimation = mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation; if (screenRotationAnimation != null) { - screenRotationAnimation.updateSurfacesInTransaction(); + screenRotationAnimation.updateSurfaces(mTransaction); } orAnimating(dc.getDockedDividerController().animate(mCurrentTime)); //TODO (multidisplay): Magnification is supported only for the default display. @@ -219,6 +222,8 @@ public class WindowAnimator { if (mService.mWatermark != null) { mService.mWatermark.drawIfNeeded(); } + + SurfaceControl.mergeToGlobalTransaction(mTransaction); } catch (RuntimeException e) { Slog.wtf(TAG, "Unhandled exception in Window Manager", e); } finally { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 563d7928bb8d..ea84b22a6237 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.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; 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.ActivityThread; 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub /** 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; @@ -667,11 +652,18 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; SettingsObserver mSettingsObserver; - // A count of the windows which are 'seamlessly rotated', e.g. a surface - // at an old orientation is being transformed. We freeze orientation updates - // while any windows are seamlessly rotated, so we need to track when this - // hits zero so we can apply deferred orientation updates. - int mSeamlessRotationCount = 0; + /** + * A count of the windows which are 'seamlessly rotated', e.g. a surface + * at an old orientation is being transformed. We freeze orientation updates + * while any windows are seamlessly rotated, so we need to track when this + * hits zero so we can apply deferred orientation updates. + */ + private int mSeamlessRotationCount = 0; + /** + * True in the interval from starting seamless rotation until the last rotated + * window draws in the new orientation. + */ + private boolean mRotatingSeamlessly = false; private final class SettingsObserver extends ContentObserver { private final Uri mDisplayInversionEnabledUri = @@ -809,6 +801,8 @@ public class WindowManagerService extends IWindowManager.Stub SurfaceBuilderFactory mSurfaceBuilderFactory = SurfaceControl.Builder::new; TransactionFactory mTransactionFactory = SurfaceControl.Transaction::new; + private final SurfaceControl.Transaction mTransaction = mTransactionFactory.make(); + static void boostPriorityForLockedSection() { sThreadPriorityBooster.boost(); } @@ -1030,8 +1024,6 @@ public class WindowManagerService extends IWindowManager.Stub 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); @@ -1487,7 +1479,7 @@ public class WindowManagerService extends IWindowManager.Stub if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client " + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5)); - if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false, displayId)) { + if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(displayId)) { reportNewConfig = true; } } @@ -1563,41 +1555,32 @@ public class WindowManagerService extends IWindowManager.Stub } } - /** - * 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)); } } @@ -2049,7 +2032,7 @@ public class WindowManagerService extends IWindowManager.Stub Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: updateOrientationFromAppTokens"); - configChanged = updateOrientationFromAppTokensLocked(false, displayId); + configChanged = updateOrientationFromAppTokensLocked(displayId); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (toBeDisplayed && win.mIsWallpaper) { @@ -2340,7 +2323,7 @@ public class WindowManagerService extends IWindowManager.Stub } Configuration config = null; - if (updateOrientationFromAppTokensLocked(false, displayId)) { + if (updateOrientationFromAppTokensLocked(displayId)) { // If we changed the orientation but mOrientationChangeComplete is already true, // we used seamless rotation, and we don't need to freeze the screen. if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) { @@ -2367,7 +2350,7 @@ public class WindowManagerService extends IWindowManager.Stub int anim[] = new int[2]; mPolicy.selectRotationAnimationLw(anim); - startFreezingDisplayLocked(false, anim[0], anim[1], displayContent); + startFreezingDisplayLocked(anim[0], anim[1], displayContent); config = new Configuration(mTempConfiguration); } } @@ -2387,7 +2370,7 @@ public class WindowManagerService extends IWindowManager.Stub * tokens. * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int) */ - boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) { + boolean updateOrientationFromAppTokensLocked(int displayId) { long ident = Binder.clearCallingIdentity(); try { final DisplayContent dc = mRoot.getDisplayContent(displayId); @@ -2400,7 +2383,7 @@ public class WindowManagerService extends IWindowManager.Stub if (dc.isDefaultDisplay) { mPolicy.setCurrentOrientationLw(req); } - if (dc.updateRotationUnchecked(inTransaction)) { + if (dc.updateRotationUnchecked()) { // changed return true; } @@ -2668,6 +2651,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { mRecentsAnimationController = new RecentsAnimationController(this, recentsAnimationRunner, callbacks, displayId); + mAppTransition.updateBooster(); mRecentsAnimationController.initialize(recentTaskIds); } } @@ -2704,6 +2688,7 @@ public class WindowManagerService extends IWindowManager.Stub if (mRecentsAnimationController != null) { mRecentsAnimationController.cleanupAnimation(); mRecentsAnimationController = null; + mAppTransition.updateBooster(); } } } @@ -2873,7 +2858,7 @@ public class WindowManagerService extends IWindowManager.Stub mClientFreezingScreen = true; final long origId = Binder.clearCallingIdentity(); try { - startFreezingDisplayLocked(false, exitAnim, enterAnim); + startFreezingDisplayLocked(exitAnim, enterAnim); mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000); } finally { @@ -3774,8 +3759,7 @@ public class WindowManagerService extends IWindowManager.Stub if (mDeferredRotationPauseCount == 0) { // TODO(multi-display): Update rotation for different displays separately. final DisplayContent displayContent = getDefaultDisplayContentLocked(); - final boolean changed = displayContent.updateRotationUnchecked( - false /* inTransaction */); + final boolean changed = displayContent.updateRotationUnchecked(); if (changed) { mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId()) .sendToTarget(); @@ -3800,8 +3784,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { final DisplayContent displayContent = getDefaultDisplayContentLocked(); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display"); - rotationChanged = displayContent.updateRotationUnchecked( - false /* inTransaction */); + rotationChanged = displayContent.updateRotationUnchecked(); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (!rotationChanged || forceRelayout) { displayContent.setLayoutNeeded(); @@ -5326,8 +5309,7 @@ public class WindowManagerService extends IWindowManager.Stub displayContent.setLayoutNeeded(); final int displayId = displayContent.getDisplayId(); - boolean configChanged = updateOrientationFromAppTokensLocked(false /* inTransaction */, - displayId); + boolean configChanged = updateOrientationFromAppTokensLocked(displayId); final Configuration currentDisplayConfig = displayContent.getConfiguration(); mTempConfiguration.setTo(currentDisplayConfig); displayContent.computeScreenConfiguration(mTempConfiguration); @@ -5335,7 +5317,7 @@ public class WindowManagerService extends IWindowManager.Stub if (configChanged) { mWaitingForConfig = true; - startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */, + startFreezingDisplayLocked(0 /* exitAnim */, 0 /* enterAnim */, displayContent); mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget(); } @@ -5651,14 +5633,14 @@ public class WindowManagerService extends IWindowManager.Stub return false; } - void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) { - startFreezingDisplayLocked(inTransaction, exitAnim, enterAnim, + void startFreezingDisplayLocked(int exitAnim, int enterAnim) { + startFreezingDisplayLocked(exitAnim, enterAnim, getDefaultDisplayContentLocked()); } - void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim, + void startFreezingDisplayLocked(int exitAnim, int enterAnim, DisplayContent displayContent) { - if (mDisplayFrozen) { + if (mDisplayFrozen || mRotatingSeamlessly) { return; } @@ -5669,8 +5651,8 @@ public class WindowManagerService extends IWindowManager.Stub } if (DEBUG_ORIENTATION) Slog.d(TAG_WM, - "startFreezingDisplayLocked: inTransaction=" + inTransaction - + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim + "startFreezingDisplayLocked: exitAnim=" + + exitAnim + " enterAnim=" + enterAnim + " called by " + Debug.getCallers(8)); mScreenFrozenLock.acquire(); @@ -5714,7 +5696,7 @@ public class WindowManagerService extends IWindowManager.Stub displayContent.updateDisplayInfo(); screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, - inTransaction, mPolicy.isDefaultOrientationForced(), isSecure, + mPolicy.isDefaultOrientationForced(), isSecure, this); mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId, screenRotationAnimation); @@ -5777,9 +5759,10 @@ public class WindowManagerService extends IWindowManager.Stub if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, false)) { mExitAnimId = mEnterAnimId = 0; } - if (screenRotationAnimation.dismiss(MAX_ANIMATION_DURATION, + if (screenRotationAnimation.dismiss(mTransaction, MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { + mTransaction.apply(); scheduleAnimationLocked(); } else { screenRotationAnimation.kill(); @@ -5802,7 +5785,7 @@ public class WindowManagerService extends IWindowManager.Stub // to avoid inconsistent states. However, something interesting // could have actually changed during that time so re-evaluate it // now to catch that. - configChanged = updateOrientationFromAppTokensLocked(false, displayId); + configChanged = updateOrientationFromAppTokensLocked(displayId); // A little kludge: a lot could have happened while the // display was frozen, so now that we are coming back we @@ -5816,8 +5799,7 @@ public class WindowManagerService extends IWindowManager.Stub if (updateRotation) { if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation"); - configChanged |= displayContent.updateRotationUnchecked( - false /* inTransaction */); + configChanged |= displayContent.updateRotationUnchecked(); } if (configChanged) { @@ -7027,8 +7009,10 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ORIENTATION) { Slog.i(TAG, "Performing post-rotate rotation after seamless rotation"); } + finishSeamlessRotation(); + final DisplayContent displayContent = w.getDisplayContent(); - if (displayContent.updateRotationUnchecked(false /* inTransaction */)) { + if (displayContent.updateRotationUnchecked()) { mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId()) .sendToTarget(); } @@ -7438,5 +7422,31 @@ public class WindowManagerService extends IWindowManager.Stub mH.obtainMessage(H.SET_RUNNING_REMOTE_ANIMATION, pid, runningRemoteAnimation ? 1 : 0) .sendToTarget(); } -} + void startSeamlessRotation() { + // We are careful to reset this in case a window was removed before it finished + // seamless rotation. + mSeamlessRotationCount = 0; + + mRotatingSeamlessly = true; + } + + void finishSeamlessRotation() { + mRotatingSeamlessly = false; + } + + /** + * Called when the state of lock task mode changes. This should be used to disable immersive + * mode confirmation. + * + * @param lockTaskState the new lock task mode state. One of + * {@link ActivityManager#LOCK_TASK_MODE_NONE}, + * {@link ActivityManager#LOCK_TASK_MODE_LOCKED}, + * {@link ActivityManager#LOCK_TASK_MODE_PINNED}. + */ + public void onLockTaskStateChanged(int lockTaskState) { + synchronized (mWindowMap) { + mPolicy.onLockTaskStateChangedLw(lockTaskState); + } + } +} diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index ab139dbb2f12..6e0ccfd5d2db 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 @@ public class WindowManagerShellCommand extends ShellCommand { 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 @@ public class WindowManagerShellCommand extends ShellCommand { 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 @@ public class WindowManagerShellCommand extends ShellCommand { 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/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 297e067ae516..91cd4bb545a1 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1573,7 +1573,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final boolean exiting = mAnimatingExit || mDestroying; return shown && !exiting; } else { - return !mAppToken.isHidden(); + final Task task = getTask(); + final boolean canFromTask = task != null && task.canAffectSystemUiFlags(); + return canFromTask && !mAppToken.isHidden(); } } @@ -2013,7 +2015,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP removeImmediately(); // Removing a visible window will effect the computed orientation // So just update orientation if needed. - if (wasVisible && mService.updateOrientationFromAppTokensLocked(false, displayId)) { + if (wasVisible && mService.updateOrientationFromAppTokensLocked(displayId)) { mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget(); } mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); @@ -4295,6 +4297,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final boolean wasVisible = isVisibleLw(); result |= (!wasVisible || !isDrawnLw()) ? RELAYOUT_RES_FIRST_TIME : 0; + + if (mWinAnimator.mChildrenDetached) { + // If there are detached children hanging around we need to force + // the client receiving a new Surface. + mWinAnimator.preserveSurfaceLocked(); + result |= RELAYOUT_RES_SURFACE_CHANGED + | RELAYOUT_RES_FIRST_TIME; + } + if (mAnimatingExit) { Slog.d(TAG, "relayoutVisibleWindow: " + this + " mAnimatingExit=true, mRemoveOnExit=" + mRemoveOnExit + ", mDestroying=" + mDestroying); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 13f05e088cb1..410eddfeb71b 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -221,6 +221,10 @@ class WindowStateAnimator { private final SurfaceControl.Transaction mReparentTransaction = new SurfaceControl.Transaction(); + // Used to track whether we have called detach children on the way to invisibility, in which + // case we need to give the client a new Surface if it lays back out to a visible state. + boolean mChildrenDetached = false; + WindowStateAnimator(final WindowState win) { final WindowManagerService service = win.mService; @@ -430,6 +434,7 @@ class WindowStateAnimator { if (mSurfaceController != null) { return mSurfaceController; } + mChildrenDetached = false; if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) { windowType = SurfaceControl.WINDOW_TYPE_DONT_SCREENSHOT; @@ -981,7 +986,7 @@ class WindowStateAnimator { mForceScaleUntilResize = true; } else { if (!w.mSeamlesslyRotated) { - mSurfaceController.setPositionInTransaction(0, 0, recoveringMemory); + mSurfaceController.setPositionInTransaction(mXOffset, mYOffset, recoveringMemory); } } @@ -1415,7 +1420,8 @@ class WindowStateAnimator { } } - void seamlesslyRotateWindow(int oldRotation, int newRotation) { + void seamlesslyRotateWindow(SurfaceControl.Transaction t, + int oldRotation, int newRotation) { final WindowState w = mWin; if (!w.isVisibleNow() || w.mIsWallpaper) { return; @@ -1456,11 +1462,9 @@ class WindowStateAnimator { float DsDy = mService.mTmpFloats[Matrix.MSCALE_Y]; float nx = mService.mTmpFloats[Matrix.MTRANS_X]; float ny = mService.mTmpFloats[Matrix.MTRANS_Y]; - mSurfaceController.setPositionInTransaction(nx, ny, false); - mSurfaceController.setMatrixInTransaction(DsDx * w.mHScale, - DtDx * w.mVScale, - DtDy * w.mHScale, - DsDy * w.mVScale, false); + mSurfaceController.setPosition(t, nx, ny, false); + mSurfaceController.setMatrix(t, DsDx * w.mHScale, DtDx * w.mVScale, DtDy + * w.mHScale, DsDy * w.mVScale, false); } /** The force-scaled state for a given window can persist past @@ -1479,6 +1483,7 @@ class WindowStateAnimator { if (mSurfaceController != null) { mSurfaceController.detachChildren(); } + mChildrenDetached = true; } int getLayer() { diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 9d6f8f78c272..f6c0a54c74ca 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -242,6 +242,11 @@ class WindowSurfaceController { } void setPositionInTransaction(float left, float top, boolean recoveringMemory) { + setPosition(null, left, top, recoveringMemory); + } + + void setPosition(SurfaceControl.Transaction t, float left, float top, + boolean recoveringMemory) { final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top; if (surfaceMoved) { mSurfaceX = left; @@ -251,7 +256,11 @@ class WindowSurfaceController { if (SHOW_TRANSACTIONS) logSurface( "POS (setPositionInTransaction) @ (" + left + "," + top + ")", null); - mSurfaceControl.setPosition(left, top); + if (t == null) { + mSurfaceControl.setPosition(left, top); + } else { + t.setPosition(mSurfaceControl, left, top); + } } catch (RuntimeException e) { Slog.w(TAG, "Error positioning surface of " + this + " pos=(" + left + "," + top + ")", e); @@ -268,6 +277,11 @@ class WindowSurfaceController { void setMatrixInTransaction(float dsdx, float dtdx, float dtdy, float dsdy, boolean recoveringMemory) { + setMatrix(null, dsdx, dtdx, dtdy, dsdy, false); + } + + void setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, + float dtdy, float dsdy, boolean recoveringMemory) { final boolean matrixChanged = mLastDsdx != dsdx || mLastDtdx != dtdx || mLastDtdy != dtdy || mLastDsdy != dsdy; if (!matrixChanged) { @@ -282,8 +296,11 @@ class WindowSurfaceController { try { if (SHOW_TRANSACTIONS) logSurface( "MATRIX [" + dsdx + "," + dtdx + "," + dtdy + "," + dsdy + "]", null); - mSurfaceControl.setMatrix( - dsdx, dtdx, dtdy, dsdy); + if (t == null) { + mSurfaceControl.setMatrix(dsdx, dtdx, dtdy, dsdy); + } else { + t.setMatrix(mSurfaceControl, dsdx, dtdx, dtdy, dsdy); + } } catch (RuntimeException e) { // If something goes wrong with the surface (such // as running out of memory), don't take down the diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 417959087de2..3256762971fc 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -52,6 +52,7 @@ import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES; +import android.app.WindowConfiguration; import android.os.Debug; import android.os.Trace; import android.util.ArraySet; @@ -294,12 +295,14 @@ class WindowSurfacePlacer { // what will control the animation theme. If all closing windows are obscured, then there is // no need to do an animation. This is the case, for example, when this transition is being // done behind a dream window. + final ArraySet<Integer> activityTypes = collectActivityTypes(mService.mOpeningApps, + mService.mClosingApps); final AppWindowToken animLpToken = mService.mPolicy.allowAppAnimationsLw() - ? findAnimLayoutParamsToken(transit) + ? findAnimLayoutParamsToken(transit, activityTypes) : null; final LayoutParams animLp = getAnimLp(animLpToken); - overrideWithRemoteAnimationIfSet(animLpToken, transit); + overrideWithRemoteAnimationIfSet(animLpToken, transit, activityTypes); final boolean voiceInteraction = containsVoiceInteraction(mService.mOpeningApps) || containsVoiceInteraction(mService.mOpeningApps); @@ -361,13 +364,14 @@ class WindowSurfacePlacer { * Overrides the pending transition with the remote animation defined for the transition in the * set of defined remote animations in the app window token. */ - private void overrideWithRemoteAnimationIfSet(AppWindowToken animLpToken, int transit) { + private void overrideWithRemoteAnimationIfSet(AppWindowToken animLpToken, int transit, + ArraySet<Integer> activityTypes) { if (animLpToken == null) { return; } final RemoteAnimationDefinition definition = animLpToken.getRemoteAnimationDefinition(); if (definition != null) { - final RemoteAnimationAdapter adapter = definition.getAdapter(transit); + final RemoteAnimationAdapter adapter = definition.getAdapter(transit, activityTypes); if (adapter != null) { mService.mAppTransition.overridePendingAppTransitionRemote(adapter); } @@ -377,13 +381,14 @@ class WindowSurfacePlacer { /** * @return The window token that determines the animation theme. */ - private AppWindowToken findAnimLayoutParamsToken(@TransitionType int transit) { + private AppWindowToken findAnimLayoutParamsToken(@TransitionType int transit, + ArraySet<Integer> activityTypes) { AppWindowToken result; // Remote animations always win, but fullscreen tokens override non-fullscreen tokens. result = lookForHighestTokenWithFilter(mService.mClosingApps, mService.mOpeningApps, w -> w.getRemoteAnimationDefinition() != null - && w.getRemoteAnimationDefinition().hasTransition(transit)); + && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes)); if (result != null) { return result; } @@ -396,6 +401,22 @@ class WindowSurfacePlacer { w -> w.findMainWindow() != null); } + /** + * @return The set of {@link WindowConfiguration.ActivityType}s contained in the set of apps in + * {@code array1} and {@code array2}. + */ + private ArraySet<Integer> collectActivityTypes(ArraySet<AppWindowToken> array1, + ArraySet<AppWindowToken> array2) { + final ArraySet<Integer> result = new ArraySet<>(); + for (int i = array1.size() - 1; i >= 0; i--) { + result.add(array1.valueAt(i).getActivityType()); + } + for (int i = array2.size() - 1; i >= 0; i--) { + result.add(array2.valueAt(i).getActivityType()); + } + return result; + } + private AppWindowToken lookForHighestTokenWithFilter(ArraySet<AppWindowToken> array1, ArraySet<AppWindowToken> array2, Predicate<AppWindowToken> filter) { final int array1count = array1.size(); @@ -403,12 +424,9 @@ class WindowSurfacePlacer { int bestPrefixOrderIndex = Integer.MIN_VALUE; AppWindowToken bestToken = null; for (int i = 0; i < count; i++) { - final AppWindowToken wtoken; - if (i < array1count) { - wtoken = array1.valueAt(i); - } else { - wtoken = array2.valueAt(i - array1count); - } + final AppWindowToken wtoken = i < array1count + ? array1.valueAt(i) + : array2.valueAt(i - array1count); final int prefixOrderIndex = wtoken.getPrefixOrderIndex(); if (filter.test(wtoken) && prefixOrderIndex > bestPrefixOrderIndex) { bestPrefixOrderIndex = prefixOrderIndex; @@ -436,7 +454,7 @@ class WindowSurfacePlacer { AppWindowToken wtoken = mService.mOpeningApps.valueAt(i); if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); - if (!wtoken.setVisibility(animLp, true, transit, false, voiceInteraction)){ + if (!wtoken.setVisibility(animLp, true, transit, false, voiceInteraction)) { // This token isn't going to be animating. Add it to the list of tokens to // be notified of app transition complete since the notification will not be // sent be the app window animator. @@ -559,7 +577,8 @@ class WindowSurfacePlacer { + wtoken.allDrawn + " startingDisplayed=" + wtoken.startingDisplayed + " startingMoved=" + wtoken.startingMoved + " isRelaunching()=" - + wtoken.isRelaunching()); + + wtoken.isRelaunching() + " startingWindow=" + + wtoken.startingWindow); final boolean allDrawn = wtoken.allDrawn && !wtoken.isRelaunching(); 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 000000000000..37b5ad1eb610 --- /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 ab8a6c4d754a..c7ae5704ae50 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.PendingIntent; 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { policyFile.delete(); Slog.i(LOG_TAG, "Removed device policy file " + policyFile.getAbsolutePath()); } - updateScreenCaptureDisabledInWindowManager(userHandle, false /* default value */); } void loadOwners() { @@ -3395,7 +3399,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override void handleStartUser(int userId) { - updateScreenCaptureDisabledInWindowManager(userId, + updateScreenCaptureDisabled(userId, getScreenCaptureDisabled(null, userId)); pushUserRestrictions(userId); @@ -6632,7 +6636,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (ap.disableScreenCapture != disabled) { ap.disableScreenCapture = disabled; saveSettingsLocked(userHandle); - updateScreenCaptureDisabledInWindowManager(userHandle, disabled); + updateScreenCaptureDisabled(userHandle, disabled); } } } @@ -6664,13 +6668,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { .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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 165aaac6a42c..70abf8054dbb 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -685,11 +685,6 @@ public final class SystemServer { * Starts some essential services that are not tangled up in the bootstrap process. */ private void startCoreServices() { - // Records errors and logs, for example wtf() - traceBeginAndSlog("StartDropBoxManager"); - mSystemServiceManager.startService(DropBoxManagerService.class); - traceEnd(); - traceBeginAndSlog("StartBatteryService"); // Tracks the battery level. Requires LightService. mSystemServiceManager.startService(BatteryService.class); @@ -816,6 +811,13 @@ public final class SystemServer { SQLiteCompatibilityWalFlags.reset(); traceEnd(); + // Records errors and logs, for example wtf() + // Currently this service indirectly depends on SettingsProvider so do this after + // InstallSystemProviders. + traceBeginAndSlog("StartDropBoxManager"); + mSystemServiceManager.startService(DropBoxManagerService.class); + traceEnd(); + traceBeginAndSlog("StartVibratorService"); vibrator = new VibratorService(context); ServiceManager.addService("vibrator", vibrator); diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk index aed57e3b6dcc..3d7fdbdd7436 100644 --- a/services/robotests/Android.mk +++ b/services/robotests/Android.mk @@ -62,7 +62,8 @@ LOCAL_SRC_FILES := \ $(call all-java-files-under, ../../core/java/android/app/backup) \ $(call all-Iaidl-files-under, ../../core/java/android/app/backup) \ ../../core/java/android/content/pm/PackageInfo.java \ - ../../core/java/android/app/IBackupAgent.aidl + ../../core/java/android/app/IBackupAgent.aidl \ + ../../core/java/android/util/KeyValueSettingObserver.java LOCAL_AIDL_INCLUDES := \ $(call all-Iaidl-files-under, $(INTERNAL_BACKUP)) \ diff --git a/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java b/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java new file mode 100644 index 000000000000..801451ee549b --- /dev/null +++ b/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java @@ -0,0 +1,140 @@ +/* + * 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.backup; + +import static org.junit.Assert.assertEquals; + +import android.content.ContentResolver; +import android.content.Context; +import android.os.Handler; +import android.platform.test.annotations.Presubmit; +import android.provider.Settings; +import android.util.KeyValueSettingObserver; +import com.android.server.testing.FrameworkRobolectricTestRunner; +import com.android.server.testing.SystemLoaderClasses; +import com.android.server.testing.SystemLoaderPackages; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +/** Tests for {@link BackupAgentTimeoutParameters}. */ +@RunWith(FrameworkRobolectricTestRunner.class) +@Config(manifest = Config.NONE, sdk = 26) +@SystemLoaderPackages({"com.android.server.backup"}) +@SystemLoaderClasses({KeyValueSettingObserver.class}) +@Presubmit +public class BackupAgentTimeoutParametersTest { + private ContentResolver mContentResolver; + private BackupAgentTimeoutParameters mParameters; + + /** Initialize timeout parameters and start observing changes. */ + @Before + public void setUp() { + Context context = RuntimeEnvironment.application.getApplicationContext(); + + mContentResolver = context.getContentResolver(); + mParameters = new BackupAgentTimeoutParameters(new Handler(), mContentResolver); + mParameters.start(); + } + + /** Stop observing changes to the setting. */ + @After + public void tearDown() { + mParameters.stop(); + } + + /** Tests that timeout parameters are initialized with default values on creation. */ + @Test + public void testGetParameters_afterConstructorWithStart_returnsDefaultValues() { + long kvBackupAgentTimeoutMillis = mParameters.getKvBackupAgentTimeoutMillis(); + long fullBackupAgentTimeoutMillis = mParameters.getFullBackupAgentTimeoutMillis(); + long sharedBackupAgentTimeoutMillis = mParameters.getSharedBackupAgentTimeoutMillis(); + long restoreAgentTimeoutMillis = mParameters.getRestoreAgentTimeoutMillis(); + long restoreAgentFinishedTimeoutMillis = mParameters.getRestoreAgentFinishedTimeoutMillis(); + + assertEquals( + BackupAgentTimeoutParameters.DEFAULT_KV_BACKUP_AGENT_TIMEOUT_MILLIS, + kvBackupAgentTimeoutMillis); + assertEquals( + BackupAgentTimeoutParameters.DEFAULT_FULL_BACKUP_AGENT_TIMEOUT_MILLIS, + fullBackupAgentTimeoutMillis); + assertEquals( + BackupAgentTimeoutParameters.DEFAULT_SHARED_BACKUP_AGENT_TIMEOUT_MILLIS, + sharedBackupAgentTimeoutMillis); + assertEquals( + BackupAgentTimeoutParameters.DEFAULT_RESTORE_AGENT_TIMEOUT_MILLIS, + restoreAgentTimeoutMillis); + assertEquals( + BackupAgentTimeoutParameters.DEFAULT_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS, + restoreAgentFinishedTimeoutMillis); + } + + /** + * Tests that timeout parameters are updated when we call start, even when a setting change + * occurs while we are not observing. + */ + @Test + public void testGetParameters_withSettingChangeBeforeStart_updatesValues() { + mParameters.stop(); + long testTimeout = BackupAgentTimeoutParameters.DEFAULT_KV_BACKUP_AGENT_TIMEOUT_MILLIS * 2; + final String setting = + BackupAgentTimeoutParameters.SETTING_KV_BACKUP_AGENT_TIMEOUT_MILLIS + + "=" + + testTimeout; + putStringAndNotify(setting); + mParameters.start(); + + long kvBackupAgentTimeoutMillis = mParameters.getKvBackupAgentTimeoutMillis(); + + assertEquals(testTimeout, kvBackupAgentTimeoutMillis); + } + + /** + * Tests that timeout parameters are updated when a setting change occurs while we are observing + * changes. + */ + @Test + public void testGetParameters_withSettingChangeAfterStart_updatesValues() { + long testTimeout = BackupAgentTimeoutParameters.DEFAULT_KV_BACKUP_AGENT_TIMEOUT_MILLIS * 2; + final String setting = + BackupAgentTimeoutParameters.SETTING_KV_BACKUP_AGENT_TIMEOUT_MILLIS + + "=" + + testTimeout; + putStringAndNotify(setting); + + long kvBackupAgentTimeoutMillis = mParameters.getKvBackupAgentTimeoutMillis(); + + assertEquals(testTimeout, kvBackupAgentTimeoutMillis); + } + + /** + * Robolectric does not notify observers of changes to settings so we have to trigger it here. + * Currently, the mock of {@link Settings.Secure#putString(ContentResolver, String, String)} + * only stores the value. TODO: Implement properly in ShadowSettings. + */ + private void putStringAndNotify(String value) { + Settings.Global.putString(mContentResolver, BackupAgentTimeoutParameters.SETTING, value); + + // We pass null as the observer since notifyChange iterates over all available observers and + // we don't have access to the local observer. + mContentResolver.notifyChange( + Settings.Global.getUriFor(BackupAgentTimeoutParameters.SETTING), /*observer*/ null); + } +} diff --git a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java index 0752537abfcc..2a32c2eef6ca 100644 --- a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java +++ b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java @@ -18,79 +18,218 @@ package com.android.server.backup; import static com.google.common.truth.Truth.assertThat; -import android.app.AlarmManager; +import android.content.ContentResolver; import android.content.Context; import android.os.Handler; import android.platform.test.annotations.Presubmit; import android.provider.Settings; - +import android.util.KeyValueSettingObserver; import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderClasses; import com.android.server.testing.SystemLoaderPackages; - +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @RunWith(FrameworkRobolectricTestRunner.class) @Config(manifest = Config.NONE, sdk = 26) @SystemLoaderPackages({"com.android.server.backup"}) +@SystemLoaderClasses({KeyValueSettingObserver.class}) @Presubmit public class BackupManagerConstantsTest { private static final String PACKAGE_NAME = "some.package.name"; private static final String ANOTHER_PACKAGE_NAME = "another.package.name"; + private ContentResolver mContentResolver; + private BackupManagerConstants mConstants; + @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + public void setUp() { + final Context context = RuntimeEnvironment.application.getApplicationContext(); + + mContentResolver = context.getContentResolver(); + mConstants = new BackupManagerConstants(new Handler(), mContentResolver); + mConstants.start(); + } + + @After + public void tearDown() { + mConstants.stop(); } @Test - public void testDefaultValues() throws Exception { - final Context context = RuntimeEnvironment.application.getApplicationContext(); - final Handler handler = new Handler(); + public void testGetConstants_afterConstructorWithStart_returnsDefaultValues() { + long keyValueBackupIntervalMilliseconds = + mConstants.getKeyValueBackupIntervalMilliseconds(); + long keyValueBackupFuzzMilliseconds = mConstants.getKeyValueBackupFuzzMilliseconds(); + boolean keyValueBackupRequireCharging = mConstants.getKeyValueBackupRequireCharging(); + int keyValueBackupRequiredNetworkType = mConstants.getKeyValueBackupRequiredNetworkType(); + long fullBackupIntervalMilliseconds = mConstants.getFullBackupIntervalMilliseconds(); + boolean fullBackupRequireCharging = mConstants.getFullBackupRequireCharging(); + int fullBackupRequiredNetworkType = mConstants.getFullBackupRequiredNetworkType(); + String[] backupFinishedNotificationReceivers = + mConstants.getBackupFinishedNotificationReceivers(); + + assertThat(keyValueBackupIntervalMilliseconds) + .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS); + assertThat(keyValueBackupFuzzMilliseconds) + .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS); + assertThat(keyValueBackupRequireCharging) + .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING); + assertThat(keyValueBackupRequiredNetworkType) + .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE); + assertThat(fullBackupIntervalMilliseconds) + .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS); + assertThat(fullBackupRequireCharging) + .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRE_CHARGING); + assertThat(fullBackupRequiredNetworkType) + .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE); + assertThat(backupFinishedNotificationReceivers).isEqualTo(new String[0]); + } - Settings.Secure.putString( - context.getContentResolver(), Settings.Secure.BACKUP_MANAGER_CONSTANTS, null); - - final BackupManagerConstants constants = - new BackupManagerConstants(handler, context.getContentResolver()); - - assertThat(constants.getKeyValueBackupIntervalMilliseconds()) - .isEqualTo(4 * AlarmManager.INTERVAL_HOUR); - assertThat(constants.getKeyValueBackupFuzzMilliseconds()).isEqualTo(10 * 60 * 1000); - assertThat(constants.getKeyValueBackupRequireCharging()).isEqualTo(true); - assertThat(constants.getKeyValueBackupRequiredNetworkType()).isEqualTo(1); - - assertThat(constants.getFullBackupIntervalMilliseconds()) - .isEqualTo(24 * AlarmManager.INTERVAL_HOUR); - assertThat(constants.getFullBackupRequireCharging()).isEqualTo(true); - assertThat(constants.getFullBackupRequiredNetworkType()).isEqualTo(2); - assertThat(constants.getBackupFinishedNotificationReceivers()).isEqualTo(new String[0]); + /** + * Tests that if there is a setting change when we are not currently observing the setting, that + * once we start observing again, we receive the most up-to-date value. + */ + @Test + public void testGetConstant_withSettingChangeBeforeStart_updatesValues() { + mConstants.stop(); + long testInterval = + BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS * 2; + final String setting = + BackupManagerConstants.KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS + "=" + testInterval; + putStringAndNotify(setting); + + mConstants.start(); + + long keyValueBackupIntervalMilliseconds = + mConstants.getKeyValueBackupIntervalMilliseconds(); + assertThat(keyValueBackupIntervalMilliseconds).isEqualTo(testInterval); } @Test - public void testParseNotificationReceivers() throws Exception { - final Context context = RuntimeEnvironment.application.getApplicationContext(); - final Handler handler = new Handler(); + public void testGetConstants_whenSettingIsNull_returnsDefaultValues() { + putStringAndNotify(null); + + long keyValueBackupIntervalMilliseconds = + mConstants.getKeyValueBackupIntervalMilliseconds(); + long keyValueBackupFuzzMilliseconds = mConstants.getKeyValueBackupFuzzMilliseconds(); + boolean keyValueBackupRequireCharging = mConstants.getKeyValueBackupRequireCharging(); + int keyValueBackupRequiredNetworkType = mConstants.getKeyValueBackupRequiredNetworkType(); + long fullBackupIntervalMilliseconds = mConstants.getFullBackupIntervalMilliseconds(); + boolean fullBackupRequireCharging = mConstants.getFullBackupRequireCharging(); + int fullBackupRequiredNetworkType = mConstants.getFullBackupRequiredNetworkType(); + String[] backupFinishedNotificationReceivers = + mConstants.getBackupFinishedNotificationReceivers(); + + assertThat(keyValueBackupIntervalMilliseconds) + .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS); + assertThat(keyValueBackupFuzzMilliseconds) + .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS); + assertThat(keyValueBackupRequireCharging) + .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING); + assertThat(keyValueBackupRequiredNetworkType) + .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE); + assertThat(fullBackupIntervalMilliseconds) + .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS); + assertThat(fullBackupRequireCharging) + .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRE_CHARGING); + assertThat(fullBackupRequiredNetworkType) + .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE); + assertThat(backupFinishedNotificationReceivers).isEqualTo(new String[0]); + } - final String recieversSetting = - "backup_finished_notification_receivers=" + /** + * Test passing in a malformed setting string. The setting expects + * "key1=value,key2=value,key3=value..." but we pass in "key1=,value" + */ + @Test + public void testGetConstant_whenSettingIsMalformed_doesNotUpdateParamsOrThrow() { + long testFuzz = BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS * 2; + final String invalidSettingFormat = + BackupManagerConstants.KEY_VALUE_BACKUP_FUZZ_MILLISECONDS + "=," + testFuzz; + putStringAndNotify(invalidSettingFormat); + + long keyValueBackupFuzzMilliseconds = mConstants.getKeyValueBackupFuzzMilliseconds(); + + assertThat(keyValueBackupFuzzMilliseconds) + .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS); + } + + /** + * Test passing in an invalid value type. {@link + * BackupManagerConstants#KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE} expects an integer, but we + * pass in a boolean. + */ + @Test + public void testGetConstant_whenSettingHasInvalidType_doesNotUpdateParamsOrThrow() { + boolean testValue = true; + final String invalidSettingType = + BackupManagerConstants.KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE + "=" + testValue; + putStringAndNotify(invalidSettingType); + + int keyValueBackupRequiredNetworkType = mConstants.getKeyValueBackupRequiredNetworkType(); + + assertThat(keyValueBackupRequiredNetworkType) + .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE); + } + + @Test + public void testGetConstants_afterSettingChange_updatesValues() { + long testKVInterval = + BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS * 2; + long testFullInterval = + BackupManagerConstants.DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS * 2; + final String intervalSetting = + BackupManagerConstants.KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS + + "=" + + testKVInterval + + "," + + BackupManagerConstants.FULL_BACKUP_INTERVAL_MILLISECONDS + + "=" + + testFullInterval; + putStringAndNotify(intervalSetting); + + long keyValueBackupIntervalMilliseconds = + mConstants.getKeyValueBackupIntervalMilliseconds(); + long fullBackupIntervalMilliseconds = mConstants.getFullBackupIntervalMilliseconds(); + + assertThat(keyValueBackupIntervalMilliseconds).isEqualTo(testKVInterval); + assertThat(fullBackupIntervalMilliseconds).isEqualTo(testFullInterval); + } + + @Test + public void testBackupNotificationReceivers_afterSetting_updatesAndParsesCorrectly() { + final String receiversSetting = + BackupManagerConstants.BACKUP_FINISHED_NOTIFICATION_RECEIVERS + + "=" + PACKAGE_NAME + ':' + ANOTHER_PACKAGE_NAME; - Settings.Secure.putString( - context.getContentResolver(), - Settings.Secure.BACKUP_MANAGER_CONSTANTS, - recieversSetting); - - final BackupManagerConstants constants = - new BackupManagerConstants(handler, context.getContentResolver()); + putStringAndNotify(receiversSetting); - assertThat(constants.getBackupFinishedNotificationReceivers()) + String[] backupFinishedNotificationReceivers = + mConstants.getBackupFinishedNotificationReceivers(); + assertThat(backupFinishedNotificationReceivers) .isEqualTo(new String[] {PACKAGE_NAME, ANOTHER_PACKAGE_NAME}); } + + /** + * Robolectric does not notify observers of changes to settings so we have to trigger it here. + * Currently, the mock of {@link Settings.Secure#putString(ContentResolver, String, String)} + * only stores the value. TODO: Implement properly in ShadowSettings. + */ + private void putStringAndNotify(String value) { + Settings.Secure.putString( + mContentResolver, Settings.Secure.BACKUP_MANAGER_CONSTANTS, value); + + // We pass null as the observer since notifyChange iterates over all available observers and + // we don't have access to the local observer. + mContentResolver.notifyChange( + Settings.Secure.getUriFor(Settings.Secure.BACKUP_MANAGER_CONSTANTS), + /*observer*/ null); + } } diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java index 24566fcf8f0d..376f5b193716 100644 --- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java +++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java @@ -17,6 +17,7 @@ package com.android.server.am; import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; @@ -24,6 +25,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.view.Display.DEFAULT_DISPLAY; import static org.junit.Assert.assertFalse; @@ -74,7 +76,7 @@ import java.util.Random; import java.util.Set; /** - * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java + * atest FrameworksServicesTests:RecentTasksTest */ @MediumTest @Presubmit @@ -145,7 +147,7 @@ public class RecentTasksTest extends ActivityTestsBase { mRecentTasks = (TestRecentTasks) mService.getRecentTasks(); mRecentTasks.loadParametersFromResources(mContext.getResources()); mHomeStack = mService.mStackSupervisor.getDefaultDisplay().createStack( - WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); mStack = mService.mStackSupervisor.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); ((MyTestActivityStackSupervisor) mService.mStackSupervisor).setHomeStack(mHomeStack); @@ -236,7 +238,7 @@ public class RecentTasksTest extends ActivityTestsBase { } @Test - public void testAddTasksMultipleTasks_expectNoTrim() throws Exception { + public void testAddTasksMultipleDocumentTasks_expectNoTrim() throws Exception { // Add same multiple-task document tasks does not trim the first tasks TaskRecord documentTask1 = createDocumentTask(".DocumentTask1", FLAG_ACTIVITY_MULTIPLE_TASK); @@ -252,6 +254,50 @@ public class RecentTasksTest extends ActivityTestsBase { } @Test + public void testAddTasksMultipleTasks_expectRemovedNoTrim() throws Exception { + // Add multiple same-affinity non-document tasks, ensure that it removes the other task, + // but that it does not trim it + TaskRecord task1 = createTaskBuilder(".Task1") + .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK) + .build(); + TaskRecord task2 = createTaskBuilder(".Task1") + .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK) + .build(); + mRecentTasks.add(task1); + assertTrue(mCallbacksRecorder.added.size() == 1); + assertTrue(mCallbacksRecorder.added.contains(task1)); + assertTrue(mCallbacksRecorder.trimmed.isEmpty()); + assertTrue(mCallbacksRecorder.removed.isEmpty()); + mCallbacksRecorder.clear(); + mRecentTasks.add(task2); + assertTrue(mCallbacksRecorder.added.size() == 1); + assertTrue(mCallbacksRecorder.added.contains(task2)); + assertTrue(mCallbacksRecorder.trimmed.isEmpty()); + assertTrue(mCallbacksRecorder.removed.size() == 1); + assertTrue(mCallbacksRecorder.removed.contains(task1)); + } + + @Test + public void testAddTasksDifferentStacks_expectNoRemove() throws Exception { + // Adding the same task with different activity types should not trigger removal of the + // other task + TaskRecord task1 = createTaskBuilder(".Task1") + .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK) + .setStack(mHomeStack).build(); + TaskRecord task2 = createTaskBuilder(".Task1") + .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK) + .setStack(mStack).build(); + mRecentTasks.add(task1); + mRecentTasks.add(task2); + assertTrue(mCallbacksRecorder.added.size() == 2); + assertTrue(mCallbacksRecorder.added.contains(task1)); + assertTrue(mCallbacksRecorder.added.contains(task2)); + assertTrue(mCallbacksRecorder.trimmed.isEmpty()); + assertTrue(mCallbacksRecorder.removed.isEmpty()); + + } + + @Test public void testUsersTasks() throws Exception { mRecentTasks.setOnlyTestVisibleRange(); 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 86c83d6707b6..d37db20f05b7 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 @@ package com.android.server.backup.utils; 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 android.support.test.runner.AndroidJUnit4; 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 @@ public class AppBackupUtilsTest { 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 @@ public class AppBackupUtilsTest { @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 @@ public class AppBackupUtilsTest { @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 class AppBackupUtilsTest { 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 class AppBackupUtilsTest { 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 @@ public class AppBackupUtilsTest { 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 @@ public class AppBackupUtilsTest { 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 class AppBackupUtilsTest { 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 class AppBackupUtilsTest { 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 @@ public class AppBackupUtilsTest { 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 @@ public class AppBackupUtilsTest { 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 @@ public class AppBackupUtilsTest { 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 @@ public class AppBackupUtilsTest { 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 0cdf04bda2d0..5f052ceb2e26 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 android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BA 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.app.backup.IBackupManagerMonitor; 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 @@ public class TarBackupReaderTest { @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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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 @@ public class TarBackupReaderTest { 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/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java index 1211f00b1252..2f2afd71706c 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -44,6 +44,7 @@ import java.util.List; import static org.mockito.Matchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.mock; @SmallTest public class DisplayManagerServiceTest extends AndroidTestCase { @@ -123,7 +124,7 @@ public class DisplayManagerServiceTest extends AndroidTestCase { "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */, uniqueId); - displayManager.performTraversalInTransactionFromWindowManagerInternal(); + displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); // flush the handler displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */); @@ -161,7 +162,7 @@ public class DisplayManagerServiceTest extends AndroidTestCase { "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */, uniqueId); - displayManager.performTraversalInTransactionFromWindowManagerInternal(); + displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class)); // flush the handler displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java index e40e3a42ee53..e9289e5cadf3 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java @@ -42,11 +42,13 @@ import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.security.keystore.recovery.KeyDerivationParams; import android.security.keystore.recovery.KeyChainSnapshot; +import android.security.keystore.recovery.RecoveryController; import android.security.keystore.recovery.WrappedApplicationKey; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; +import android.util.Log; import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb; import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage; @@ -516,6 +518,34 @@ public class KeySyncTaskTest { recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID2); } + @Test + public void run_customLockScreen_RecoveryStatusFailure() throws Exception { + mKeySyncTask = new KeySyncTask( + mRecoverableKeyStoreDb, + mRecoverySnapshotStorage, + mSnapshotListenersStorage, + TEST_USER_ID, + /*credentialType=*/ 3, + "12345", + /*credentialUpdated=*/ false, + mPlatformKeyManager); + + addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); + + int status = + mRecoverableKeyStoreDb + .getStatusForAllKeys(TEST_RECOVERY_AGENT_UID) + .get(TEST_APP_KEY_ALIAS); + assertEquals(RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS, status); + + mKeySyncTask.run(); + + status = mRecoverableKeyStoreDb + .getStatusForAllKeys(TEST_RECOVERY_AGENT_UID) + .get(TEST_APP_KEY_ALIAS); + assertEquals(RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE, status); + } + private SecretKey addApplicationKey(int userId, int recoveryAgentUid, String alias) throws Exception{ SecretKey applicationKey = generateKey(); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java index dfb2dbf884f0..8b01d972f7e5 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java @@ -342,6 +342,30 @@ public class RecoverableKeyStoreDbTest { } @Test + public void testInvalidateKeysForUserIdOnCustomScreenLock() { + int userId = 12; + int uid = 1009; + int generationId = 6; + int status = 120; + int status2 = 121; + String alias = "test"; + byte[] nonce = getUtf8Bytes("nonce"); + byte[] keyMaterial = getUtf8Bytes("keymaterial"); + WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, generationId, status); + mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey); + + WrappedKey retrievedKey = mRecoverableKeyStoreDb.getKey(uid, alias); + assertThat(retrievedKey.getRecoveryStatus()).isEqualTo(status); + + mRecoverableKeyStoreDb.setRecoveryStatus(uid, alias, status2); + mRecoverableKeyStoreDb.invalidateKeysForUserIdOnCustomScreenLock(userId); + + retrievedKey = mRecoverableKeyStoreDb.getKey(uid, alias); + assertThat(retrievedKey.getRecoveryStatus()) + .isEqualTo(RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE); + } + + @Test public void setRecoveryServicePublicKey_replaceOldKey() throws Exception { int userId = 12; int uid = 10009; 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 51d27fe016f0..197475032ea8 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 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { | 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 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { !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 845e05d28465..7815004c18f9 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 com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils 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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { 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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { 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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { 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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { 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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { addPackage(LAUNCHER_1, LAUNCHER_UID_1, 10, "sigx"); // different signature - checkBackupAndRestore_launcherNotRestored(); + checkBackupAndRestore_launcherNotRestored(true); } public void testBackupAndRestore_launcherNoLongerBackupTarget() { @@ -5285,10 +5299,13 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { 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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { "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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { "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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { } 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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { 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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { .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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { .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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { 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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { 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 29c98dcf5228..cd7feea08caa 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 @@ public class ShortcutManagerTest5 extends BaseShortcutManagerTest { 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 c016e6104755..1ac7cb86f867 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 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 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 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; + + ArrayList<byte[]> storedSigHashes = new ArrayList<>(); + storedSigHashes.add(SIGNATURE_HASH_1); + boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo, + mMockPackageManagerInternal); + + 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(); - PackageInfo pi; + 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); - // False for null package. - assertFalse(BackupUtils.signaturesMatch(stored1, null)); + assertThat(result).isTrue(); + } - // If it's a system app, signatures don't matter. - pi = genPackage("xyz"); - pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; - assertTrue(BackupUtils.signaturesMatch(stored1, pi)); + @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(); - // Non system apps. - assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("abc"))); + ArrayList<byte[]> storedSigHashes = new ArrayList<>(); + storedSigHashes.add(SIGNATURE_HASH_1); + storedSigHashes.add(SIGNATURE_HASH_2); + boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo, + mMockPackageManagerInternal); - // Superset is okay. - assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("abc", "xyz"))); - assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("xyz", "abc"))); + assertThat(result).isTrue(); + } - assertFalse(BackupUtils.signaturesMatch(stored1, genPackage("xyz"))); - assertFalse(BackupUtils.signaturesMatch(stored1, genPackage("xyz", "def"))); + @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(); - assertTrue(BackupUtils.signaturesMatch(stored2, genPackage("def", "abc"))); - assertTrue(BackupUtils.signaturesMatch(stored2, genPackage("x", "def", "abc", "y"))); + 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); - // Subset is not okay. - assertFalse(BackupUtils.signaturesMatch(stored2, genPackage("abc"))); - assertFalse(BackupUtils.signaturesMatch(stored2, genPackage("def"))); + 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 @@ public class BackupUtilsTest extends AndroidTestCase { 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/power/batterysaver/BatterySavingStatsTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java index f7112d43443b..0f3ca03fa6d7 100644 --- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java +++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java @@ -15,8 +15,6 @@ */ package com.android.server.power.batterysaver; -import static com.android.server.power.batterysaver.BatterySavingStats.SEND_TRON_EVENTS; - import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -105,9 +103,23 @@ public class BatterySavingStatsTest { public MetricsLogger mMetricsLogger = mock(MetricsLogger.class); + private boolean sendTronEvents; + @Test - public void testAll() { + public void testAll_withTron() { + sendTronEvents = true; + checkAll(); + } + + @Test + public void testAll_noTron() { + sendTronEvents = false; + checkAll(); + } + + private void checkAll() { final BatterySavingStatsTestable target = new BatterySavingStatsTestable(); + target.setSendTronLog(sendTronEvents); target.assertDumpable(); @@ -229,7 +241,7 @@ public class BatterySavingStatsTest { private void assertLog(boolean batterySaver, boolean interactive, long deltaTimeMs, int deltaBatteryLevelUa, int deltaBatteryLevelPercent) { - if (SEND_TRON_EVENTS) { + if (sendTronEvents) { ArgumentCaptor<LogMaker> ac = ArgumentCaptor.forClass(LogMaker.class); verify(mMetricsLogger, times(1)).write(ac.capture()); @@ -251,9 +263,22 @@ public class BatterySavingStatsTest { } } + + @Test + public void testMetricsLogger_withTron() { + sendTronEvents = true; + checkMetricsLogger(); + } + @Test - public void testMetricsLogger() { + public void testMetricsLogger_noTron() { + sendTronEvents = false; + checkMetricsLogger(); + } + + private void checkMetricsLogger() { final BatterySavingStatsTestable target = new BatterySavingStatsTestable(); + target.setSendTronLog(sendTronEvents); target.advanceClock(1); target.drainBattery(1000); diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java index 76e4e895278e..e0645b1f4bfb 100644 --- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java @@ -20,11 +20,9 @@ import android.support.test.filters.FlakyTest; import org.junit.Test; import android.platform.test.annotations.Presubmit; -import android.platform.test.annotations.SecurityTest; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; -import android.view.WindowManager; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -36,13 +34,12 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; -import java.util.function.Consumer; +import com.android.server.wm.WindowTestUtils.TestTaskWindowContainerController; /** * Test class for {@link AppWindowContainerController}. * - * Build/Install/Run: - * bit FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests + * atest FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests */ @SmallTest @Presubmit @@ -176,6 +173,33 @@ public class AppWindowContainerControllerTests extends WindowTestsBase { } @Test + public void testTryTransferStartingWindowFromHiddenAboveToken() throws Exception { + + // Add two tasks on top of each other. + TestTaskWindowContainerController taskController = + new WindowTestUtils.TestTaskWindowContainerController(this); + final WindowTestUtils.TestAppWindowContainerController controllerTop = + createAppWindowController(taskController); + final WindowTestUtils.TestAppWindowContainerController controllerBottom = + createAppWindowController(taskController); + + // Add a starting window. + controllerTop.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(), + android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true, + false, false); + waitUntilHandlersIdle(); + + // Make the top one invisible, and try transfering the starting window from the top to the + // bottom one. + controllerTop.setVisibility(false, false); + controllerBottom.mContainer.transferStartingWindowFromHiddenAboveTokenIfNeeded(); + + // Assert that the bottom window now has the starting window. + assertNoStartingWindow(controllerTop.getAppWindowToken(mDisplayContent)); + assertHasStartingWindow(controllerBottom.getAppWindowToken(mDisplayContent)); + } + + @Test public void testReparent() throws Exception { final StackWindowController stackController = createStackControllerOnDisplay(mDisplayContent); diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java index 8d5214a86d84..0c63cd270d39 100644 --- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java @@ -20,6 +20,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import android.platform.test.annotations.Presubmit; +import android.support.test.filters.FlakyTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.view.Surface; @@ -29,12 +30,14 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; +import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static android.view.WindowManager.TRANSIT_UNSET; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -43,7 +46,7 @@ import static org.junit.Assert.assertTrue; * Tests for the {@link AppWindowToken} class. * * Build/Install/Run: - * bit FrameworksServicesTests:com.android.server.wm.AppWindowTokenTests + * atest FrameworksServicesTests:com.android.server.wm.AppWindowTokenTests */ @SmallTest // TODO: b/68267650 @@ -231,4 +234,20 @@ public class AppWindowTokenTests extends WindowTestsBase { mToken.finishRelaunching(); assertFalse(mToken.containsShowWhenLockedWindow() || mToken.containsDismissKeyguardWindow()); } + + @Test + @FlakyTest(detail = "Promote once confirmed non-flaky") + public void testStuckExitingWindow() throws Exception { + final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW, + "closingWindow"); + closingWindow.mAnimatingExit = true; + closingWindow.mRemoveOnExit = true; + closingWindow.mAppToken.setVisibility(null, false /* visible */, TRANSIT_UNSET, + true /* performLayout */, false /* isVoiceInteraction */); + + // We pretended that we were running an exit animation, but that should have been cleared up + // by changing visibility of AppWindowToken + closingWindow.removeIfPossible(); + assertTrue(closingWindow.mRemoved); + } } 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 b36c7d91c807..edac8a5202d7 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 @@ public class SurfaceAnimationRunnerTest extends WindowTestsBase { verify(mMockAnimationSpec, atLeastOnce()).apply(any(), any(), eq(0L)); } + @FlakyTest(bugId = 74780584) @Test public void testDeferStartingAnimations() throws Exception { mSurfaceAnimationRunner.deferStartingAnimations(); diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java index 6784e302a5c4..6d9167fda585 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -656,4 +656,8 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { @Override public void requestUserActivityNotification() { } + + @Override + public void onLockTaskStateChangedLw(int lockTaskState) { + } } diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java index cdcb949b2a3c..56b7d9f40ec0 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java @@ -38,7 +38,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; -import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static org.junit.Assert.assertEquals; @@ -288,6 +287,16 @@ public class WindowStateTests extends WindowTestsBase { app.mToken.setHidden(false); app.mAttrs.alpha = 0.0f; assertFalse(app.canAffectSystemUiFlags()); + + } + + @Test + public void testCanAffectSystemUiFlags_disallow() throws Exception { + final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); + app.mToken.setHidden(false); + assertTrue(app.canAffectSystemUiFlags()); + app.getTask().setCanAffectSystemUiFlags(false); + assertFalse(app.canAffectSystemUiFlags()); } @Test diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java index 1052e8f377a7..3c4e333b6be9 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java @@ -1,7 +1,5 @@ package com.android.server.slice; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; - import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -12,23 +10,18 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.slice.ISliceListener; -import android.app.slice.Slice; import android.app.slice.SliceProvider; import android.app.slice.SliceSpec; import android.content.ContentProvider; -import android.content.Context; import android.content.IContentProvider; import android.net.Uri; import android.os.Binder; -import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; @@ -83,7 +76,7 @@ public class PinnedSliceStateTest extends UiServiceTestCase { mIContentProvider = mock(IContentProvider.class); when(mContentProvider.getIContentProvider()).thenReturn(mIContentProvider); mContext.getContentResolver().addProvider(AUTH, mContentProvider); - mPinnedSliceManager = new PinnedSliceState(mSliceService, TEST_URI); + mPinnedSliceManager = new PinnedSliceState(mSliceService, TEST_URI, "pkg"); } @Test @@ -164,4 +157,4 @@ public class PinnedSliceStateTest extends UiServiceTestCase { verify(mSliceService).removePinnedSlice(eq(TEST_URI)); assertFalse(mPinnedSliceManager.hasPinOrListener()); } -}
\ No newline at end of file +} diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java index 6fc300959144..4f446a9afb98 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java @@ -18,6 +18,7 @@ import static android.content.ContentProvider.maybeAddUserId; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -28,7 +29,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.AppOpsManager; -import android.app.slice.ISliceListener; import android.app.slice.SliceSpec; import android.content.pm.PackageManagerInternal; import android.net.Uri; @@ -71,7 +71,7 @@ public class SliceManagerServiceTest extends UiServiceTestCase { mService = spy(new SliceManagerService(mContext, TestableLooper.get(this).getLooper())); mCreatedSliceState = mock(PinnedSliceState.class); - doReturn(mCreatedSliceState).when(mService).createPinnedSlice(eq(TEST_URI)); + doReturn(mCreatedSliceState).when(mService).createPinnedSlice(eq(TEST_URI), anyString()); } @After @@ -85,7 +85,7 @@ public class SliceManagerServiceTest extends UiServiceTestCase { mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); - verify(mService, times(1)).createPinnedSlice(eq(TEST_URI)); + verify(mService, times(1)).createPinnedSlice(eq(TEST_URI), eq("pkg")); } @Test diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java new file mode 100644 index 000000000000..5d2c225f28ec --- /dev/null +++ b/telephony/java/android/telephony/AccessNetworkUtils.java @@ -0,0 +1,167 @@ +package android.telephony; + +import static android.telephony.ServiceState.DUPLEX_MODE_FDD; +import static android.telephony.ServiceState.DUPLEX_MODE_TDD; +import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN; + +import android.telephony.AccessNetworkConstants.EutranBand; +import android.telephony.ServiceState.DuplexMode; + + +/** + * Utilities to map between radio constants. + * + * @hide + */ +public class AccessNetworkUtils { + + // do not instantiate + private AccessNetworkUtils() {} + + public static final int INVALID_BAND = -1; + + /** + * Gets the duplex mode for the given EUTRAN operating band. + * + * <p>See 3GPP 36.101 sec 5.5-1 for calculation + * + * @param band The EUTRAN band number + * @return The duplex mode of the given EUTRAN band + */ + @DuplexMode + public static int getDuplexModeForEutranBand(int band) { + if (band == INVALID_BAND) { + return DUPLEX_MODE_UNKNOWN; + } + + if (band >= EutranBand.BAND_68) { + return DUPLEX_MODE_UNKNOWN; + } else if (band >= EutranBand.BAND_65) { + return DUPLEX_MODE_FDD; + } else if (band >= EutranBand.BAND_47) { + return DUPLEX_MODE_UNKNOWN; + } else if (band >= EutranBand.BAND_33) { + return DUPLEX_MODE_TDD; + } else if (band >= EutranBand.BAND_1) { + return DUPLEX_MODE_FDD; + } + + return DUPLEX_MODE_UNKNOWN; + } + + /** + * Gets the EUTRAN Operating band for a given downlink EARFCN. + * + * <p>See 3GPP 36.101 sec 5.7.3-1 for calculation. + * + * @param earfcn The downlink EARFCN + * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists + */ + public static int getOperatingBandForEarfcn(int earfcn) { + if (earfcn > 67535) { + return INVALID_BAND; + } else if (earfcn >= 67366) { + return INVALID_BAND; // band 67 only for CarrierAgg + } else if (earfcn >= 66436) { + return EutranBand.BAND_66; + } else if (earfcn >= 65536) { + return EutranBand.BAND_65; + } else if (earfcn > 54339) { + return INVALID_BAND; + } else if (earfcn >= 46790 /* inferred from the end range of BAND_45 */) { + return EutranBand.BAND_46; + } else if (earfcn >= 46590) { + return EutranBand.BAND_45; + } else if (earfcn >= 45590) { + return EutranBand.BAND_44; + } else if (earfcn >= 43590) { + return EutranBand.BAND_43; + } else if (earfcn >= 41590) { + return EutranBand.BAND_42; + } else if (earfcn >= 39650) { + return EutranBand.BAND_41; + } else if (earfcn >= 38650) { + return EutranBand.BAND_40; + } else if (earfcn >= 38250) { + return EutranBand.BAND_39; + } else if (earfcn >= 37750) { + return EutranBand.BAND_38; + } else if (earfcn >= 37550) { + return EutranBand.BAND_37; + } else if (earfcn >= 36950) { + return EutranBand.BAND_36; + } else if (earfcn >= 36350) { + return EutranBand.BAND_35; + } else if (earfcn >= 36200) { + return EutranBand.BAND_34; + } else if (earfcn >= 36000) { + return EutranBand.BAND_33; + } else if (earfcn > 10359) { + return INVALID_BAND; + } else if (earfcn >= 9920) { + return INVALID_BAND; // band 32 only for CarrierAgg + } else if (earfcn >= 9870) { + return EutranBand.BAND_31; + } else if (earfcn >= 9770) { + return EutranBand.BAND_30; + } else if (earfcn >= 9660) { + return INVALID_BAND; // band 29 only for CarrierAgg + } else if (earfcn >= 9210) { + return EutranBand.BAND_28; + } else if (earfcn >= 9040) { + return EutranBand.BAND_27; + } else if (earfcn >= 8690) { + return EutranBand.BAND_26; + } else if (earfcn >= 8040) { + return EutranBand.BAND_25; + } else if (earfcn >= 7700) { + return EutranBand.BAND_24; + } else if (earfcn >= 7500) { + return EutranBand.BAND_23; + } else if (earfcn >= 6600) { + return EutranBand.BAND_22; + } else if (earfcn >= 6450) { + return EutranBand.BAND_21; + } else if (earfcn >= 6150) { + return EutranBand.BAND_20; + } else if (earfcn >= 6000) { + return EutranBand.BAND_19; + } else if (earfcn >= 5850) { + return EutranBand.BAND_18; + } else if (earfcn >= 5730) { + return EutranBand.BAND_17; + } else if (earfcn > 5379) { + return INVALID_BAND; + } else if (earfcn >= 5280) { + return EutranBand.BAND_14; + } else if (earfcn >= 5180) { + return EutranBand.BAND_13; + } else if (earfcn >= 5010) { + return EutranBand.BAND_12; + } else if (earfcn >= 4750) { + return EutranBand.BAND_11; + } else if (earfcn >= 4150) { + return EutranBand.BAND_10; + } else if (earfcn >= 3800) { + return EutranBand.BAND_9; + } else if (earfcn >= 3450) { + return EutranBand.BAND_8; + } else if (earfcn >= 2750) { + return EutranBand.BAND_7; + } else if (earfcn >= 2650) { + return EutranBand.BAND_6; + } else if (earfcn >= 2400) { + return EutranBand.BAND_5; + } else if (earfcn >= 1950) { + return EutranBand.BAND_4; + } else if (earfcn >= 1200) { + return EutranBand.BAND_3; + } else if (earfcn >= 600) { + return EutranBand.BAND_2; + } else if (earfcn >= 0) { + return EutranBand.BAND_1; + } + + return INVALID_BAND; + } +} diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java index e092d52d91bc..08f8bb6494a0 100644 --- a/telephony/java/android/telephony/CellIdentity.java +++ b/telephony/java/android/telephony/CellIdentity.java @@ -68,6 +68,9 @@ public abstract class CellIdentity implements Parcelable { */ public static final int TYPE_TDSCDMA = 5; + /** @hide */ + public static final int INVALID_CHANNEL_NUMBER = -1; + // Log tag /** @hide */ protected final String mTag; @@ -125,6 +128,16 @@ public abstract class CellIdentity implements Parcelable { public @Type int getType() { return mType; } /** + * Returns the channel number of the cell identity. + * + * @hide + * @return The channel number, or {@link #INVALID_CHANNEL_NUMBER} if not implemented + */ + public int getChannelNumber() { + return INVALID_CHANNEL_NUMBER; + } + + /** * Used by child classes for parceling. * * @hide diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java index d35eb60916f3..52944a8ac261 100644 --- a/telephony/java/android/telephony/CellIdentityGsm.java +++ b/telephony/java/android/telephony/CellIdentityGsm.java @@ -203,6 +203,11 @@ public final class CellIdentityGsm extends CellIdentity { return mAlphaShort; } + /** @hide */ + @Override + public int getChannelNumber() { + return mArfcn; + } /** * @deprecated Primary Scrambling Code is not applicable to GSM. diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java index 2b8eb5f3cca6..37fb07521b0e 100644 --- a/telephony/java/android/telephony/CellIdentityLte.java +++ b/telephony/java/android/telephony/CellIdentityLte.java @@ -213,6 +213,12 @@ public final class CellIdentityLte extends CellIdentity { return mAlphaShort; } + /** @hide */ + @Override + public int getChannelNumber() { + return mEarfcn; + } + @Override public int hashCode() { return Objects.hash(mMccStr, mMncStr, mCi, mPci, mTac, mAlphaLong, mAlphaShort); diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java index a5fd7dd97941..affa0c15862d 100644 --- a/telephony/java/android/telephony/CellIdentityWcdma.java +++ b/telephony/java/android/telephony/CellIdentityWcdma.java @@ -206,6 +206,12 @@ public final class CellIdentityWcdma extends CellIdentity { return mUarfcn; } + /** @hide */ + @Override + public int getChannelNumber() { + return mUarfcn; + } + @Override public boolean equals(Object other) { if (this == other) { diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java index ce1b80c2c860..81a966b7de2f 100644 --- a/telephony/java/android/telephony/MbmsDownloadSession.java +++ b/telephony/java/android/telephony/MbmsDownloadSession.java @@ -131,6 +131,14 @@ public class MbmsDownloadSession implements AutoCloseable { */ public static final String DEFAULT_TOP_LEVEL_TEMP_DIRECTORY = "androidMbmsTempFileRoot"; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {RESULT_SUCCESSFUL, RESULT_CANCELLED, RESULT_EXPIRED, RESULT_IO_ERROR, + RESULT_SERVICE_ID_NOT_DEFINED, RESULT_DOWNLOAD_FAILURE, RESULT_OUT_OF_STORAGE, + RESULT_FILE_ROOT_UNREACHABLE}, prefix = { "RESULT_" }) + public @interface DownloadResultCode{} + /** * Indicates that the download was successful. */ diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 6d1a8e8d36b2..9c831b9be0dd 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -471,9 +471,13 @@ public class ServiceState implements Parcelable { */ @DuplexMode public int getDuplexMode() { - // TODO(b/72117602) determine duplex mode from channel number, using 3GPP 36.101 sections - // 5.7.3-1 and 5.5-1 - return DUPLEX_MODE_UNKNOWN; + // only support LTE duplex mode + if (!isLte(mRilDataRadioTechnology)) { + return DUPLEX_MODE_UNKNOWN; + } + + int band = AccessNetworkUtils.getOperatingBandForEarfcn(mChannelNumber); + return AccessNetworkUtils.getDuplexModeForEutranBand(band); } /** @@ -891,6 +895,7 @@ public class ServiceState implements Parcelable { .append(", mDataRegState=").append(mDataRegState) .append("(" + rilServiceStateToString(mDataRegState) + ")") .append(", mChannelNumber=").append(mChannelNumber) + .append(", duplexMode()=").append(getDuplexMode()) .append(", mCellBandwidths=").append(Arrays.toString(mCellBandwidths)) .append(", mVoiceRoamingType=").append(getRoamingLogString(mVoiceRoamingType)) .append(", mDataRoamingType=").append(getRoamingLogString(mDataRoamingType)) diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 7add893e3ff4..4a0027b7fd77 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -5183,7 +5183,7 @@ public class TelephonyManager { ITelephony telephony = getITelephony(); if (telephony == null) return null; - return telephony.getForbiddenPlmns(subId, appType); + return telephony.getForbiddenPlmns(subId, appType, mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java index 0c17147ca3fa..125161d62373 100644 --- a/telephony/java/android/telephony/UiccSlotInfo.java +++ b/telephony/java/android/telephony/UiccSlotInfo.java @@ -60,6 +60,7 @@ public class UiccSlotInfo implements Parcelable { private final String mCardId; private final @CardStateInfo int mCardStateInfo; private final int mLogicalSlotIdx; + private final boolean mIsExtendedApduSupported; public static final Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() { @Override @@ -79,6 +80,7 @@ public class UiccSlotInfo implements Parcelable { mCardId = in.readString(); mCardStateInfo = in.readInt(); mLogicalSlotIdx = in.readInt(); + mIsExtendedApduSupported = in.readByte() != 0; } @Override @@ -88,6 +90,7 @@ public class UiccSlotInfo implements Parcelable { dest.writeString(mCardId); dest.writeInt(mCardStateInfo); dest.writeInt(mLogicalSlotIdx); + dest.writeByte((byte) (mIsExtendedApduSupported ? 1 : 0)); } @Override @@ -96,12 +99,13 @@ public class UiccSlotInfo implements Parcelable { } public UiccSlotInfo(boolean isActive, boolean isEuicc, String cardId, - @CardStateInfo int cardStateInfo, int logicalSlotIdx) { + @CardStateInfo int cardStateInfo, int logicalSlotIdx, boolean isExtendedApduSupported) { this.mIsActive = isActive; this.mIsEuicc = isEuicc; this.mCardId = cardId; this.mCardStateInfo = cardStateInfo; this.mLogicalSlotIdx = logicalSlotIdx; + this.mIsExtendedApduSupported = isExtendedApduSupported; } public boolean getIsActive() { @@ -125,6 +129,13 @@ public class UiccSlotInfo implements Parcelable { return mLogicalSlotIdx; } + /** + * @return {@code true} if this slot supports extended APDU from ATR, {@code false} otherwise. + */ + public boolean getIsExtendedApduSupported() { + return mIsExtendedApduSupported; + } + @Override public boolean equals(Object obj) { if (this == obj) { @@ -139,7 +150,8 @@ public class UiccSlotInfo implements Parcelable { && (mIsEuicc == that.mIsEuicc) && (mCardId == that.mCardId) && (mCardStateInfo == that.mCardStateInfo) - && (mLogicalSlotIdx == that.mLogicalSlotIdx); + && (mLogicalSlotIdx == that.mLogicalSlotIdx) + && (mIsExtendedApduSupported == that.mIsExtendedApduSupported); } @Override @@ -150,6 +162,7 @@ public class UiccSlotInfo implements Parcelable { result = 31 * result + Objects.hashCode(mCardId); result = 31 * result + mCardStateInfo; result = 31 * result + mLogicalSlotIdx; + result = 31 * result + (mIsExtendedApduSupported ? 1 : 0); return result; } @@ -165,6 +178,8 @@ public class UiccSlotInfo implements Parcelable { + mCardStateInfo + ", phoneId=" + mLogicalSlotIdx + + ", mIsExtendedApduSupported=" + + mIsExtendedApduSupported + ")"; } } diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java index 2748cb5470bf..c008711ff236 100644 --- a/telephony/java/android/telephony/ims/ImsService.java +++ b/telephony/java/android/telephony/ims/ImsService.java @@ -161,11 +161,6 @@ public class ImsService extends Service { } @Override - public void notifyImsFeatureReady(int slotId, int featureType) { - ImsService.this.notifyImsFeatureReady(slotId, featureType); - } - - @Override public IImsConfig getConfig(int slotId) { ImsConfigImplBase c = ImsService.this.getConfig(slotId); return c != null ? c.getIImsConfig() : null; @@ -274,25 +269,6 @@ public class ImsService extends Service { } } - private void notifyImsFeatureReady(int slotId, int featureType) { - synchronized (mFeaturesBySlot) { - // get ImsFeature associated with the slot/feature - SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId); - if (features == null) { - Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " + - "slot " + slotId); - return; - } - ImsFeature f = features.get(featureType); - if (f == null) { - Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type " - + featureType + " exists on slot " + slotId); - return; - } - f.onFeatureReady(); - } - } - /** * When called, provide the {@link ImsFeatureConfiguration} that this {@link ImsService} * currently supports. This will trigger the framework to set up the {@link ImsFeature}s that diff --git a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl index 86f8606ac39f..c7da681b86a3 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl @@ -36,8 +36,6 @@ interface IImsServiceController { ImsFeatureConfiguration querySupportedImsFeatures(); // Synchronous call to ensure the ImsService is ready before continuing with feature creation. void notifyImsServiceReadyForFeatureCreation(); - // Synchronous call to ensure the new ImsFeature is ready before using the Feature. - void notifyImsFeatureReady(int slotId, int featureType); void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c); IImsConfig getConfig(int slotId); IImsRegistration getRegistration(int slotId); diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index afbb94776641..7c7700bb9a7d 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1444,13 +1444,12 @@ interface ITelephony { * Returns a list of Forbidden PLMNs from the specified SIM App * Returns null if the query fails. * - * - * <p>Requires that the calling app has READ_PRIVILEGED_PHONE_STATE + * <p>Requires that the calling app has READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE * * @param subId subscription ID used for authentication * @param appType the icc application type, like {@link #APPTYPE_USIM} */ - String[] getForbiddenPlmns(int subId, int appType); + String[] getForbiddenPlmns(int subId, int appType, String callingPackage); /** * Check if phone is in emergency callback mode diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index a3a30807986e..ee7084ad86c0 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -25,6 +25,7 @@ package com.android.internal.telephony; */ import android.os.SystemProperties; +import android.telephony.TelephonyManager; /** * {@hide} @@ -162,8 +163,8 @@ public interface RILConstants { int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA = 20; /* TD-SCDMA, GSM/WCDMA and LTE */ int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 21; /*TD-SCDMA,EvDo,CDMA,GSM/WCDMA*/ int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 22; /* TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo */ - int PREFERRED_NETWORK_MODE = SystemProperties.getInt("ro.telephony.default_network", - NETWORK_MODE_WCDMA_PREF); + int PREFERRED_NETWORK_MODE = Integer.parseInt(TelephonyManager.getTelephonyProperty(0, + "ro.telephony.default_network", Integer.toString(NETWORK_MODE_WCDMA_PREF))); int BAND_MODE_UNSPECIFIED = 0; //"unspecified" (selected by baseband automatically) int BAND_MODE_EURO = 1; //"EURO band" (GSM-900 / DCS-1800 / WCDMA-IMT-2000) diff --git a/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java index 38c298c5e9ff..d36d84e8f51d 100644 --- a/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java +++ b/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java @@ -229,6 +229,9 @@ public class AppLaunch extends InstrumentationTestCase { setLaunchOrder(); for (LaunchOrder launch : mLaunchOrderList) { + if (mNameToIntent.get(launch.getApp()) == null) { + continue; + } dropCache(); String appPkgName = mNameToIntent.get(launch.getApp()) .getComponent().getPackageName(); diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp index 8219150d3029..7e922e6528de 100644 --- a/tools/incident_section_gen/main.cpp +++ b/tools/incident_section_gen/main.cpp @@ -427,6 +427,7 @@ static bool generateSectionListCpp(Descriptor const* descriptor) { 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; diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 93fa5987aa9c..6865f77fa717 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -86,9 +86,6 @@ public class WifiConfiguration implements Parcelable { /** WPA is not used; plaintext or static WEP could be used. */ public static final int NONE = 0; /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */ - /** @deprecated Due to security and performance limitations, use of WPA-1 networks - * is discouraged. WPA-2 (RSN) should be used instead. */ - @Deprecated public static final int WPA_PSK = 1; /** WPA using EAP authentication. Generally used with an external authentication server. */ public static final int WPA_EAP = 2; @@ -122,7 +119,7 @@ public class WifiConfiguration implements Parcelable { public static final String varName = "key_mgmt"; - public static final String[] strings = { "NONE", /* deprecated */ "WPA_PSK", "WPA_EAP", + public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" }; } diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java index eca840644fc6..ebf60076bd02 100644 --- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java +++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java @@ -133,7 +133,8 @@ public class DiscoverySessionCallback { * match filter. For {@link PublishConfig#PUBLISH_TYPE_SOLICITED}, * {@link SubscribeConfig#SUBSCRIBE_TYPE_ACTIVE} discovery sessions this * is the subscriber's match filter. - * @param distanceMm The measured distance to the Publisher in mm. + * @param distanceMm The measured distance to the Publisher in mm. Note: the measured distance + * may be negative for very close devices. */ public void onServiceDiscoveredWithinRange(PeerHandle peerHandle, byte[] serviceSpecificInfo, List<byte[]> matchFilter, int distanceMm) { diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java index 2ec3b704f0f9..51353c618b97 100644 --- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java +++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java @@ -418,8 +418,8 @@ public final class SubscribeConfig implements Parcelable { * notification. I.e. discovery will be triggered if we've found a matching publisher * (based on the other criteria in this configuration) <b>and</b> the distance to the * publisher is larger than the value specified in this API. Can be used in conjunction with - * {@link #setMaxDistanceMm(int)} to specify a geofence, i.e. discovery with min < - * distance < max. + * {@link #setMaxDistanceMm(int)} to specify a geofence, i.e. discovery with min <= + * distance <= max. * <p> * For ranging to be used in discovery it must also be enabled on the publisher using * {@link PublishConfig.Builder#setRangingEnabled(boolean)}. However, ranging may @@ -453,8 +453,8 @@ public final class SubscribeConfig implements Parcelable { * notification. I.e. discovery will be triggered if we've found a matching publisher * (based on the other criteria in this configuration) <b>and</b> the distance to the * publisher is smaller than the value specified in this API. Can be used in conjunction - * with {@link #setMinDistanceMm(int)} to specify a geofence, i.e. discovery with min < - * distance < max. + * with {@link #setMinDistanceMm(int)} to specify a geofence, i.e. discovery with min <= + * distance <= max. * <p> * For ranging to be used in discovery it must also be enabled on the publisher using * {@link PublishConfig.Builder#setRangingEnabled(boolean)}. However, ranging may diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.java b/wifi/java/android/net/wifi/rtt/RangingResult.java index 4705e1d4913f..7fe85be80964 100644 --- a/wifi/java/android/net/wifi/rtt/RangingResult.java +++ b/wifi/java/android/net/wifi/rtt/RangingResult.java @@ -147,6 +147,8 @@ public final class RangingResult implements Parcelable { * @return The distance (in mm) to the device specified by {@link #getMacAddress()} or * {@link #getPeerHandle()}. * <p> + * Note: the measured distance may be negative for very close devices. + * <p> * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an * exception. */ |