diff options
238 files changed, 4487 insertions, 3089 deletions
diff --git a/Android.mk b/Android.mk index 7bb64482df73..aa7caa547e43 100644 --- a/Android.mk +++ b/Android.mk @@ -270,6 +270,7 @@ LOCAL_SRC_FILES += \ core/java/android/os/IRecoverySystemProgressListener.aidl \ core/java/android/os/IRemoteCallback.aidl \ core/java/android/os/ISchedulingPolicyService.aidl \ + core/java/android/os/IStatsCompanionService.aidl \ core/java/android/os/IStatsManager.aidl \ core/java/android/os/IThermalEventListener.aidl \ core/java/android/os/IThermalService.aidl \ diff --git a/api/current.txt b/api/current.txt index d7e1a7a6bb0e..f6410834f257 100644 --- a/api/current.txt +++ b/api/current.txt @@ -39997,8 +39997,10 @@ package android.telephony { public class PhoneNumberUtils { ctor public PhoneNumberUtils(); method public static void addTtsSpan(android.text.Spannable, int, int); - method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int); - method public static java.lang.String calledPartyBCDToString(byte[], int, int); + method public static deprecated java.lang.String calledPartyBCDFragmentToString(byte[], int, int); + method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int, int); + method public static deprecated java.lang.String calledPartyBCDToString(byte[], int, int); + method public static java.lang.String calledPartyBCDToString(byte[], int, int, int); method public static boolean compare(java.lang.String, java.lang.String); method public static boolean compare(android.content.Context, java.lang.String, java.lang.String); method public static java.lang.String convertKeypadLettersToDigits(java.lang.String); @@ -40031,12 +40033,15 @@ package android.telephony { method public static byte[] networkPortionToCalledPartyBCD(java.lang.String); method public static byte[] networkPortionToCalledPartyBCDWithLength(java.lang.String); method public static java.lang.String normalizeNumber(java.lang.String); - method public static byte[] numberToCalledPartyBCD(java.lang.String); + method public static deprecated byte[] numberToCalledPartyBCD(java.lang.String); + method public static byte[] numberToCalledPartyBCD(java.lang.String, int); method public static java.lang.String replaceUnicodeDigits(java.lang.String); method public static java.lang.String stringFromStringAndTOA(java.lang.String, int); method public static java.lang.String stripSeparators(java.lang.String); method public static java.lang.String toCallerIDMinMatch(java.lang.String); method public static int toaFromString(java.lang.String); + field public static final int BCD_EXTENDED_TYPE_CALLED_PARTY = 2; // 0x2 + field public static final int BCD_EXTENDED_TYPE_EF_ADN = 1; // 0x1 field public static final int FORMAT_JAPAN = 2; // 0x2 field public static final int FORMAT_NANP = 1; // 0x1 field public static final int FORMAT_UNKNOWN = 0; // 0x0 diff --git a/api/system-current.txt b/api/system-current.txt index 4f4b9db1b43a..eee24dea55dc 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -43472,8 +43472,10 @@ package android.telephony { public class PhoneNumberUtils { ctor public PhoneNumberUtils(); method public static void addTtsSpan(android.text.Spannable, int, int); - method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int); - method public static java.lang.String calledPartyBCDToString(byte[], int, int); + method public static deprecated java.lang.String calledPartyBCDFragmentToString(byte[], int, int); + method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int, int); + method public static deprecated java.lang.String calledPartyBCDToString(byte[], int, int); + method public static java.lang.String calledPartyBCDToString(byte[], int, int, int); method public static boolean compare(java.lang.String, java.lang.String); method public static boolean compare(android.content.Context, java.lang.String, java.lang.String); method public static java.lang.String convertKeypadLettersToDigits(java.lang.String); @@ -43506,12 +43508,15 @@ package android.telephony { method public static byte[] networkPortionToCalledPartyBCD(java.lang.String); method public static byte[] networkPortionToCalledPartyBCDWithLength(java.lang.String); method public static java.lang.String normalizeNumber(java.lang.String); - method public static byte[] numberToCalledPartyBCD(java.lang.String); + method public static deprecated byte[] numberToCalledPartyBCD(java.lang.String); + method public static byte[] numberToCalledPartyBCD(java.lang.String, int); method public static java.lang.String replaceUnicodeDigits(java.lang.String); method public static java.lang.String stringFromStringAndTOA(java.lang.String, int); method public static java.lang.String stripSeparators(java.lang.String); method public static java.lang.String toCallerIDMinMatch(java.lang.String); method public static int toaFromString(java.lang.String); + field public static final int BCD_EXTENDED_TYPE_CALLED_PARTY = 2; // 0x2 + field public static final int BCD_EXTENDED_TYPE_EF_ADN = 1; // 0x1 field public static final int FORMAT_JAPAN = 2; // 0x2 field public static final int FORMAT_NANP = 1; // 0x1 field public static final int FORMAT_UNKNOWN = 0; // 0x0 diff --git a/api/test-current.txt b/api/test-current.txt index 7256e5cf1cf9..2d7f67fe1650 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4052,10 +4052,11 @@ package android.app { method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int); method public void requestUsageTimeReport(android.app.PendingIntent); method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle); + method public void setLaunchActivityType(int); method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect); method public android.app.ActivityOptions setLaunchDisplayId(int); - method public void setLaunchStackId(int); method public void setLaunchTaskId(int); + method public void setLaunchWindowingMode(int); method public void setTaskOverlay(boolean, boolean); method public android.os.Bundle toBundle(); method public void update(android.app.ActivityOptions); @@ -6244,6 +6245,7 @@ package android.app { field public static final int ACTIVITY_TYPE_UNDEFINED = 0; // 0x0 field public static final int WINDOWING_MODE_FREEFORM = 5; // 0x5 field public static final int WINDOWING_MODE_FULLSCREEN = 1; // 0x1 + field public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY = 4; // 0x4 field public static final int WINDOWING_MODE_PINNED = 2; // 0x2 field public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY = 3; // 0x3 field public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4; // 0x4 @@ -31816,7 +31818,7 @@ package android.os { method public static android.os.StrictMode.VmPolicy getVmPolicy(); method public static void noteSlowCall(java.lang.String); method public static void setThreadPolicy(android.os.StrictMode.ThreadPolicy); - method public static void setViolationListener(android.os.StrictMode.ViolationListener); + method public static void setViolationLogger(android.os.StrictMode.ViolationLogger); method public static void setVmPolicy(android.os.StrictMode.VmPolicy); } @@ -31850,8 +31852,30 @@ package android.os { method public android.os.StrictMode.ThreadPolicy.Builder permitUnbufferedIo(); } - public static abstract interface StrictMode.ViolationListener { - method public abstract void onViolation(java.lang.String); + public static final class StrictMode.ViolationInfo implements android.os.Parcelable { + ctor public StrictMode.ViolationInfo(); + ctor public StrictMode.ViolationInfo(java.lang.Throwable, int); + ctor public StrictMode.ViolationInfo(java.lang.String, java.lang.Throwable, int); + ctor public StrictMode.ViolationInfo(android.os.Parcel); + ctor public StrictMode.ViolationInfo(android.os.Parcel, boolean); + method public int describeContents(); + method public void dump(android.util.Printer, java.lang.String); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.os.StrictMode.ViolationInfo> CREATOR; + field public java.lang.String broadcastIntentAction; + field public final android.app.ApplicationErrorReport.CrashInfo crashInfo; + field public int durationMillis; + field public final java.lang.String message; + field public int numAnimationsRunning; + field public long numInstances; + field public final int policy; + field public java.lang.String[] tags; + field public int violationNumThisLoop; + field public long violationUptimeMillis; + } + + public static abstract interface StrictMode.ViolationLogger { + method public abstract void log(android.os.StrictMode.ViolationInfo); } public static final class StrictMode.VmPolicy { @@ -40306,8 +40330,10 @@ package android.telephony { public class PhoneNumberUtils { ctor public PhoneNumberUtils(); method public static void addTtsSpan(android.text.Spannable, int, int); - method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int); - method public static java.lang.String calledPartyBCDToString(byte[], int, int); + method public static deprecated java.lang.String calledPartyBCDFragmentToString(byte[], int, int); + method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int, int); + method public static deprecated java.lang.String calledPartyBCDToString(byte[], int, int); + method public static java.lang.String calledPartyBCDToString(byte[], int, int, int); method public static boolean compare(java.lang.String, java.lang.String); method public static boolean compare(android.content.Context, java.lang.String, java.lang.String); method public static java.lang.String convertKeypadLettersToDigits(java.lang.String); @@ -40340,12 +40366,15 @@ package android.telephony { method public static byte[] networkPortionToCalledPartyBCD(java.lang.String); method public static byte[] networkPortionToCalledPartyBCDWithLength(java.lang.String); method public static java.lang.String normalizeNumber(java.lang.String); - method public static byte[] numberToCalledPartyBCD(java.lang.String); + method public static deprecated byte[] numberToCalledPartyBCD(java.lang.String); + method public static byte[] numberToCalledPartyBCD(java.lang.String, int); method public static java.lang.String replaceUnicodeDigits(java.lang.String); method public static java.lang.String stringFromStringAndTOA(java.lang.String, int); method public static java.lang.String stripSeparators(java.lang.String); method public static java.lang.String toCallerIDMinMatch(java.lang.String); method public static int toaFromString(java.lang.String); + field public static final int BCD_EXTENDED_TYPE_CALLED_PARTY = 2; // 0x2 + field public static final int BCD_EXTENDED_TYPE_EF_ADN = 1; // 0x1 field public static final int FORMAT_JAPAN = 2; // 0x2 field public static final int FORMAT_NANP = 1; // 0x1 field public static final int FORMAT_UNKNOWN = 0; // 0x0 diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp index 35f8bbb57e50..6ded24648353 100644 --- a/cmds/screencap/screencap.cpp +++ b/cmds/screencap/screencap.cpp @@ -101,9 +101,6 @@ static uint32_t dataSpaceToInt(android_dataspace d) static status_t notifyMediaScanner(const char* fileName) { String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://"); - String8 fileUrl("\""); - fileUrl.append(fileName); - fileUrl.append("\""); cmd.append(fileName); cmd.append(" > /dev/null"); int result = system(cmd.string()); diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index f1b3c053b2cb..6de530319727 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -41,11 +41,14 @@ LOCAL_MODULE := statsd LOCAL_SRC_FILES := \ ../../core/java/android/os/IStatsManager.aidl \ + ../../core/java/android/os/IStatsCompanionService.aidl \ src/StatsService.cpp \ + src/AnomalyMonitor.cpp \ src/LogEntryPrinter.cpp \ src/LogReader.cpp \ src/main.cpp \ src/DropboxWriter.cpp \ + src/parse_util.cpp \ src/StatsLogProcessor.cpp \ src/stats_log.proto \ src/statsd_config.proto \ @@ -118,6 +121,7 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \ LOCAL_SRC_FILES := \ ../../core/java/android/os/IStatsManager.aidl \ src/StatsService.cpp \ + tests/indexed_priority_queue_test.cpp \ src/LogEntryPrinter.cpp \ src/LogReader.cpp \ tests/LogReader_test.cpp \ diff --git a/cmds/statsd/src/AnomalyMonitor.cpp b/cmds/statsd/src/AnomalyMonitor.cpp new file mode 100644 index 000000000000..d73de957881a --- /dev/null +++ b/cmds/statsd/src/AnomalyMonitor.cpp @@ -0,0 +1,111 @@ +/* + * 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. + */ + +#define LOG_TAG "AnomalyMonitor" +#define DEBUG true + +#include <AnomalyMonitor.h> + +#include <binder/IServiceManager.h> +#include <cutils/log.h> + +namespace statsd { + +AnomalyMonitor::AnomalyMonitor(uint32_t minDiffToUpdateRegisteredAlarmTimeSec) + : mRegisteredAlarmTimeSec(0), + mMinUpdateTimeSec(minDiffToUpdateRegisteredAlarmTimeSec) { +} + +AnomalyMonitor::~AnomalyMonitor() { +} + +void AnomalyMonitor::add(sp<const AnomalyAlarm> alarm) { + if (alarm == nullptr) { + ALOGW("Asked to add a null alarm."); + return; + } + if (alarm->timestampSec < 1) { + // forbidden since a timestamp 0 is used to indicate no alarm registered + ALOGW("Asked to add a 0-time alarm."); + return; + } + std::lock_guard<std::mutex> lock(mLock); + // TODO: Ensure that refractory period is respected. + if (DEBUG) ALOGD("Adding alarm with time %u", alarm->timestampSec); + mPq.push(alarm); + if (mRegisteredAlarmTimeSec < 1 || + alarm->timestampSec + mMinUpdateTimeSec < mRegisteredAlarmTimeSec) { + updateRegisteredAlarmTime(alarm->timestampSec); + } +} + +void AnomalyMonitor::remove(sp<const AnomalyAlarm> alarm) { + if (alarm == nullptr) { + ALOGW("Asked to remove a null alarm."); + return; + } + std::lock_guard<std::mutex> lock(mLock); + if (DEBUG) ALOGD("Removing alarm with time %u", alarm->timestampSec); + mPq.remove(alarm); + if (mPq.empty()) { + if (DEBUG) ALOGD("Queue is empty. Cancel any alarm."); + mRegisteredAlarmTimeSec = 0; + // TODO: Make this resistant to doing work when companion is not ready yet + sp<IStatsCompanionService> statsCompanionService = getStatsCompanion_l(); + if (statsCompanionService != nullptr) { + statsCompanionService->cancelAnomalyAlarm(); + } + return; + } + uint32_t soonestAlarmTimeSec = mPq.top()->timestampSec; + if (DEBUG) ALOGD("Soonest alarm is %u", soonestAlarmTimeSec); + if (soonestAlarmTimeSec > mRegisteredAlarmTimeSec + mMinUpdateTimeSec) { + updateRegisteredAlarmTime(soonestAlarmTimeSec); + } +} + +void AnomalyMonitor::updateRegisteredAlarmTime(uint32_t timestampSec) { + if (DEBUG) ALOGD("Updating reg alarm time to %u", timestampSec); + mRegisteredAlarmTimeSec = timestampSec; + sp<IStatsCompanionService> statsCompanionService = getStatsCompanion_l(); + if (statsCompanionService != nullptr) { + statsCompanionService->setAnomalyAlarm(secToMs(mRegisteredAlarmTimeSec)); + } +} + +sp<IStatsCompanionService> AnomalyMonitor::getStatsCompanion_l() { + if (mStatsCompanion != nullptr) { + return mStatsCompanion; + } + // Get statscompanion service from service manager + const sp<IServiceManager> sm(defaultServiceManager()); + if (sm != nullptr) { + const String16 name("statscompanion"); + mStatsCompanion = + interface_cast<IStatsCompanionService>(sm->checkService(name)); + if (mStatsCompanion == nullptr) { + ALOGW("statscompanion service unavailable!"); + return nullptr; + } + } + return mStatsCompanion; +} + +int64_t AnomalyMonitor::secToMs(uint32_t timeSec) { + return ((int64_t) timeSec) * 1000; +} + +} // namespace statsd
\ No newline at end of file diff --git a/cmds/statsd/src/AnomalyMonitor.h b/cmds/statsd/src/AnomalyMonitor.h new file mode 100644 index 000000000000..5418cf0dc552 --- /dev/null +++ b/cmds/statsd/src/AnomalyMonitor.h @@ -0,0 +1,129 @@ +/* + * 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. + */ + +#ifndef ANOMALY_MONITOR_H +#define ANOMALY_MONITOR_H + +#include <indexed_priority_queue.h> +#include <android/os/IStatsCompanionService.h> +#include <utils/RefBase.h> + +#include <queue> +#include <vector> + +using namespace android::os; +using namespace android; + +namespace statsd { + +/** + * Represents an alarm, associated with some aggregate metric, holding a + * projected time at which the metric is expected to exceed its anomaly + * threshold. + * Timestamps are in seconds since epoch in a uint32, so will fail in year 2106. + */ +struct AnomalyAlarm : public RefBase { + AnomalyAlarm(uint32_t timestampSec) : timestampSec(timestampSec) { + } + + const uint32_t timestampSec; + + /** AnomalyAlarm a is smaller (higher priority) than b if its timestamp is sooner. */ + struct SmallerTimestamp { + bool operator()(sp<const AnomalyAlarm> a, sp<const AnomalyAlarm> b) const { + return (a->timestampSec < b->timestampSec); + } + }; +}; + +/** + * Manages alarms for Anomaly Detection. + */ +class AnomalyMonitor { + public: + /** + * @param minDiffToUpdateRegisteredAlarmTimeSec If the soonest alarm differs + * from the registered alarm by more than this amount, update the registered + * alarm. + */ + AnomalyMonitor(uint32_t minDiffToUpdateRegisteredAlarmTimeSec); + ~AnomalyMonitor(); + + /** + * Adds the given alarm (reference) to the queue. + */ + void add(sp<const AnomalyAlarm> alarm); + + /** + * Removes the given alarm (reference) from the queue. + * Note that alarm comparison is reference-based; if another alarm exists + * with the same timestampSec, that alarm will still remain in the queue. + */ + void remove(sp<const AnomalyAlarm> alarm); + + /** + * Returns the projected alarm timestamp that is registered with + * StatsCompanionService. This may not be equal to the soonest alarm, + * but should be within minDiffToUpdateRegisteredAlarmTimeSec of it. + */ + uint32_t getRegisteredAlarmTimeSec() const { + return mRegisteredAlarmTimeSec; + } + + private: + /** Lock for accessing/writing to mPq. */ + std::mutex mLock; + + /** + * Timestamp (seconds since epoch) of the alarm registered with + * StatsCompanionService. This, in general, may not be equal to the soonest + * alarm stored in mPq, but should be within minUpdateTimeSec of it. + * A value of 0 indicates that no alarm is currently registered. + */ + uint32_t mRegisteredAlarmTimeSec; + + /** + * Priority queue of alarms, prioritized by soonest alarm.timestampSec. + */ + indexed_priority_queue<AnomalyAlarm, AnomalyAlarm::SmallerTimestamp> mPq; + + /** + * Binder interface for communicating with StatsCompanionService. + */ + sp<IStatsCompanionService> mStatsCompanion; + + /** + * Amount by which the soonest projected alarm must differ from + * mRegisteredAlarmTimeSec before updateRegisteredAlarmTime is called. + */ + uint32_t mMinUpdateTimeSec; + + /** + * Updates the alarm registered with StatsCompanionService to the given time. + * Also correspondingly updates mRegisteredAlarmTimeSec. + */ + void updateRegisteredAlarmTime(uint32_t timestampSec); + + /** Returns the StatsCompanionService. */ + sp<IStatsCompanionService> getStatsCompanion_l(); + + /** Converts uint32 timestamp in seconds to a Java long in msec. */ + int64_t secToMs(uint32_t timeSec); +}; + +} // namespace statsd + +#endif // ANOMALY_MONITOR_H
\ No newline at end of file diff --git a/cmds/statsd/src/DropboxReader.cpp b/cmds/statsd/src/DropboxReader.cpp index 187f4ada61ca..cda2f431e435 100644 --- a/cmds/statsd/src/DropboxReader.cpp +++ b/cmds/statsd/src/DropboxReader.cpp @@ -15,9 +15,7 @@ */ #include <android/os/DropBoxManager.h> #include <android-base/file.h> -#include <cutils/log.h> #include <androidfw/ZipUtils.h> -#include <stdio.h> #include "DropboxReader.h" @@ -25,14 +23,14 @@ using android::sp; using android::String16; using android::binder::Status; using android::base::unique_fd; +using android::os::statsd::EventMetricData; using android::os::DropBoxManager; -using android::os::statsd::StatsLogEntry; using android::ZipUtils; using std::vector; status_t DropboxReader::readStatsLogs(FILE* out, const string& tag, long msec) { sp<DropBoxManager> dropbox = new DropBoxManager(); - StatsLogList logList; + StatsLogReport logReport; long timestamp = msec; // instead of while(true), put a hard limit 1000. Dropbox won't have more than 1000 files. @@ -51,23 +49,23 @@ status_t DropboxReader::readStatsLogs(FILE* out, const string& tag, long msec) { timestamp = entry.getTimestamp(); if (entry.getFlags() & DropBoxManager::IS_GZIPPED) { - if (!parseFromGzipFile(fd, logList)) { + if (!parseFromGzipFile(fd, logReport)) { // Failed to parse from the file. Continue to fetch the next entry. continue; } } else { - if (!parseFromFile(fd, logList)) { + if (!parseFromFile(fd, logReport)) { // Failed to parse from the file. Continue to fetch the next entry. continue; } } - printLog(out, logList); + printLog(out, logReport); } return android::OK; } -bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogList& list) { +bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogReport& logReport) { FILE *file = fdopen(fd, "r"); bool result = false; bool scanResult; @@ -80,7 +78,7 @@ bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogList& list) { if (scanResult && method == kCompressDeflated) { vector<uint8_t> buf(uncompressedLen); if (ZipUtils::inflateToBuffer(file, &buf[0], uncompressedLen, compressedLen)) { - if (list.ParseFromArray(&buf[0], uncompressedLen)) { + if (logReport.ParseFromArray(&buf[0], uncompressedLen)) { result = true; } } @@ -92,29 +90,30 @@ bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogList& list) { } // parse a non zipped file. -bool DropboxReader::parseFromFile(const unique_fd& fd, StatsLogList& list) { +bool DropboxReader::parseFromFile(const unique_fd& fd, StatsLogReport& logReport) { string content; if (!android::base::ReadFdToString(fd, &content)) { ALOGE("Failed to read file"); return false; } - if (!list.ParseFromString(content)) { + if (!logReport.ParseFromString(content)) { ALOGE("failed to parse log entry from data"); return false; } return true; } -void DropboxReader::printLog(FILE* out, const StatsLogList& list) { - for (int i = 0; i < list.stats_log_entry_size(); i++) { - const StatsLogEntry entry = list.stats_log_entry(i); - // TODO: print pretty - fprintf(out, "time_msec=%lld, type=%d, aggregate_type=%d, uid=%d, pid=%d ", - entry.start_report_millis(), entry.type(), entry.aggregate_type(), - entry.uid(), entry.pid()); - for (int j = 0; j < entry.pairs_size(); j++) { - fprintf(out, "msg=%s ", entry.pairs(j).value_str().c_str()); +void DropboxReader::printLog(FILE* out, const StatsLogReport& logReport) { + fprintf(out, "start_time_msec=%lld, end_time_msec=%lld, ", + logReport.start_report_millis(), logReport.end_report_millis()); + for (int i = 0; i < logReport.event_metrics().data_size(); i++) { + EventMetricData eventMetricData = logReport.event_metrics().data(i); + for (int j = 0; j < eventMetricData.key_value_pair_size(); j++) { + fprintf(out, "key=%d, ", eventMetricData.key_value_pair(j).key()); + fprintf(out, "value_str=%s ", eventMetricData.key_value_pair(j).value_str().c_str()); + fprintf(out, "value_int=%lld ", eventMetricData.key_value_pair(j).value_int()); + fprintf(out, "value_float=%f ", eventMetricData.key_value_pair(j).value_float()); } - fprintf(out, "\n"); } + fprintf(out, "\n"); } diff --git a/cmds/statsd/src/DropboxReader.h b/cmds/statsd/src/DropboxReader.h index a62ffde6b255..f7d5a8205f57 100644 --- a/cmds/statsd/src/DropboxReader.h +++ b/cmds/statsd/src/DropboxReader.h @@ -23,7 +23,7 @@ #include <stdio.h> using android::base::unique_fd; -using android::os::statsd::StatsLogList; +using android::os::statsd::StatsLogReport; using android::status_t; using std::string; @@ -33,13 +33,13 @@ public: static status_t readStatsLogs(FILE* out, const string& tag, long msec); private: - static bool parseFromFile(const unique_fd& fd, StatsLogList& list); - static bool parseFromGzipFile(const unique_fd& fd, StatsLogList& list); - static void printLog(FILE* out, const StatsLogList& list); + static bool parseFromFile(const unique_fd& fd, StatsLogReport& logReport); + static bool parseFromGzipFile(const unique_fd& fd, StatsLogReport& logReport); + static void printLog(FILE* out, const StatsLogReport& logReport); enum { kCompressStored = 0, // no compression kCompressDeflated = 8, // standard deflate }; }; -#endif //DROPBOX_READER_H
\ No newline at end of file +#endif //DROPBOX_READER_H diff --git a/cmds/statsd/src/DropboxWriter.cpp b/cmds/statsd/src/DropboxWriter.cpp index a251056d9e81..01a9eac317d8 100644 --- a/cmds/statsd/src/DropboxWriter.cpp +++ b/cmds/statsd/src/DropboxWriter.cpp @@ -15,7 +15,6 @@ */ #include <android/os/DropBoxManager.h> -#include <cutils/log.h> #include "DropboxWriter.h" @@ -26,36 +25,35 @@ using android::String16; using std::vector; DropboxWriter::DropboxWriter(const string& tag) - : mTag(tag), mLogList(), mBufferSize(0) { + : mTag(tag), mLogReport(), mBufferSize(0) { } -void DropboxWriter::addEntry(const StatsLogEntry& entry) { - flushIfNecessary(entry); - StatsLogEntry* newEntry = mLogList.add_stats_log_entry(); - newEntry->CopyFrom(entry); - mBufferSize += entry.ByteSize(); +void DropboxWriter::addStatsLogReport(const StatsLogReport& log) { + mLogReport = log; + flushIfNecessary(log); + mBufferSize += log.ByteSize(); } -void DropboxWriter::flushIfNecessary(const StatsLogEntry& entry) { - // The serialized size of the StatsLogList is approximately the sum of the serialized size of - // every StatsLogEntry inside it. - if (entry.ByteSize() + mBufferSize > kMaxSerializedBytes) { - flush(); - } +void DropboxWriter::flushIfNecessary(const StatsLogReport& log) { + // TODO: Decide to flush depending on the serialized size of the StatsLogReport. + // if (entry.ByteSize() + mBufferSize > kMaxSerializedBytes) { + // flush(); + // } + flush(); } void DropboxWriter::flush() { // now we get an exact byte size of the output - const int numBytes = mLogList.ByteSize(); + const int numBytes = mLogReport.ByteSize(); vector<uint8_t> buffer(numBytes); sp<DropBoxManager> dropbox = new DropBoxManager(); - mLogList.SerializeToArray(&buffer[0], numBytes); + mLogReport.SerializeToArray(&buffer[0], numBytes); Status status = dropbox->addData(String16(mTag.c_str()), &buffer[0], numBytes, 0 /* no flag */); if (!status.isOk()) { ALOGE("failed to write to dropbox"); //TODO: What to do if flush fails?? } - mLogList.Clear(); + mLogReport.Clear(); mBufferSize = 0; } diff --git a/cmds/statsd/src/DropboxWriter.h b/cmds/statsd/src/DropboxWriter.h index 176ac8b944a7..31b3f2764bb9 100644 --- a/cmds/statsd/src/DropboxWriter.h +++ b/cmds/statsd/src/DropboxWriter.h @@ -20,8 +20,7 @@ #include <frameworks/base/cmds/statsd/src/stats_log.pb.h> using std::string; -using android::os::statsd::StatsLogEntry; -using android::os::statsd::StatsLogList; +using android::os::statsd::StatsLogReport; class DropboxWriter { public: @@ -30,7 +29,7 @@ public: */ DropboxWriter(const string& tag); - void addEntry(const StatsLogEntry& entry); + void addStatsLogReport(const StatsLogReport& log); /* Request a flush to dropbox. */ void flush(); @@ -46,11 +45,11 @@ private: const string mTag; - /* StatsLogList is a wrapper for storing a list of StatsLogEntry */ - StatsLogList mLogList; + /* Data that was captured for a single metric over a given interval of time. */ + StatsLogReport mLogReport; /* Current *serialized* size of the logs kept in memory. - To save computation, we will not calculate the size of the StatsLogList every time when a new + To save computation, we will not calculate the size of the StatsLogReport every time when a new entry is added, which would recursively call ByteSize() on every log entry. Instead, we keep the sum of all individual stats log entry sizes. The size of a proto is approximately the sum of the size of all member protos. @@ -59,7 +58,7 @@ private: /* Check if the buffer size exceeds the max buffer size when the new entry is added, and flush the logs to dropbox if true. */ - void flushIfNecessary(const StatsLogEntry& entry); + void flushIfNecessary(const StatsLogReport& log); }; diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 5f5e216fe3a6..c2fffd8a2d84 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -16,14 +16,13 @@ #include <StatsLogProcessor.h> -#include <log/event_tag_map.h> -#include <log/logprint.h> +#include <log/log_event_list.h> #include <utils/Errors.h> -#include <cutils/log.h> -#include <frameworks/base/cmds/statsd/src/stats_log.pb.h> +#include <parse_util.h> using namespace android; -using android::os::statsd::StatsLogEntry; +using android::os::statsd::EventMetricData; +using android::os::statsd::StatsLogReport; StatsLogProcessor::StatsLogProcessor() : m_dropbox_writer("all-logs") { @@ -57,12 +56,12 @@ StatsLogProcessor::OnLogEvent(const log_msg& msg) // dump all statsd logs to dropbox for now. // TODO: Add filtering, aggregation, etc. if (err == NO_ERROR) { - StatsLogEntry logEntry; - logEntry.set_uid(entry.uid); - logEntry.set_pid(entry.pid); - logEntry.set_start_report_millis(entry.tv_sec / 1000 + entry.tv_nsec / 1000 / 1000); - logEntry.add_pairs()->set_value_str(entry.message, entry.messageLen); - m_dropbox_writer.addEntry(logEntry); + StatsLogReport logReport; + logReport.set_start_report_millis(entry.tv_sec / 1000 + entry.tv_nsec / 1000 / 1000); + EventMetricData *eventMetricData = logReport.mutable_event_metrics()->add_data(); + *eventMetricData = parse(msg); + + m_dropbox_writer.addStatsLogReport(logReport); } } @@ -71,4 +70,4 @@ StatsLogProcessor::UpdateConfig(const int config_source, StatsdConfig config) { m_configs[config_source] = config; ALOGD("Updated configuration for source %i", config_source); -}
\ No newline at end of file +} diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index d2daecd541db..5df84245a406 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -16,12 +16,8 @@ #ifndef STATS_LOG_PROCESSOR_H #define STATS_LOG_PROCESSOR_H -#include "LogReader.h" -#include "DropboxWriter.h" +#include "parse_util.h" -#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> -#include <log/logprint.h> -#include <stdio.h> #include <unordered_map> using android::os::statsd::StatsdConfig; diff --git a/cmds/statsd/src/indexed_priority_queue.h b/cmds/statsd/src/indexed_priority_queue.h new file mode 100644 index 000000000000..d302f855b1bf --- /dev/null +++ b/cmds/statsd/src/indexed_priority_queue.h @@ -0,0 +1,195 @@ +/* + * 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. + */ + +#ifndef STATSD_INDEXED_PRIORITY_QUEUE_H +#define STATSD_INDEXED_PRIORITY_QUEUE_H + +// ALOGE can be called from this file. If header loaded by another class, use their LOG_TAG instead. +#ifndef LOG_TAG +#define LOG_TAG "statsd(indexed_priority_queue)" +#endif //LOG_TAG + +#include <cutils/log.h> +#include <unordered_map> +#include <utils/RefBase.h> +#include <vector> + +using namespace android; + +namespace statsd { + +/** Defines a hash function for sp<AA>, returning the hash of the underlying pointer. */ +template <class AA> +struct SpHash { + size_t operator()(const sp<const AA>& k) const { + return std::hash<const AA*>()(k.get()); + } +}; + +/** + * Min priority queue for generic type AA. + * Unlike a regular priority queue, this class is also capable of removing interior elements. + * @tparam Comparator must implement [bool operator()(sp<const AA> a, sp<const AA> b)], returning + * whether a should be closer to the top of the queue than b. + */ +template <class AA, class Comparator> +class indexed_priority_queue { + public: + indexed_priority_queue(); + /** Adds a into the priority queue. If already present or a==nullptr, does nothing. */ + void push(sp<const AA> a); + /** Removes a from the priority queue. If not present or a==nullptr, does nothing. */ + void remove(sp<const AA> a); + /** Removes all elements. */ + void clear(); + /** Returns whether priority queue contains a (not just a copy of a, but a itself). */ + bool contains(sp<const AA> a) const; + /** Returns min element. Returns nullptr iff empty(). */ + sp<const AA> top() const; + /** Returns number of elements in priority queue. */ + size_t size() const { return pq.size() - 1; } // pq is 1-indexed + /** Returns true iff priority queue is empty. */ + bool empty() const { return size() < 1; } + + private: + /** Vector representing a min-heap (1-indexed, with nullptr at 0). */ + std::vector<sp<const AA>> pq; + /** Mapping of each element in pq to its index in pq (i.e. the inverse of a=pq[i]). */ + std::unordered_map<sp<const AA>, size_t, SpHash<AA>> indices; + + void init(); + void sift_up(size_t idx); + void sift_down(size_t idx); + /** Returns whether pq[idx1] is considered higher than pq[idx2], according to Comparator. */ + bool higher(size_t idx1, size_t idx2) const; + void swap_indices(size_t i, size_t j); +}; + +// Implementation must be done in this file due to use of template. + +template <class AA, class Comparator> +indexed_priority_queue<AA,Comparator>::indexed_priority_queue() { + init(); +} + +template <class AA, class Comparator> +void indexed_priority_queue<AA,Comparator>::push(sp<const AA> a) { + if (a == nullptr) return; + if (contains(a)) return; + pq.push_back(a); + size_t idx = size(); // index of last element since 1-indexed + indices.insert({a, idx}); + sift_up(idx); // get the pq back in order +} + +template <class AA, class Comparator> +void indexed_priority_queue<AA,Comparator>::remove(sp<const AA> a) { + if (a == nullptr) return; + if (!contains(a)) return; + size_t idx = indices[a]; + if (idx >= pq.size()) { + ALOGE("indexed_priority_queue: Invalid index in map of indices."); + return; + } + if (idx == size()) { // if a is the last element, i.e. at index idx == size() == (pq.size()-1) + pq.pop_back(); + indices.erase(a); + return; + } + // move last element (guaranteed not to be at idx) to idx, then delete a + sp<const AA> last_a = pq.back(); + pq[idx] = last_a; + pq.pop_back(); + indices[last_a] = idx; + indices.erase(a); + + // get the heap back in order (since the element at idx is not in order) + sift_up(idx); + sift_down(idx); +} + +template <class AA, class Comparator> +void indexed_priority_queue<AA,Comparator>::clear() { + pq.clear(); + indices.clear(); + init(); +} + +template <class AA, class Comparator> +sp<const AA> indexed_priority_queue<AA,Comparator>::top() const { + if (empty()) return nullptr; + return pq[1]; +} + +template <class AA, class Comparator> +void indexed_priority_queue<AA,Comparator>::init() { + pq.push_back(nullptr); // so that pq is 1-indexed. + indices.insert({nullptr, 0}); // just to be consistent with pq. +} + +template <class AA, class Comparator> +void indexed_priority_queue<AA,Comparator>::sift_up(size_t idx) { + while (idx > 1) { + size_t parent = idx/2; + if (higher(idx, parent)) swap_indices(idx, parent); + else break; + idx = parent; + } +} + +template <class AA, class Comparator> +void indexed_priority_queue<AA,Comparator>::sift_down(size_t idx) { + while (2*idx <= size()) { + size_t child = 2 * idx; + if (child < size() && higher(child+1, child)) child++; + if (higher(child, idx)) swap_indices(child, idx); + else break; + idx = child; + } +} + +template <class AA, class Comparator> +bool indexed_priority_queue<AA,Comparator>::higher(size_t idx1, size_t idx2) const { + if (!(0u < idx1 && idx1 < pq.size() && 0u < idx2 && idx2 < pq.size())) { + ALOGE("indexed_priority_queue: Attempting to access invalid index"); + return false; // got to do something. + } + return Comparator()(pq[idx1], pq[idx2]); +} + +template <class AA, class Comparator> +bool indexed_priority_queue<AA,Comparator>::contains(sp<const AA> a) const { + if (a == nullptr) return false; // publicly, we pretend that nullptr is not actually in pq. + return indices.count(a) > 0; +} + +template <class AA, class Comparator> +void indexed_priority_queue<AA,Comparator>::swap_indices(size_t i, size_t j) { + if (!(0u < i && i < pq.size() && 0u < j && j < pq.size())) { + ALOGE("indexed_priority_queue: Attempting to swap invalid index"); + return; + } + sp<const AA> val_i = pq[i]; + sp<const AA> val_j = pq[j]; + pq[i] = val_j; + pq[j] = val_i; + indices[val_i] = j; + indices[val_j] = i; +} + +} // namespace statsd + +#endif //STATSD_INDEXED_PRIORITY_QUEUE_H diff --git a/cmds/statsd/src/parse_util.cpp b/cmds/statsd/src/parse_util.cpp new file mode 100644 index 000000000000..9caeacf3b538 --- /dev/null +++ b/cmds/statsd/src/parse_util.cpp @@ -0,0 +1,113 @@ +/* + * 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 <parse_util.h> +#include <log/log_event_list.h> + +using android::os::statsd::EventMetricData; +using android::os::statsd::KeyId; +using android::os::statsd::KeyId_IsValid; +using android::os::statsd::KeyValuePair; +using android::os::statsd::TagId; +using android::os::statsd::TagId_IsValid; + +EventMetricData parse(log_msg msg) +{ + // dump all statsd logs to dropbox for now. + // TODO: Add filtering, aggregation, etc. + EventMetricData eventMetricData; + android_log_context context = create_android_log_parser(const_cast<log_msg*>(&msg)->msg() + + sizeof(uint32_t), + const_cast<log_msg*>(&msg)->len() + - sizeof(uint32_t)); + android_log_list_element elem; + + if (context) { + memset(&elem, 0, sizeof(elem)); + size_t index = 0; + int32_t key = -1; + int32_t tag = -1; + + do { + elem = android_log_read_next(context); + switch ((int)elem.type) { + case EVENT_TYPE_INT: + if (index == 0) { + tag = elem.data.int32; + if (TagId_IsValid(tag)) { + eventMetricData.set_tag(static_cast<TagId>(tag)); + } else { + break; + } + } else if (index % 2 == 1) { + key = elem.data.int32; + } else if (KeyId_IsValid(key)) { + int32_t val = elem.data.int32; + KeyValuePair *keyValuePair = eventMetricData.add_key_value_pair(); + keyValuePair->set_key(static_cast<KeyId>(key)); + keyValuePair->set_value_int(val); + } else { + } + index++; + break; + case EVENT_TYPE_FLOAT: + if (index % 2 == 0 && KeyId_IsValid(key)) { + float val = elem.data.float32; + KeyValuePair *keyValuePair = eventMetricData.add_key_value_pair(); + keyValuePair->set_key(static_cast<KeyId>(key)); + keyValuePair->set_value_float(val); + } + index++; + break; + case EVENT_TYPE_STRING: + if (index % 2 == 0 && KeyId_IsValid(key)) { + char* val = elem.data.string; + KeyValuePair *keyValuePair = eventMetricData.add_key_value_pair(); + keyValuePair->set_key(static_cast<KeyId>(key)); + keyValuePair->set_value_str(val); + } + index++; + break; + case EVENT_TYPE_LONG: + if (index % 2 == 0 && KeyId_IsValid(key)) { + int64_t val = elem.data.int64; + KeyValuePair *keyValuePair = eventMetricData.add_key_value_pair(); + keyValuePair->set_key(static_cast<KeyId>(key)); + keyValuePair->set_value_int(val); + } + index++; + break; + case EVENT_TYPE_LIST: + break; + case EVENT_TYPE_LIST_STOP: + break; + case EVENT_TYPE_UNKNOWN: + break; + default: + elem.complete = true; + break; + } + + if (elem.complete) { + break; + } + } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete); + + android_log_destroy(&context); + } + + return eventMetricData; +} diff --git a/cmds/statsd/src/parse_util.h b/cmds/statsd/src/parse_util.h new file mode 100644 index 000000000000..8750f822102d --- /dev/null +++ b/cmds/statsd/src/parse_util.h @@ -0,0 +1,28 @@ +/* + * 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. + */ +#ifndef PARSE_UTIL_H +#define PARSE_UTIL_H + +#include "LogReader.h" +#include "DropboxWriter.h" + +#include <log/logprint.h> + +using android::os::statsd::EventMetricData; + +EventMetricData parse(const log_msg msg); + +#endif // PARSE_UTIL_H diff --git a/cmds/statsd/src/stats_constants.proto b/cmds/statsd/src/stats_constants.proto index 1787ae3cba2e..3f8bd1c5a9fc 100644 --- a/cmds/statsd/src/stats_constants.proto +++ b/cmds/statsd/src/stats_constants.proto @@ -22,10 +22,17 @@ option optimize_for = LITE_RUNTIME; option java_package = "com.android.internal.logging"; option java_outer_classname = "StatsConstantsProto"; -message StatsConstants { - // Event type. - enum Type { - WAKELOCK = 1; - SCREEN= 2; - } +enum TagId { + WAKELOCK = 1; + SCREEN = 1003; +} + +enum KeyId { + STATE = 1; + ANOTHER_STATE = 2; + EVENT_TIMESTAMP = 1001; + PACKAGE_NAME = 1002; + PACKAGE_VERSION = 1003; + PACKAGE_VERSION_STRING = 1004; + ATTRIBUTION_CHAIN = 1005; } diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index ec92023c873a..2c66ded0c7ed 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -25,53 +25,53 @@ option java_outer_classname = "StatsLog"; import "frameworks/base/cmds/statsd/src/statsd_config.proto"; import "frameworks/base/cmds/statsd/src/stats_constants.proto"; -// StatsLogEntry is a generic proto holding a single metrics data. -message StatsLogEntry { - // Type of stats. - optional android.os.statsd.StatsConstants.Type type = 1; - - // Aggregation type of the data. - optional android.os.statsd.TrackedAggregateType aggregate_type = 2; - - // Start timestamp of the interval. Timestamp for event-type data will have - // equal value for start_report_millis and end_report_millis. - optional int64 start_report_millis = 3; - - // End timestamp of the interval. - optional int64 end_report_millis = 4; - - // Package information for application-level data. - optional string package_name = 5; - optional int32 package_version = 6; - optional string package_version_string = 7; - - // UID associated with the data. - optional int32 uid = 8; - - // PID associated with the data. - optional int32 pid = 9; - - // Payload contains key value pairs of the data from statsd. - message KeyValuePair { - // Integer representation of data type. - optional int32 key = 1; - - oneof value { - string value_str = 2; - int64 value_int = 3; - bool value_bool = 4; - } +message KeyValuePair { + optional KeyId key = 1; + + oneof value { + string value_str = 2; + int64 value_int = 3; + bool value_bool = 4; + float value_float = 5; } - repeated KeyValuePair pairs = 10; +} + +message EventMetricData { + optional TagId tag = 1; + + repeated KeyValuePair key_value_pair = 2; +} - // Next tag: 11 +message CountBucketInfo { + optional int64 start_bucket_millis = 1; + + optional int64 end_bucket_millis = 2; + + optional int64 count = 3; } -// Data captured for a given metric during a given period of time. -message StatsLogList { - // Unique ID for this metric. +message CountMetricData { + repeated KeyValuePair dimension = 1; + + repeated CountBucketInfo bucket_info = 2; +} + +message StatsLogReport { optional int32 metric_id = 1; - // List of stats log entry. - repeated StatsLogEntry stats_log_entry = 2; + optional int64 start_report_millis = 2; + + optional int64 end_report_millis = 3; + + message EventMetricDataWrapper { + repeated EventMetricData data = 1; + } + message CountMetricDataWrapper { + repeated CountMetricData data = 1; + } + + oneof data { + EventMetricDataWrapper event_metrics = 4; + CountMetricDataWrapper count_metrics = 5; + } } diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto index 2d034e50f4b5..c6119df691a3 100644 --- a/cmds/statsd/src/statsd_config.proto +++ b/cmds/statsd/src/statsd_config.proto @@ -1,40 +1,3 @@ -/* - * 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. - */ - - -// Version 1. -// Important: Update the version line above before copy-pasting this file -// from/to Google3 and Android repository. -// This proto needs to be manually synced between Google3 and Android versions. - -/* - * Note about semantics of the buckets: - * In this current proto scheme, the buckets are updated only when an event - * occurs. In the case of durations, this means that we update at the end of a - * duration. - * - * For example, suppose we have buckets at every 10 min: - * 0, 10, 20, 30, 40, etc. - * And then suppose a wakelock is first held starting at min 5 and lasts for 21 - * mins. Then the buckets for 0-10 and 10-20 don't contain anything and inside - * the bucket for 20-30, we add the value of 21 minutes. - * - * Also note that buckets are only aligned to wall-clock (no custom time-bases). - */ - syntax = "proto2"; package android.os.statsd; @@ -43,30 +6,21 @@ option optimize_for = LITE_RUNTIME; option java_package = "com.android.internal.os"; option java_outer_classname = "StatsdConfigProto"; -// KeyMatcher specifies how to match the key. -message KeyMatcher { - oneof contents { - int32 key = 1; // ID of the key to match. +import "frameworks/base/cmds/statsd/src/stats_constants.proto"; - // Special matcher for package name. This will match either the package name - // or the UID (statsD will map the UID of the source event to a package - // name). Specify the package name to match in eq_string. - bool use_package = 2; - } +message KeyMatcher { + optional KeyId key = 1; + optional bool as_package_name = 2 [ default = false ]; } -// FieldMatcher allows us to match specific fields/keys in an event. -message FieldMatcher { +message KeyValueMatcher { optional KeyMatcher key_matcher = 1; oneof value_matcher { - // Equality matchers bool eq_bool = 2; string eq_string = 3; int32 eq_int32 = 4; int64 eq_int64 = 5; - - // Numeric comparisons; int32 lt_int32 = 6; int32 gt_int32 = 7; int64 lt_int64 = 8; @@ -76,374 +30,90 @@ message FieldMatcher { } } -enum OperationType { +enum LogicalOperation { AND = 1; OR = 2; - NOT = 3; // Must have only a single operand when using NOT operator. - NAND = 4; // NAND and NOR as conveniences to avoid NOT+(AND/OR)-layers. + NOT = 3; + NAND = 4; NOR = 5; } -enum TrackedAggregateType { - // IS_RUNNING; // whether it is currently running - VALUE_COUNT = 1; // count number of events - VALUE_SUM = 2; - VALUE_MAX = 3; - VALUE_MIN = 4; - DURATION_SUM = 5; // cumulative total time - DURATION_MAX = 6; // longest continuously-on time - DURATION_MIN = 7; // shortest continuously-on time - //DURATION_CURRENT = 6; // current continuously-on time (not bucketed) +message SimpleLogEntryMatcher { + repeated TagId tag = 1; + + repeated KeyValueMatcher key_value_matcher = 2; } -// Assume the events come in with a tag and an array of (key, value) tuples -// where the key must be an int32 and value can be any type. -message LineMatcher { - // For now, we assume that we don't flatten the tags (ie, one tag corresponds - // to screen-on and screen-off events and key 1 represents ON or OFF). - repeated int32 tag = 1; // Must match at least one of the tags. +message LogEntryMatcher { + optional string name = 1; - message Nested { - optional OperationType operation = 1; - repeated LineMatcher matcher = 2; + message Combination { + optional LogicalOperation operation = 1; + repeated LogEntryMatcher matcher = 2; } oneof contents { - FieldMatcher requirement = 2; - Nested nested = 3; + SimpleLogEntryMatcher simple_log_entry_matcher = 2; + Combination combination = 3; } } -// Defines when an AggregateCounter or EventMatcher applies. +message SimpleCondition { + optional string start = 1; + + optional string stop = 2; + + optional bool count_nesting = 3 [default = true]; + + optional string stop_all = 4; +} + message Condition { - message Nested { - optional OperationType operation = 1; - repeated Condition nested_conditions = 2; // operands that are themselves - // conditions (recursively) - } + optional string name = 1; + + message Combination { + optional LogicalOperation operation = 1; - // Leaf node of condition. - message RangeMatcher { - optional LineMatcher start = 1; - optional LineMatcher stop = 2; - optional bool count_nesting = 3 - [default = true]; // true if "start start stop" is still - // considered running - - // Configure which fields define the slices. These fields must be present in - // both the start and stop lines. Note that this can be a subset of all the - // slices defined in the AggregateCounter. - // For example, if the counter slices on both app name and wake lock name, - // we can define that this range only slices on app name. - repeated KeyMatcher slice = 4; + repeated string condition = 2; } oneof contents { - RangeMatcher range = 1; // Represents a leaf node. - Nested nested = 2; // Represents a non-leaf node. + SimpleCondition simple_condition = 2; + Combination combination = 3; } } -// Emits matching events to statsd event buffer. -message EventMatcher { - // Tracks what configuration led to uploading of this event. - optional int32 metric_id = 1; +message Bucket { + optional int64 bucket_size_millis = 1; +} - // LineMatcher for the event to emit. - optional LineMatcher what = 2; +message EventMetric { + optional int64 metric_id = 1; - optional Condition condition = 3; + optional string what = 2; - // TODO: Have a clear use-case for this in P or-else drop this for P. - message Filter { - } - optional Filter filter = 4; + optional string condition = 3; } -// Hard-code the possible metrics that we can pull. -// For example, NETSTATS_BY_UID would provide network usage per uid. -// We should treat the results like a batch of individual log events, and we -// should process them one-by-one to re-use our LineMatcher logic. -enum PulledMetricSource { - NETSTATS = 1; -} +message CountMetric { + optional int64 metric_id = 1; -message AggregateCounter { // previously called Timer - // Specifies which fields in the message act as dimensions. - // For both pushed and pulled metrics, we assume every record has all the - // dimensions set. - message Slicer { - repeated KeyMatcher keys = 1; - } - optional Slicer slicer = 1; - - message ValueSource { - message PushedMetric { - // LineMatcher for the event to apply. - // Slicing (which keys act as dimensions) should not be specified here. - optional LineMatcher what = 1; - - // Only needed if one key should be treated as the value. - optional int32 value_key = 2; - } - - // The values for pulled metrics are computed and aggregated at the end of - // the condition. - message PulledMetric { - optional bool compute_diff = - 1; // If we want the diff (if this - // metric is pulled when condition opens/closes). - optional PulledMetricSource metric = 2; - - // We treat the pulled metrics as a batch of log-records that look like - // they came from LogD. - optional LineMatcher what = 3; - optional int32 value_field = 4; - } - - oneof value { - PushedMetric pushed_metric = 1; - - // Pulled metrics are computed when the duration closes (and are also - // fetched at the open if we need to compute a diff). - // Pulled metrics require a condition being defined. - // These metrics are not pulled at the end of every bucket. - PulledMetric pulled_metric = 2; - - // Polled Metrics are pulled at the end of every bucket. - // Since the buckets are only planned to be on wall-clock for Android P, - // condition is NOT supported for polled metrics. - PulledMetric polled_metric = 3; - } - } - optional ValueSource value = 2; - - message TrackedAggregate { - // Must be an integer that is uniquely chosen so we can identify the metric - // on server. We will provide a tool on server to help generate this. - optional int32 metric_id = 1; - - optional TrackedAggregateType type = 2; - - // Alert if the value, when summed over the Counter's number_of_buckets - // most-recent bins, exceeds min_threshold or is below max_threshold. For - // Anomaly Detection. - message Alert { - message IncidentdDetails { - optional string - alert_name = 1; // for humans and incidentd to identify this issue - repeated int32 incidentd_sections = 2; // tells incidentd what to do if - // alert triggers - } - optional IncidentdDetails incidentd_details = 1; - optional int32 number_of_buckets = 2; - // NOTE: that we assume the aggregate is only int. - optional int64 trigger_if_gt = 3; // min threshold - optional int64 trigger_if_lt = 4; // max_threshold; - optional int32 refractory_period_secs = 5; // alarm cannot fire a second - // time until elapsed - } - repeated Alert alerts = 3; // Support diff alert params for same aggregate. - } // end TrackedAggregate - repeated TrackedAggregate tracked_aggregates = 3; - - optional Condition condition = 4; - - message Bucket { - // TODO: Consider switching to second granularity. - // In practice, this must be chosen from a pre-defined list. So that we have - // flexiblity, we don't hard-code this as an enum today. - optional int64 bucket_size_msec = 1; - optional int32 max_number_of_bits = 2; // Max bits per bucket. - } - optional Bucket bucket = 5; + optional string what = 2; - message MiscellaneousEffect { - optional LineMatcher matcher = 1; // When to trigger the effect - - enum Effect { - STOP_ALL = 1; // Needed for stop-all events, where nested start value is - // forced to 0. - } - repeated Effect effects = 2; - } // end MiscellaneousEffect - repeated MiscellaneousEffect misc_effects = 6; -} // end Counter - -// Alarm configs not tied to a particular Counter. -message GlobalAlertParameters { - // No alarm can fire after any other alarm fired until this many seconds has - // elapsed. - optional int32 global_refractory_period_seconds = 1; + optional string condition = 3; + + repeated KeyMatcher dimension = 4; + + optional Bucket bucket = 5; } -// The config defining all metrics to be captured. message StatsdConfig { - // Event matchers. - repeated EventMatcher event_matchers = 1; + optional int64 config_id = 1; - // Aggregate counters. - repeated AggregateCounter aggregate_counters = 2; -} + repeated EventMetric event_metric = 2; -/* Sample configurations start here: -----Screen on time---- -AggregateCounter < - condition < - range < - start < - tag: SCREEN_ON - requirement < - key_matcher< - key: SCREEN_ON_VALUE - eq_bool: true - stop < - tag: SCREEN_ON - requirement < - key_matcher< - key: SCREEN_ON_VALUE - eq_bool: false - metric_id: # set on server - tracked_aggregates < - DURATION_SUM - (For brevity, omit the bucket options but they can also be set) - -----Screen off time---- -Should be like aboe but reversing start and stop - -----Log the screen change events---- -EventMatcher < - metric_id: # set on server - what < - tag: SCREEN_ON - -----Number of crashes (across system)---- -AggregateCounter < - metric_id: # set on server - tracked_aggregates < - VALUE_COUNT - value < - pushed_metric < - what < - tag: CRASH_TAG - -----Network Usage in bytes Per App While in Background---- -AggregateCounter < - metric_id: # set on server - slicer < - keys < - use_package_name: true - tracked_aggregates < - VALUE_SUM - value < - pulled_metric < - compute_diff: true - metric: Enum corresponding to network usage in bytes - condition < - range < - sliced: true - start < - tag: APP_FOREGROUND_TRANSITION (assume false means move to background) - requirement < - key_matcher< - key: APP_FOREGROUND_STATE - eq_bool: false - stop < - tag: APP_FOREGROUND_TRANSITION (assume false means move to background) - requirement < - key_matcher< - key: APP_FOREGROUND_STATE - eq_bool: true - -----Wakelock Acquire time per app and wakelock - while unplugged and screen off and in background process state---- -AggregateCounter < - metric_id: # set on server - slicer < - keys < - use_package_name: true - keys < - key: Key corresponding to wake_lock ID - tracked_aggregates < - DURATION_SUM - condition < - nested < - operation: AND - nested_conditions < - range < - start < - tag: PLUGGED_IN (assume false means uncharged) - requirement < - key_matcher< - key: PLUGGED_IN_STATE - eq_bool: false - stop < - tag: PLUGGED_IN (assume false means uncharged) - requirement < - key_matcher< - key: PLUGGED_IN_STATE - eq_bool: true - nested_conditions < - range < - start < - tag: SCREEN_ON - requirement < - key_matcher< - key: SCREEN_ON_STATE - eq_bool: false - stop < - tag: SCREEN_ON - requirement < - key_matcher< - key: SCREEN_ON_STATE - eq_bool: true - nested_conditions < - range < - start < - tag: PROCESS_CHANGE - requirement < - key_matcher< - key: PROCESS_STATE_VALUE - eq_int32: BACKGROUND_PROCESS - stop < - tag: PROCESS_CHANGE - nested < - operation: NOT - matcher< (This is an example of using the NOT to define stop) - requirement < (Note this requirement should match the start.) - key_matcher< - key: PROCESS_STATE_VALUE - eq_int32: BACKGROUND_PROCESS - slice< - use_package_name: true - - -----Number of crashes (per app) ---- -AggregateCounter < - metric_id: # set on server - slicer < - keys< - use_package_name: true - tracked_aggregates < - VALUE_COUNT - value < - pushed_metric < - what < - tag: CRASH_TAG - ----- Number of transitions to background (per app) ---- -AggregateCounter < - metric_id: # set on server - slicer < - keys< - use_package_name: true - tracked_aggregates < - VALUE_COUNT - value < - pushed_metric < - what < - tag: APP_FOREGROUND_TRANSITION - requirement< - key: APP_FOREGROUND_TRANSITION_STATE - eq_bool: false - -*/ + repeated CountMetric count_metric = 3; + + repeated LogEntryMatcher log_entry_matcher = 4; + + repeated Condition condition = 5; +} diff --git a/cmds/statsd/tests/indexed_priority_queue_test.cpp b/cmds/statsd/tests/indexed_priority_queue_test.cpp new file mode 100644 index 000000000000..a679128dd37e --- /dev/null +++ b/cmds/statsd/tests/indexed_priority_queue_test.cpp @@ -0,0 +1,188 @@ +/* + * 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 "../src/indexed_priority_queue.h" + +#include <gtest/gtest.h> + +using namespace statsd; + +/** struct for template in indexed_priority_queue */ +struct AATest : public RefBase { + AATest(uint32_t val) : val(val) { + } + + const int val; + + struct Smaller { + bool operator()(const sp<const AATest> a, const sp<const AATest> b) const { + return (a->val < b->val); + } + }; +}; + +#ifdef __ANDROID__ +TEST(indexed_priority_queue, empty_and_size) { + indexed_priority_queue<AATest, AATest::Smaller> ipq; + sp<const AATest> aa4 = new AATest{4}; + sp<const AATest> aa8 = new AATest{8}; + + EXPECT_EQ(0u, ipq.size()); + EXPECT_TRUE(ipq.empty()); + + ipq.push(aa4); + EXPECT_EQ(1u, ipq.size()); + EXPECT_FALSE(ipq.empty()); + + ipq.push(aa8); + EXPECT_EQ(2u, ipq.size()); + EXPECT_FALSE(ipq.empty()); + + ipq.remove(aa4); + EXPECT_EQ(1u, ipq.size()); + EXPECT_FALSE(ipq.empty()); + + ipq.remove(aa8); + EXPECT_EQ(0u, ipq.size()); + EXPECT_TRUE(ipq.empty()); +} + +TEST(indexed_priority_queue, top) { + indexed_priority_queue<AATest, AATest::Smaller> ipq; + sp<const AATest> aa2 = new AATest{2}; + sp<const AATest> aa4 = new AATest{4}; + sp<const AATest> aa8 = new AATest{8}; + sp<const AATest> aa12 = new AATest{12}; + sp<const AATest> aa16 = new AATest{16}; + sp<const AATest> aa20 = new AATest{20}; + + EXPECT_EQ(ipq.top(), nullptr); + + // add 8, 4, 12 + ipq.push(aa8); + EXPECT_EQ(ipq.top(), aa8); + + ipq.push(aa12); + EXPECT_EQ(ipq.top(), aa8); + + ipq.push(aa4); + EXPECT_EQ(ipq.top(), aa4); + + // remove 12, 4 + ipq.remove(aa12); + EXPECT_EQ(ipq.top(), aa4); + + ipq.remove(aa4); + EXPECT_EQ(ipq.top(), aa8); + + // add 16, 2, 20 + ipq.push(aa16); + EXPECT_EQ(ipq.top(), aa8); + + ipq.push(aa2); + EXPECT_EQ(ipq.top(), aa2); + + ipq.push(aa20); + EXPECT_EQ(ipq.top(), aa2); + + // remove 2, 20, 16, 8 + ipq.remove(aa2); + EXPECT_EQ(ipq.top(), aa8); + + ipq.remove(aa20); + EXPECT_EQ(ipq.top(), aa8); + + ipq.remove(aa16); + EXPECT_EQ(ipq.top(), aa8); + + ipq.remove(aa8); + EXPECT_EQ(ipq.top(), nullptr); +} + +TEST(indexed_priority_queue, push_same_aa) { + indexed_priority_queue<AATest, AATest::Smaller> ipq; + sp<const AATest> aa4_a = new AATest{4}; + sp<const AATest> aa4_b = new AATest{4}; + + ipq.push(aa4_a); + EXPECT_EQ(1u, ipq.size()); + EXPECT_TRUE(ipq.contains(aa4_a)); + EXPECT_FALSE(ipq.contains(aa4_b)); + + ipq.push(aa4_a); + EXPECT_EQ(1u, ipq.size()); + EXPECT_TRUE(ipq.contains(aa4_a)); + EXPECT_FALSE(ipq.contains(aa4_b)); + + ipq.push(aa4_b); + EXPECT_EQ(2u, ipq.size()); + EXPECT_TRUE(ipq.contains(aa4_a)); + EXPECT_TRUE(ipq.contains(aa4_b)); +} + + +TEST(indexed_priority_queue, remove_nonexistant) { + indexed_priority_queue<AATest, AATest::Smaller> ipq; + sp<const AATest> aa4 = new AATest{4}; + sp<const AATest> aa5 = new AATest{5}; + + ipq.push(aa4); + ipq.remove(aa5); + EXPECT_EQ(1u, ipq.size()); + EXPECT_TRUE(ipq.contains(aa4)); + EXPECT_FALSE(ipq.contains(aa5)); +} + +TEST(indexed_priority_queue, remove_same_aa) { + indexed_priority_queue<AATest, AATest::Smaller> ipq; + sp<const AATest> aa4_a = new AATest{4}; + sp<const AATest> aa4_b = new AATest{4}; + + ipq.push(aa4_a); + ipq.push(aa4_b); + EXPECT_EQ(2u, ipq.size()); + EXPECT_TRUE(ipq.contains(aa4_a)); + EXPECT_TRUE(ipq.contains(aa4_b)); + + ipq.remove(aa4_b); + EXPECT_EQ(1u, ipq.size()); + EXPECT_TRUE(ipq.contains(aa4_a)); + EXPECT_FALSE(ipq.contains(aa4_b)); + + ipq.remove(aa4_a); + EXPECT_EQ(0u, ipq.size()); + EXPECT_FALSE(ipq.contains(aa4_a)); + EXPECT_FALSE(ipq.contains(aa4_b)); +} + +TEST(indexed_priority_queue, nulls) { + indexed_priority_queue<AATest, AATest::Smaller> ipq; + + EXPECT_TRUE(ipq.empty()); + EXPECT_FALSE(ipq.contains(nullptr)); + + ipq.push(nullptr); + EXPECT_TRUE(ipq.empty()); + EXPECT_FALSE(ipq.contains(nullptr)); + + ipq.remove(nullptr); + EXPECT_TRUE(ipq.empty()); + EXPECT_FALSE(ipq.contains(nullptr)); +} + +#else +GTEST_LOG_(INFO) << "This test does nothing.\n"; +#endif diff --git a/config/compiled-classes-phone b/config/compiled-classes-phone index c8297286b784..c1cbb648aae6 100644 --- a/config/compiled-classes-phone +++ b/config/compiled-classes-phone @@ -5243,7 +5243,6 @@ com.android.internal.app.IVoiceInteractor com.android.internal.app.IVoiceInteractor$Stub com.android.internal.app.NightDisplayController com.android.internal.app.NightDisplayController$Callback -com.android.internal.app.NightDisplayController$LocalTime com.android.internal.app.ProcessMap com.android.internal.app.ResolverActivity com.android.internal.app.ToolbarActionBar diff --git a/config/preloaded-classes b/config/preloaded-classes index cd2965392c44..2844efb302de 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -1848,6 +1848,7 @@ android.os.SharedMemory android.os.ShellCallback android.os.StatFs android.os.StrictMode +android.os.StrictMode$$Lambda$0 android.os.StrictMode$1 android.os.StrictMode$2 android.os.StrictMode$3 @@ -1872,6 +1873,7 @@ android.os.StrictMode$ThreadPolicy$Builder android.os.StrictMode$ThreadSpanState android.os.StrictMode$ViolationInfo android.os.StrictMode$ViolationInfo$1 +android.os.StrictMode$ViolationLogger android.os.StrictMode$VmPolicy android.os.StrictMode$VmPolicy$Builder android.os.SystemClock @@ -2784,7 +2786,6 @@ com.android.internal.app.IVoiceInteractionManagerService$Stub com.android.internal.app.IVoiceInteractor com.android.internal.app.IVoiceInteractor$Stub com.android.internal.app.NightDisplayController -com.android.internal.app.NightDisplayController$1 com.android.internal.appwidget.IAppWidgetService com.android.internal.appwidget.IAppWidgetService$Stub com.android.internal.appwidget.IAppWidgetService$Stub$Proxy diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java index bf9bd79e63ef..a3b3a9f21954 100644 --- a/core/java/android/accounts/AbstractAccountAuthenticator.java +++ b/core/java/android/accounts/AbstractAccountAuthenticator.java @@ -175,6 +175,9 @@ public abstract class AbstractAccountAuthenticator { } if (result != null) { response.onResult(result); + } else { + response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, + "null bundle returned"); } } catch (Exception e) { handleException(response, "addAccount", accountType, e); diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index dd6ad55fba6d..bd9c9fa30536 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -2321,6 +2321,10 @@ public class AccountManager { private class Response extends IAccountManagerResponse.Stub { @Override public void onResult(Bundle bundle) { + if (bundle == null) { + onError(ERROR_CODE_INVALID_RESPONSE, "null bundle returned"); + return; + } Intent intent = bundle.getParcelable(KEY_INTENT); if (intent != null && mActivity != null) { // since the user provided an Activity we will silently start intents diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index a8665037f8d3..78d05f5123c8 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -770,21 +770,6 @@ public class ActivityManager { } /** - * Returns true if animation specs should be constructed for app transition that moves - * the task to the specified stack. - * @hide - */ - public static boolean useAnimationSpecForAppTransition(int stackId) { - // TODO: INVALID_STACK_ID is also animated because we don't persist stack id's across - // reboots. - return stackId == FREEFORM_WORKSPACE_STACK_ID - || stackId == FULLSCREEN_WORKSPACE_STACK_ID - || stackId == ASSISTANT_STACK_ID - || stackId == DOCKED_STACK_ID - || stackId == INVALID_STACK_ID; - } - - /** * Returns true if activities from stasks in the given {@param stackId} are allowed to * enter picture-in-picture. * @hide @@ -885,6 +870,18 @@ public class ActivityManager { return windowingMode; } + /** Returns the stack id for the input windowing mode. + * @hide */ + // TODO: To be removed once we are not using stack id for stuff... + public static int getStackIdForWindowingMode(int windowingMode) { + switch (windowingMode) { + case WINDOWING_MODE_PINNED: return PINNED_STACK_ID; + case WINDOWING_MODE_FREEFORM: return FREEFORM_WORKSPACE_STACK_ID; + case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return DOCKED_STACK_ID; + default: return INVALID_STACK_ID; + } + } + /** Returns the activity type that should be used for this input stack id. * @hide */ // TODO: To be removed once we are not using stack id for stuff... @@ -905,6 +902,18 @@ public class ActivityManager { } return activityType; } + + /** Returns the stack id for the input activity type. + * @hide */ + // TODO: To be removed once we are not using stack id for stuff... + public static int getStackIdForActivityType(int activityType) { + switch (activityType) { + case ACTIVITY_TYPE_HOME: return HOME_STACK_ID; + case ACTIVITY_TYPE_RECENTS: return RECENTS_STACK_ID; + case ACTIVITY_TYPE_ASSISTANT: return ASSISTANT_STACK_ID; + default: return INVALID_STACK_ID; + } + } } /** diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 0bffc9e6cee5..a68c3a5c29a6 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -18,6 +18,8 @@ package android.app; import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; import android.annotation.Nullable; @@ -164,10 +166,16 @@ public class ActivityOptions { private static final String KEY_LAUNCH_DISPLAY_ID = "android.activity.launchDisplayId"; /** - * The stack id the activity should be launched into. + * The windowing mode the activity should be launched into. * @hide */ - private static final String KEY_LAUNCH_STACK_ID = "android.activity.launchStackId"; + private static final String KEY_LAUNCH_WINDOWING_MODE = "android.activity.windowingMode"; + + /** + * The activity type the activity should be launched as. + * @hide + */ + private static final String KEY_LAUNCH_ACTIVITY_TYPE = "android.activity.activityType"; /** * The task id the activity should be launched into. @@ -272,7 +280,10 @@ public class ActivityOptions { private int mExitCoordinatorIndex; private PendingIntent mUsageTimeReport; private int mLaunchDisplayId = INVALID_DISPLAY; - private int mLaunchStackId = INVALID_STACK_ID; + @WindowConfiguration.WindowingMode + private int mLaunchWindowingMode = WINDOWING_MODE_UNDEFINED; + @WindowConfiguration.ActivityType + private int mLaunchActivityType = ACTIVITY_TYPE_UNDEFINED; private int mLaunchTaskId = -1; private int mDockCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; private boolean mDisallowEnterPictureInPictureWhileLaunching; @@ -860,7 +871,8 @@ public class ActivityOptions { break; } mLaunchDisplayId = opts.getInt(KEY_LAUNCH_DISPLAY_ID, INVALID_DISPLAY); - mLaunchStackId = opts.getInt(KEY_LAUNCH_STACK_ID, INVALID_STACK_ID); + mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED); + mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED); mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1); mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false); mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false); @@ -1070,14 +1082,34 @@ public class ActivityOptions { } /** @hide */ - public int getLaunchStackId() { - return mLaunchStackId; + public int getLaunchWindowingMode() { + return mLaunchWindowingMode; + } + + /** + * Sets the windowing mode the activity should launch into. If the input windowing mode is + * {@link android.app.WindowConfiguration#WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} and the device + * isn't currently in split-screen windowing mode, then the activity will be launched in + * {@link android.app.WindowConfiguration#WINDOWING_MODE_FULLSCREEN} windowing mode. For clarity + * on this you can use + * {@link android.app.WindowConfiguration#WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY} + * + * @hide + */ + @TestApi + public void setLaunchWindowingMode(int windowingMode) { + mLaunchWindowingMode = windowingMode; + } + + /** @hide */ + public int getLaunchActivityType() { + return mLaunchActivityType; } /** @hide */ @TestApi - public void setLaunchStackId(int launchStackId) { - mLaunchStackId = launchStackId; + public void setLaunchActivityType(int activityType) { + mLaunchActivityType = activityType; } /** @@ -1291,7 +1323,8 @@ public class ActivityOptions { break; } b.putInt(KEY_LAUNCH_DISPLAY_ID, mLaunchDisplayId); - b.putInt(KEY_LAUNCH_STACK_ID, mLaunchStackId); + b.putInt(KEY_LAUNCH_WINDOWING_MODE, mLaunchWindowingMode); + b.putInt(KEY_LAUNCH_ACTIVITY_TYPE, mLaunchActivityType); b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId); b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay); b.putBoolean(KEY_TASK_OVERLAY_CAN_RESUME, mTaskOverlayCanResume); diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 0ceb28841e40..eccb264796f8 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -307,7 +307,15 @@ interface IActivityManager { boolean shouldUpRecreateTask(in IBinder token, in String destAffinity); boolean navigateUpTo(in IBinder token, in Intent target, int resultCode, in Intent resultData); - void setLockScreenShown(boolean showing); + /** + * Informs ActivityManagerService that the keyguard is showing. + * + * @param showing True if the keyguard is showing, false otherwise. + * @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard + * is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if + * showing is true. + */ + void setLockScreenShown(boolean showing, int secondaryDisplayShowing); boolean finishActivityAffinity(in IBinder token); // This is not public because you need to be very careful in how you // manage your activity to make sure it is always the uid you expect. @@ -545,11 +553,6 @@ interface IActivityManager { */ void resizePinnedStack(in Rect pinnedBounds, in Rect tempPinnedTaskBounds); boolean isVrModePackageEnabled(in ComponentName packageName); - /** - * Moves all tasks from the docked stack in the fullscreen stack and puts the top task of the - * fullscreen stack into the docked stack. - */ - void swapDockedAndFullscreenStack(); void notifyLockedProfile(int userId); void startConfirmDeviceCredentialIntent(in Intent intent, in Bundle options); void sendIdleJobTrigger(); diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java index 363e20a76a1f..578623892a9d 100644 --- a/core/java/android/app/VrManager.java +++ b/core/java/android/app/VrManager.java @@ -62,7 +62,10 @@ public class VrManager { * @param callback The callback to register. * @hide */ - @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) + @RequiresPermission(anyOf = { + android.Manifest.permission.RESTRICTED_VR_ACCESS, + android.Manifest.permission.ACCESS_VR_STATE + }) public void registerVrStateCallback(VrStateCallback callback, @NonNull Handler handler) { if (callback == null || mCallbackMap.containsKey(callback)) { return; @@ -88,7 +91,10 @@ public class VrManager { * @param callback The callback to deregister. * @hide */ - @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) + @RequiresPermission(anyOf = { + android.Manifest.permission.RESTRICTED_VR_ACCESS, + android.Manifest.permission.ACCESS_VR_STATE + }) public void unregisterVrStateCallback(VrStateCallback callback) { CallbackEntry entry = mCallbackMap.remove(callback); if (entry != null) { @@ -110,7 +116,10 @@ public class VrManager { * Returns the current VrMode state. * @hide */ - @RequiresPermission(android.Manifest.permission.ACCESS_VR_STATE) + @RequiresPermission(anyOf = { + android.Manifest.permission.RESTRICTED_VR_ACCESS, + android.Manifest.permission.ACCESS_VR_STATE + }) public boolean getVrModeEnabled() { try { return mService.getVrModeState(); @@ -124,7 +133,10 @@ public class VrManager { * Returns the current VrMode state. * @hide */ - @RequiresPermission(android.Manifest.permission.ACCESS_VR_STATE) + @RequiresPermission(anyOf = { + android.Manifest.permission.RESTRICTED_VR_ACCESS, + android.Manifest.permission.ACCESS_VR_STATE + }) public boolean getPersistentVrModeEnabled() { try { return mService.getPersistentVrModeEnabled(); diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java index 07eb5de15d9f..0cb38046826f 100644 --- a/core/java/android/app/WindowConfiguration.java +++ b/core/java/android/app/WindowConfiguration.java @@ -63,8 +63,21 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu /** * The containers adjacent to the {@link #WINDOWING_MODE_SPLIT_SCREEN_PRIMARY} container in * split-screen mode. + * NOTE: Containers launched with the windowing mode with APIs like + * {@link ActivityOptions#setLaunchWindowingMode(int)} will be launched in + * {@link #WINDOWING_MODE_FULLSCREEN} if the display isn't currently in split-screen windowing + * mode + * @see #WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY */ public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4; + /** + * Alias for {@link #WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} that makes it clear that the usage + * points for APIs like {@link ActivityOptions#setLaunchWindowingMode(int)} that the container + * will launch into fullscreen or split-screen secondary depending on if the device is currently + * in fullscreen mode or split-screen mode. + */ + public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY = + WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; /** Can be freely resized within its parent container. */ public static final int WINDOWING_MODE_FREEFORM = 5; @@ -75,6 +88,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu WINDOWING_MODE_PINNED, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, + WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, WINDOWING_MODE_FREEFORM, }) public @interface WindowingMode {} diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 2d8249acb5bf..03e4dfe829de 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2991,6 +2991,7 @@ public abstract class Context { //@hide: CONTEXTHUB_SERVICE, SYSTEM_HEALTH_SERVICE, //@hide: INCIDENT_SERVICE, + //@hide: STATS_COMPANION_SERVICE, COMPANION_DEVICE_SERVICE }) @Retention(RetentionPolicy.SOURCE) @@ -4020,6 +4021,12 @@ public abstract class Context { public static final String INCIDENT_SERVICE = "incident"; /** + * Service to assist statsd in obtaining general stats. + * @hide + */ + public static final String STATS_COMPANION_SERVICE = "statscompanion"; + + /** * Use with {@link #getSystemService} to retrieve a {@link * android.content.om.OverlayManager} for managing overlay packages. * diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 08acfb651b18..c238ffbbaf4d 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -10071,6 +10071,27 @@ public class Intent implements Parcelable, Cloneable { return false; } + /** + * Convert the dock state to a human readable format. + * @hide + */ + public static String dockStateToString(int dock) { + switch (dock) { + case EXTRA_DOCK_STATE_HE_DESK: + return "EXTRA_DOCK_STATE_HE_DESK"; + case EXTRA_DOCK_STATE_LE_DESK: + return "EXTRA_DOCK_STATE_LE_DESK"; + case EXTRA_DOCK_STATE_CAR: + return "EXTRA_DOCK_STATE_CAR"; + case EXTRA_DOCK_STATE_DESK: + return "EXTRA_DOCK_STATE_DESK"; + case EXTRA_DOCK_STATE_UNDOCKED: + return "EXTRA_DOCK_STATE_UNDOCKED"; + default: + return Integer.toString(dock); + } + } + private static ClipData.Item makeClipItem(ArrayList<Uri> streams, ArrayList<CharSequence> texts, ArrayList<String> htmlTexts, int which) { Uri uri = streams != null ? streams.get(which) : null; diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 48587b3630d9..486ff43a6467 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -34,8 +34,7 @@ import java.lang.annotation.RetentionPolicy; * from the AndroidManifest.xml's <activity> and * <receiver> tags. */ -public class ActivityInfo extends ComponentInfo - implements Parcelable { +public class ActivityInfo extends ComponentInfo implements Parcelable { // NOTE: When adding new data members be sure to update the copy-constructor, Parcel // constructor, and writeToParcel. @@ -1211,6 +1210,51 @@ public class ActivityInfo extends ComponentInfo return isFloating || isTranslucent || isSwipeToDismiss; } + /** + * Convert the screen orientation constant to a human readable format. + * @hide + */ + public static String screenOrientationToString(int orientation) { + switch(orientation) { + case SCREEN_ORIENTATION_UNSET: + return "SCREEN_ORIENTATION_UNSET"; + case SCREEN_ORIENTATION_UNSPECIFIED: + return "SCREEN_ORIENTATION_UNSPECIFIED"; + case SCREEN_ORIENTATION_LANDSCAPE: + return "SCREEN_ORIENTATION_LANDSCAPE"; + case SCREEN_ORIENTATION_PORTRAIT: + return "SCREEN_ORIENTATION_PORTRAIT"; + case SCREEN_ORIENTATION_USER: + return "SCREEN_ORIENTATION_USER"; + case SCREEN_ORIENTATION_BEHIND: + return "SCREEN_ORIENTATION_BEHIND"; + case SCREEN_ORIENTATION_SENSOR: + return "SCREEN_ORIENTATION_SENSOR"; + case SCREEN_ORIENTATION_NOSENSOR: + return "SCREEN_ORIENTATION_NOSENSOR"; + case SCREEN_ORIENTATION_SENSOR_LANDSCAPE: + return "SCREEN_ORIENTATION_SENSOR_LANDSCAPE"; + case SCREEN_ORIENTATION_SENSOR_PORTRAIT: + return "SCREEN_ORIENTATION_SENSOR_PORTRAIT"; + case SCREEN_ORIENTATION_REVERSE_LANDSCAPE: + return "SCREEN_ORIENTATION_REVERSE_LANDSCAPE"; + case SCREEN_ORIENTATION_REVERSE_PORTRAIT: + return "SCREEN_ORIENTATION_REVERSE_PORTRAIT"; + case SCREEN_ORIENTATION_FULL_SENSOR: + return "SCREEN_ORIENTATION_FULL_SENSOR"; + case SCREEN_ORIENTATION_USER_LANDSCAPE: + return "SCREEN_ORIENTATION_USER_LANDSCAPE"; + case SCREEN_ORIENTATION_USER_PORTRAIT: + return "SCREEN_ORIENTATION_USER_PORTRAIT"; + case SCREEN_ORIENTATION_FULL_USER: + return "SCREEN_ORIENTATION_FULL_USER"; + case SCREEN_ORIENTATION_LOCKED: + return "SCREEN_ORIENTATION_LOCKED"; + default: + return Integer.toString(orientation); + } + } + public static final Parcelable.Creator<ActivityInfo> CREATOR = new Parcelable.Creator<ActivityInfo>() { public ActivityInfo createFromParcel(Parcel source) { diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 1310e30300e2..dfd3bbf04d35 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -1089,6 +1089,33 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** + * Convert the UI mode to a human readable format. + * @hide + */ + public static String uiModeToString(int uiMode) { + switch (uiMode) { + case UI_MODE_TYPE_UNDEFINED: + return "UI_MODE_TYPE_UNDEFINED"; + case UI_MODE_TYPE_NORMAL: + return "UI_MODE_TYPE_NORMAL"; + case UI_MODE_TYPE_DESK: + return "UI_MODE_TYPE_DESK"; + case UI_MODE_TYPE_CAR: + return "UI_MODE_TYPE_CAR"; + case UI_MODE_TYPE_TELEVISION: + return "UI_MODE_TYPE_TELEVISION"; + case UI_MODE_TYPE_APPLIANCE: + return "UI_MODE_TYPE_APPLIANCE"; + case UI_MODE_TYPE_WATCH: + return "UI_MODE_TYPE_WATCH"; + case UI_MODE_TYPE_VR_HEADSET: + return "UI_MODE_TYPE_VR_HEADSET"; + default: + return Integer.toString(uiMode); + } + } + + /** * Set this object to the system defaults. */ public void setToDefaults() { diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java index ac6d83f622b2..26238304d8e9 100644 --- a/core/java/android/hardware/location/NanoAppInstanceInfo.java +++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java @@ -287,8 +287,10 @@ public class NanoAppInstanceInfo { mPublisher = in.readString(); mName = in.readString(); + mHandle = in.readInt(); mAppId = in.readLong(); mAppVersion = in.readInt(); + mContexthubId = in.readInt(); mNeededReadMemBytes = in.readInt(); mNeededWriteMemBytes = in.readInt(); mNeededExecMemBytes = in.readInt(); @@ -309,6 +311,8 @@ public class NanoAppInstanceInfo { public void writeToParcel(Parcel out, int flags) { out.writeString(mPublisher); out.writeString(mName); + + out.writeInt(mHandle); out.writeLong(mAppId); out.writeInt(mAppVersion); out.writeInt(mContexthubId); diff --git a/core/java/android/net/metrics/WakeupStats.java b/core/java/android/net/metrics/WakeupStats.java index d520b9745918..97e83f969c38 100644 --- a/core/java/android/net/metrics/WakeupStats.java +++ b/core/java/android/net/metrics/WakeupStats.java @@ -35,7 +35,7 @@ public class WakeupStats { public long systemWakeups = 0; public long nonApplicationWakeups = 0; public long applicationWakeups = 0; - public long unroutedWakeups = 0; + public long noUidWakeups = 0; public long durationSec = 0; public WakeupStats(String iface) { @@ -58,7 +58,7 @@ public class WakeupStats { systemWakeups++; break; case NO_UID: - unroutedWakeups++; + noUidWakeups++; break; default: if (ev.uid >= Process.FIRST_APPLICATION_UID) { @@ -80,7 +80,7 @@ public class WakeupStats { .append(", system: ").append(systemWakeups) .append(", apps: ").append(applicationWakeups) .append(", non-apps: ").append(nonApplicationWakeups) - .append(", unrouted: ").append(unroutedWakeups) + .append(", no uid: ").append(noUidWakeups) .append(", ").append(durationSec).append("s)") .toString(); } diff --git a/core/java/android/os/IStatsCompanionService.aidl b/core/java/android/os/IStatsCompanionService.aidl new file mode 100644 index 000000000000..a29e375bcfbd --- /dev/null +++ b/core/java/android/os/IStatsCompanionService.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +/** + * Binder interface to communicate with the Java-based statistics service helper. + * {@hide} + */ +interface IStatsCompanionService { + /** + * Register an alarm for anomaly detection to fire at the given timestamp (ms since epoch). + * If anomaly alarm had already been registered, it will be replaced with the new timestamp. + * Uses AlarmManager.set API, so if the timestamp is in the past, alarm fires immediately, and + * alarm is inexact. + */ + void setAnomalyAlarm(long timestampMs); + /** Cancel any anomaly detection alarm. */ + void cancelAnomalyAlarm(); + + /** + * Register a repeating alarm for polling to fire at the given timestamp and every + * intervalMs thereafter (in ms since epoch). + * If polling alarm had already been registered, it will be replaced by new one. + * Uses AlarmManager.setRepeating API, so if the timestamp is in past, alarm fires immediately, + * and alarm is inexact. + */ + void setPollingAlarms(long timestampMs, long intervalMs); + /** Cancel any repeating polling alarm. */ + void cancelPollingAlarms(); +} diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index f02631c7fe61..2528439a5e1f 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -16,6 +16,7 @@ package android.os; import android.animation.ValueAnimator; +import android.annotation.Nullable; import android.annotation.TestApi; import android.app.ActivityManager; import android.app.ActivityThread; @@ -322,16 +323,36 @@ public final class StrictMode { /** {@hide} */ @TestApi - public interface ViolationListener { - public void onViolation(String message); + public interface ViolationLogger { + + /** Called when penaltyLog is enabled and a violation needs logging. */ + void log(ViolationInfo info); } - private static volatile ViolationListener sListener; + private static final ViolationLogger LOGCAT_LOGGER = + info -> { + String msg; + if (info.durationMillis != -1) { + msg = "StrictMode policy violation; ~duration=" + info.durationMillis + " ms:"; + } else { + msg = "StrictMode policy violation:"; + } + if (info.crashInfo != null) { + Log.d(TAG, msg + " " + info.crashInfo.stackTrace); + } else { + Log.d(TAG, msg + " missing stack trace!"); + } + }; + + private static volatile ViolationLogger sLogger = LOGCAT_LOGGER; /** {@hide} */ @TestApi - public static void setViolationListener(ViolationListener listener) { - sListener = listener; + public static void setViolationLogger(ViolationLogger listener) { + if (listener == null) { + listener = LOGCAT_LOGGER; + } + sLogger = listener; } /** @@ -1512,28 +1533,16 @@ public final class StrictMode { lastViolationTime = vtime; } } else { - mLastViolationTime = new ArrayMap<Integer, Long>(1); + mLastViolationTime = new ArrayMap<>(1); } long now = SystemClock.uptimeMillis(); mLastViolationTime.put(crashFingerprint, now); long timeSinceLastViolationMillis = lastViolationTime == 0 ? Long.MAX_VALUE : (now - lastViolationTime); - if ((info.policy & PENALTY_LOG) != 0 && sListener != null) { - sListener.onViolation(info.crashInfo.stackTrace); - } if ((info.policy & PENALTY_LOG) != 0 && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) { - if (info.durationMillis != -1) { - Log.d( - TAG, - "StrictMode policy violation; ~duration=" - + info.durationMillis - + " ms: " - + info.crashInfo.stackTrace); - } else { - Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace); - } + sLogger.log(info); } // The violationMaskSubset, passed to ActivityManager, is a @@ -1925,11 +1934,11 @@ public final class StrictMode { } } - if (penaltyLog && sListener != null) { - sListener.onViolation(originStack.toString()); + if (penaltyLog && sLogger != null) { + sLogger.log(info); } if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) { - Log.e(TAG, message, originStack); + sLogger.log(info); } int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicy.mask); @@ -2339,11 +2348,12 @@ public final class StrictMode { * * @hide */ - public static class ViolationInfo implements Parcelable { + @TestApi + public static final class ViolationInfo implements Parcelable { public final String message; /** Stack and other stuff info. */ - public final ApplicationErrorReport.CrashInfo crashInfo; + @Nullable public final ApplicationErrorReport.CrashInfo crashInfo; /** The strict mode policy mask at the time of violation. */ public final int policy; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 40ced6ce4815..a5c55ba74a70 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6966,8 +6966,9 @@ public final class Settings { public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time"; /** - * Time in milliseconds (since epoch) when Night display was last activated. Use to decide - * whether to apply the current activated state after a reboot or user change. + * A String representing the LocalDateTime when Night display was last activated. Use to + * decide whether to apply the current activated state after a reboot or user change. In + * legacy cases, this is represented by the time in milliseconds (since epoch). * @hide */ public static final String NIGHT_DISPLAY_LAST_ACTIVATED_TIME = diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 2c1f73468ca6..ddced6cdd83f 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -762,7 +762,7 @@ public class Surface implements Parcelable { return "ROTATION_270"; } default: { - throw new IllegalArgumentException("Invalid rotation: " + rotation); + return Integer.toString(rotation); } } } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 66506a18296b..4131fd1ae9ff 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -617,6 +617,38 @@ public interface WindowManagerPolicy { * @param listener callback to call when display can be turned off */ void screenTurningOff(ScreenOffListener listener); + + /** + * Convert the lid state to a human readable format. + */ + static String lidStateToString(int lid) { + switch (lid) { + case LID_ABSENT: + return "LID_ABSENT"; + case LID_CLOSED: + return "LID_CLOSED"; + case LID_OPEN: + return "LID_OPEN"; + default: + return Integer.toString(lid); + } + } + + /** + * Convert the camera lens state to a human readable format. + */ + static String cameraLensStateToString(int lens) { + switch (lens) { + case CAMERA_LENS_COVER_ABSENT: + return "CAMERA_LENS_COVER_ABSENT"; + case CAMERA_LENS_UNCOVERED: + return "CAMERA_LENS_UNCOVERED"; + case CAMERA_LENS_COVERED: + return "CAMERA_LENS_COVERED"; + default: + return Integer.toString(lens); + } + } } public interface PointerEventListener { @@ -1750,4 +1782,34 @@ public interface WindowManagerPolicy { * @return true if ready; false otherwise. */ boolean canDismissBootAnimation(); + + /** + * Convert the user rotation mode to a human readable format. + */ + static String userRotationModeToString(int mode) { + switch(mode) { + case USER_ROTATION_FREE: + return "USER_ROTATION_FREE"; + case USER_ROTATION_LOCKED: + return "USER_ROTATION_LOCKED"; + default: + return Integer.toString(mode); + } + } + + /** + * Convert the off reason to a human readable format. + */ + static String offReasonToString(int why) { + switch (why) { + case OFF_BECAUSE_OF_ADMIN: + return "OFF_BECAUSE_OF_ADMIN"; + case OFF_BECAUSE_OF_USER: + return "OFF_BECAUSE_OF_USER"; + case OFF_BECAUSE_OF_TIMEOUT: + return "OFF_BECAUSE_OF_TIMEOUT"; + default: + return Integer.toString(why); + } + } } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 61cbce976844..f888ba298339 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -37,14 +37,13 @@ import android.service.autofill.AutofillService; import android.service.autofill.FillEventHistory; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.DebugUtils; import android.util.Log; import android.util.SparseArray; import android.view.View; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.nano.MetricsProto; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -202,9 +201,12 @@ public final class AutofillManager { * Initial state of the autofill context, set when there is no session (i.e., when * {@link #mSessionId} is {@link #NO_SESSION}). * + * <p>In this state, app callbacks (such as {@link #notifyViewEntered(View)}) are notified to + * the server. + * * @hide */ - public static final int STATE_UNKNOWN = 1; + public static final int STATE_UNKNOWN = 0; /** * State where the autofill context hasn't been {@link #commit() finished} nor @@ -212,7 +214,18 @@ public final class AutofillManager { * * @hide */ - public static final int STATE_ACTIVE = 2; + public static final int STATE_ACTIVE = 1; + + /** + * State where the autofill context was finished by the server because the autofill + * service could not autofill the page. + * + * <p>In this state, most apps callback (such as {@link #notifyViewEntered(View)}) are ignored, + * exception {@link #requestAutofill(View)} (and {@link #requestAutofill(View, int, Rect)}). + * + * @hide + */ + public static final int STATE_FINISHED = 2; /** * State where the autofill context has been {@link #commit() finished} but the server still has @@ -220,7 +233,7 @@ public final class AutofillManager { * * @hide */ - public static final int STATE_SHOWING_SAVE_UI = 4; + public static final int STATE_SHOWING_SAVE_UI = 3; /** * Makes an authentication id from a request id and a dataset id. @@ -559,6 +572,14 @@ public final class AutofillManager { } AutofillCallback callback = null; synchronized (mLock) { + if (isFinishedLocked() && (flags & FLAG_MANUAL_REQUEST) == 0) { + if (sVerbose) { + Log.v(TAG, "notifyViewEntered(flags=" + flags + ", view=" + view + + "): ignored on state " + getStateAsStringLocked()); + } + return; + } + ensureServiceClientAddedIfNeededLocked(); if (!mEnabled) { @@ -682,6 +703,14 @@ public final class AutofillManager { } AutofillCallback callback = null; synchronized (mLock) { + if (isFinishedLocked() && (flags & FLAG_MANUAL_REQUEST) == 0) { + if (sVerbose) { + Log.v(TAG, "notifyViewEntered(flags=" + flags + ", view=" + view + + ", virtualId=" + virtualId + + "): ignored on state " + getStateAsStringLocked()); + } + return; + } ensureServiceClientAddedIfNeededLocked(); if (!mEnabled) { @@ -765,6 +794,10 @@ public final class AutofillManager { } if (!mEnabled || !isActiveLocked()) { + if (sVerbose && mEnabled) { + Log.v(TAG, "notifyValueChanged(" + view + "): ignoring on state " + + getStateAsStringLocked()); + } return; } @@ -950,10 +983,13 @@ public final class AutofillManager { @NonNull AutofillValue value, int flags) { if (sVerbose) { Log.v(TAG, "startSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value - + ", flags=" + flags + ", state=" + mState); + + ", flags=" + flags + ", state=" + getStateAsStringLocked()); } - if (mState != STATE_UNKNOWN) { - if (sDebug) Log.d(TAG, "not starting session for " + id + " on state " + mState); + if (mState != STATE_UNKNOWN && (flags & FLAG_MANUAL_REQUEST) == 0) { + if (sVerbose) { + Log.v(TAG, "not automatically starting session for " + id + + " on state " + getStateAsStringLocked()); + } return; } try { @@ -973,7 +1009,7 @@ public final class AutofillManager { } private void finishSessionLocked() { - if (sVerbose) Log.v(TAG, "finishSessionLocked(): " + mState); + if (sVerbose) Log.v(TAG, "finishSessionLocked(): " + getStateAsStringLocked()); if (!isActiveLocked()) return; @@ -987,7 +1023,7 @@ public final class AutofillManager { } private void cancelSessionLocked() { - if (sVerbose) Log.v(TAG, "cancelSessionLocked(): " + mState); + if (sVerbose) Log.v(TAG, "cancelSessionLocked(): " + getStateAsStringLocked()); if (!isActiveLocked()) return; @@ -1245,10 +1281,10 @@ public final class AutofillManager { } } - final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED); - log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount); - log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, - numApplied); + final LogMaker log = new LogMaker(MetricsEvent.AUTOFILL_DATASET_APPLIED) + .setPackageName(mContext.getPackageName()) + .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount) + .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, numApplied); mMetricsLogger.write(log); } } @@ -1306,6 +1342,14 @@ public final class AutofillManager { } } + private void setSessionFinished() { + if (sVerbose) Log.v(TAG, "setSessionFinished()"); + synchronized (mLock) { + resetSessionLocked(); + mState = STATE_FINISHED; + } + } + private void requestHideFillUi(AutofillId id) { final View anchor = findView(id); if (sVerbose) Log.v(TAG, "requestHideFillUi(" + id + "): anchor = " + anchor); @@ -1341,7 +1385,11 @@ public final class AutofillManager { } } - private void notifyNoFillUi(int sessionId, AutofillId id) { + private void notifyNoFillUi(int sessionId, AutofillId id, boolean sessionFinished) { + if (sVerbose) { + Log.v(TAG, "notifyNoFillUi(): sessionId=" + sessionId + ", autofillId=" + id + + ", finished=" + sessionFinished); + } final View anchor = findView(id); if (anchor == null) { return; @@ -1361,7 +1409,11 @@ public final class AutofillManager { } else { callback.onAutofillEvent(anchor, AutofillCallback.EVENT_INPUT_UNAVAILABLE); } + } + if (sessionFinished) { + // Callback call was "hijacked" to also update the session state. + setSessionFinished(); } } @@ -1434,8 +1486,7 @@ public final class AutofillManager { pw.print(outerPrefix); pw.println("AutofillManager:"); final String pfx = outerPrefix + " "; pw.print(pfx); pw.print("sessionId: "); pw.println(mSessionId); - pw.print(pfx); pw.print("state: "); pw.println( - DebugUtils.flagsToString(AutofillManager.class, "STATE_", mState)); + pw.print(pfx); pw.print("state: "); pw.println(getStateAsStringLocked()); pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled); pw.print(pfx); pw.print("hasService: "); pw.println(mService != null); pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null); @@ -1452,10 +1503,29 @@ public final class AutofillManager { pw.print(pfx); pw.print("fillable ids: "); pw.println(mFillableIds); } + private String getStateAsStringLocked() { + switch (mState) { + case STATE_UNKNOWN: + return "STATE_UNKNOWN"; + case STATE_ACTIVE: + return "STATE_ACTIVE"; + case STATE_FINISHED: + return "STATE_FINISHED"; + case STATE_SHOWING_SAVE_UI: + return "STATE_SHOWING_SAVE_UI"; + default: + return "INVALID:" + mState; + } + } + private boolean isActiveLocked() { return mState == STATE_ACTIVE; } + private boolean isFinishedLocked() { + return mState == STATE_FINISHED; + } + private void post(Runnable runnable) { final AutofillClient client = getClientLocked(); if (client == null) { @@ -1787,10 +1857,10 @@ public final class AutofillManager { } @Override - public void notifyNoFillUi(int sessionId, AutofillId id) { + public void notifyNoFillUi(int sessionId, AutofillId id, boolean sessionFinished) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.post(() -> afm.notifyNoFillUi(sessionId, id)); + afm.post(() -> afm.notifyNoFillUi(sessionId, id, sessionFinished)); } } @@ -1823,7 +1893,15 @@ public final class AutofillManager { public void setSaveUiState(int sessionId, boolean shown) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.post(() ->afm.setSaveUiState(sessionId, shown)); + afm.post(() -> afm.setSaveUiState(sessionId, shown)); + } + } + + @Override + public void setSessionFinished() { + final AutofillManager afm = mAfm.get(); + if (afm != null) { + afm.post(() -> afm.setSessionFinished()); } } } diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index 0eae85860383..db6855a4dbf4 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -67,9 +67,9 @@ oneway interface IAutoFillManagerClient { void requestHideFillUi(int sessionId, in AutofillId id); /** - * Notifies no fill UI will be shown. + * Notifies no fill UI will be shown, and also mark the state as finished if necessary. */ - void notifyNoFillUi(int sessionId, in AutofillId id); + void notifyNoFillUi(int sessionId, in AutofillId id, boolean sessionFinished); /** * Starts the provided intent sender. @@ -80,4 +80,10 @@ oneway interface IAutoFillManagerClient { * Sets the state of the Autofill Save UI for a given session. */ void setSaveUiState(int sessionId, boolean shown); + + /** + * Marks the state of the session as finished (because the AutofillService returned a null + * FillResponse). + */ + void setSessionFinished(); } diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 7c4154f5c648..994512f7c897 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -463,7 +463,7 @@ public final class WebViewFactory { */ public static int onWebViewProviderChanged(PackageInfo packageInfo) { String[] nativeLibs = null; - String originalSourceDir = packageInfo.applicationInfo.sourceDir; + ApplicationInfo originalAppInfo = new ApplicationInfo(packageInfo.applicationInfo); try { fixupStubApplicationInfo(packageInfo.applicationInfo, AppGlobals.getInitialApplication().getPackageManager()); @@ -474,7 +474,7 @@ public final class WebViewFactory { Log.e(LOGTAG, "error preparing webview native library", t); } - WebViewZygote.onWebViewProviderChanged(packageInfo, originalSourceDir); + WebViewZygote.onWebViewProviderChanged(packageInfo, originalAppInfo); return prepareWebViewInSystemServer(nativeLibs); } diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java index 6e65c7a11d2f..db60ad8d1c05 100644 --- a/core/java/android/webkit/WebViewZygote.java +++ b/core/java/android/webkit/WebViewZygote.java @@ -17,6 +17,7 @@ package android.webkit; import android.app.LoadedApk; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.os.Build; import android.os.SystemService; @@ -67,11 +68,11 @@ public class WebViewZygote { private static PackageInfo sPackage; /** - * Cache key for the selected WebView package's classloader. This is set from + * Original ApplicationInfo for the selected WebView package before stub fixup. This is set from * #onWebViewProviderChanged(). */ @GuardedBy("sLock") - private static String sPackageCacheKey; + private static ApplicationInfo sPackageOriginalAppInfo; /** * Flag for whether multi-process WebView is enabled. If this is {@code false}, the zygote @@ -125,10 +126,11 @@ public class WebViewZygote { } } - public static void onWebViewProviderChanged(PackageInfo packageInfo, String cacheKey) { + public static void onWebViewProviderChanged(PackageInfo packageInfo, + ApplicationInfo originalAppInfo) { synchronized (sLock) { sPackage = packageInfo; - sPackageCacheKey = cacheKey; + sPackageOriginalAppInfo = originalAppInfo; // If multi-process is not enabled, then do not start the zygote service. if (!sMultiprocessEnabled) { @@ -217,10 +219,17 @@ public class WebViewZygote { final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : TextUtils.join(File.pathSeparator, zipPaths); + // In the case where the ApplicationInfo has been modified by the stub WebView, + // we need to use the original ApplicationInfo to determine what the original classpath + // would have been to use as a cache key. + LoadedApk.makePaths(null, false, sPackageOriginalAppInfo, zipPaths, null); + final String cacheKey = (zipPaths.size() == 1) ? zipPaths.get(0) : + TextUtils.join(File.pathSeparator, zipPaths); + ZygoteProcess.waitForConnectionToZygote(WEBVIEW_ZYGOTE_SOCKET); Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath); - sZygote.preloadPackageForAbi(zip, librarySearchPath, sPackageCacheKey, + sZygote.preloadPackageForAbi(zip, librarySearchPath, cacheKey, Build.SUPPORTED_ABIS[0]); } catch (Exception e) { Log.e(LOGTAG, "Error connecting to " + serviceName, e); diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index bc85fadb5ad9..7903d6fdc614 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -16,9 +16,10 @@ package android.widget; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; + import android.annotation.ColorInt; import android.annotation.DimenRes; -import android.app.ActivityManager.StackId; import android.app.ActivityOptions; import android.app.ActivityThread; import android.app.Application; @@ -324,11 +325,11 @@ public class RemoteViews implements Parcelable, Filter { public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) { - return onClickHandler(view, pendingIntent, fillInIntent, StackId.INVALID_STACK_ID); + return onClickHandler(view, pendingIntent, fillInIntent, WINDOWING_MODE_UNDEFINED); } public boolean onClickHandler(View view, PendingIntent pendingIntent, - Intent fillInIntent, int launchStackId) { + Intent fillInIntent, int windowingMode) { try { // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT? Context context = view.getContext(); @@ -339,8 +340,8 @@ public class RemoteViews implements Parcelable, Filter { opts = ActivityOptions.makeBasic(); } - if (launchStackId != StackId.INVALID_STACK_ID) { - opts.setLaunchStackId(launchStackId); + if (windowingMode != WINDOWING_MODE_UNDEFINED) { + opts.setLaunchWindowingMode(windowingMode); } context.startIntentSender( pendingIntent.getIntentSender(), fillInIntent, diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index efcc3a2f7a2b..2de552777756 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -5549,7 +5549,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public final void setHint(CharSequence hint) { setHintInternal(hint); - if (isInputMethodTarget()) { + if (mEditor != null && isInputMethodTarget()) { mEditor.reportExtractedText(); } } diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java index 860c5c4c3d3b..7a1383c7a01c 100644 --- a/core/java/com/android/internal/app/NightDisplayController.java +++ b/core/java/com/android/internal/app/NightDisplayController.java @@ -32,8 +32,12 @@ import com.android.internal.R; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.Calendar; -import java.util.Locale; +import java.time.DateTimeException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.format.DateTimeParseException; /** * Controller for managing Night display settings. @@ -116,8 +120,9 @@ public final class NightDisplayController { */ public boolean setActivated(boolean activated) { if (isActivated() != activated) { - Secure.putLongForUser(mContext.getContentResolver(), - Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(), + Secure.putStringForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, + LocalDateTime.now().toString(), mUserId); } return Secure.putIntForUser(mContext.getContentResolver(), @@ -128,17 +133,22 @@ public final class NightDisplayController { * Returns the time when Night display's activation state last changed, or {@code null} if it * has never been changed. */ - public Calendar getLastActivatedTime() { + public LocalDateTime getLastActivatedTime() { final ContentResolver cr = mContext.getContentResolver(); - final long lastActivatedTimeMillis = Secure.getLongForUser( - cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mUserId); - if (lastActivatedTimeMillis < 0) { - return null; + final String lastActivatedTime = Secure.getStringForUser( + cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, mUserId); + if (lastActivatedTime != null) { + try { + return LocalDateTime.parse(lastActivatedTime); + } catch (DateTimeParseException ignored) {} + // Uses the old epoch time. + try { + return LocalDateTime.ofInstant( + Instant.ofEpochMilli(Long.parseLong(lastActivatedTime)), + ZoneId.systemDefault()); + } catch (DateTimeException|NumberFormatException ignored) {} } - - final Calendar lastActivatedTime = Calendar.getInstance(); - lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis); - return lastActivatedTime; + return null; } /** @@ -183,8 +193,10 @@ public final class NightDisplayController { } if (getAutoMode() != autoMode) { - Secure.putLongForUser(mContext.getContentResolver(), - Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1L, mUserId); + Secure.putStringForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, + null, + mUserId); } return Secure.putIntForUser(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_AUTO_MODE, autoMode, mUserId); @@ -206,7 +218,7 @@ public final class NightDisplayController { R.integer.config_defaultNightDisplayCustomStartTime); } - return LocalTime.valueOf(startTimeValue); + return LocalTime.ofSecondOfDay(startTimeValue / 1000); } /** @@ -221,7 +233,7 @@ public final class NightDisplayController { throw new IllegalArgumentException("startTime cannot be null"); } return Secure.putIntForUser(mContext.getContentResolver(), - Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, startTime.toMillis(), mUserId); + Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, startTime.toSecondOfDay() * 1000, mUserId); } /** @@ -240,7 +252,7 @@ public final class NightDisplayController { R.integer.config_defaultNightDisplayCustomEndTime); } - return LocalTime.valueOf(endTimeValue); + return LocalTime.ofSecondOfDay(endTimeValue / 1000); } /** @@ -255,7 +267,7 @@ public final class NightDisplayController { throw new IllegalArgumentException("endTime cannot be null"); } return Secure.putIntForUser(mContext.getContentResolver(), - Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.toMillis(), mUserId); + Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.toSecondOfDay() * 1000, mUserId); } /** @@ -379,106 +391,6 @@ public final class NightDisplayController { } /** - * A time without a time-zone or date. - */ - public static class LocalTime { - - /** - * The hour of the day from 0 - 23. - */ - public final int hourOfDay; - /** - * The minute within the hour from 0 - 59. - */ - public final int minute; - - public LocalTime(int hourOfDay, int minute) { - if (hourOfDay < 0 || hourOfDay > 23) { - throw new IllegalArgumentException("Invalid hourOfDay: " + hourOfDay); - } else if (minute < 0 || minute > 59) { - throw new IllegalArgumentException("Invalid minute: " + minute); - } - - this.hourOfDay = hourOfDay; - this.minute = minute; - } - - /** - * Returns the first date time corresponding to this local time that occurs before the - * provided date time. - * - * @param time the date time to compare against - * @return the prior date time corresponding to this local time - */ - public Calendar getDateTimeBefore(Calendar time) { - final Calendar c = Calendar.getInstance(); - c.set(Calendar.YEAR, time.get(Calendar.YEAR)); - c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR)); - - c.set(Calendar.HOUR_OF_DAY, hourOfDay); - c.set(Calendar.MINUTE, minute); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - // Check if the local time has past, if so return the same time tomorrow. - if (c.after(time)) { - c.add(Calendar.DATE, -1); - } - - return c; - } - - /** - * Returns the first date time corresponding to this local time that occurs after the - * provided date time. - * - * @param time the date time to compare against - * @return the next date time corresponding to this local time - */ - public Calendar getDateTimeAfter(Calendar time) { - final Calendar c = Calendar.getInstance(); - c.set(Calendar.YEAR, time.get(Calendar.YEAR)); - c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR)); - - c.set(Calendar.HOUR_OF_DAY, hourOfDay); - c.set(Calendar.MINUTE, minute); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - - // Check if the local time has past, if so return the same time tomorrow. - if (c.before(time)) { - c.add(Calendar.DATE, 1); - } - - return c; - } - - /** - * Returns a local time corresponding the given number of milliseconds from midnight. - * - * @param millis the number of milliseconds from midnight - * @return the corresponding local time - */ - private static LocalTime valueOf(int millis) { - final int hourOfDay = (millis / 3600000) % 24; - final int minutes = (millis / 60000) % 60; - return new LocalTime(hourOfDay, minutes); - } - - /** - * Returns the local time represented as milliseconds from midnight. - */ - private int toMillis() { - return hourOfDay * 3600000 + minute * 60000; - } - - @Override - public String toString() { - return String.format(Locale.US, "%02d:%02d", hourOfDay, minute); - } - } - - /** * Callback invoked whenever the Night display settings are changed. */ public interface Callback { diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 5ee0918c336a..cbc63cf813cb 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -49,6 +49,11 @@ public final class Zygote { /** Make the code Java debuggable by turning off some optimizations. */ public static final int DEBUG_JAVA_DEBUGGABLE = 1 << 8; + /** Turn off the verifier. */ + public static final int DISABLE_VERIFIER = 1 << 9; + /** Only use oat files located in /system. Otherwise use dex/jar/apk . */ + public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10; + /** No external storage should be mounted. */ public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE; /** Default external storage should be mounted. */ diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 8122eb7de9b9..695fdac70280 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3074,6 +3074,12 @@ <permission android:name="android.permission.BATTERY_STATS" android:protectionLevel="signature|privileged|development" /> + <!--Allows an application to manage statscompanion. + <p>Not for use by third-party applications. + @hide --> + <permission android:name="android.permission.STATSCOMPANION" + android:protectionLevel="signature" /> + <!-- @SystemApi Allows an application to control the backup and restore process. <p>Not for use by third-party applications. @hide pending API council --> @@ -3859,6 +3865,16 @@ </intent-filter> </receiver> + <receiver android:name="com.android.server.stats.StatsCompanionService$AnomalyAlarmReceiver" + android:permission="android.permission.STATSCOMPANION" + android:exported="false"> + </receiver> + + <receiver android:name="com.android.server.stats.StatsCompanionService$PollingAlarmReceiver" + android:permission="android.permission.STATSCOMPANION" + android:exported="false"> + </receiver> + <service android:name="android.hardware.location.GeofenceHardwareService" android:permission="android.permission.LOCATION_HARDWARE" android:exported="false" /> @@ -3910,6 +3926,9 @@ android:permission="android.permission.BIND_JOB_SERVICE" > </service> + <service android:name="com.android.server.timezone.TimeZoneUpdateIdler" + android:permission="android.permission.BIND_JOB_SERVICE" > + </service> </application> </manifest> diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml index 92419c8c525b..5c5b985b26a2 100644 --- a/core/res/res/layout/autofill_save.xml +++ b/core/res/res/layout/autofill_save.xml @@ -46,13 +46,14 @@ <ImageView android:id="@+id/autofill_save_icon" - android:layout_width="wrap_content" - android:layout_height="24sp"/> + android:scaleType="fitStart" + android:layout_width="24dp" + android:layout_height="24dp"/> <TextView android:id="@+id/autofill_save_title" android:paddingLeft="8dp" - android:layout_width="0dp" + android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/autofill_save_title" android:textSize="16sp" diff --git a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java index 50e29c2863c2..9d75c784fe41 100644 --- a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java +++ b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java @@ -267,7 +267,7 @@ public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceT * @throws Exception */ @SmallTest - public void testPhoneNumbersEqualInternationl() throws Exception { + public void testPhoneNumbersEqualInternational() throws Exception { assertPhoneNumberEqual("1", "1"); assertPhoneNumberEqual("123123", "123123"); assertPhoneNumberNotEqual("123123", "923123"); @@ -288,6 +288,16 @@ public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceT // French trunk digit assertPhoneNumberEqual("+33123456789", "0123456789"); + // Hungarian two digit trunk (currently only works for loose comparison) + assertPhoneNumberEqual("+36 1 234 5678", "06 1234-5678", false); + + // Mexican two digit trunk (currently only works for loose comparison) + assertPhoneNumberEqual("+52 55 1234 5678", "01 55 1234 5678", false); + + // Mongolian two digit trunk (currently only works for loose comparison) + assertPhoneNumberEqual("+976 1 123 4567", "01 1 23 4567", false); + assertPhoneNumberEqual("+976 2 234 5678", "02 2 34 5678", false); + // Trunk digit for city codes in the Netherlands assertPhoneNumberEqual("+31771234567", "0771234567"); @@ -317,9 +327,22 @@ public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceT assertPhoneNumberEqual("008001231234", "8001231234", false); assertPhoneNumberNotEqual("008001231234", "8001231234", true); - // Confirm that the bug found before does not re-appear in the strict compalation - assertPhoneNumberEqual("080-1234-5678", "+819012345678", false); - assertPhoneNumberNotEqual("080-1234-5678", "+819012345678", true); + // Confirm that the bug found before does not re-appear + assertPhoneNumberNotEqual("080-1234-5678", "+819012345678"); + + // Wrong prefix for Japan (currently only works for loose comparison) + assertPhoneNumberNotEqual("290-1234-5678", "+819012345678", false); + assertPhoneNumberNotEqual("+819012345678", "290-1234-5678", false); + + // Wrong prefix for USA + assertPhoneNumberNotEqual("550-450-3605", "+14504503605"); + assertPhoneNumberNotEqual("550-450-3605", "+15404503605"); + assertPhoneNumberNotEqual("550-450-3605", "+15514503605"); + assertPhoneNumberNotEqual("5504503605", "+14504503605"); + assertPhoneNumberNotEqual("+14504503605", "550-450-3605"); + assertPhoneNumberNotEqual("+15404503605", "550-450-3605"); + assertPhoneNumberNotEqual("+15514503605", "550-450-3605"); + assertPhoneNumberNotEqual("+14504503605", "5504503605"); } @MediumTest diff --git a/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java b/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java index bcd90600b48a..75809c0fce4b 100644 --- a/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java +++ b/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java @@ -18,41 +18,70 @@ package android.database; import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; +import android.os.SystemProperties; import android.test.PerformanceTestCase; +import android.util.ArrayMap; import android.util.Log; import junit.framework.TestCase; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.List; +import java.util.Map; import java.util.Random; /** - * Database Performance Tests - * + * Database Performance Tests. + * + * <p>Usage: + * <code>./frameworks/base/core/tests/coretests/src/android/database/run_newdb_perf_test.sh</code> + * <p>Test with WAL journaling enabled: + * <code>setprop debug.NewDatabasePerformanceTests.enable_wal 1</code> */ - public class NewDatabasePerformanceTests { private static final String TAG = "NewDatabasePerformanceTests"; + private static final boolean DEBUG_ENABLE_WAL = SystemProperties + .getBoolean("debug.NewDatabasePerformanceTests.enable_wal", false); + private static final int DATASET_SIZE = 100; // Size of dataset to use for testing private static final int FAST_OP_MULTIPLIER = 25; private static final int FAST_OP_COUNT = FAST_OP_MULTIPLIER * DATASET_SIZE; + private static Long sInitialWriteBytes; + + static { + sInitialWriteBytes = getIoStats().get("write_bytes"); + if (DEBUG_ENABLE_WAL) { + Log.i(TAG, "Testing with WAL enabled"); + } + } + public static class PerformanceBase extends TestCase - implements PerformanceTestCase { + implements PerformanceTestCase { protected static final int CURRENT_DATABASE_VERSION = 42; protected SQLiteDatabase mDatabase; protected File mDatabaseFile; private long mSetupFinishedTime; + private Long mSetupWriteBytes; public void setUp() { long setupStarted = System.currentTimeMillis(); mDatabaseFile = new File("/sdcard", "perf_database_test.db"); if (mDatabaseFile.exists()) { - mDatabaseFile.delete(); + SQLiteDatabase.deleteDatabase(mDatabaseFile); + } + SQLiteDatabase.OpenParams.Builder params = new SQLiteDatabase.OpenParams.Builder(); + params.addOpenFlags(SQLiteDatabase.CREATE_IF_NECESSARY); + if (DEBUG_ENABLE_WAL) { + params.addOpenFlags(SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING); + } + mDatabase = SQLiteDatabase.openDatabase(mDatabaseFile, params.build()); + if (DEBUG_ENABLE_WAL) { + assertTrue("Cannot enable WAL", mDatabase.isWriteAheadLoggingEnabled()); } - mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null); - assertTrue(mDatabase != null); mDatabase.setVersion(CURRENT_DATABASE_VERSION); mDatabase.beginTransactionNonExclusive(); prepareForTest(); @@ -61,6 +90,7 @@ public class NewDatabasePerformanceTests { mSetupFinishedTime = System.currentTimeMillis(); Log.i(TAG, "Setup for " + getClass().getSimpleName() + " took " + (mSetupFinishedTime - setupStarted) + " ms"); + mSetupWriteBytes = getIoStats().get("write_bytes"); } protected void prepareForTest() { @@ -70,7 +100,14 @@ public class NewDatabasePerformanceTests { long duration = System.currentTimeMillis() - mSetupFinishedTime; Log.i(TAG, "Test " + getClass().getSimpleName() + " took " + duration + " ms"); mDatabase.close(); - mDatabaseFile.delete(); + SQLiteDatabase.deleteDatabase(mDatabaseFile); + Long writeBytes = getIoStats().get("write_bytes"); + if (writeBytes != null && sInitialWriteBytes != null) { + long testWriteBytes = writeBytes - mSetupWriteBytes; + long totalWriteBytes = (writeBytes - sInitialWriteBytes); + Log.i(TAG, "Test " + getClass().getSimpleName() + " write_bytes=" + testWriteBytes + + ". Since tests started - totalWriteBytes=" + totalWriteBytes); + } } public boolean isPerformanceOnly() { @@ -897,4 +934,31 @@ public class NewDatabasePerformanceTests { static final String[] TENS = {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"}; + + static Map<String, Long> getIoStats() { + String ioStat = "/proc/self/io"; + Map<String, Long> results = new ArrayMap<>(); + try { + List<String> lines = Files.readAllLines(new File(ioStat).toPath()); + for (String line : lines) { + line = line.trim(); + String[] split = line.split(":"); + if (split.length == 2) { + try { + String key = split[0].trim(); + Long value = Long.valueOf(split[1].trim()); + results.put(key, value); + } catch (NumberFormatException e) { + Log.e(TAG, "Cannot parse number from " + line); + } + } else if (line.isEmpty()) { + Log.e(TAG, "Cannot parse line " + line); + } + } + } catch (IOException e) { + Log.e(TAG, "Can't read: " + ioStat, e); + } + return results; + } + } diff --git a/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py b/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py index 1faeceb78d8b..27b20c327c0b 100644 --- a/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py +++ b/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py @@ -25,7 +25,16 @@ def main(): all_lines = f.readlines() timings = {} running_sum = 0 + # If WAL was enabled for the test + wal_enabled = False + # Number of bytes which test process caused to be sent to the storage layer. + # Reported as max value across all runs. + max_write_bytes = 0 for line in all_lines: + if "NewDatabasePerformanceTests: Testing with WAL enabled" in line: + wal_enabled = True + continue + regex = r"NewDatabasePerformanceTests: Test (\w+) took (\d+) ms" matches = re.search(regex, line) if matches: @@ -35,16 +44,31 @@ def main(): timings[test_name] = [] timings[test_name].append(duration) running_sum += duration + continue + if ("TestRunner: run finished:" in line) and (running_sum > 0): - test_name = '*** TOTAL ALL TESTS (ms) ***' + test_name = ('*** TOTAL ALL TESTS [WAL] (ms) ***' if wal_enabled + else '*** TOTAL ALL TESTS (ms) ***') if not test_name in timings: timings[test_name] = [] timings[test_name].append(running_sum) running_sum=0 + continue + + # Determine max from all reported totalWriteBytes + regex = r"Test .* totalWriteBytes=(\d+)" + matches = re.search(regex, line) + if matches: + max_write_bytes = max(max_write_bytes, int(matches.group(1))) + continue for k in sorted(timings): timings_ar = timings[k] print "%s: %s avg: %s" % (k, timings_ar, sum(timings_ar) / float(len(timings_ar)) ) + + print "\nAdditional stats: " + print " max write_bytes: %d" % max_write_bytes + if __name__ == '__main__': main() diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java index bc2b9a632b72..1cb0ecdba7f3 100644 --- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java +++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java @@ -753,7 +753,7 @@ public class LinkPropertiesTest extends TestCase { @SmallTest public void testCompareResult() { // Either adding or removing items - testCompareResult(Arrays.asList(1), Arrays.asList(1, 2, 3, 4), + testCompareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1), Arrays.asList(2, 3, 4), new ArrayList<>()); testCompareResult(Arrays.asList(1, 2), Arrays.asList(3, 2, 1, 4), new ArrayList<>(), Arrays.asList(3, 4)); @@ -780,9 +780,9 @@ public class LinkPropertiesTest extends TestCase { assertEquals(expectedSet, actualSet); } - private <T> void testCompareResult(List<T> oldItems, List<T> newItems, List<T> expectAdded, - List<T> expectRemoved) { - CompareResult<T> result = new CompareResult<>(newItems, oldItems); + private <T> void testCompareResult(List<T> oldItems, List<T> newItems, List<T> expectRemoved, + List<T> expectAdded) { + CompareResult<T> result = new CompareResult<>(oldItems, newItems); assertEquals(new ArraySet<>(expectAdded), new ArraySet<>(result.added)); assertEquals(new ArraySet<>(expectRemoved), (new ArraySet<>(result.removed))); } diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index 10d3e05c067f..4b80542ad0d0 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -558,6 +558,16 @@ public: SkPaint* getPaint(); void syncProperties() { if (mStagingProperties.mNonAnimatablePropertiesDirty) { + mCache.dirty |= (mProperties.mNonAnimatableProperties.viewportWidth + != mStagingProperties.mNonAnimatableProperties.viewportWidth) + || (mProperties.mNonAnimatableProperties.viewportHeight + != mStagingProperties.mNonAnimatableProperties.viewportHeight) + || (mProperties.mNonAnimatableProperties.scaledWidth + != mStagingProperties.mNonAnimatableProperties.scaledWidth) + || (mProperties.mNonAnimatableProperties.scaledHeight + != mStagingProperties.mNonAnimatableProperties.scaledHeight) + || (mProperties.mNonAnimatableProperties.bounds + != mStagingProperties.mNonAnimatableProperties.bounds); mProperties.syncNonAnimatableProperties(mStagingProperties); mStagingProperties.mNonAnimatablePropertiesDirty = false; } diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp index 3a77195824ad..afb1193657e1 100644 --- a/libs/hwui/service/GraphicsStatsService.cpp +++ b/libs/hwui/service/GraphicsStatsService.cpp @@ -40,7 +40,7 @@ static_assert(sizeof(sCurrentFileVersion) == sHeaderSize, "Header size is wrong" constexpr int sHistogramSize = ProfileData::HistogramSize(); -static void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, +static bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package, int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data); static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd); @@ -159,7 +159,7 @@ bool GraphicsStatsService::parseFromFile(const std::string& path, service::Graph return success; } -void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package, +bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package, int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) { if (proto->stats_start() == 0 || proto->stats_start() > startTime) { proto->set_stats_start(startTime); @@ -188,23 +188,31 @@ void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::st proto->mutable_histogram()->Reserve(sHistogramSize); creatingHistogram = true; } else if (proto->histogram_size() != sHistogramSize) { - LOG_ALWAYS_FATAL("Histogram size mismatch, proto is %d expected %d", + ALOGE("Histogram size mismatch, proto is %d expected %d", proto->histogram_size(), sHistogramSize); + return false; } int index = 0; + bool hitMergeError = false; data->histogramForEach([&](ProfileData::HistogramEntry entry) { + if (hitMergeError) return; + service::GraphicsStatsHistogramBucketProto* bucket; if (creatingHistogram) { bucket = proto->add_histogram(); bucket->set_render_millis(entry.renderTimeMs); } else { bucket = proto->mutable_histogram(index); - LOG_ALWAYS_FATAL_IF(bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs), - "Frame time mistmatch %d vs. %u", bucket->render_millis(), entry.renderTimeMs); + if (bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs)) { + ALOGW("Frame time mistmatch %d vs. %u", bucket->render_millis(), entry.renderTimeMs); + hitMergeError = true; + return; + } } bucket->set_frame_count(bucket->frame_count() + entry.frameCount); index++; }); + return !hitMergeError; } static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile) { @@ -221,9 +229,11 @@ static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) { // This isn't a full validation, just enough that we can deref at will - LOG_ALWAYS_FATAL_IF(proto->package_name().empty() - || !proto->has_summary(), "package_name() '%s' summary %d", - proto->package_name().c_str(), proto->has_summary()); + if (proto->package_name().empty() || !proto->has_summary()) { + ALOGW("Skipping dump, invalid package_name() '%s' or summary %d", + proto->package_name().c_str(), proto->has_summary()); + return; + } dprintf(fd, "\nPackage: %s", proto->package_name().c_str()); dprintf(fd, "\nVersion: %d", proto->version_code()); dprintf(fd, "\nStats since: %lldns", proto->stats_start()); @@ -254,14 +264,20 @@ void GraphicsStatsService::saveBuffer(const std::string& path, const std::string if (!parseFromFile(path, &statsProto)) { statsProto.Clear(); } - mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data); + if (!mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data)) { + return; + } // Although we might not have read any data from the file, merging the existing data // should always fully-initialize the proto - LOG_ALWAYS_FATAL_IF(!statsProto.IsInitialized(), "%s", - statsProto.InitializationErrorString().c_str()); - LOG_ALWAYS_FATAL_IF(statsProto.package_name().empty() - || !statsProto.has_summary(), "package_name() '%s' summary %d", - statsProto.package_name().c_str(), statsProto.has_summary()); + if (!statsProto.IsInitialized()) { + ALOGE("proto initialization error %s", statsProto.InitializationErrorString().c_str()); + return; + } + if (statsProto.package_name().empty() || !statsProto.has_summary()) { + ALOGE("missing package_name() '%s' summary %d", + statsProto.package_name().c_str(), statsProto.has_summary()); + return; + } int outFd = open(path.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0660); if (outFd <= 0) { int err = errno; @@ -312,8 +328,9 @@ void GraphicsStatsService::addToDump(Dump* dump, const std::string& path, const if (!path.empty() && !parseFromFile(path, &statsProto)) { statsProto.Clear(); } - if (data) { - mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data); + if (data && !mergeProfileDataIntoProto( + &statsProto, package, versionCode, startTime, endTime, data)) { + return; } if (!statsProto.IsInitialized()) { ALOGW("Failed to load profile data from path '%s' and data %p", diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index f85925d8d867..f41e33f7c102 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -2749,8 +2749,8 @@ public final class MediaCodecInfo { mQualityRange = Utils .parseIntRange(info.getString("quality-range"), mQualityRange); } - if (info.containsKey("feature-bitrate-control")) { - for (String mode: info.getString("feature-bitrate-control").split(",")) { + if (info.containsKey("feature-bitrate-modes")) { + for (String mode: info.getString("feature-bitrate-modes").split(",")) { mBitControl |= parseBitrateMode(mode); } } diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java index fe427a73bf96..8707ad017f51 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -204,7 +204,6 @@ public class MediaRouter { audioRoutesChanged = true; } - final int mainType = mCurAudioRoutesInfo.mainType; if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) { mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName; if (mCurAudioRoutesInfo.bluetoothName != null) { @@ -231,8 +230,11 @@ public class MediaRouter { } if (audioRoutesChanged) { - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, getDefaultSystemAudioRoute(), false); Log.v(TAG, "Audio routes updated: " + newRoutes + ", a2dp=" + isBluetoothA2dpOn()); + if (mSelectedRoute == null || mSelectedRoute == mDefaultAudioVideo + || mSelectedRoute == mBluetoothA2dpRoute) { + selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, getDefaultSystemAudioRoute(), false); + } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java index 9b75c00aeb3a..35ba6ae975d8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java @@ -26,7 +26,6 @@ import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.drawable.Icon; import android.net.Uri; -import android.os.AsyncTask; import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; @@ -320,6 +319,15 @@ public class TileUtils { Context context, UserHandle user, Intent intent, Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles, boolean usePriority, boolean checkCategory, boolean forceTintExternalIcon) { + getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles, + usePriority, checkCategory, forceTintExternalIcon, false /* shouldUpdateTiles */); + } + + public static void getTilesForIntent( + Context context, UserHandle user, Intent intent, + Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles, + boolean usePriority, boolean checkCategory, boolean forceTintExternalIcon, + boolean shouldUpdateTiles) { PackageManager pm = context.getPackageManager(); List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent, PackageManager.GET_META_DATA, user.getIdentifier()); @@ -357,9 +365,11 @@ public class TileUtils { updateTileData(context, tile, activityInfo, activityInfo.applicationInfo, pm, providerMap, forceTintExternalIcon); if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title); - addedCache.put(key, tile); + } else if (shouldUpdateTiles) { + updateSummaryAndTitle(context, providerMap, tile); } + if (!tile.userHandle.contains(user)) { tile.userHandle.add(user); } @@ -380,7 +390,6 @@ public class TileUtils { String summary = null; String keyHint = null; boolean isIconTintable = false; - RemoteViews remoteViews = null; // Get the activity's meta-data try { @@ -428,7 +437,8 @@ public class TileUtils { } if (metaData.containsKey(META_DATA_PREFERENCE_CUSTOM_VIEW)) { int layoutId = metaData.getInt(META_DATA_PREFERENCE_CUSTOM_VIEW); - remoteViews = new RemoteViews(applicationInfo.packageName, layoutId); + tile.remoteViews = new RemoteViews(applicationInfo.packageName, layoutId); + updateSummaryAndTitle(context, providerMap, tile); } } } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) { @@ -462,7 +472,6 @@ public class TileUtils { // Suggest a key for this tile tile.key = keyHint; tile.isIconTintable = isIconTintable; - tile.remoteViews = remoteViews; return true; } @@ -470,6 +479,26 @@ public class TileUtils { return false; } + private static void updateSummaryAndTitle( + Context context, Map<String, IContentProvider> providerMap, Tile tile) { + if (tile == null || tile.metaData == null + || !tile.metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) { + return; + } + + String uriString = tile.metaData.getString(META_DATA_PREFERENCE_SUMMARY_URI); + Bundle bundle = getBundleFromUri(context, uriString, providerMap); + String overrideSummary = getString(bundle, META_DATA_PREFERENCE_SUMMARY); + String overrideTitle = getString(bundle, META_DATA_PREFERENCE_TITLE); + if (overrideSummary != null) { + tile.remoteViews.setTextViewText(android.R.id.summary, overrideSummary); + } + + if (overrideTitle != null) { + tile.remoteViews.setTextViewText(android.R.id.title, overrideTitle); + } + } + /** * Gets the icon package name and resource id from content provider. * @param context context @@ -535,37 +564,6 @@ public class TileUtils { } } - public static void updateTileUsingSummaryUri(Context context, final Tile tile) { - if (tile == null || tile.metaData == null || - !tile.metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) { - return; - } - - new AsyncTask<Void, Void, Bundle>() { - @Override - protected Bundle doInBackground(Void... params) { - return getBundleFromUri(context, - tile.metaData.getString(META_DATA_PREFERENCE_SUMMARY_URI), new HashMap<>()); - } - - @Override - protected void onPostExecute(Bundle bundle) { - if (bundle == null) { - return; - } - final String overrideSummary = getString(bundle, META_DATA_PREFERENCE_SUMMARY); - final String overrideTitle = getString(bundle, META_DATA_PREFERENCE_TITLE); - - if (overrideSummary != null) { - tile.remoteViews.setTextViewText(android.R.id.summary, overrideSummary); - } - if (overrideTitle != null) { - tile.remoteViews.setTextViewText(android.R.id.title, overrideTitle); - } - } - }.execute(); - } - private static String getString(Bundle bundle, String key) { return bundle == null ? null : bundle.getString(key); } diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java index 00f32b2839af..56b84415e907 100644 --- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java +++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java @@ -195,7 +195,7 @@ public class SuggestionParser { intent.setPackage(category.pkg); } TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent, - mAddCache, null, suggestions, true, false, false); + mAddCache, null, suggestions, true, false, false, true /* shouldUpdateTiles */); filterSuggestions(suggestions, countBefore, isSmartSuggestionEnabled); if (!category.multiple && suggestions.size() > (countBefore + 1)) { // If there are too many, remove them all and only re-add the one with the highest diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java index 76f6a20959fb..3e90435b21d7 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java @@ -22,12 +22,10 @@ import static org.mockito.ArgumentMatchers.any; 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.ArgumentMatchers.isNull; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.robolectric.RuntimeEnvironment.application; @@ -66,7 +64,9 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowApplication; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.internal.ShadowExtractor; import java.util.ArrayList; import java.util.Collections; @@ -75,7 +75,8 @@ import java.util.Map; @RunWith(RobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, - sdk = TestConfig.SDK_VERSION) + sdk = TestConfig.SDK_VERSION, + shadows = {TileUtilsTest.TileUtilsShadowRemoteViews.class}) public class TileUtilsTest { @Mock @@ -420,12 +421,24 @@ public class TileUtilsTest { } @Test - public void updateTileUsingSummaryUri_summaryUriSpecified_shouldOverrideRemoteViewSummary() + public void getTilesForIntent_summaryUriSpecified_shouldOverrideRemoteViewSummary() throws RemoteException { + Intent intent = new Intent(); + Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>(); + List<Tile> outTiles = new ArrayList<>(); + List<ResolveInfo> info = new ArrayList<>(); + ResolveInfo resolveInfo = newInfo(true, null /* category */, null, + null, URI_GET_SUMMARY); + resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view", + R.layout.user_preference); + info.add(resolveInfo); + + when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt())) + .thenReturn(info); + // Mock the content provider interaction. Bundle bundle = new Bundle(); - String expectedSummary = "new summary text"; - bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, expectedSummary); + bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text"); when(mIContentProvider.call(anyString(), eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY), any())).thenReturn(bundle); @@ -434,14 +447,57 @@ public class TileUtilsTest { when(mContentResolver.acquireUnstableProvider(any(Uri.class))) .thenReturn(mIContentProvider); - Tile tile = new Tile(); - tile.metaData = new Bundle(); - tile.metaData.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, URI_GET_SUMMARY); - tile.remoteViews = mock(RemoteViews.class); - TileUtils.updateTileUsingSummaryUri(mContext, tile); - ShadowApplication.runBackgroundTasks(); + TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache, + null /* defaultCategory */, outTiles, false /* usePriority */, + false /* checkCategory */, true /* forceTintExternalIcon */); - verify(tile.remoteViews, times(1)).setTextViewText(anyInt(), eq(expectedSummary)); + assertThat(outTiles.size()).isEqualTo(1); + Tile tile = outTiles.get(0); + assertThat(tile.remoteViews).isNotNull(); + assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference); + // Make sure the summary TextView got a new text string. + TileUtilsShadowRemoteViews shadowRemoteViews = + (TileUtilsShadowRemoteViews) ShadowExtractor.extract(tile.remoteViews); + assertThat(shadowRemoteViews.overrideViewId).isEqualTo(android.R.id.summary); + assertThat(shadowRemoteViews.overrideText).isEqualTo("new summary text"); + } + + @Test + public void getTilesForIntent_providerUnavailable_shouldNotOverrideRemoteViewSummary() + throws RemoteException { + Intent intent = new Intent(); + Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>(); + List<Tile> outTiles = new ArrayList<>(); + List<ResolveInfo> info = new ArrayList<>(); + ResolveInfo resolveInfo = newInfo(true, null /* category */, null, + null, URI_GET_SUMMARY); + resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view", + R.layout.user_preference); + info.add(resolveInfo); + + when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt())) + .thenReturn(info); + + // Mock the content provider interaction. + Bundle bundle = new Bundle(); + bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text"); + when(mIContentProvider.call(anyString(), + eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY), + any())).thenReturn(bundle); + + TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache, + null /* defaultCategory */, outTiles, false /* usePriority */, + false /* checkCategory */, true /* forceTintExternalIcon */); + + assertThat(outTiles.size()).isEqualTo(1); + Tile tile = outTiles.get(0); + assertThat(tile.remoteViews).isNotNull(); + assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference); + // Make sure the summary TextView didn't get any text view updates. + TileUtilsShadowRemoteViews shadowRemoteViews = + (TileUtilsShadowRemoteViews) ShadowExtractor.extract(tile.remoteViews); + assertThat(shadowRemoteViews.overrideViewId).isNull(); + assertThat(shadowRemoteViews.overrideText).isNull(); } public static ResolveInfo newInfo(boolean systemApp, String category) { @@ -502,4 +558,16 @@ public class TileUtilsTest { } } + @Implements(RemoteViews.class) + public static class TileUtilsShadowRemoteViews { + + private Integer overrideViewId; + private CharSequence overrideText; + + @Implementation + public void setTextViewText(int viewId, CharSequence text) { + overrideViewId = viewId; + overrideText = text; + } + } } diff --git a/packages/SettingsProvider/res/values-af/defaults.xml b/packages/SettingsProvider/res/values-af/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-af/defaults.xml +++ b/packages/SettingsProvider/res/values-af/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-am/defaults.xml b/packages/SettingsProvider/res/values-am/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-am/defaults.xml +++ b/packages/SettingsProvider/res/values-am/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ar/defaults.xml b/packages/SettingsProvider/res/values-ar/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-ar/defaults.xml +++ b/packages/SettingsProvider/res/values-ar/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-az/defaults.xml b/packages/SettingsProvider/res/values-az/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-az/defaults.xml +++ b/packages/SettingsProvider/res/values-az/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-b+sr+Latn/defaults.xml b/packages/SettingsProvider/res/values-b+sr+Latn/defaults.xml index 524132e57827..16aed2ec05a3 100644 --- a/packages/SettingsProvider/res/values-b+sr+Latn/defaults.xml +++ b/packages/SettingsProvider/res/values-b+sr+Latn/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%2$s %1$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-be/defaults.xml b/packages/SettingsProvider/res/values-be/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-be/defaults.xml +++ b/packages/SettingsProvider/res/values-be/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-bg/defaults.xml b/packages/SettingsProvider/res/values-bg/defaults.xml index 715e78f83391..7a4c28c65a97 100644 --- a/packages/SettingsProvider/res/values-bg/defaults.xml +++ b/packages/SettingsProvider/res/values-bg/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%2$s от %1$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-bn/defaults.xml b/packages/SettingsProvider/res/values-bn/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-bn/defaults.xml +++ b/packages/SettingsProvider/res/values-bn/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-bs/defaults.xml b/packages/SettingsProvider/res/values-bs/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-bs/defaults.xml +++ b/packages/SettingsProvider/res/values-bs/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ca/defaults.xml b/packages/SettingsProvider/res/values-ca/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-ca/defaults.xml +++ b/packages/SettingsProvider/res/values-ca/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-cs/defaults.xml b/packages/SettingsProvider/res/values-cs/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-cs/defaults.xml +++ b/packages/SettingsProvider/res/values-cs/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-da/defaults.xml b/packages/SettingsProvider/res/values-da/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-da/defaults.xml +++ b/packages/SettingsProvider/res/values-da/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-de/defaults.xml b/packages/SettingsProvider/res/values-de/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-de/defaults.xml +++ b/packages/SettingsProvider/res/values-de/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-el/defaults.xml b/packages/SettingsProvider/res/values-el/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-el/defaults.xml +++ b/packages/SettingsProvider/res/values-el/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-en-rAU/defaults.xml b/packages/SettingsProvider/res/values-en-rAU/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-en-rAU/defaults.xml +++ b/packages/SettingsProvider/res/values-en-rAU/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-en-rCA/defaults.xml b/packages/SettingsProvider/res/values-en-rCA/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-en-rCA/defaults.xml +++ b/packages/SettingsProvider/res/values-en-rCA/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-en-rGB/defaults.xml b/packages/SettingsProvider/res/values-en-rGB/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-en-rGB/defaults.xml +++ b/packages/SettingsProvider/res/values-en-rGB/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-en-rIN/defaults.xml b/packages/SettingsProvider/res/values-en-rIN/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-en-rIN/defaults.xml +++ b/packages/SettingsProvider/res/values-en-rIN/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-en-rXC/defaults.xml b/packages/SettingsProvider/res/values-en-rXC/defaults.xml index b32199f372dc..34f63e7abebf 100644 --- a/packages/SettingsProvider/res/values-en-rXC/defaults.xml +++ b/packages/SettingsProvider/res/values-en-rXC/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-es-rUS/defaults.xml b/packages/SettingsProvider/res/values-es-rUS/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-es-rUS/defaults.xml +++ b/packages/SettingsProvider/res/values-es-rUS/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-es/defaults.xml b/packages/SettingsProvider/res/values-es/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-es/defaults.xml +++ b/packages/SettingsProvider/res/values-es/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-et/defaults.xml b/packages/SettingsProvider/res/values-et/defaults.xml index 5ec05cb5688e..37dab156c59f 100644 --- a/packages/SettingsProvider/res/values-et/defaults.xml +++ b/packages/SettingsProvider/res/values-et/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%2$s, %1$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-eu/defaults.xml b/packages/SettingsProvider/res/values-eu/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-eu/defaults.xml +++ b/packages/SettingsProvider/res/values-eu/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-fa/defaults.xml b/packages/SettingsProvider/res/values-fa/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-fa/defaults.xml +++ b/packages/SettingsProvider/res/values-fa/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-fi/defaults.xml b/packages/SettingsProvider/res/values-fi/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-fi/defaults.xml +++ b/packages/SettingsProvider/res/values-fi/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-fr-rCA/defaults.xml b/packages/SettingsProvider/res/values-fr-rCA/defaults.xml index b7280139184a..f439312cbfe9 100644 --- a/packages/SettingsProvider/res/values-fr-rCA/defaults.xml +++ b/packages/SettingsProvider/res/values-fr-rCA/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%2$s de %1$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-fr/defaults.xml b/packages/SettingsProvider/res/values-fr/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-fr/defaults.xml +++ b/packages/SettingsProvider/res/values-fr/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-gl/defaults.xml b/packages/SettingsProvider/res/values-gl/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-gl/defaults.xml +++ b/packages/SettingsProvider/res/values-gl/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-gu/defaults.xml b/packages/SettingsProvider/res/values-gu/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-gu/defaults.xml +++ b/packages/SettingsProvider/res/values-gu/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-hi/defaults.xml b/packages/SettingsProvider/res/values-hi/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-hi/defaults.xml +++ b/packages/SettingsProvider/res/values-hi/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-hr/defaults.xml b/packages/SettingsProvider/res/values-hr/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-hr/defaults.xml +++ b/packages/SettingsProvider/res/values-hr/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-hu/defaults.xml b/packages/SettingsProvider/res/values-hu/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-hu/defaults.xml +++ b/packages/SettingsProvider/res/values-hu/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-hy/defaults.xml b/packages/SettingsProvider/res/values-hy/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-hy/defaults.xml +++ b/packages/SettingsProvider/res/values-hy/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-in/defaults.xml b/packages/SettingsProvider/res/values-in/defaults.xml index 71f1d3b1569d..a63de85206eb 100644 --- a/packages/SettingsProvider/res/values-in/defaults.xml +++ b/packages/SettingsProvider/res/values-in/defaults.xml @@ -24,4 +24,5 @@ <!-- no translation found for def_device_name_simple (9037785625140748221) --> <skip /> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-is/defaults.xml b/packages/SettingsProvider/res/values-is/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-is/defaults.xml +++ b/packages/SettingsProvider/res/values-is/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-it/defaults.xml b/packages/SettingsProvider/res/values-it/defaults.xml index 524132e57827..16aed2ec05a3 100644 --- a/packages/SettingsProvider/res/values-it/defaults.xml +++ b/packages/SettingsProvider/res/values-it/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%2$s %1$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-iw/defaults.xml b/packages/SettingsProvider/res/values-iw/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-iw/defaults.xml +++ b/packages/SettingsProvider/res/values-iw/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ja/defaults.xml b/packages/SettingsProvider/res/values-ja/defaults.xml index 524132e57827..16aed2ec05a3 100644 --- a/packages/SettingsProvider/res/values-ja/defaults.xml +++ b/packages/SettingsProvider/res/values-ja/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%2$s %1$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ka/defaults.xml b/packages/SettingsProvider/res/values-ka/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-ka/defaults.xml +++ b/packages/SettingsProvider/res/values-ka/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-kk/defaults.xml b/packages/SettingsProvider/res/values-kk/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-kk/defaults.xml +++ b/packages/SettingsProvider/res/values-kk/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-km/defaults.xml b/packages/SettingsProvider/res/values-km/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-km/defaults.xml +++ b/packages/SettingsProvider/res/values-km/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-kn/defaults.xml b/packages/SettingsProvider/res/values-kn/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-kn/defaults.xml +++ b/packages/SettingsProvider/res/values-kn/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ko/defaults.xml b/packages/SettingsProvider/res/values-ko/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-ko/defaults.xml +++ b/packages/SettingsProvider/res/values-ko/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ky/defaults.xml b/packages/SettingsProvider/res/values-ky/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-ky/defaults.xml +++ b/packages/SettingsProvider/res/values-ky/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-lo/defaults.xml b/packages/SettingsProvider/res/values-lo/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-lo/defaults.xml +++ b/packages/SettingsProvider/res/values-lo/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-lt/defaults.xml b/packages/SettingsProvider/res/values-lt/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-lt/defaults.xml +++ b/packages/SettingsProvider/res/values-lt/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-lv/defaults.xml b/packages/SettingsProvider/res/values-lv/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-lv/defaults.xml +++ b/packages/SettingsProvider/res/values-lv/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-mk/defaults.xml b/packages/SettingsProvider/res/values-mk/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-mk/defaults.xml +++ b/packages/SettingsProvider/res/values-mk/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ml/defaults.xml b/packages/SettingsProvider/res/values-ml/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-ml/defaults.xml +++ b/packages/SettingsProvider/res/values-ml/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-mn/defaults.xml b/packages/SettingsProvider/res/values-mn/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-mn/defaults.xml +++ b/packages/SettingsProvider/res/values-mn/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-mr/defaults.xml b/packages/SettingsProvider/res/values-mr/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-mr/defaults.xml +++ b/packages/SettingsProvider/res/values-mr/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ms/defaults.xml b/packages/SettingsProvider/res/values-ms/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-ms/defaults.xml +++ b/packages/SettingsProvider/res/values-ms/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-my/defaults.xml b/packages/SettingsProvider/res/values-my/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-my/defaults.xml +++ b/packages/SettingsProvider/res/values-my/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-nb/defaults.xml b/packages/SettingsProvider/res/values-nb/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-nb/defaults.xml +++ b/packages/SettingsProvider/res/values-nb/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ne/defaults.xml b/packages/SettingsProvider/res/values-ne/defaults.xml index 71f1d3b1569d..a63de85206eb 100644 --- a/packages/SettingsProvider/res/values-ne/defaults.xml +++ b/packages/SettingsProvider/res/values-ne/defaults.xml @@ -24,4 +24,5 @@ <!-- no translation found for def_device_name_simple (9037785625140748221) --> <skip /> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-nl/defaults.xml b/packages/SettingsProvider/res/values-nl/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-nl/defaults.xml +++ b/packages/SettingsProvider/res/values-nl/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-pa/defaults.xml b/packages/SettingsProvider/res/values-pa/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-pa/defaults.xml +++ b/packages/SettingsProvider/res/values-pa/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-pl/defaults.xml b/packages/SettingsProvider/res/values-pl/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-pl/defaults.xml +++ b/packages/SettingsProvider/res/values-pl/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-pt-rBR/defaults.xml b/packages/SettingsProvider/res/values-pt-rBR/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-pt-rBR/defaults.xml +++ b/packages/SettingsProvider/res/values-pt-rBR/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-pt-rPT/defaults.xml b/packages/SettingsProvider/res/values-pt-rPT/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-pt-rPT/defaults.xml +++ b/packages/SettingsProvider/res/values-pt-rPT/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-pt/defaults.xml b/packages/SettingsProvider/res/values-pt/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-pt/defaults.xml +++ b/packages/SettingsProvider/res/values-pt/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ro/defaults.xml b/packages/SettingsProvider/res/values-ro/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-ro/defaults.xml +++ b/packages/SettingsProvider/res/values-ro/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ru/defaults.xml b/packages/SettingsProvider/res/values-ru/defaults.xml index 524132e57827..16aed2ec05a3 100644 --- a/packages/SettingsProvider/res/values-ru/defaults.xml +++ b/packages/SettingsProvider/res/values-ru/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%2$s %1$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-si/defaults.xml b/packages/SettingsProvider/res/values-si/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-si/defaults.xml +++ b/packages/SettingsProvider/res/values-si/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-sk/defaults.xml b/packages/SettingsProvider/res/values-sk/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-sk/defaults.xml +++ b/packages/SettingsProvider/res/values-sk/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-sl/defaults.xml b/packages/SettingsProvider/res/values-sl/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-sl/defaults.xml +++ b/packages/SettingsProvider/res/values-sl/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-sq/defaults.xml b/packages/SettingsProvider/res/values-sq/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-sq/defaults.xml +++ b/packages/SettingsProvider/res/values-sq/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-sr/defaults.xml b/packages/SettingsProvider/res/values-sr/defaults.xml index 524132e57827..16aed2ec05a3 100644 --- a/packages/SettingsProvider/res/values-sr/defaults.xml +++ b/packages/SettingsProvider/res/values-sr/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%2$s %1$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-sv/defaults.xml b/packages/SettingsProvider/res/values-sv/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-sv/defaults.xml +++ b/packages/SettingsProvider/res/values-sv/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-sw/defaults.xml b/packages/SettingsProvider/res/values-sw/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-sw/defaults.xml +++ b/packages/SettingsProvider/res/values-sw/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ta/defaults.xml b/packages/SettingsProvider/res/values-ta/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-ta/defaults.xml +++ b/packages/SettingsProvider/res/values-ta/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-te/defaults.xml b/packages/SettingsProvider/res/values-te/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-te/defaults.xml +++ b/packages/SettingsProvider/res/values-te/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-th/defaults.xml b/packages/SettingsProvider/res/values-th/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-th/defaults.xml +++ b/packages/SettingsProvider/res/values-th/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-tl/defaults.xml b/packages/SettingsProvider/res/values-tl/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-tl/defaults.xml +++ b/packages/SettingsProvider/res/values-tl/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-tr/defaults.xml b/packages/SettingsProvider/res/values-tr/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-tr/defaults.xml +++ b/packages/SettingsProvider/res/values-tr/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-uk/defaults.xml b/packages/SettingsProvider/res/values-uk/defaults.xml index a8e1fe819184..71b29ef66489 100644 --- a/packages/SettingsProvider/res/values-uk/defaults.xml +++ b/packages/SettingsProvider/res/values-uk/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%2$s о %1$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-ur/defaults.xml b/packages/SettingsProvider/res/values-ur/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-ur/defaults.xml +++ b/packages/SettingsProvider/res/values-ur/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-uz/defaults.xml b/packages/SettingsProvider/res/values-uz/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-uz/defaults.xml +++ b/packages/SettingsProvider/res/values-uz/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-vi/defaults.xml b/packages/SettingsProvider/res/values-vi/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-vi/defaults.xml +++ b/packages/SettingsProvider/res/values-vi/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-zh-rCN/defaults.xml b/packages/SettingsProvider/res/values-zh-rCN/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-zh-rCN/defaults.xml +++ b/packages/SettingsProvider/res/values-zh-rCN/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-zh-rHK/defaults.xml b/packages/SettingsProvider/res/values-zh-rHK/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-zh-rHK/defaults.xml +++ b/packages/SettingsProvider/res/values-zh-rHK/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-zh-rTW/defaults.xml b/packages/SettingsProvider/res/values-zh-rTW/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-zh-rTW/defaults.xml +++ b/packages/SettingsProvider/res/values-zh-rTW/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SettingsProvider/res/values-zu/defaults.xml b/packages/SettingsProvider/res/values-zu/defaults.xml index 4a87a1250404..2b8033c98c5f 100644 --- a/packages/SettingsProvider/res/values-zu/defaults.xml +++ b/packages/SettingsProvider/res/values-zu/defaults.xml @@ -22,4 +22,5 @@ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> + <string name="def_backup_manager_constants" msgid="75273734665044867"></string> </resources> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java index 8de1d317c5ed..2bc0e45c725d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java @@ -15,6 +15,8 @@ */ package com.android.keyguard; +import static android.view.Display.INVALID_DISPLAY; + import android.app.Presentation; import android.content.Context; import android.content.DialogInterface; @@ -28,16 +30,21 @@ import android.view.Display; import android.view.View; import android.view.WindowManager; +// TODO(multi-display): Support multiple external displays public class KeyguardDisplayManager { protected static final String TAG = "KeyguardDisplayManager"; private static boolean DEBUG = KeyguardConstants.DEBUG; + + private final ViewMediatorCallback mCallback; + private final MediaRouter mMediaRouter; + private final Context mContext; + Presentation mPresentation; - private MediaRouter mMediaRouter; - private Context mContext; private boolean mShowing; - public KeyguardDisplayManager(Context context) { + public KeyguardDisplayManager(Context context, ViewMediatorCallback callback) { mContext = context; + mCallback = callback; mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE); } @@ -90,6 +97,7 @@ public class KeyguardDisplayManager { }; protected void updateDisplays(boolean showing) { + Presentation originalPresentation = mPresentation; if (showing) { MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute( MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY); @@ -121,6 +129,13 @@ public class KeyguardDisplayManager { mPresentation = null; } } + + // mPresentation is only updated when the display changes + if (mPresentation != originalPresentation) { + final int displayId = mPresentation != null + ? mPresentation.getDisplay().getDisplayId() : INVALID_DISPLAY; + mCallback.onSecondaryDisplayShowingChanged(displayId); + } } private final static class KeyguardPresentation extends Presentation { diff --git a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java index 327d218913d2..b194de43a718 100644 --- a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java +++ b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java @@ -88,4 +88,9 @@ public interface ViewMediatorCallback { * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}. */ int getBouncerPromptReason(); + + /** + * Invoked when the secondary display showing a keyguard window changes. + */ + void onSecondaryDisplayShowingChanged(int displayId); } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 4cbbbd6c2e90..189badfc42fc 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -1280,7 +1280,23 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn mGradientDrawable.setScreenSize(displaySize.x, displaySize.y); GradientColors colors = mColorExtractor.getColors(mKeyguardShowing ? WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM); - mGradientDrawable.setColors(colors, false); + updateColors(colors, false /* animate */); + } + + /** + * Updates background and system bars according to current GradientColors. + * @param colors Colors and hints to use. + * @param animate Interpolates gradient if true, just sets otherwise. + */ + private void updateColors(GradientColors colors, boolean animate) { + mGradientDrawable.setColors(colors, animate); + View decorView = getWindow().getDecorView(); + if (colors.supportsDarkText()) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR | + View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } else { + decorView.setSystemUiVisibility(0); + } } @Override @@ -1350,11 +1366,13 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn public void onColorsChanged(ColorExtractor extractor, int which) { if (mKeyguardShowing) { if ((WallpaperManager.FLAG_LOCK & which) != 0) { - mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_LOCK)); + updateColors(extractor.getColors(WallpaperManager.FLAG_LOCK), + true /* animate */); } } else { if ((WallpaperManager.FLAG_SYSTEM & which) != 0) { - mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_SYSTEM)); + updateColors(extractor.getColors(WallpaperManager.FLAG_SYSTEM), + true /* animate */); } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 3eb68f5214c0..28adca97b8bf 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -17,6 +17,7 @@ package com.android.systemui.keyguard; import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; +import static android.view.Display.INVALID_DISPLAY; import static com.android.internal.telephony.IccCardConstants.State.ABSENT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; @@ -239,6 +240,9 @@ public class KeyguardViewMediator extends SystemUI { // answer whether the input should be restricted) private boolean mShowing; + // display id of the secondary display on which we have put a keyguard window + private int mSecondaryDisplayShowing = INVALID_DISPLAY; + /** Cached value of #isInputRestricted */ private boolean mInputRestricted; @@ -646,6 +650,13 @@ public class KeyguardViewMediator extends SystemUI { } return KeyguardSecurityView.PROMPT_REASON_NONE; } + + @Override + public void onSecondaryDisplayShowingChanged(int displayId) { + synchronized (KeyguardViewMediator.this) { + setShowingLocked(mShowing, displayId, false); + } + } }; public void userActivity() { @@ -670,7 +681,7 @@ public class KeyguardViewMediator extends SystemUI { filter.addAction(Intent.ACTION_SHUTDOWN); mContext.registerReceiver(mBroadcastReceiver, filter); - mKeyguardDisplayManager = new KeyguardDisplayManager(mContext); + mKeyguardDisplayManager = new KeyguardDisplayManager(mContext, mViewMediatorCallback); mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); @@ -685,7 +696,8 @@ public class KeyguardViewMediator extends SystemUI { com.android.keyguard.R.bool.config_enableKeyguardService)) { setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled( - KeyguardUpdateMonitor.getCurrentUser()), true /* forceCallbacks */); + KeyguardUpdateMonitor.getCurrentUser()), + mSecondaryDisplayShowing, true /* forceCallbacks */); } mStatusBarKeyguardViewManager = @@ -1694,10 +1706,10 @@ public class KeyguardViewMediator extends SystemUI { playSound(mTrustedSoundId); } - private void updateActivityLockScreenState(boolean showing) { + private void updateActivityLockScreenState(boolean showing, int secondaryDisplayShowing) { mUiOffloadThread.submit(() -> { try { - ActivityManager.getService().setLockScreenShown(showing); + ActivityManager.getService().setLockScreenShown(showing, secondaryDisplayShowing); } catch (RemoteException e) { } }); @@ -2060,30 +2072,39 @@ public class KeyguardViewMediator extends SystemUI { } private void setShowingLocked(boolean showing) { - setShowingLocked(showing, false /* forceCallbacks */); + setShowingLocked(showing, mSecondaryDisplayShowing, false /* forceCallbacks */); } - private void setShowingLocked(boolean showing, boolean forceCallbacks) { - if (showing != mShowing || forceCallbacks) { + private void setShowingLocked( + boolean showing, int secondaryDisplayShowing, boolean forceCallbacks) { + final boolean notifyDefaultDisplayCallbacks = showing != mShowing || forceCallbacks; + if (notifyDefaultDisplayCallbacks || secondaryDisplayShowing != mSecondaryDisplayShowing) { mShowing = showing; - int size = mKeyguardStateCallbacks.size(); - for (int i = size - 1; i >= 0; i--) { - IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i); - try { - callback.onShowingStateChanged(showing); - } catch (RemoteException e) { - Slog.w(TAG, "Failed to call onShowingStateChanged", e); - if (e instanceof DeadObjectException) { - mKeyguardStateCallbacks.remove(callback); - } + mSecondaryDisplayShowing = secondaryDisplayShowing; + if (notifyDefaultDisplayCallbacks) { + notifyDefaultDisplayCallbacks(showing); + } + updateActivityLockScreenState(showing, secondaryDisplayShowing); + } + } + + private void notifyDefaultDisplayCallbacks(boolean showing) { + int size = mKeyguardStateCallbacks.size(); + for (int i = size - 1; i >= 0; i--) { + IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i); + try { + callback.onShowingStateChanged(showing); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call onShowingStateChanged", e); + if (e instanceof DeadObjectException) { + mKeyguardStateCallbacks.remove(callback); } } - updateInputRestrictedLocked(); - mUiOffloadThread.submit(() -> { - mTrustManager.reportKeyguardShowingChanged(); - }); - updateActivityLockScreenState(showing); } + updateInputRestrictedLocked(); + mUiOffloadThread.submit(() -> { + mTrustManager.reportKeyguardShowingChanged(); + }); } private void notifyTrustedChangedLocked(boolean trusted) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index aecf95fc677f..c4e870135a6d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -565,8 +565,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // Launch the task ssp.startActivityFromRecents( - mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID, - null /* resultListener */); + mContext, toTask.key, toTask.title, launchOpts, null /* resultListener */); } /** @@ -639,8 +638,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // Launch the task ssp.startActivityFromRecents( - mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID, - null /* resultListener */); + mContext, toTask.key, toTask.title, launchOpts, null /* resultListener */); } public void showNextAffiliatedTask() { diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java index 3db106e7200f..862a1eee8c39 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java @@ -16,6 +16,9 @@ package com.android.systemui.recents.events.activity; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; + import android.graphics.Rect; import com.android.systemui.recents.events.EventBus; @@ -30,15 +33,23 @@ public class LaunchTaskEvent extends EventBus.Event { public final TaskView taskView; public final Task task; public final Rect targetTaskBounds; - public final int targetTaskStack; + public final int targetWindowingMode; + public final int targetActivityType; public final boolean screenPinningRequested; - public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds, int targetTaskStack, + public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds, boolean screenPinningRequested) { + this(taskView, task, targetTaskBounds, screenPinningRequested, + WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED); + } + + public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds, + boolean screenPinningRequested, int windowingMode, int activityType) { this.taskView = taskView; this.task = task; this.targetTaskBounds = targetTaskBounds; - this.targetTaskStack = targetTaskStack; + this.targetWindowingMode = windowingMode; + this.targetActivityType = activityType; this.screenPinningRequested = screenPinningRequested; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 717778228989..366a908f15bd 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -23,6 +23,10 @@ import static android.app.ActivityManager.StackId.HOME_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManager.StackId.RECENTS_STACK_ID; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT; import android.annotation.NonNull; @@ -576,7 +580,7 @@ public class SystemServicesProxy { try { final ActivityOptions options = ActivityOptions.makeBasic(); options.setDockCreateMode(createMode); - options.setLaunchStackId(DOCKED_STACK_ID); + options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); mIam.startActivityFromRecents(taskId, options.toBundle()); return true; } catch (Exception e) { @@ -1120,9 +1124,16 @@ public class SystemServicesProxy { opts != null ? opts.toBundle() : null, UserHandle.CURRENT)); } + public void startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName, + ActivityOptions options, + @Nullable final StartActivityFromRecentsResultListener resultListener) { + startActivityFromRecents(context, taskKey, taskName, options, + WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED, resultListener); + } + /** Starts an activity from recents. */ public void startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName, - ActivityOptions options, int stackId, + ActivityOptions options, int windowingMode, int activityType, @Nullable final StartActivityFromRecentsResultListener resultListener) { if (mIam == null) { return; @@ -1133,12 +1144,14 @@ public class SystemServicesProxy { if (options == null) { options = ActivityOptions.makeBasic(); } - options.setLaunchStackId(FULLSCREEN_WORKSPACE_STACK_ID); - } else if (stackId != INVALID_STACK_ID) { + options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + } else if (windowingMode != WINDOWING_MODE_UNDEFINED + || activityType != ACTIVITY_TYPE_UNDEFINED) { if (options == null) { options = ActivityOptions.makeBasic(); } - options.setLaunchStackId(stackId); + options.setLaunchWindowingMode(windowingMode); + options.setLaunchActivityType(activityType); } final ActivityOptions finalOptions = options; diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java index b2675d7ac858..4d3321638e8e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java @@ -21,6 +21,15 @@ import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import android.annotation.Nullable; import android.app.ActivityManager.StackId; @@ -107,7 +116,7 @@ public class RecentsTransitionHelper { */ public void launchTaskFromRecents(final TaskStack stack, @Nullable final Task task, final TaskStackView stackView, final TaskView taskView, - final boolean screenPinningRequested, final int destinationStack) { + final boolean screenPinningRequested, final int windowingMode, final int activityType) { final ActivityOptions.OnAnimationStartedListener animStartedListener; final AppTransitionAnimationSpecsFuture transitionFuture; @@ -116,8 +125,8 @@ public class RecentsTransitionHelper { // Fetch window rect here already in order not to be blocked on lock contention in WM // when the future calls it. final Rect windowRect = Recents.getSystemServices().getWindowRect(); - transitionFuture = getAppTransitionFuture( - () -> composeAnimationSpecs(task, stackView, destinationStack, windowRect)); + transitionFuture = getAppTransitionFuture(() -> composeAnimationSpecs( + task, stackView, windowingMode, activityType, windowRect)); animStartedListener = new OnAnimationStartedListener() { private boolean mHandled; @@ -180,7 +189,8 @@ public class RecentsTransitionHelper { if (taskView == null) { // If there is no task view, then we do not need to worry about animating out occluding // task views, and we can launch immediately - startTaskActivity(stack, task, taskView, opts, transitionFuture, destinationStack); + startTaskActivity(stack, task, taskView, opts, transitionFuture, + windowingMode, activityType); } else { LaunchTaskStartedEvent launchStartedEvent = new LaunchTaskStartedEvent(taskView, screenPinningRequested); @@ -189,13 +199,14 @@ public class RecentsTransitionHelper { @Override public void run() { startTaskActivity(stack, task, taskView, opts, transitionFuture, - destinationStack); + windowingMode, activityType); } }); EventBus.getDefault().send(launchStartedEvent); } else { EventBus.getDefault().send(launchStartedEvent); - startTaskActivity(stack, task, taskView, opts, transitionFuture, destinationStack); + startTaskActivity(stack, task, taskView, opts, transitionFuture, + windowingMode, activityType); } } Recents.getSystemServices().sendCloseSystemWindows( @@ -224,13 +235,13 @@ public class RecentsTransitionHelper { * * @param taskView this is the {@link TaskView} that we are launching from. This can be null if * we are toggling recents and the launch-to task is now offscreen. - * @param destinationStack id of the stack to put the task into. */ private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskView taskView, ActivityOptions opts, AppTransitionAnimationSpecsFuture transitionFuture, - int destinationStack) { + int windowingMode, int activityType) { SystemServicesProxy ssp = Recents.getSystemServices(); - ssp.startActivityFromRecents(mContext, task.key, task.title, opts, destinationStack, + ssp.startActivityFromRecents(mContext, task.key, task.title, opts, windowingMode, + activityType, succeeded -> { if (succeeded) { // Keep track of the index of the task launch @@ -310,11 +321,9 @@ public class RecentsTransitionHelper { * Composes the animation specs for all the tasks in the target stack. */ private List<AppTransitionAnimationSpec> composeAnimationSpecs(final Task task, - final TaskStackView stackView, final int destinationStack, Rect windowRect) { - // Ensure we have a valid target stack id - final int targetStackId = destinationStack != INVALID_STACK_ID ? - destinationStack : task.key.stackId; - if (!StackId.useAnimationSpecForAppTransition(targetStackId)) { + final TaskStackView stackView, int windowingMode, int activityType, Rect windowRect) { + if (activityType == ACTIVITY_TYPE_RECENTS || activityType == ACTIVITY_TYPE_HOME + || windowingMode == WINDOWING_MODE_PINNED) { return null; } @@ -329,9 +338,12 @@ public class RecentsTransitionHelper { List<AppTransitionAnimationSpec> specs = new ArrayList<>(); // TODO: Sometimes targetStackId is not initialized after reboot, so we also have to - // check for INVALID_STACK_ID - if (targetStackId == FULLSCREEN_WORKSPACE_STACK_ID || targetStackId == DOCKED_STACK_ID - || targetStackId == ASSISTANT_STACK_ID || targetStackId == INVALID_STACK_ID) { + // check for INVALID_STACK_ID (now WINDOWING_MODE_UNDEFINED) + if (windowingMode == WINDOWING_MODE_FULLSCREEN + || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY + || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY + || activityType == ACTIVITY_TYPE_ASSISTANT + || windowingMode == WINDOWING_MODE_UNDEFINED) { if (taskView == null) { specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect)); } else { @@ -353,7 +365,7 @@ public class RecentsTransitionHelper { int taskCount = tasks.size(); for (int i = taskCount - 1; i >= 0; i--) { Task t = tasks.get(i); - if (t.isFreeformTask() || targetStackId == FREEFORM_WORKSPACE_STACK_ID) { + if (t.isFreeformTask() || windowingMode == WINDOWING_MODE_FREEFORM) { TaskView tv = stackView.getChildViewForTask(t); if (tv == null) { // TODO: Create a different animation task rect for this case (though it should diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index c44cd7287625..fd1b806abf24 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -338,8 +338,7 @@ public class RecentsView extends FrameLayout { Task task = mTaskStackView.getFocusedTask(); if (task != null) { TaskView taskView = mTaskStackView.getChildViewForTask(task); - EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null, - INVALID_STACK_ID, false)); + EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null, false)); if (logEvent != 0) { MetricsLogger.action(getContext(), logEvent, @@ -363,32 +362,13 @@ public class RecentsView extends FrameLayout { Task task = getStack().getLaunchTarget(); if (task != null) { TaskView taskView = mTaskStackView.getChildViewForTask(task); - EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null, - INVALID_STACK_ID, false)); + EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null, false)); return true; } } return false; } - /** Launches a given task. */ - public boolean launchTask(Task task, Rect taskBounds, int destinationStack) { - if (mTaskStackView != null) { - // Iterate the stack views and try and find the given task. - List<TaskView> taskViews = mTaskStackView.getTaskViews(); - int taskViewCount = taskViews.size(); - for (int j = 0; j < taskViewCount; j++) { - TaskView tv = taskViews.get(j); - if (tv.getTask() == task) { - EventBus.getDefault().send(new LaunchTaskEvent(tv, task, taskBounds, - destinationStack, false)); - return true; - } - } - } - return false; - } - /** * Hides the task stack and shows the empty view. */ @@ -570,7 +550,8 @@ public class RecentsView extends FrameLayout { public final void onBusEvent(LaunchTaskEvent event) { mLastTaskLaunchedWasFreeform = event.task.isFreeformTask(); mTransitionHelper.launchTaskFromRecents(getStack(), event.task, mTaskStackView, - event.taskView, event.screenPinningRequested, event.targetTaskStack); + event.taskView, event.screenPinningRequested, event.targetWindowingMode, + event.targetActivityType); if (Recents.getConfiguration().isLowRamDevice) { hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, false /* translate */); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 8899e307bb16..74e9ef2b3efb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -1487,7 +1487,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal Task frontTask = tasks.get(tasks.size() - 1); if (frontTask != null && frontTask.isFreeformTask()) { EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(frontTask), - frontTask, null, INVALID_STACK_ID, false)); + frontTask, null, false)); return true; } } @@ -2369,12 +2369,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal public void run() { EventBus.getDefault().send(new LaunchTaskEvent( getChildViewForTask(task), task, null, - INVALID_STACK_ID, false /* screenPinningRequested */)); + false /* screenPinningRequested */)); } }); } else { - EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(task), - task, null, INVALID_STACK_ID, false /* screenPinningRequested */)); + EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(task), task, null, + false /* screenPinningRequested */)); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index ceeebd96a3e1..c64f6dfcea4a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -674,8 +674,7 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks mActionButtonView.setTranslationZ(0f); screenPinningRequested = true; } - EventBus.getDefault().send(new LaunchTaskEvent(this, mTask, null, INVALID_STACK_ID, - screenPinningRequested)); + EventBus.getDefault().send(new LaunchTaskEvent(this, mTask, null, screenPinningRequested)); MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT, mTask.key.getComponent().toString()); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index ae922fcc218e..198ecae2d1a9 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -16,6 +16,11 @@ package com.android.systemui.recents.views; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.Nullable; @@ -57,10 +62,6 @@ import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task; -import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; -import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; -import static android.app.ActivityManager.StackId.INVALID_STACK_ID; - /* The task bar view */ public class TaskViewHeader extends FrameLayout implements View.OnClickListener, View.OnLongClickListener { @@ -172,7 +173,7 @@ public class TaskViewHeader extends FrameLayout int mTaskBarViewLightTextColor; int mTaskBarViewDarkTextColor; int mDisabledTaskBarBackgroundColor; - int mMoveTaskTargetStackId = INVALID_STACK_ID; + int mTaskWindowingMode = WINDOWING_MODE_UNDEFINED; // Header background private HighlightColorDrawable mBackground; @@ -485,12 +486,12 @@ public class TaskViewHeader extends FrameLayout // current task if (mMoveTaskButton != null) { if (t.isFreeformTask()) { - mMoveTaskTargetStackId = FULLSCREEN_WORKSPACE_STACK_ID; + mTaskWindowingMode = WINDOWING_MODE_FULLSCREEN; mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor ? mLightFullscreenIcon : mDarkFullscreenIcon); } else { - mMoveTaskTargetStackId = FREEFORM_WORKSPACE_STACK_ID; + mTaskWindowingMode = WINDOWING_MODE_FREEFORM; mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor ? mLightFreeformIcon : mDarkFreeformIcon); @@ -621,8 +622,8 @@ public class TaskViewHeader extends FrameLayout Constants.Metrics.DismissSourceHeaderButton); } else if (v == mMoveTaskButton) { TaskView tv = Utilities.findParent(this, TaskView.class); - EventBus.getDefault().send(new LaunchTaskEvent(tv, mTask, null, - mMoveTaskTargetStackId, false)); + EventBus.getDefault().send(new LaunchTaskEvent(tv, mTask, null, false, + mTaskWindowingMode, ACTIVITY_TYPE_UNDEFINED)); } else if (v == mAppInfoView) { EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask)); } else if (v == mAppIconView) { diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 6bfef20c9f53..44e60eed8c7c 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -93,7 +93,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, private static final int LOG_VALUE_UNDOCK_MAX_OTHER = 1; private static final int TASK_POSITION_SAME = Integer.MAX_VALUE; - private static final boolean SWAPPING_ENABLED = false; /** * How much the background gets scaled when we are in the minimized dock state. @@ -153,7 +152,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, private boolean mEntranceAnimationRunning; private boolean mExitAnimationRunning; private int mExitStartPosition; - private GestureDetector mGestureDetector; private boolean mDockedStackMinimized; private boolean mHomeStackResizable; private boolean mAdjustedForIme; @@ -295,21 +293,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, landscape ? TYPE_HORIZONTAL_DOUBLE_ARROW : TYPE_VERTICAL_DOUBLE_ARROW)); getViewTreeObserver().addOnComputeInternalInsetsListener(this); mHandle.setAccessibilityDelegate(mHandleDelegate); - mGestureDetector = new GestureDetector(mContext, new SimpleOnGestureListener() { - @Override - public boolean onSingleTapUp(MotionEvent e) { - if (SWAPPING_ENABLED) { - updateDockSide(); - SystemServicesProxy ssp = Recents.getSystemServices(); - if (mDockSide != WindowManager.DOCKED_INVALID - && !ssp.isRecentsActivityVisible()) { - mWindowManagerProxy.swapTasks(); - return true; - } - } - return false; - } - }); } @Override @@ -478,7 +461,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, @Override public boolean onTouch(View v, MotionEvent event) { convertToScreenCoordinates(event); - mGestureDetector.onTouchEvent(event); final int action = event.getAction() & MotionEvent.ACTION_MASK; switch (action) { case MotionEvent.ACTION_DOWN: diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java index c24512649c2f..185f6e369f76 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java @@ -120,17 +120,6 @@ public class WindowManagerProxy { } }; - private final Runnable mSwapRunnable = new Runnable() { - @Override - public void run() { - try { - ActivityManager.getService().swapDockedAndFullscreenStack(); - } catch (RemoteException e) { - Log.w(TAG, "Failed to resize stack: " + e); - } - } - }; - private final Runnable mSetTouchableRegionRunnable = new Runnable() { @Override public void run() { @@ -218,10 +207,6 @@ public class WindowManagerProxy { mExecutor.execute(mDimLayerRunnable); } - public void swapTasks() { - mExecutor.execute(mSwapRunnable); - } - public void setTouchRegion(Rect region) { synchronized (mDockedRect) { mTouchableRegion.set(region); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java index 7e08d5605f40..9d2d71e28e5e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java @@ -15,6 +15,12 @@ */ package com.android.systemui.statusbar.car; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; + import android.app.ActivityManager.StackId; import android.content.Context; import android.content.Intent; @@ -117,7 +123,8 @@ class CarNavigationBarController { // Set up the persistent docked task if needed. if (mPersistentTaskIntent != null && !mStatusBar.hasDockedTask() && stackId != StackId.HOME_STACK_ID) { - mStatusBar.startActivityOnStack(mPersistentTaskIntent, StackId.DOCKED_STACK_ID); + mStatusBar.startActivityOnStack(mPersistentTaskIntent, + WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED); } } @@ -375,13 +382,15 @@ class CarNavigationBarController { // rather than the "preferred/last run" app. intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, index == mCurrentFacetIndex); - int stackId = StackId.FULLSCREEN_WORKSPACE_STACK_ID; + int windowingMode = WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; + int activityType = ACTIVITY_TYPE_UNDEFINED; if (intent.getCategories().contains(Intent.CATEGORY_HOME)) { - stackId = StackId.HOME_STACK_ID; + windowingMode = WINDOWING_MODE_UNDEFINED; + activityType = ACTIVITY_TYPE_HOME; } setCurrentFacet(index); - mStatusBar.startActivityOnStack(intent, stackId); + mStatusBar.startActivityOnStack(intent, windowingMode, activityType); } /** @@ -391,6 +400,7 @@ class CarNavigationBarController { */ private void onFacetLongClicked(Intent intent, int index) { setCurrentFacet(index); - mStatusBar.startActivityOnStack(intent, StackId.FULLSCREEN_WORKSPACE_STACK_ID); + mStatusBar.startActivityOnStack(intent, + WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_UNDEFINED); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index 680f693a83f8..10fc496fcfd2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -378,9 +378,10 @@ public class CarStatusBar extends StatusBar implements return result; } - public int startActivityOnStack(Intent intent, int stackId) { - ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchStackId(stackId); + public int startActivityOnStack(Intent intent, int windowingMode, int activityType) { + final ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchWindowingMode(windowingMode); + options.setLaunchActivityType(activityType); return startActivityWithOptions(intent, options.toBundle()); } 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 200cada972a7..4739a2eed6de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -20,6 +20,7 @@ import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; import static android.app.StatusBarManager.windowStateToString; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; @@ -37,7 +38,6 @@ import android.animation.AnimatorListenerAdapter; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; -import android.app.ActivityManager.StackId; import android.app.ActivityOptions; import android.app.INotificationManager; import android.app.KeyguardManager; @@ -1057,6 +1057,7 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationData.setHeadsUpManager(mHeadsUpManager); mGroupManager.setHeadsUpManager(mHeadsUpManager); mHeadsUpManager.setVisualStabilityManager(mVisualStabilityManager); + putComponent(HeadsUpManager.class, mHeadsUpManager); if (MULTIUSER_DEBUG) { mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById( @@ -5931,7 +5932,7 @@ public class StatusBar extends SystemUI implements DemoMode, private boolean superOnClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) { return super.onClickHandler(view, pendingIntent, fillInIntent, - StackId.FULLSCREEN_WORKSPACE_STACK_ID); + WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); } private boolean handleRemoteInput(View view, PendingIntent pendingIntent, Intent fillInIntent) { @@ -7148,10 +7149,10 @@ public class StatusBar extends SystemUI implements DemoMode, } protected Bundle getActivityOptions() { - // Anything launched from the notification shade should always go into the - // fullscreen stack. - ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchStackId(StackId.FULLSCREEN_WORKSPACE_STACK_ID); + // Anything launched from the notification shade should always go into the secondary + // split-screen windowing mode. + final ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); return options.toBundle(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index bb7b197c2a05..b7e6a40c6880 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -16,11 +16,21 @@ package com.android.systemui.statusbar.policy; +import static junit.framework.Assert.assertEquals; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkCapabilities; import android.net.wifi.WifiManager; -import android.os.Looper; import android.provider.Settings; import android.provider.Settings.Global; import android.telephony.PhoneStateListener; @@ -29,16 +39,18 @@ import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.testing.TestableLooper; import android.util.Log; + import com.android.internal.telephony.cdma.EriInfo; import com.android.settingslib.net.DataUsageController; +import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.phone.SignalDrawable; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults; -import com.android.systemui.SysuiTestCase; import org.junit.Before; import org.junit.Rule; @@ -46,25 +58,12 @@ import org.junit.rules.TestWatcher; import org.junit.runner.Description; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; -import static junit.framework.Assert.assertEquals; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - public class NetworkControllerBaseTest extends SysuiTestCase { private static final String TAG = "NetworkControllerBaseTest"; protected static final int DEFAULT_LEVEL = 2; @@ -131,11 +130,12 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mUserCallback = (DeviceProvisionedListener) invocation.getArguments()[0]; mUserCallback.onUserSetupChanged(); mUserCallback.onDeviceProvisionedChanged(); + TestableLooper.get(this).processAllMessages(); return null; }).when(mMockProvisionController).addCallback(any()); mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm, - mConfig, Looper.getMainLooper(), mCallbackHandler, + mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler, mock(AccessPointControllerImpl.class), mock(DataUsageController.class), mMockSubDefaults, mMockProvisionController); setupNetworkController(); @@ -176,7 +176,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false); NetworkControllerImpl networkControllerNoMobile = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm, - mConfig, mContext.getMainLooper(), mCallbackHandler, + mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler, mock(AccessPointControllerImpl.class), mock(DataUsageController.class), mMockSubDefaults, mock(DeviceProvisionedController.class)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index 0313a4374d55..1419e9ad43a2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -9,6 +9,9 @@ import android.os.Looper; import android.support.test.runner.AndroidJUnit4; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.testing.TestableLooper.RunWithLooper; import com.android.settingslib.net.DataUsageController; @@ -16,7 +19,8 @@ import org.junit.Test; import org.junit.runner.RunWith; @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(AndroidTestingRunner.class) +@RunWithLooper public class NetworkControllerDataTest extends NetworkControllerBaseTest { @Test @@ -126,6 +130,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(false); mUserCallback.onUserSetupChanged(); + TestableLooper.get(this).processAllMessages(); // Don't show the X until the device is setup. verifyDataIndicators(0, 0); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java index 9ac51b65f382..d2d73470efe7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java @@ -3,6 +3,8 @@ package com.android.systemui.statusbar.policy; import android.net.NetworkCapabilities; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; import com.android.systemui.statusbar.policy.NetworkController.IconState; @@ -14,7 +16,8 @@ import org.mockito.Mockito; import static junit.framework.Assert.assertEquals; @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(AndroidTestingRunner.class) +@RunWithLooper public class NetworkControllerEthernetTest extends NetworkControllerBaseTest { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index b353f5ab5137..3ad107c22245 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -25,6 +25,8 @@ import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyIntents; @@ -46,7 +48,8 @@ import static junit.framework.Assert.assertFalse; import static org.mockito.Mockito.mock; @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(AndroidTestingRunner.class) +@RunWithLooper public class NetworkControllerSignalTest extends NetworkControllerBaseTest { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java index ffd0165195e5..4c18f8d82750 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java @@ -7,6 +7,8 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; import com.android.systemui.statusbar.policy.NetworkController.IconState; @@ -21,7 +23,8 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; @SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(AndroidTestingRunner.class) +@RunWithLooper public class NetworkControllerWifiTest extends NetworkControllerBaseTest { // These match the constants in WifiManager and need to be kept up to date. private static final int MIN_RSSI = -100; diff --git a/proto/src/ipconnectivity.proto b/proto/src/ipconnectivity.proto index 777468a9e0d2..437da8f3f17a 100644 --- a/proto/src/ipconnectivity.proto +++ b/proto/src/ipconnectivity.proto @@ -501,8 +501,8 @@ message WakeupStats { // between [1001, 9999]. See android.os.Process for possible uids. optional int64 non_application_wakeups = 6; - // The total number of wakeup packets with no associated sockets. - optional int64 unrouted_wakeups = 7; + // The total number of wakeup packets with no associated socket or uid. + optional int64 no_uid_wakeups = 7; } // Represents one of the IP connectivity event defined in this file. diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index aa4217cec802..07302706d134 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -4451,6 +4451,82 @@ message MetricsEvent { // OS: O MR FIELD_SELECTION_SMART_RANGE = 1123; + // The value of an autofillable and savable view was reset + // Package: Package of app that was autofilled + // OS: O MR + // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request + // Tag FIELD_AUTOFILL_PREVIOUS_LENGTH: the previous length of the value + AUTOFILL_VALUE_RESET = 1124; + + // Tag of AUTOFILL_VALUE_RESET + // OS: O MR + FIELD_AUTOFILL_PREVIOUS_LENGTH = 1125; + + // An autofill dataset authentification succeeded + // Package: Package of app that was autofilled + // OS: O MR + // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request + AUTOFILL_DATASET_AUTHENTICATED = 1126; + + // An autofill service provided an invalid dataset authentification + // Package: Package of app that was autofilled + // OS: O MR + // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request + AUTOFILL_INVALID_DATASET_AUTHENTICATION = 1127; + + // An autofill service provided an invalid authentification extra + // Package: Package of app that was autofilled + // OS: O MR + // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request + AUTOFILL_INVALID_AUTHENTICATION = 1128; + + // An autofill service used a custom description (using RemoteViews) in the Save affordance + // Package: Package of app that is autofilled + // OS: O MR + // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request + // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service + AUTOFILL_SAVE_CUSTOM_DESCRIPTION = 1129; + + // FIELD - Type of save object passed by the service when the Save UI is shown + // OS: O MR + FIELD_AUTOFILL_SAVE_TYPE = 1130; + + // An autofill service used a custom subtitle (String) in the Save affordance + // Package: Package of app that is autofilled + // OS: O MR + // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request + // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service + AUTOFILL_SAVE_CUSTOM_SUBTITLE = 1131; + + // User tapped a link in the custom description of the Save affordance provided by an autofill service + // Package: Package of app that is autofilled + // OS: O MR + // Type TYPE_UNKNOWN: The link was not properly set by the service + // Type TYPE_OPEN: The link launched an activity + // Type TYPE_FAILURE: The link could not launc an activity + // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request + // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service + AUTOFILL_SAVE_LINK_TAPPED = 1132; + + // Result of the validation on save when an autofill service provided a validator + // Package: Package of app that is autofilled + // OS: O MR + // Type TYPE_FAILURE: The validation could not be performed due to an error + // Type TYPE_SUCCESS: The validation passed + // Type TYPE_DISMISS: The validation failed + // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request + // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service + AUTOFILL_SAVE_VALIDATION = 1133; + + // Result of an operation in the autofill save affordance after the user tapped a link in the custom description + // provided by the autofill service + // Package: Package of app that is autofilled + // OS: O MR + // Type TYPE_OPEN: The save affordance was restored + // Type TYPE_DISMISS: The save affordcance was destroyed + // Type TYPE_FAILURE: An invalid opperation was reported by the app's AutofillManager + AUTOFILL_PENDING_SAVE_UI_OPERATION = 1134; + // ---- End O-MR1 Constants, all O-MR1 constants go above this line ---- // OPEN: Settings > Network & Internet > Mobile network diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index ddc819d39d5e..a1c75bfc16c0 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -650,7 +650,7 @@ public final class AutofillManagerService extends SystemService { synchronized (mLock) { final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); if (service == null) return false; - return Objects.equals(packageName, service.getPackageName()); + return Objects.equals(packageName, service.getServicePackageName()); } } diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index f2f96f824e5b..7212b2335a47 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -146,8 +146,9 @@ final class AutofillManagerServiceImpl { updateLocked(disabled); } + @Nullable CharSequence getServiceName() { - final String packageName = getPackageName(); + final String packageName = getServicePackageName(); if (packageName == null) { return null; } @@ -162,7 +163,8 @@ final class AutofillManagerServiceImpl { } } - String getPackageName() { + @Nullable + String getServicePackageName() { final ComponentName serviceComponent = getServiceComponentName(); if (serviceComponent != null) { return serviceComponent.getPackageName(); @@ -636,7 +638,7 @@ final class AutofillManagerServiceImpl { void destroySessionsLocked() { if (mSessions.size() == 0) { - mUi.destroyAll(null, null); + mUi.destroyAll(null, null, false); return; } while (mSessions.size() > 0) { diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java index 086dd29f0c97..236fbfd94f53 100644 --- a/services/autofill/java/com/android/server/autofill/Helper.java +++ b/services/autofill/java/com/android/server/autofill/Helper.java @@ -18,6 +18,7 @@ package com.android.server.autofill; import android.annotation.NonNull; import android.annotation.Nullable; +import android.metrics.LogMaker; import android.os.Bundle; import android.service.autofill.Dataset; import android.util.ArrayMap; @@ -25,6 +26,8 @@ import android.util.ArraySet; import android.view.autofill.AutofillId; import android.view.autofill.AutofillValue; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; + import java.util.ArrayList; import java.util.Arrays; import java.util.Objects; @@ -99,4 +102,14 @@ public final class Helper { } return fields; } + + @NonNull + public static LogMaker newLogMaker(int category, String packageName, + String servicePackageName) { + final LogMaker log = new LogMaker(category).setPackageName(packageName); + if (servicePackageName != null) { + log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName); + } + return log; + } } diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index f315148547e9..af55807ff1f0 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -578,9 +578,8 @@ final class RemoteFillService implements DeathRecipient { public void run() { synchronized (mLock) { if (isCancelledLocked()) { - // TODO(b/653742740): we should probably return here, but for now we're justing - // logging to confirm this is the problem if it happens again. - Slog.e(LOG_TAG, "run() called after canceled: " + mRequest); + if (sDebug) Slog.d(LOG_TAG, "run() called after canceled: " + mRequest); + return; } } final RemoteFillService remoteService = getService(); diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 171053fd8ddf..ed3441ff7328 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -417,7 +417,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mPackageName = packageName; mClient = IAutoFillManagerClient.Stub.asInterface(client); - mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_STARTED, mPackageName); + writeLog(MetricsEvent.AUTOFILL_SESSION_STARTED); } /** @@ -471,19 +471,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if ((response.getDatasets() == null || response.getDatasets().isEmpty()) && response.getAuthentication() == null) { // Response is "empty" from an UI point of view, need to notify client. - notifyUnavailableToClient(); + notifyUnavailableToClient(false); } synchronized (mLock) { processResponseLocked(response, requestFlags); } - final LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST)) + final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName) .setType(MetricsEvent.TYPE_SUCCESS) - .setPackageName(mPackageName) .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, - response.getDatasets() == null ? 0 : response.getDatasets().size()) - .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, - servicePackageName); + response.getDatasets() == null ? 0 : response.getDatasets().size()); mMetricsLogger.write(log); } @@ -499,10 +496,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } mService.resetLastResponse(); } - LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST)) - .setType(MetricsEvent.TYPE_FAILURE) - .setPackageName(mPackageName) - .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName); + LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName) + .setType(MetricsEvent.TYPE_FAILURE); mMetricsLogger.write(log); getUiForShowing().showError(message, this); @@ -521,11 +516,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } } - LogMaker log = (new LogMaker( - MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST)) - .setType(MetricsEvent.TYPE_SUCCESS) - .setPackageName(mPackageName) - .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName); + LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST, servicePackageName) + .setType(MetricsEvent.TYPE_SUCCESS); mMetricsLogger.write(log); // Nothing left to do... @@ -545,11 +537,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } } - LogMaker log = (new LogMaker( - MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST)) - .setType(MetricsEvent.TYPE_FAILURE) - .setPackageName(mPackageName) - .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName); + LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST, servicePackageName) + .setType(MetricsEvent.TYPE_FAILURE); mMetricsLogger.write(log); getUiForShowing().showError(message, this); @@ -583,6 +572,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // FillServiceCallbacks @Override public void authenticate(int requestId, int datasetIndex, IntentSender intent, Bundle extras) { + if (sDebug) { + Slog.d(TAG, "authenticate(): requestId=" + requestId + "; datasetIdx=" + datasetIndex + + "; intentSender=" + intent); + } final Intent fillInIntent; synchronized (mLock) { if (mDestroyed) { @@ -591,6 +584,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } fillInIntent = createAuthFillInIntentLocked(requestId, extras); + if (fillInIntent == null) { + forceRemoveSelfLocked(); + return; + } } mService.setAuthenticationSelected(id, mClientState); @@ -746,21 +743,22 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final Parcelable result = data.getParcelable(AutofillManager.EXTRA_AUTHENTICATION_RESULT); if (sDebug) Slog.d(TAG, "setAuthenticationResultLocked(): result=" + result); if (result instanceof FillResponse) { - final FillResponse response = (FillResponse) result; - mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName); - replaceResponseLocked(authenticatedResponse, response); + writeLog(MetricsEvent.AUTOFILL_AUTHENTICATED); + replaceResponseLocked(authenticatedResponse, (FillResponse) result); } else if (result instanceof Dataset) { - // TODO: add proper metric if (datasetIdx != AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED) { + writeLog(MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED); final Dataset dataset = (Dataset) result; authenticatedResponse.getDatasets().set(datasetIdx, dataset); autoFill(requestId, datasetIdx, dataset, false); + } else { + writeLog(MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION); } } else { if (result != null) { Slog.w(TAG, "service returned invalid auth type: " + result); } - // TODO: add proper metric (on else) + writeLog(MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION); processNullResponseLocked(0); } } @@ -774,43 +772,57 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mHasCallback = hasIt; } - /** - * Shows the save UI, when session can be saved. - * - * @return {@code true} if session is done, or {@code false} if it's pending user action. - */ - public boolean showSaveLocked() { - if (mDestroyed) { - Slog.w(TAG, "Call to Session#showSaveLocked() rejected - session: " - + id + " destroyed"); - return false; - } + @Nullable + private FillResponse getLastResponseLocked(@Nullable String logPrefix) { if (mContexts == null) { - Slog.d(TAG, "showSaveLocked(): no contexts"); - return true; + if (sDebug && logPrefix != null) Slog.d(TAG, logPrefix + ": no contexts"); + return null; } if (mResponses == null) { // Happens when the activity / session was finished before the service replied, or // when the service cannot autofill it (and returned a null response). - if (sVerbose) { - Slog.v(TAG, "showSaveLocked(): no responses on session"); + if (sVerbose && logPrefix != null) { + Slog.v(TAG, logPrefix + ": no responses on session"); } - return true; + return null; } final int lastResponseIdx = getLastResponseIndexLocked(); if (lastResponseIdx < 0) { - Slog.w(TAG, "showSaveLocked(): did not get last response. mResponses=" + mResponses - + ", mViewStates=" + mViewStates); - return true; + if (logPrefix != null) { + Slog.w(TAG, logPrefix + ": did not get last response. mResponses=" + mResponses + + ", mViewStates=" + mViewStates); + } + return null; } final FillResponse response = mResponses.valueAt(lastResponseIdx); - final SaveInfo saveInfo = response.getSaveInfo(); - if (sVerbose) { - Slog.v(TAG, "showSaveLocked(): mResponses=" + mResponses + ", mContexts=" + mContexts + if (sVerbose && logPrefix != null) { + Slog.v(TAG, logPrefix + ": mResponses=" + mResponses + ", mContexts=" + mContexts + ", mViewStates=" + mViewStates); } + return response; + } + + @Nullable + private SaveInfo getSaveInfoLocked() { + final FillResponse response = getLastResponseLocked(null); + return response == null ? null : response.getSaveInfo(); + } + + /** + * Shows the save UI, when session can be saved. + * + * @return {@code true} if session is done, or {@code false} if it's pending user action. + */ + public boolean showSaveLocked() { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#showSaveLocked() rejected - session: " + + id + " destroyed"); + return false; + } + final FillResponse response = getLastResponseLocked("showSaveLocked()"); + final SaveInfo saveInfo = response == null ? null : response.getSaveInfo(); /* * The Save dialog is only shown if all conditions below are met: @@ -922,15 +934,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final InternalValidator validator = saveInfo.getValidator(); if (validator != null) { + final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_SAVE_VALIDATION); boolean isValid; try { isValid = validator.isValid(valueFinder); + log.setType(isValid + ? MetricsEvent.TYPE_SUCCESS + : MetricsEvent.TYPE_DISMISS); } catch (Exception e) { - Slog.e(TAG, "Not showing save UI because of exception during validation " - + e.getClass()); + Slog.e(TAG, "Not showing save UI because validation failed:", e); + log.setType(MetricsEvent.TYPE_FAILURE); + mMetricsLogger.write(log); return true; } + mMetricsLogger.write(log); if (!isValid) { Slog.i(TAG, "not showing save UI because fields failed validation"); return true; @@ -978,7 +996,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final IAutoFillManagerClient client = getClient(); mPendingSaveUi = new PendingUi(mActivityToken, id, client); getUiForShowing().showSaveUi(mService.getServiceLabel(), mService.getServiceIcon(), - saveInfo, valueFinder, mPackageName, this, mPendingSaveUi); + mService.getServicePackageName(), saveInfo, valueFinder, mPackageName, this, + mPendingSaveUi); if (client != null) { try { client.setSaveUiState(id, true); @@ -1244,6 +1263,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState break; case ACTION_VALUE_CHANGED: if (value != null && !value.equals(viewState.getCurrentValue())) { + if (value.isEmpty() + && viewState.getCurrentValue() != null + && viewState.getCurrentValue().isText() + && viewState.getCurrentValue().getTextValue() != null + && getSaveInfoLocked() != null) { + final int length = viewState.getCurrentValue().getTextValue().length(); + if (sDebug) { + Slog.d(TAG, "updateLocked(" + id + "): resetting value that was " + + length + " chars long"); + } + final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_VALUE_RESET) + .addTaggedData(MetricsEvent.FIELD_AUTOFILL_PREVIOUS_LENGTH, length); + mMetricsLogger.write(log); + } + // Always update the internal state. viewState.setCurrentValue(value); @@ -1319,7 +1353,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState filterText = value.getTextValue().toString(); } - getUiForShowing().showFillUi(filledId, response, filterText, mPackageName, this); + getUiForShowing().showFillUi(filledId, response, filterText, + mService.getServicePackageName(), mPackageName, this); } boolean isDestroyed() { @@ -1334,11 +1369,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - private void notifyUnavailableToClient() { + private void notifyUnavailableToClient(boolean sessionFinished) { synchronized (mLock) { - if (!mHasCallback || mCurrentViewId == null) return; + if (mCurrentViewId == null) return; try { - mClient.notifyNoFillUi(id, mCurrentViewId); + if (mHasCallback) { + mClient.notifyNoFillUi(id, mCurrentViewId, sessionFinished); + } else if (sessionFinished) { + mClient.setSessionFinished(); + } } catch (RemoteException e) { Slog.e(TAG, "Error notifying client no fill UI: id=" + mCurrentViewId, e); } @@ -1426,7 +1465,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } mService.resetLastResponse(); // Nothing to be done, but need to notify client. - notifyUnavailableToClient(); + notifyUnavailableToClient(true); removeSelf(); } @@ -1545,6 +1584,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } void autoFill(int requestId, int datasetIndex, Dataset dataset, boolean generateEvent) { + if (sDebug) { + Slog.d(TAG, "autoFill(): requestId=" + requestId + "; datasetIdx=" + datasetIndex + + "; dataset=" + dataset); + } synchronized (mLock) { if (mDestroyed) { Slog.w(TAG, "Call to Session#autoFill() rejected - session: " @@ -1565,10 +1608,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mService.logDatasetAuthenticationSelected(dataset.getId(), id, mClientState); setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH, false); final Intent fillInIntent = createAuthFillInIntentLocked(requestId, mClientState); - + if (fillInIntent == null) { + forceRemoveSelfLocked(); + return; + } final int authenticationId = AutofillManager.makeAuthenticationId(requestId, datasetIndex); startAuthentication(authenticationId, dataset.getAuthentication(), fillInIntent); + } } @@ -1578,14 +1625,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } + // TODO: this should never be null, but we got at least one occurrence, probably due to a race. + @Nullable private Intent createAuthFillInIntentLocked(int requestId, Bundle extras) { final Intent fillInIntent = new Intent(); final FillContext context = getFillContextByRequestIdLocked(requestId); if (context == null) { - // TODO(b/653742740): this will crash system_server. We need to handle it, but we're - // keeping it crashing for now so we can diagnose when it happens again - Slog.wtf(TAG, "no FillContext for requestId" + requestId + "; mContexts= " + mContexts); + Slog.wtf(TAG, "createAuthFillInIntentLocked(): no FillContext. requestId=" + requestId + + "; mContexts= " + mContexts); + return null; } fillInIntent.putExtra(AutofillManager.EXTRA_ASSIST_STRUCTURE, context.getStructure()); fillInIntent.putExtra(AutofillManager.EXTRA_CLIENT_STATE, extras); @@ -1732,10 +1781,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (mDestroyed) { return null; } - mUi.destroyAll(mPendingSaveUi, this); + mUi.destroyAll(mPendingSaveUi, this, true); mUi.clearCallback(this); mDestroyed = true; - mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_FINISHED, mPackageName); + writeLog(MetricsEvent.AUTOFILL_SESSION_FINISHED); return mRemoteFillService; } @@ -1748,7 +1797,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mPendingSaveUi = null; removeSelfLocked(); - mUi.destroyAll(mPendingSaveUi, this); + + mHandlerCaller.getHandler().post(() -> { + try { + mClient.setState(mService.isEnabled(), true, false); + } catch (RemoteException e) { + Slog.w(TAG, "error updating client state: " + e); + } + }); + + mUi.destroyAll(mPendingSaveUi, this, false); } /** @@ -1820,4 +1878,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } return lastResponseIdx; } + + private LogMaker newLogMaker(int category) { + return newLogMaker(category, mService.getServicePackageName()); + } + + private LogMaker newLogMaker(int category, String servicePackageName) { + return Helper.newLogMaker(category, mPackageName, servicePackageName); + } + + private void writeLog(int category) { + mMetricsLogger.write(newLogMaker(category)); + } } diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java index cac2bff579ed..36b95fc02ed8 100644 --- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java @@ -40,8 +40,9 @@ import android.view.autofill.IAutofillWindowPresenter; import android.widget.Toast; import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.nano.MetricsProto; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.server.UiThread; +import com.android.server.autofill.Helper; import java.io.PrintWriter; @@ -158,21 +159,22 @@ public final class AutoFillUI { * @param focusedId the currently focused field * @param response the current fill response * @param filterText text of the view to be filled + * @param servicePackageName package name of the autofill service filling the activity * @param packageName package name of the activity that is filled * @param callback Identifier for the caller */ public void showFillUi(@NonNull AutofillId focusedId, @NonNull FillResponse response, - @Nullable String filterText, @NonNull String packageName, - @NonNull AutoFillUiCallback callback) { + @Nullable String filterText, @Nullable String servicePackageName, + @NonNull String packageName, @NonNull AutoFillUiCallback callback) { if (sDebug) { final int size = filterText == null ? 0 : filterText.length(); Slog.d(TAG, "showFillUi(): id=" + focusedId + ", filter=" + size + " chars"); } - final LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_FILL_UI)) - .setPackageName(packageName) - .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_FILTERTEXT_LEN, + final LogMaker log = + Helper.newLogMaker(MetricsEvent.AUTOFILL_FILL_UI, packageName, servicePackageName) + .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FILTERTEXT_LEN, filterText == null ? 0 : filterText.length()) - .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, + .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, response.getDatasets() == null ? 0 : response.getDatasets().size()); mHandler.post(() -> { @@ -184,7 +186,7 @@ public final class AutoFillUI { filterText, mOverlayControl, new FillUi.Callback() { @Override public void onResponsePicked(FillResponse response) { - log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL); + log.setType(MetricsEvent.TYPE_DETAIL); hideFillUiUiThread(callback); if (mCallback != null) { mCallback.authenticate(response.getRequestId(), @@ -195,7 +197,7 @@ public final class AutoFillUI { @Override public void onDatasetPicked(Dataset dataset) { - log.setType(MetricsProto.MetricsEvent.TYPE_ACTION); + log.setType(MetricsEvent.TYPE_ACTION); hideFillUiUiThread(callback); if (mCallback != null) { final int datasetIndex = response.getDatasets().indexOf(dataset); @@ -205,14 +207,14 @@ public final class AutoFillUI { @Override public void onCanceled() { - log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS); + log.setType(MetricsEvent.TYPE_DISMISS); hideFillUiUiThread(callback); } @Override public void onDestroy() { - if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) { - log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE); + if (log.getType() == MetricsEvent.TYPE_UNKNOWN) { + log.setType(MetricsEvent.TYPE_CLOSE); } mMetricsLogger.write(log); } @@ -246,37 +248,39 @@ public final class AutoFillUI { * Shows the UI asking the user to save for autofill. */ public void showSaveUi(@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon, - @NonNull SaveInfo info,@NonNull ValueFinder valueFinder, @NonNull String packageName, + @Nullable String servicePackageName, @NonNull SaveInfo info, + @NonNull ValueFinder valueFinder, @NonNull String packageName, @NonNull AutoFillUiCallback callback, @NonNull PendingUi pendingSaveUi) { if (sVerbose) Slog.v(TAG, "showSaveUi() for " + packageName + ": " + info); int numIds = 0; numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length; numIds += info.getOptionalIds() == null ? 0 : info.getOptionalIds().length; - LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_SAVE_UI)) - .setPackageName(packageName).addTaggedData( - MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds); + final LogMaker log = + Helper.newLogMaker(MetricsEvent.AUTOFILL_SAVE_UI, packageName, servicePackageName) + .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds); mHandler.post(() -> { if (callback != mCallback) { return; } hideAllUiThread(callback); - mSaveUi = new SaveUi(mContext, pendingSaveUi, serviceLabel, serviceIcon, info, - valueFinder, mOverlayControl, new SaveUi.OnSaveListener() { + mSaveUi = new SaveUi(mContext, pendingSaveUi, serviceLabel, serviceIcon, + servicePackageName, packageName, info, valueFinder, mOverlayControl, + new SaveUi.OnSaveListener() { @Override public void onSave() { - log.setType(MetricsProto.MetricsEvent.TYPE_ACTION); + log.setType(MetricsEvent.TYPE_ACTION); hideSaveUiUiThread(mCallback); if (mCallback != null) { mCallback.save(); } - destroySaveUiUiThread(pendingSaveUi); + destroySaveUiUiThread(pendingSaveUi, true); } @Override public void onCancel(IntentSender listener) { - log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS); + log.setType(MetricsEvent.TYPE_DISMISS); hideSaveUiUiThread(mCallback); if (listener != null) { try { @@ -289,13 +293,13 @@ public final class AutoFillUI { if (mCallback != null) { mCallback.cancelSave(); } - destroySaveUiUiThread(pendingSaveUi); + destroySaveUiUiThread(pendingSaveUi, true); } @Override public void onDestroy() { - if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) { - log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE); + if (log.getType() == MetricsEvent.TYPE_UNKNOWN) { + log.setType(MetricsEvent.TYPE_CLOSE); if (mCallback != null) { mCallback.cancelSave(); @@ -331,8 +335,8 @@ public final class AutoFillUI { * Destroy all UI affordances. */ public void destroyAll(@Nullable PendingUi pendingSaveUi, - @Nullable AutoFillUiCallback callback) { - mHandler.post(() -> destroyAllUiThread(pendingSaveUi, callback)); + @Nullable AutoFillUiCallback callback, boolean notifyClient) { + mHandler.post(() -> destroyAllUiThread(pendingSaveUi, callback, notifyClient)); } public void dump(PrintWriter pw) { @@ -375,7 +379,7 @@ public final class AutoFillUI { } @android.annotation.UiThread - private void destroySaveUiUiThread(@Nullable PendingUi pendingSaveUi) { + private void destroySaveUiUiThread(@Nullable PendingUi pendingSaveUi, boolean notifyClient) { if (mSaveUi == null) { // Calling destroySaveUiUiThread() twice is normal - it usually happens when the // first call is made after the SaveUI is hidden and the second when the session is @@ -387,7 +391,7 @@ public final class AutoFillUI { if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): " + pendingSaveUi); mSaveUi.destroy(); mSaveUi = null; - if (pendingSaveUi != null) { + if (pendingSaveUi != null && notifyClient) { try { if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): notifying client"); pendingSaveUi.client.setSaveUiState(pendingSaveUi.id, false); @@ -399,9 +403,9 @@ public final class AutoFillUI { @android.annotation.UiThread private void destroyAllUiThread(@Nullable PendingUi pendingSaveUi, - @Nullable AutoFillUiCallback callback) { + @Nullable AutoFillUiCallback callback, boolean notifyClient) { hideFillUiUiThread(callback); - destroySaveUiUiThread(pendingSaveUi); + destroySaveUiUiThread(pendingSaveUi, notifyClient); } @android.annotation.UiThread @@ -413,7 +417,7 @@ public final class AutoFillUI { Slog.d(TAG, "hideAllUiThread(): " + "destroying Save UI because pending restoration is finished"); } - destroySaveUiUiThread(pendingSaveUi); + destroySaveUiUiThread(pendingSaveUi, true); } } } diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index d0b2e9240b58..32f4d69fc3e3 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -20,16 +20,15 @@ import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sVerbose; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.Dialog; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.IntentSender; import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.metrics.LogMaker; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; @@ -53,6 +52,8 @@ import android.widget.ScrollView; import android.widget.TextView; import com.android.internal.R; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.server.UiThread; import java.io.PrintWriter; @@ -111,6 +112,7 @@ final class SaveUi { } private final Handler mHandler = UiThread.getHandler(); + private final MetricsLogger mMetricsLogger = new MetricsLogger(); private final @NonNull Dialog mDialog; @@ -121,16 +123,21 @@ final class SaveUi { private final CharSequence mTitle; private final CharSequence mSubTitle; private final PendingUi mPendingUi; + private final String mServicePackageName; + private final String mPackageName; private boolean mDestroyed; SaveUi(@NonNull Context context, @NonNull PendingUi pendingUi, @NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon, + @Nullable String servicePackageName, @NonNull String packageName, @NonNull SaveInfo info, @NonNull ValueFinder valueFinder, @NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener) { mPendingUi= pendingUi; mListener = new OneTimeListener(listener); mOverlayControl = overlayControl; + mServicePackageName = servicePackageName; + mPackageName = packageName; final LayoutInflater inflater = LayoutInflater.from(context); final View view = inflater.inflate(R.layout.autofill_save, null); @@ -181,6 +188,8 @@ final class SaveUi { ScrollView subtitleContainer = null; final CustomDescription customDescription = info.getCustomDescription(); if (customDescription != null) { + writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION, type); + mSubTitle = null; if (sDebug) Slog.d(TAG, "Using custom description"); @@ -190,40 +199,35 @@ final class SaveUi { @Override public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent intent) { + final LogMaker log = + newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, type); // We need to hide the Save UI before launching the pending intent, and // restore back it once the activity is finished, and that's achieved by // adding a custom extra in the activity intent. - if (pendingIntent != null) { - if (intent == null) { - Slog.w(TAG, - "remote view on custom description does not have intent"); - return false; - } - if (!pendingIntent.isActivity()) { - Slog.w(TAG, "ignoring custom description pending intent that's not " - + "for an activity: " + pendingIntent); - return false; - } - if (sVerbose) { - Slog.v(TAG, - "Intercepting custom description intent: " + intent); - } - final IBinder token = mPendingUi.getToken(); - intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token); - try { - pendingUi.client.startIntentSender(pendingIntent.getIntentSender(), - intent); - mPendingUi.setState(PendingUi.STATE_PENDING); - if (sDebug) { - Slog.d(TAG, "hiding UI until restored with token " + token); - } - hide(); - } catch (RemoteException e) { - Slog.w(TAG, "error triggering pending intent: " + intent); - return false; - } + final boolean isValid = isValidLink(pendingIntent, intent); + if (!isValid) { + log.setType(MetricsEvent.TYPE_UNKNOWN); + mMetricsLogger.write(log); + return false; + } + if (sVerbose) Slog.v(TAG, "Intercepting custom description intent"); + final IBinder token = mPendingUi.getToken(); + intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token); + try { + pendingUi.client.startIntentSender(pendingIntent.getIntentSender(), + intent); + mPendingUi.setState(PendingUi.STATE_PENDING); + if (sDebug) Slog.d(TAG, "hiding UI until restored with token " + token); + hide(); + log.setType(MetricsEvent.TYPE_OPEN); + mMetricsLogger.write(log); + return true; + } catch (RemoteException e) { + Slog.w(TAG, "error triggering pending intent: " + intent); + log.setType(MetricsEvent.TYPE_FAILURE); + mMetricsLogger.write(log); + return false; } - return true; } }; @@ -241,6 +245,7 @@ final class SaveUi { } else { mSubTitle = info.getDescription(); if (mSubTitle != null) { + writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_SUBTITLE, type); subtitleContainer = view.findViewById(R.id.autofill_save_custom_subtitle); final TextView subtitleView = new TextView(context); subtitleView.setText(mSubTitle); @@ -309,8 +314,39 @@ final class SaveUi { Slog.w(TAG, "Not adding service icon of size " + "(" + actualWidth + "x" + actualHeight + ") because maximum is " + "(" + maxWidth + "x" + maxHeight + ")."); - iconView.setVisibility(View.INVISIBLE); + ((ViewGroup)iconView.getParent()).removeView(iconView); + } + } + + private static boolean isValidLink(PendingIntent pendingIntent, Intent intent) { + if (pendingIntent == null) { + Slog.w(TAG, "isValidLink(): custom description without pending intent"); + return false; } + if (!pendingIntent.isActivity()) { + Slog.w(TAG, "isValidLink(): pending intent not for activity"); + return false; + } + if (intent == null) { + Slog.w(TAG, "isValidLink(): no intent"); + return false; + } + return true; + } + + private LogMaker newLogMaker(int category, int saveType) { + return newLogMaker(category) + .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SAVE_TYPE, saveType); + } + + private LogMaker newLogMaker(int category) { + return new LogMaker(category) + .setPackageName(mPackageName) + .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, mServicePackageName); + } + + private void writeLog(int category, int saveType) { + mMetricsLogger.write(newLogMaker(category, saveType)); } /** @@ -326,17 +362,25 @@ final class SaveUi { + mPendingUi.getToken()); return; } - switch (operation) { - case AutofillManager.PENDING_UI_OPERATION_RESTORE: - if (sDebug) Slog.d(TAG, "Restoring save dialog for " + token); - show(); - break; - case AutofillManager.PENDING_UI_OPERATION_CANCEL: - if (sDebug) Slog.d(TAG, "Cancelling pending save dialog for " + token); - hide(); - break; - default: - Slog.w(TAG, "restore(): invalid operation " + operation); + final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_PENDING_SAVE_UI_OPERATION); + try { + switch (operation) { + case AutofillManager.PENDING_UI_OPERATION_RESTORE: + if (sDebug) Slog.d(TAG, "Restoring save dialog for " + token); + log.setType(MetricsEvent.TYPE_OPEN); + show(); + break; + case AutofillManager.PENDING_UI_OPERATION_CANCEL: + log.setType(MetricsEvent.TYPE_DISMISS); + if (sDebug) Slog.d(TAG, "Cancelling pending save dialog for " + token); + hide(); + break; + default: + log.setType(MetricsEvent.TYPE_FAILURE); + Slog.w(TAG, "restore(): invalid operation " + operation); + } + } finally { + mMetricsLogger.write(log); } mPendingUi.setState(PendingUi.STATE_FINISHED); } @@ -385,6 +429,8 @@ final class SaveUi { pw.print(prefix); pw.print("title: "); pw.println(mTitle); pw.print(prefix); pw.print("subtitle: "); pw.println(mSubTitle); pw.print(prefix); pw.print("pendingUi: "); pw.println(mPendingUi); + pw.print(prefix); pw.print("service: "); pw.println(mServicePackageName); + pw.print(prefix); pw.print("app: "); pw.println(mPackageName); final View view = mDialog.getWindow().getDecorView(); final int[] loc = view.getLocationOnScreen(); diff --git a/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java b/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java index 187d5d93bfdd..e29b7d58e018 100644 --- a/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java +++ b/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java @@ -21,7 +21,10 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.server.backup.RefactoredBackupManagerService; +import java.io.BufferedInputStream; +import java.io.DataInputStream; import java.io.EOFException; +import java.io.FileInputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; @@ -130,7 +133,8 @@ final class ProcessedPackagesJournal { return; } - try (RandomAccessFile oldJournal = new RandomAccessFile(journalFile, "r")) { + try (DataInputStream oldJournal = new DataInputStream( + new BufferedInputStream(new FileInputStream(journalFile)))) { while (true) { String packageName = oldJournal.readUTF(); if (DEBUG) { diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java index 1dede4713ab8..8b4cc7f6d22b 100644 --- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java @@ -679,6 +679,29 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter return token; } + /* + * Construct a backup agent instance for the metadata pseudopackage. This is a + * process-local non-lifecycle agent instance, so we manually set up the context + * topology for it. + */ + public PackageManagerBackupAgent makeMetadataAgent() { + PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager); + pmAgent.attach(mContext); + pmAgent.onCreate(); + return pmAgent; + } + + /* + * Same as above but with the explicit package-set configuration. + */ + public PackageManagerBackupAgent makeMetadataAgent(List<PackageInfo> packages) { + PackageManagerBackupAgent pmAgent = + new PackageManagerBackupAgent(mPackageManager, packages); + pmAgent.attach(mContext); + pmAgent.onCreate(); + return pmAgent; + } + // ----- Debug-only backup operation trace ----- public void addBackupTrace(String s) { if (DEBUG_BACKUP_TRACE) { @@ -809,17 +832,18 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter // Remember our ancestral dataset mTokenFile = new File(mBaseStateDir, "ancestral"); - try (RandomAccessFile tf = new RandomAccessFile(mTokenFile, "r")) { - int version = tf.readInt(); + try (DataInputStream tokenStream = new DataInputStream(new BufferedInputStream( + new FileInputStream(mTokenFile)))) { + int version = tokenStream.readInt(); if (version == CURRENT_ANCESTRAL_RECORD_VERSION) { - mAncestralToken = tf.readLong(); - mCurrentToken = tf.readLong(); + mAncestralToken = tokenStream.readLong(); + mCurrentToken = tokenStream.readLong(); - int numPackages = tf.readInt(); + int numPackages = tokenStream.readInt(); if (numPackages >= 0) { mAncestralPackages = new HashSet<>(); for (int i = 0; i < numPackages; i++) { - String pkgName = tf.readUTF(); + String pkgName = tokenStream.readUTF(); mAncestralPackages.add(pkgName); } } 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 edb65a42035f..90134e1a3ead 100644 --- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java +++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java @@ -306,6 +306,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba final int N = mPackages.size(); final byte[] buffer = new byte[8192]; for (int i = 0; i < N; i++) { + mBackupRunner = null; PackageInfo currentPackage = mPackages.get(i); String packageName = currentPackage.packageName; if (DEBUG) { @@ -491,7 +492,13 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba } EventLog.writeEvent(EventLogTags.FULL_BACKUP_AGENT_FAILURE, packageName, "transport rejected"); - // Do nothing, clean up, and continue looping. + // This failure state can come either a-priori from the transport, or + // from the preflight pass. If we got as far as preflight, we now need + // to tear down the target process. + if (mBackupRunner != null) { + backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); + } + // ... and continue looping. } else if (backupPackageStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) { BackupObserverUtils .sendBackupOnPackageResult(mBackupObserver, packageName, @@ -501,6 +508,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba EventLog.writeEvent(EventLogTags.FULL_BACKUP_QUOTA_EXCEEDED, packageName); } + backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); // Do nothing, clean up, and continue looping. } else if (backupPackageStatus == BackupTransport.AGENT_ERROR) { BackupObserverUtils @@ -527,6 +535,7 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba EventLog.writeEvent(EventLogTags.FULL_BACKUP_TRANSPORT_FAILURE); // Abort entire backup pass. backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED; + backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo); return; } else { // Success! 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 93277d460da4..7a8a920e7df7 100644 --- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java +++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java @@ -321,8 +321,7 @@ public class PerformBackupTask implements BackupRestoreTask { // because it's cheap and this way we guarantee that we don't get out of // step even if we're selecting among various transports at run time. if (mStatus == BackupTransport.TRANSPORT_OK) { - PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent( - backupManagerService.getPackageManager()); + PackageManagerBackupAgent pmAgent = backupManagerService.makeMetadataAgent(); mStatus = invokeAgentForBackup( PACKAGE_MANAGER_SENTINEL, IBackupAgent.Stub.asInterface(pmAgent.onBind()), mTransport); 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 62ae065be1ac..22691bb60bfa 100644 --- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java +++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java @@ -150,8 +150,7 @@ public class PerformAdbRestoreTask implements Runnable { mObserver = observer; mLatchObject = latch; mAgent = null; - mPackageManagerBackupAgent = new PackageManagerBackupAgent( - backupManagerService.getPackageManager()); + mPackageManagerBackupAgent = backupManagerService.makeMetadataAgent(); mAgentPackage = null; mTargetApp = null; mObbConnection = new FullBackupObbConnection(backupManagerService); 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 4c0bb48792ae..b538c6d4e472 100644 --- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java +++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java @@ -386,8 +386,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // Pull the Package Manager metadata from the restore set first mCurrentPackage = new PackageInfo(); mCurrentPackage.packageName = PACKAGE_MANAGER_SENTINEL; - mPmAgent = new PackageManagerBackupAgent(backupManagerService.getPackageManager(), - null); + mPmAgent = backupManagerService.makeMetadataAgent(null); mAgent = IBackupAgent.Stub.asInterface(mPmAgent.onBind()); if (MORE_DEBUG) { Slog.v(TAG, "initiating restore for PMBA"); 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 86877bab961d..d7cac7770cc8 100644 --- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java +++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java @@ -61,6 +61,11 @@ public class AppBackupUtils { return false; } + // 4. it is an "instant" app + if (app.isInstantApp()) { + return false; + } + // Everything else checks out; the only remaining roadblock would be if the // package were disabled return !appIsDisabled(app, pm); diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index c0fcfd07a75f..c7e22be1972d 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -111,8 +111,6 @@ import com.android.internal.util.HexDump; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.internal.widget.LockPatternUtils; -import com.android.server.NativeDaemonConnector.Command; -import com.android.server.NativeDaemonConnector.SensitiveArg; import com.android.server.pm.PackageManagerService; import com.android.server.storage.AppFuseBridge; @@ -138,7 +136,6 @@ import java.security.spec.KeySpec; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -161,8 +158,7 @@ import javax.crypto.spec.PBEKeySpec; * watch for and manage dynamically added storage, such as SD cards and USB mass * storage. Also decides how storage should be presented to users on the device. */ -class StorageManagerService extends IStorageManager.Stub - implements INativeDaemonConnectorCallbacks, Watchdog.Monitor { +class StorageManagerService extends IStorageManager.Stub implements Watchdog.Monitor { // Static direct instance pointer for the tightly-coupled idle service to use static StorageManagerService sSelf = null; @@ -206,18 +202,12 @@ class StorageManagerService extends IStorageManager.Stub } } - /** Flag to enable binder-based interface to vold */ - private static final boolean ENABLE_BINDER = true; - private static final boolean DEBUG_EVENTS = false; private static final boolean DEBUG_OBB = false; // Disable this since it messes up long-running cryptfs operations. private static final boolean WATCHDOG_ENABLE = false; - /** Flag to enable ASECs */ - private static final boolean ASEC_ENABLE = false; - /** * Our goal is for all Android devices to be usable as development devices, * which includes the new Direct Boot mode added in N. For devices that @@ -232,66 +222,9 @@ class StorageManagerService extends IStorageManager.Stub private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark"; private static final String TAG_STORAGE_TRIM = "storage_trim"; - private static final String VOLD_TAG = "VoldConnector"; - private static final String CRYPTD_TAG = "CryptdConnector"; - - /** Maximum number of ASEC containers allowed to be mounted. */ - private static final int MAX_CONTAINERS = 250; - /** Magic value sent by MoveTask.cpp */ private static final int MOVE_STATUS_COPY_FINISHED = 82; - /* - * Internal vold response code constants - */ - class VoldResponseCode { - /* - * 100 series - Requestion action was initiated; expect another reply - * before proceeding with a new command. - */ - public static final int VolumeListResult = 110; - public static final int AsecListResult = 111; - public static final int StorageUsersListResult = 112; - public static final int CryptfsGetfieldResult = 113; - - /* - * 200 series - Requestion action has been successfully completed. - */ - public static final int ShareStatusResult = 210; - public static final int AsecPathResult = 211; - public static final int ShareEnabledResult = 212; - - /* - * 400 series - Command was accepted, but the requested action - * did not take place. - */ - public static final int OpFailedNoMedia = 401; - public static final int OpFailedMediaBlank = 402; - public static final int OpFailedMediaCorrupt = 403; - public static final int OpFailedVolNotMounted = 404; - public static final int OpFailedStorageBusy = 405; - public static final int OpFailedStorageNotFound = 406; - - /* - * 600 series - Unsolicited broadcasts. - */ - public static final int DISK_CREATED = 640; - public static final int DISK_SIZE_CHANGED = 641; - public static final int DISK_LABEL_CHANGED = 642; - public static final int DISK_SCANNED = 643; - public static final int DISK_SYS_PATH_CHANGED = 644; - public static final int DISK_DESTROYED = 649; - - public static final int VOLUME_CREATED = 650; - public static final int VOLUME_STATE_CHANGED = 651; - public static final int VOLUME_FS_TYPE_CHANGED = 652; - public static final int VOLUME_FS_UUID_CHANGED = 653; - public static final int VOLUME_FS_LABEL_CHANGED = 654; - public static final int VOLUME_PATH_CHANGED = 655; - public static final int VOLUME_INTERNAL_PATH_CHANGED = 656; - public static final int VOLUME_DESTROYED = 659; - } - private static final int VERSION_INIT = 1; private static final int VERSION_ADD_PRIMARY = 2; private static final int VERSION_FIX_PRIMARY = 3; @@ -472,12 +405,6 @@ class StorageManagerService extends IStorageManager.Stub private final Context mContext; - private final NativeDaemonConnector mConnector; - private final NativeDaemonConnector mCryptConnector; - - private final Thread mConnectorThread; - private final Thread mCryptConnectorThread; - private volatile IVold mVold; private volatile boolean mSystemReady = false; @@ -489,21 +416,11 @@ class StorageManagerService extends IStorageManager.Stub private final Callbacks mCallbacks; private final LockPatternUtils mLockPatternUtils; - // Two connectors - mConnector & mCryptConnector - private final CountDownLatch mConnectedSignal = new CountDownLatch(2); - private final CountDownLatch mAsecsScanned = new CountDownLatch(1); - private final Object mUnmountLock = new Object(); @GuardedBy("mUnmountLock") private CountDownLatch mUnmountSignal; /** - * Private hash of currently mounted secure containers. - * Used as a lock in methods to manipulate secure containers. - */ - final private HashSet<String> mAsecMountSet = new HashSet<String>(); - - /** * The size of the crypto algorithm key in bits for OBB files. Currently * Twofish is used which takes 128-bit keys. */ @@ -616,7 +533,7 @@ class StorageManagerService extends IStorageManager.Stub if (DEBUG_OBB) Slog.i(TAG, "onServiceDisconnected"); } - }; + } // Used in the ObbActionHandler private IMediaContainerService mContainerService = null; @@ -655,13 +572,6 @@ class StorageManagerService extends IStorageManager.Stub break; } case H_FSTRIM: { - if (!isReady()) { - Slog.i(TAG, "fstrim requested, but no daemon connection yet; trying again"); - sendMessageDelayed(obtainMessage(H_FSTRIM, msg.obj), - DateUtils.SECOND_IN_MILLIS); - break; - } - Slog.i(TAG, "Running fstrim idle maintenance"); // Remember when we kicked it off @@ -687,12 +597,8 @@ class StorageManagerService extends IStorageManager.Stub final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj; boolean success = false; try { - if (ENABLE_BINDER) { - mVold.shutdown(); - success = true; - } else { - success = mConnector.execute("volume", "shutdown").isClassOk(); - } + mVold.shutdown(); + success = true; } catch (Exception e) { Slog.wtf(TAG, e); } @@ -711,12 +617,7 @@ class StorageManagerService extends IStorageManager.Stub break; } try { - if (ENABLE_BINDER) { - mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); - } else { - mConnector.execute("volume", "mount", vol.id, vol.mountFlags, - vol.mountUserId); - } + mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -778,11 +679,7 @@ class StorageManagerService extends IStorageManager.Stub if (Intent.ACTION_USER_ADDED.equals(action)) { final UserManager um = mContext.getSystemService(UserManager.class); final int userSerialNumber = um.getUserSerialNumber(userId); - if (ENABLE_BINDER) { - mVold.onUserAdded(userId, userSerialNumber); - } else { - mConnector.execute("volume", "user_added", userId, userSerialNumber); - } + mVold.onUserAdded(userId, userSerialNumber); } else if (Intent.ACTION_USER_REMOVED.equals(action)) { synchronized (mVolumes) { final int size = mVolumes.size(); @@ -794,11 +691,7 @@ class StorageManagerService extends IStorageManager.Stub } } } - if (ENABLE_BINDER) { - mVold.onUserRemoved(userId); - } else { - mConnector.execute("volume", "user_removed", userId); - } + mVold.onUserRemoved(userId); } } catch (Exception e) { Slog.wtf(TAG, e); @@ -808,11 +701,7 @@ class StorageManagerService extends IStorageManager.Stub @Override public void waitForAsecScan() { - waitForLatch(mAsecsScanned, "mAsecsScanned"); - } - - private void waitForReady() { - waitForLatch(mConnectedSignal, "mConnectedSignal"); + throw new UnsupportedOperationException(); } private void waitForLatch(CountDownLatch latch, String condition) { @@ -843,14 +732,6 @@ class StorageManagerService extends IStorageManager.Stub } } - private boolean isReady() { - try { - return mConnectedSignal.await(0, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - return false; - } - } - private void handleSystemReady() { initIfReadyAndConnected(); resetIfReadyAndConnected(); @@ -917,19 +798,10 @@ class StorageManagerService extends IStorageManager.Stub for (UserInfo user : users) { try { if (initLocked) { - if (ENABLE_BINDER) { - mVold.lockUserKey(user.id); - } else { - mCryptConnector.execute("cryptfs", "lock_user_key", user.id); - } + mVold.lockUserKey(user.id); } else { - if (ENABLE_BINDER) { - mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null), - encodeBytes(null)); - } else { - mCryptConnector.execute("cryptfs", "unlock_user_key", user.id, - user.serialNumber, "!", "!"); - } + mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null), + encodeBytes(null)); } } catch (Exception e) { Slog.wtf(TAG, e); @@ -956,26 +828,14 @@ class StorageManagerService extends IStorageManager.Stub } try { - if (ENABLE_BINDER) { - mVold.reset(); - } else { - mConnector.execute("volume", "reset"); - } + mVold.reset(); // Tell vold about all existing and started users for (UserInfo user : users) { - if (ENABLE_BINDER) { - mVold.onUserAdded(user.id, user.serialNumber); - } else { - mConnector.execute("volume", "user_added", user.id, user.serialNumber); - } + mVold.onUserAdded(user.id, user.serialNumber); } for (int userId : systemUnlockedUsers) { - if (ENABLE_BINDER) { - mVold.onUserStarted(userId); - } else { - mConnector.execute("volume", "user_started", userId); - } + mVold.onUserStarted(userId); } } catch (Exception e) { Slog.wtf(TAG, e); @@ -990,11 +850,7 @@ class StorageManagerService extends IStorageManager.Stub // staging area is ready so it's ready for zygote-forked apps to // bind mount against. try { - if (ENABLE_BINDER) { - mVold.onUserStarted(userId); - } else { - mConnector.execute("volume", "user_started", userId); - } + mVold.onUserStarted(userId); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -1020,11 +876,7 @@ class StorageManagerService extends IStorageManager.Stub Slog.d(TAG, "onCleanupUser " + userId); try { - if (ENABLE_BINDER) { - mVold.onUserStopped(userId); - } else { - mConnector.execute("volume", "user_stopped", userId); - } + mVold.onUserStopped(userId); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -1050,10 +902,6 @@ class StorageManagerService extends IStorageManager.Stub return mLastMaintenance; } - /** - * Callback from NativeDaemonConnector - */ - @Override public void onDaemonConnected() { mDaemonConnected = true; mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget(); @@ -1063,29 +911,11 @@ class StorageManagerService extends IStorageManager.Stub initIfReadyAndConnected(); resetIfReadyAndConnected(); - /* - * Now that we've done our initialization, release - * the hounds! - */ - mConnectedSignal.countDown(); - if (mConnectedSignal.getCount() != 0) { - // More daemons need to connect - return; - } - // On an encrypted device we can't see system properties yet, so pull // the system locale out of the mount service. if ("".equals(SystemProperties.get("vold.encrypt_progress"))) { copyLocaleFromMountService(); } - - // Let package manager load internal ASECs. - if (ASEC_ENABLE) { - mPms.scanAvailableAsecs(); - } - - // Notify people waiting for ASECs to be scanned that it's done. - mAsecsScanned.countDown(); } private void copyLocaleFromMountService() { @@ -1114,148 +944,6 @@ class StorageManagerService extends IStorageManager.Stub SystemProperties.set("persist.sys.locale", locale.toLanguageTag()); } - /** - * Callback from NativeDaemonConnector - */ - @Override - public boolean onCheckHoldWakeLock(int code) { - return false; - } - - /** - * Callback from NativeDaemonConnector - */ - @Override - public boolean onEvent(int code, String raw, String[] cooked) { - synchronized (mLock) { - try { - return onEventLocked(code, raw, cooked); - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); - } - } - } - - private boolean onEventLocked(int code, String raw, String[] cooked) throws RemoteException { - switch (code) { - case VoldResponseCode.DISK_CREATED: { - if (cooked.length != 3) break; - final String diskId = cooked[1]; - final int flags = Integer.parseInt(cooked[2]); - mListener.onDiskCreated(diskId, flags); - break; - } - case VoldResponseCode.DISK_SIZE_CHANGED: { - if (cooked.length != 3) break; - final DiskInfo disk = mDisks.get(cooked[1]); - if (disk != null) { - disk.size = Long.parseLong(cooked[2]); - } - break; - } - case VoldResponseCode.DISK_LABEL_CHANGED: { - final DiskInfo disk = mDisks.get(cooked[1]); - if (disk != null) { - final StringBuilder builder = new StringBuilder(); - for (int i = 2; i < cooked.length; i++) { - builder.append(cooked[i]).append(' '); - } - disk.label = builder.toString().trim(); - } - break; - } - case VoldResponseCode.DISK_SCANNED: { - if (cooked.length != 2) break; - final String diskId = cooked[1]; - mListener.onDiskScanned(diskId); - break; - } - case VoldResponseCode.DISK_SYS_PATH_CHANGED: { - if (cooked.length != 3) break; - final DiskInfo disk = mDisks.get(cooked[1]); - if (disk != null) { - disk.sysPath = cooked[2]; - } - break; - } - case VoldResponseCode.DISK_DESTROYED: { - if (cooked.length != 2) break; - final String diskId = cooked[1]; - mListener.onDiskDestroyed(diskId); - break; - } - - case VoldResponseCode.VOLUME_CREATED: { - final String volId = cooked[1]; - final int type = Integer.parseInt(cooked[2]); - final String diskId = TextUtils.nullIfEmpty(cooked[3]); - final String partGuid = TextUtils.nullIfEmpty(cooked[4]); - mListener.onVolumeCreated(volId, type, diskId, partGuid); - break; - } - case VoldResponseCode.VOLUME_STATE_CHANGED: { - if (cooked.length != 3) break; - final String volId = cooked[1]; - final int state = Integer.parseInt(cooked[2]); - mListener.onVolumeStateChanged(volId, state); - break; - } - case VoldResponseCode.VOLUME_FS_TYPE_CHANGED: { - if (cooked.length != 3) break; - final VolumeInfo vol = mVolumes.get(cooked[1]); - if (vol != null) { - vol.fsType = cooked[2]; - } - break; - } - case VoldResponseCode.VOLUME_FS_UUID_CHANGED: { - if (cooked.length != 3) break; - final VolumeInfo vol = mVolumes.get(cooked[1]); - if (vol != null) { - vol.fsUuid = cooked[2]; - } - break; - } - case VoldResponseCode.VOLUME_FS_LABEL_CHANGED: { - final VolumeInfo vol = mVolumes.get(cooked[1]); - if (vol != null) { - final StringBuilder builder = new StringBuilder(); - for (int i = 2; i < cooked.length; i++) { - builder.append(cooked[i]).append(' '); - } - vol.fsLabel = builder.toString().trim(); - } - // TODO: notify listeners that label changed - break; - } - case VoldResponseCode.VOLUME_PATH_CHANGED: { - if (cooked.length != 3) break; - final String volId = cooked[1]; - final String path = cooked[2]; - mListener.onVolumePathChanged(volId, path); - break; - } - case VoldResponseCode.VOLUME_INTERNAL_PATH_CHANGED: { - if (cooked.length != 3) break; - final String volId = cooked[1]; - final String internalPath = cooked[2]; - mListener.onVolumeInternalPathChanged(volId, internalPath); - break; - } - case VoldResponseCode.VOLUME_DESTROYED: { - if (cooked.length != 2) break; - final String volId = cooked[1]; - mListener.onVolumeDestroyed(volId); - break; - } - default: { - Slog.d(TAG, "Unhandled vold event " + code); - } - } - - return true; - } - private final IVoldListener mListener = new IVoldListener.Stub() { @Override public void onDiskCreated(String diskId, int flags) { @@ -1654,24 +1342,6 @@ class StorageManagerService extends IStorageManager.Stub LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal); - /* - * Create the connection to vold with a maximum queue of twice the - * amount of containers we'd ever expect to have. This keeps an - * "asec list" from blocking a thread repeatedly. - */ - - mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25, - null); - mConnector.setDebug(true); - mConnector.setWarnIfHeld(mLock); - mConnectorThread = new Thread(mConnector, VOLD_TAG); - - // Reuse parameters from first connector since they are tested and safe - mCryptConnector = new NativeDaemonConnector(this, "cryptd", - MAX_CONTAINERS * 2, CRYPTD_TAG, 25, null); - mCryptConnector.setDebug(true); - mCryptConnectorThread = new Thread(mCryptConnector, CRYPTD_TAG); - final IntentFilter userFilter = new IntentFilter(); userFilter.addAction(Intent.ACTION_USER_ADDED); userFilter.addAction(Intent.ACTION_USER_REMOVED); @@ -1689,8 +1359,6 @@ class StorageManagerService extends IStorageManager.Stub private void start() { connect(); - mConnectorThread.start(); - mCryptConnectorThread.start(); } private void connect() { @@ -1713,6 +1381,7 @@ class StorageManagerService extends IStorageManager.Stub mVold = IVold.Stub.asInterface(binder); try { mVold.setListener(mListener); + onDaemonConnected(); return; } catch (RemoteException e) { Slog.w(TAG, "vold listener rejected; trying again", e); @@ -1908,18 +1577,13 @@ class StorageManagerService extends IStorageManager.Stub @Override public void mount(String volId) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - waitForReady(); final VolumeInfo vol = findVolumeByIdOrThrow(volId); if (isMountDisallowed(vol)) { throw new SecurityException("Mounting " + volId + " restricted by policy"); } try { - if (ENABLE_BINDER) { - mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); - } else { - mConnector.execute("volume", "mount", vol.id, vol.mountFlags, vol.mountUserId); - } + mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -1928,7 +1592,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void unmount(String volId) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - waitForReady(); final VolumeInfo vol = findVolumeByIdOrThrow(volId); @@ -1948,11 +1611,7 @@ class StorageManagerService extends IStorageManager.Stub } try { - if (ENABLE_BINDER) { - mVold.unmount(vol.id); - } else { - mConnector.execute("volume", "unmount", vol.id); - } + mVold.unmount(vol.id); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -1961,15 +1620,10 @@ class StorageManagerService extends IStorageManager.Stub @Override public void format(String volId) { enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); - waitForReady(); final VolumeInfo vol = findVolumeByIdOrThrow(volId); try { - if (ENABLE_BINDER) { - mVold.format(vol.id, "auto"); - } else { - mConnector.execute("volume", "format", vol.id, "auto"); - } + mVold.format(vol.id, "auto"); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -1978,7 +1632,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public long benchmark(String volId) { enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); - waitForReady(); // TODO: refactor for callers to provide a listener try { @@ -2022,15 +1675,10 @@ class StorageManagerService extends IStorageManager.Stub @Override public void partitionPublic(String diskId) { enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); - waitForReady(); final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); try { - if (ENABLE_BINDER) { - mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1); - } else { - mConnector.execute("volume", "partition", diskId, "public"); - } + mVold.partition(diskId, IVold.PARTITION_TYPE_PUBLIC, -1); waitForLatch(latch, "partitionPublic", 3 * DateUtils.MINUTE_IN_MILLIS); } catch (Exception e) { Slog.wtf(TAG, e); @@ -2041,15 +1689,10 @@ class StorageManagerService extends IStorageManager.Stub public void partitionPrivate(String diskId) { enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); enforceAdminUser(); - waitForReady(); final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); try { - if (ENABLE_BINDER) { - mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1); - } else { - mConnector.execute("volume", "partition", diskId, "private"); - } + mVold.partition(diskId, IVold.PARTITION_TYPE_PRIVATE, -1); waitForLatch(latch, "partitionPrivate", 3 * DateUtils.MINUTE_IN_MILLIS); } catch (Exception e) { Slog.wtf(TAG, e); @@ -2060,15 +1703,10 @@ class StorageManagerService extends IStorageManager.Stub public void partitionMixed(String diskId, int ratio) { enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); enforceAdminUser(); - waitForReady(); final CountDownLatch latch = findOrCreateDiskScanLatch(diskId); try { - if (ENABLE_BINDER) { - mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio); - } else { - mConnector.execute("volume", "partition", diskId, "mixed", ratio); - } + mVold.partition(diskId, IVold.PARTITION_TYPE_MIXED, ratio); waitForLatch(latch, "partitionMixed", 3 * DateUtils.MINUTE_IN_MILLIS); } catch (Exception e) { Slog.wtf(TAG, e); @@ -2078,7 +1716,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void setVolumeNickname(String fsUuid, String nickname) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - waitForReady(); Preconditions.checkNotNull(fsUuid); synchronized (mLock) { @@ -2092,7 +1729,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void setVolumeUserFlags(String fsUuid, int flags, int mask) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - waitForReady(); Preconditions.checkNotNull(fsUuid); synchronized (mLock) { @@ -2106,7 +1742,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void forgetVolume(String fsUuid) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - waitForReady(); Preconditions.checkNotNull(fsUuid); @@ -2131,7 +1766,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void forgetAllVolumes() { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - waitForReady(); synchronized (mLock) { for (int i = 0; i < mRecords.size(); i++) { @@ -2155,11 +1789,7 @@ class StorageManagerService extends IStorageManager.Stub private void forgetPartition(String partGuid) { try { - if (ENABLE_BINDER) { - mVold.forgetPartition(partGuid); - } else { - mConnector.execute("volume", "forget_partition", partGuid); - } + mVold.forgetPartition(partGuid); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -2168,14 +1798,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void fstrim(int flags) { enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS); - waitForReady(); - - String cmd; - if ((flags & StorageManager.FSTRIM_FLAG_DEEP) != 0) { - cmd = "dodtrim"; - } else { - cmd = "dotrim"; - } try { mVold.fstrim(flags, new IVoldTaskListener.Stub() { @@ -2212,27 +1834,8 @@ class StorageManagerService extends IStorageManager.Stub } private void remountUidExternalStorage(int uid, int mode) { - waitForReady(); - - String modeName = "none"; - switch (mode) { - case Zygote.MOUNT_EXTERNAL_DEFAULT: { - modeName = "default"; - } break; - case Zygote.MOUNT_EXTERNAL_READ: { - modeName = "read"; - } break; - case Zygote.MOUNT_EXTERNAL_WRITE: { - modeName = "write"; - } break; - } - try { - if (ENABLE_BINDER) { - mVold.remountUid(uid, mode); - } else { - mConnector.execute("volume", "remount_uid", uid, modeName); - } + mVold.remountUid(uid, mode); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -2241,7 +1844,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void setDebugFlags(int flags, int mask) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - waitForReady(); if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) { if (!EMULATE_FBE_SUPPORTED) { @@ -2331,7 +1933,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - waitForReady(); final VolumeInfo from; final VolumeInfo to; @@ -2405,29 +2006,7 @@ class StorageManagerService extends IStorageManager.Stub @Override public int[] getStorageUsers(String path) { - enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - waitForReady(); - try { - final String[] r = NativeDaemonEvent.filterMessageList( - mConnector.executeForList("storage", "users", path), - VoldResponseCode.StorageUsersListResult); - - // FMT: <pid> <process name> - int[] data = new int[r.length]; - for (int i = 0; i < r.length; i++) { - String[] tok = r[i].split(" "); - try { - data[i] = Integer.parseInt(tok[0]); - } catch (NumberFormatException nfe) { - Slog.e(TAG, String.format("Error parsing pid %s", tok[0])); - return new int[0]; - } - } - return data; - } catch (NativeDaemonConnectorException e) { - Slog.e(TAG, "Failed to retrieve storage users list", e); - return new int[0]; - } + throw new UnsupportedOperationException(); } private void warnOnNotMounted() { @@ -2444,290 +2023,65 @@ class StorageManagerService extends IStorageManager.Stub Slog.w(TAG, "No primary storage mounted!"); } + @Override public String[] getSecureContainerList() { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_ACCESS); - waitForReady(); - warnOnNotMounted(); - - try { - return NativeDaemonEvent.filterMessageList( - mConnector.executeForList("asec", "list"), VoldResponseCode.AsecListResult); - } catch (NativeDaemonConnectorException e) { - return new String[0]; - } + throw new UnsupportedOperationException(); } + @Override public int createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid, boolean external) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_CREATE); - waitForReady(); - warnOnNotMounted(); - - int rc = StorageResultCode.OperationSucceeded; - try { - mConnector.execute("asec", "create", id, sizeMb, fstype, new SensitiveArg(key), - ownerUid, external ? "1" : "0"); - } catch (NativeDaemonConnectorException e) { - rc = StorageResultCode.OperationFailedInternalError; - } - - if (rc == StorageResultCode.OperationSucceeded) { - synchronized (mAsecMountSet) { - mAsecMountSet.add(id); - } - } - return rc; + throw new UnsupportedOperationException(); } @Override public int resizeSecureContainer(String id, int sizeMb, String key) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_CREATE); - waitForReady(); - warnOnNotMounted(); - - int rc = StorageResultCode.OperationSucceeded; - try { - mConnector.execute("asec", "resize", id, sizeMb, new SensitiveArg(key)); - } catch (NativeDaemonConnectorException e) { - rc = StorageResultCode.OperationFailedInternalError; - } - return rc; + throw new UnsupportedOperationException(); } + @Override public int finalizeSecureContainer(String id) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_CREATE); - warnOnNotMounted(); - - int rc = StorageResultCode.OperationSucceeded; - try { - mConnector.execute("asec", "finalize", id); - /* - * Finalization does a remount, so no need - * to update mAsecMountSet - */ - } catch (NativeDaemonConnectorException e) { - rc = StorageResultCode.OperationFailedInternalError; - } - return rc; + throw new UnsupportedOperationException(); } + @Override public int fixPermissionsSecureContainer(String id, int gid, String filename) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_CREATE); - warnOnNotMounted(); - - int rc = StorageResultCode.OperationSucceeded; - try { - mConnector.execute("asec", "fixperms", id, gid, filename); - /* - * Fix permissions does a remount, so no need to update - * mAsecMountSet - */ - } catch (NativeDaemonConnectorException e) { - rc = StorageResultCode.OperationFailedInternalError; - } - return rc; + throw new UnsupportedOperationException(); } + @Override public int destroySecureContainer(String id, boolean force) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_DESTROY); - waitForReady(); - warnOnNotMounted(); - - /* - * Force a GC to make sure AssetManagers in other threads of the - * system_server are cleaned up. We have to do this since AssetManager - * instances are kept as a WeakReference and it's possible we have files - * open on the external storage. - */ - Runtime.getRuntime().gc(); - - int rc = StorageResultCode.OperationSucceeded; - try { - final Command cmd = new Command("asec", "destroy", id); - if (force) { - cmd.appendArg("force"); - } - mConnector.execute(cmd); - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code == VoldResponseCode.OpFailedStorageBusy) { - rc = StorageResultCode.OperationFailedStorageBusy; - } else { - rc = StorageResultCode.OperationFailedInternalError; - } - } - - if (rc == StorageResultCode.OperationSucceeded) { - synchronized (mAsecMountSet) { - if (mAsecMountSet.contains(id)) { - mAsecMountSet.remove(id); - } - } - } - - return rc; + throw new UnsupportedOperationException(); } + @Override public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT); - waitForReady(); - warnOnNotMounted(); - - synchronized (mAsecMountSet) { - if (mAsecMountSet.contains(id)) { - return StorageResultCode.OperationFailedStorageMounted; - } - } - - int rc = StorageResultCode.OperationSucceeded; - try { - mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid, - readOnly ? "ro" : "rw"); - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code != VoldResponseCode.OpFailedStorageBusy) { - rc = StorageResultCode.OperationFailedInternalError; - } - } - - if (rc == StorageResultCode.OperationSucceeded) { - synchronized (mAsecMountSet) { - mAsecMountSet.add(id); - } - } - return rc; + throw new UnsupportedOperationException(); } + @Override public int unmountSecureContainer(String id, boolean force) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT); - waitForReady(); - warnOnNotMounted(); - - synchronized (mAsecMountSet) { - if (!mAsecMountSet.contains(id)) { - return StorageResultCode.OperationFailedStorageNotMounted; - } - } - - /* - * Force a GC to make sure AssetManagers in other threads of the - * system_server are cleaned up. We have to do this since AssetManager - * instances are kept as a WeakReference and it's possible we have files - * open on the external storage. - */ - Runtime.getRuntime().gc(); - - int rc = StorageResultCode.OperationSucceeded; - try { - final Command cmd = new Command("asec", "unmount", id); - if (force) { - cmd.appendArg("force"); - } - mConnector.execute(cmd); - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code == VoldResponseCode.OpFailedStorageBusy) { - rc = StorageResultCode.OperationFailedStorageBusy; - } else { - rc = StorageResultCode.OperationFailedInternalError; - } - } - - if (rc == StorageResultCode.OperationSucceeded) { - synchronized (mAsecMountSet) { - mAsecMountSet.remove(id); - } - } - return rc; + throw new UnsupportedOperationException(); } + @Override public boolean isSecureContainerMounted(String id) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_ACCESS); - waitForReady(); - warnOnNotMounted(); - - synchronized (mAsecMountSet) { - return mAsecMountSet.contains(id); - } + throw new UnsupportedOperationException(); } + @Override public int renameSecureContainer(String oldId, String newId) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_RENAME); - waitForReady(); - warnOnNotMounted(); - - synchronized (mAsecMountSet) { - /* - * Because a mounted container has active internal state which cannot be - * changed while active, we must ensure both ids are not currently mounted. - */ - if (mAsecMountSet.contains(oldId) || mAsecMountSet.contains(newId)) { - return StorageResultCode.OperationFailedStorageMounted; - } - } - - int rc = StorageResultCode.OperationSucceeded; - try { - mConnector.execute("asec", "rename", oldId, newId); - } catch (NativeDaemonConnectorException e) { - rc = StorageResultCode.OperationFailedInternalError; - } - - return rc; + throw new UnsupportedOperationException(); } + @Override public String getSecureContainerPath(String id) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_ACCESS); - waitForReady(); - warnOnNotMounted(); - - final NativeDaemonEvent event; - try { - event = mConnector.execute("asec", "path", id); - event.checkCode(VoldResponseCode.AsecPathResult); - return event.getMessage(); - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code == VoldResponseCode.OpFailedStorageNotFound) { - Slog.i(TAG, String.format("Container '%s' not found", id)); - return null; - } else { - throw new IllegalStateException(String.format("Unexpected response code %d", code)); - } - } + throw new UnsupportedOperationException(); } + @Override public String getSecureContainerFilesystemPath(String id) { - if (!ASEC_ENABLE) throw new UnsupportedOperationException(); - enforcePermission(android.Manifest.permission.ASEC_ACCESS); - waitForReady(); - warnOnNotMounted(); - - final NativeDaemonEvent event; - try { - event = mConnector.execute("asec", "fspath", id); - event.checkCode(VoldResponseCode.AsecPathResult); - return event.getMessage(); - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code == VoldResponseCode.OpFailedStorageNotFound) { - Slog.i(TAG, String.format("Container '%s' not found", id)); - return null; - } else { - throw new IllegalStateException(String.format("Unexpected response code %d", code)); - } - } + throw new UnsupportedOperationException(); } @Override @@ -2762,10 +2116,10 @@ class StorageManagerService extends IStorageManager.Stub return callerUid == packageUid; } + @Override public String getMountedObbPath(String rawPath) { Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); - waitForReady(); warnOnNotMounted(); final ObbState state; @@ -2777,23 +2131,7 @@ class StorageManagerService extends IStorageManager.Stub return null; } - if (ENABLE_BINDER) { - return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath(); - } - - final NativeDaemonEvent event; - try { - event = mConnector.execute("obb", "path", state.canonicalPath); - event.checkCode(VoldResponseCode.AsecPathResult); - return event.getMessage(); - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code == VoldResponseCode.OpFailedStorageNotFound) { - return null; - } else { - throw new IllegalStateException(String.format("Unexpected response code %d", code)); - } - } + return findVolumeByIdOrThrow(state.volId).getPath().getAbsolutePath(); } @Override @@ -2850,28 +2188,10 @@ class StorageManagerService extends IStorageManager.Stub mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, "no permission to access the crypt keeper"); - waitForReady(); - - if (ENABLE_BINDER) { - try { - return mVold.fdeComplete(); - } catch (Exception e) { - Slog.wtf(TAG, e); - return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; - } - } - - final NativeDaemonEvent event; try { - event = mCryptConnector.execute("cryptfs", "cryptocomplete"); - return Integer.parseInt(event.getMessage()); - } catch (NumberFormatException e) { - // Bad result - unexpected. - Slog.w(TAG, "Unable to parse result from cryptfs cryptocomplete"); - return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; - } catch (NativeDaemonConnectorException e) { - // Something bad happened. - Slog.w(TAG, "Error in communicating with cryptfs in validating"); + return mVold.fdeComplete(); + } catch (Exception e) { + Slog.wtf(TAG, e); return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; } } @@ -2881,8 +2201,6 @@ class StorageManagerService extends IStorageManager.Stub mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, "no permission to access the crypt keeper"); - waitForReady(); - if (TextUtils.isEmpty(password)) { throw new IllegalArgumentException("password cannot be empty"); } @@ -2891,55 +2209,27 @@ class StorageManagerService extends IStorageManager.Stub Slog.i(TAG, "decrypting storage..."); } - if (ENABLE_BINDER) { - try { - mVold.fdeCheckPassword(password); - mHandler.postDelayed(() -> { - try { - mVold.fdeRestart(); - } catch (Exception e) { - Slog.wtf(TAG, e); - } - }, DateUtils.SECOND_IN_MILLIS); - return 0; - } catch (Exception e) { - Slog.wtf(TAG, e); - return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; - } - } - - final NativeDaemonEvent event; try { - event = mCryptConnector.execute("cryptfs", "checkpw", new SensitiveArg(password)); - - final int code = Integer.parseInt(event.getMessage()); - if (code == 0) { - // Decrypt was successful. Post a delayed message before restarting in order - // to let the UI to clear itself - mHandler.postDelayed(new Runnable() { - public void run() { - try { - mCryptConnector.execute("cryptfs", "restart"); - } catch (NativeDaemonConnectorException e) { - Slog.e(TAG, "problem executing in background", e); - } - } - }, 1000); // 1 second - } - - return code; - } catch (NativeDaemonConnectorException e) { - // Decryption failed - return e.getCode(); + mVold.fdeCheckPassword(password); + mHandler.postDelayed(() -> { + try { + mVold.fdeRestart(); + } catch (Exception e) { + Slog.wtf(TAG, e); + } + }, DateUtils.SECOND_IN_MILLIS); + return 0; + } catch (Exception e) { + Slog.wtf(TAG, e); + return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN; } } + @Override public int encryptStorage(int type, String password) { mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, "no permission to access the crypt keeper"); - waitForReady(); - if (type == StorageManager.CRYPT_TYPE_DEFAULT) { password = ""; } else if (TextUtils.isEmpty(password)) { @@ -2951,17 +2241,7 @@ class StorageManagerService extends IStorageManager.Stub } try { - if (ENABLE_BINDER) { - mVold.fdeEnable(type, password, IVold.ENCRYPTION_FLAG_IN_PLACE); - } else { - if (type == StorageManager.CRYPT_TYPE_DEFAULT) { - mCryptConnector.execute("cryptfs", "enablecrypto", "inplace", - CRYPTO_TYPES[type]); - } else { - mCryptConnector.execute("cryptfs", "enablecrypto", "inplace", - CRYPTO_TYPES[type], new SensitiveArg(password)); - } - } + mVold.fdeEnable(type, password, IVold.ENCRYPTION_FLAG_IN_PLACE); } catch (Exception e) { Slog.wtf(TAG, e); return -1; @@ -2974,12 +2254,11 @@ class StorageManagerService extends IStorageManager.Stub * @param type One of the CRYPTO_TYPE_XXX consts defined in StorageManager. * @param password The password to set. */ + @Override public int changeEncryptionPassword(int type, String password) { mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, "no permission to access the crypt keeper"); - waitForReady(); - if (type == StorageManager.CRYPT_TYPE_DEFAULT) { password = ""; } else if (TextUtils.isEmpty(password)) { @@ -2990,23 +2269,12 @@ class StorageManagerService extends IStorageManager.Stub Slog.i(TAG, "changing encryption password..."); } - if (ENABLE_BINDER) { - try { - mVold.fdeChangePassword(type, password); - return 0; - } catch (Exception e) { - Slog.wtf(TAG, e); - return -1; - } - } - try { - NativeDaemonEvent event = mCryptConnector.execute("cryptfs", "changepw", CRYPTO_TYPES[type], - new SensitiveArg(password)); - return Integer.parseInt(event.getMessage()); - } catch (NativeDaemonConnectorException e) { - // Encryption failed - return e.getCode(); + mVold.fdeChangePassword(type, password); + return 0; + } catch (Exception e) { + Slog.wtf(TAG, e); + return -1; } } @@ -3027,30 +2295,16 @@ class StorageManagerService extends IStorageManager.Stub throw new IllegalArgumentException("password cannot be empty"); } - waitForReady(); - if (DEBUG_EVENTS) { Slog.i(TAG, "validating encryption password..."); } - if (ENABLE_BINDER) { - try { - mVold.fdeVerifyPassword(password); - return 0; - } catch (Exception e) { - Slog.wtf(TAG, e); - return -1; - } - } - - final NativeDaemonEvent event; try { - event = mCryptConnector.execute("cryptfs", "verifypw", new SensitiveArg(password)); - Slog.i(TAG, "cryptfs verifypw => " + event.getMessage()); - return Integer.parseInt(event.getMessage()); - } catch (NativeDaemonConnectorException e) { - // Encryption failed - return e.getCode(); + mVold.fdeVerifyPassword(password); + return 0; + } catch (Exception e) { + Slog.wtf(TAG, e); + return -1; } } @@ -3063,28 +2317,11 @@ class StorageManagerService extends IStorageManager.Stub mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, "no permission to access the crypt keeper"); - waitForReady(); - - if (ENABLE_BINDER) { - try { - return mVold.fdeGetPasswordType(); - } catch (Exception e) { - Slog.wtf(TAG, e); - return -1; - } - } - - final NativeDaemonEvent event; try { - event = mCryptConnector.execute("cryptfs", "getpwtype"); - for (int i = 0; i < CRYPTO_TYPES.length; ++i) { - if (CRYPTO_TYPES[i].equals(event.getMessage())) - return i; - } - - throw new IllegalStateException("unexpected return from cryptfs"); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + return mVold.fdeGetPasswordType(); + } catch (Exception e) { + Slog.wtf(TAG, e); + return -1; } } @@ -3098,23 +2335,12 @@ class StorageManagerService extends IStorageManager.Stub mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, "no permission to access the crypt keeper"); - waitForReady(); - - if (ENABLE_BINDER) { - try { - mVold.fdeSetField(field, contents); - return; - } catch (Exception e) { - Slog.wtf(TAG, e); - return; - } - } - - final NativeDaemonEvent event; try { - event = mCryptConnector.execute("cryptfs", "setfield", field, contents); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mVold.fdeSetField(field, contents); + return; + } catch (Exception e) { + Slog.wtf(TAG, e); + return; } } @@ -3128,29 +2354,11 @@ class StorageManagerService extends IStorageManager.Stub mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, "no permission to access the crypt keeper"); - waitForReady(); - - if (ENABLE_BINDER) { - try { - return mVold.fdeGetField(field); - } catch (Exception e) { - Slog.wtf(TAG, e); - return null; - } - } - - final NativeDaemonEvent event; try { - final String[] contents = NativeDaemonEvent.filterMessageList( - mCryptConnector.executeForList("cryptfs", "getfield", field), - VoldResponseCode.CryptfsGetfieldResult); - String result = new String(); - for (String content : contents) { - result += content; - } - return result; - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + return mVold.fdeGetField(field); + } catch (Exception e) { + Slog.wtf(TAG, e); + return null; } } @@ -3163,23 +2371,11 @@ class StorageManagerService extends IStorageManager.Stub mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, "no permission to access the crypt keeper"); - waitForReady(); - - if (ENABLE_BINDER) { - try { - return mVold.isConvertibleToFbe(); - } catch (Exception e) { - Slog.wtf(TAG, e); - return false; - } - } - - final NativeDaemonEvent event; try { - event = mCryptConnector.execute("cryptfs", "isConvertibleToFBE"); - return Integer.parseInt(event.getMessage()) != 0; - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + return mVold.isConvertibleToFbe(); + } catch (Exception e) { + Slog.wtf(TAG, e); + return false; } } @@ -3188,31 +2384,10 @@ class StorageManagerService extends IStorageManager.Stub mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, "only keyguard can retrieve password"); - if (!isReady()) { - return new String(); - } - - if (ENABLE_BINDER) { - try { - return mVold.fdeGetPassword(); - } catch (Exception e) { - Slog.wtf(TAG, e); - return null; - } - } - - final NativeDaemonEvent event; try { - event = mCryptConnector.execute("cryptfs", "getpw"); - if ("-1".equals(event.getMessage())) { - // -1 equals no password - return null; - } - return event.getMessage(); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } catch (IllegalArgumentException e) { - Slog.e(TAG, "Invalid response to getPassword"); + return mVold.fdeGetPassword(); + } catch (Exception e) { + Slog.wtf(TAG, e); return null; } } @@ -3222,40 +2397,21 @@ class StorageManagerService extends IStorageManager.Stub mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, "only keyguard can clear password"); - if (!isReady()) { - return; - } - - if (ENABLE_BINDER) { - try { - mVold.fdeClearPassword(); - return; - } catch (Exception e) { - Slog.wtf(TAG, e); - return; - } - } - - final NativeDaemonEvent event; try { - event = mCryptConnector.execute("cryptfs", "clearpw"); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + mVold.fdeClearPassword(); + return; + } catch (Exception e) { + Slog.wtf(TAG, e); + return; } } @Override public void createUserKey(int userId, int serialNumber, boolean ephemeral) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); - waitForReady(); try { - if (ENABLE_BINDER) { - mVold.createUserKey(userId, serialNumber, ephemeral); - } else { - mCryptConnector.execute("cryptfs", "create_user_key", userId, serialNumber, - ephemeral ? 1 : 0); - } + mVold.createUserKey(userId, serialNumber, ephemeral); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -3264,14 +2420,9 @@ class StorageManagerService extends IStorageManager.Stub @Override public void destroyUserKey(int userId) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); - waitForReady(); try { - if (ENABLE_BINDER) { - mVold.destroyUserKey(userId); - } else { - mCryptConnector.execute("cryptfs", "destroy_user_key", userId); - } + mVold.destroyUserKey(userId); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -3295,16 +2446,9 @@ class StorageManagerService extends IStorageManager.Stub @Override public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); - waitForReady(); try { - if (ENABLE_BINDER) { - mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); - } else { - mCryptConnector.execute("cryptfs", "add_user_key_auth", userId, serialNumber, - new SensitiveArg(encodeBytes(token)), - new SensitiveArg(encodeBytes(secret))); - } + mVold.addUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -3316,14 +2460,9 @@ class StorageManagerService extends IStorageManager.Stub @Override public void fixateNewestUserKeyAuth(int userId) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); - waitForReady(); try { - if (ENABLE_BINDER) { - mVold.fixateNewestUserKeyAuth(userId); - } else { - mCryptConnector.execute("cryptfs", "fixate_newest_user_key_auth", userId); - } + mVold.fixateNewestUserKeyAuth(userId); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -3332,7 +2471,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); - waitForReady(); if (StorageManager.isFileEncryptedNativeOrEmulated()) { // When a user has secure lock screen, require secret to actually unlock. @@ -3342,14 +2480,8 @@ class StorageManagerService extends IStorageManager.Stub } try { - if (ENABLE_BINDER) { - mVold.unlockUserKey(userId, serialNumber, encodeBytes(token), - encodeBytes(secret)); - } else { - mCryptConnector.execute("cryptfs", "unlock_user_key", userId, serialNumber, - new SensitiveArg(encodeBytes(token)), - new SensitiveArg(encodeBytes(secret))); - } + mVold.unlockUserKey(userId, serialNumber, encodeBytes(token), + encodeBytes(secret)); } catch (Exception e) { Slog.wtf(TAG, e); return; @@ -3369,14 +2501,9 @@ class StorageManagerService extends IStorageManager.Stub @Override public void lockUserKey(int userId) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); - waitForReady(); try { - if (ENABLE_BINDER) { - mVold.lockUserKey(userId); - } else { - mCryptConnector.execute("cryptfs", "lock_user_key", userId); - } + mVold.lockUserKey(userId); } catch (Exception e) { Slog.wtf(TAG, e); return; @@ -3397,15 +2524,9 @@ class StorageManagerService extends IStorageManager.Stub @Override public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); - waitForReady(); try { - if (ENABLE_BINDER) { - mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags); - } else { - mCryptConnector.execute("cryptfs", "prepare_user_storage", escapeNull(volumeUuid), - userId, serialNumber, flags); - } + mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -3414,15 +2535,9 @@ class StorageManagerService extends IStorageManager.Stub @Override public void destroyUserStorage(String volumeUuid, int userId, int flags) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); - waitForReady(); try { - if (ENABLE_BINDER) { - mVold.destroyUserStorage(volumeUuid, userId, flags); - } else { - mCryptConnector.execute("cryptfs", "destroy_user_storage", escapeNull(volumeUuid), - userId, flags); - } + mVold.destroyUserStorage(volumeUuid, userId, flags); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -3431,14 +2546,9 @@ class StorageManagerService extends IStorageManager.Stub @Override public void secdiscard(String path) { enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); - waitForReady(); try { - if (ENABLE_BINDER) { - mVold.secdiscard(path); - } else { - mCryptConnector.execute("cryptfs", "secdiscard", escapeNull(path)); - } + mVold.secdiscard(path); } catch (Exception e) { Slog.wtf(TAG, e); } @@ -3453,33 +2563,18 @@ class StorageManagerService extends IStorageManager.Stub @Override public ParcelFileDescriptor open() throws NativeDaemonConnectorException { - if (ENABLE_BINDER) { - try { - return new ParcelFileDescriptor( - mVold.mountAppFuse(uid, Process.myPid(), mountId)); - } catch (Exception e) { - throw new NativeDaemonConnectorException("Failed to mount", e); - } - } else { - final NativeDaemonEvent event = mConnector.execute( - "appfuse", "mount", uid, Process.myPid(), mountId); - opened = true; - if (event.getFileDescriptors() == null || - event.getFileDescriptors().length == 0) { - throw new NativeDaemonConnectorException("Cannot obtain device FD"); - } - return new ParcelFileDescriptor(event.getFileDescriptors()[0]); + try { + return new ParcelFileDescriptor( + mVold.mountAppFuse(uid, Process.myPid(), mountId)); + } catch (Exception e) { + throw new NativeDaemonConnectorException("Failed to mount", e); } } @Override public void close() throws Exception { if (opened) { - if (ENABLE_BINDER) { - mVold.unmountAppFuse(uid, Process.myPid(), mountId); - } else { - mConnector.execute("appfuse", "unmount", uid, Process.myPid(), mountId); - } + mVold.unmountAppFuse(uid, Process.myPid(), mountId); opened = false; } } @@ -3568,11 +2663,7 @@ class StorageManagerService extends IStorageManager.Stub } try { - if (ENABLE_BINDER) { - mVold.mkdirs(appPath); - } else { - mConnector.execute("volume", "mkdirs", appPath); - } + mVold.mkdirs(appPath); return 0; } catch (Exception e) { Slog.wtf(TAG, e); @@ -4124,7 +3215,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void handleExecute() throws IOException, RemoteException { - waitForReady(); warnOnNotMounted(); final ObbInfo obbInfo = getObbInfo(); @@ -4174,19 +3264,9 @@ class StorageManagerService extends IStorageManager.Stub int rc = StorageResultCode.OperationSucceeded; try { - if (ENABLE_BINDER) { - mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey, - mObbState.ownerGid); - mVold.mount(mObbState.volId, 0, -1); - } else { - mConnector.execute("obb", "mount", mObbState.canonicalPath, - new SensitiveArg(hashedKey), mObbState.ownerGid); - } - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code != VoldResponseCode.OpFailedStorageBusy) { - rc = StorageResultCode.OperationFailedInternalError; - } + mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey, + mObbState.ownerGid); + mVold.mount(mObbState.volId, 0, -1); } catch (Exception e) { Slog.w(TAG, e); rc = StorageResultCode.OperationFailedInternalError; @@ -4233,7 +3313,6 @@ class StorageManagerService extends IStorageManager.Stub @Override public void handleExecute() throws IOException { - waitForReady(); warnOnNotMounted(); final ObbState existingState; @@ -4255,27 +3334,9 @@ class StorageManagerService extends IStorageManager.Stub int rc = StorageResultCode.OperationSucceeded; try { - if (ENABLE_BINDER) { - mVold.unmount(mObbState.volId); - mVold.destroyObb(mObbState.volId); - mObbState.volId = null; - } else { - final Command cmd = new Command("obb", "unmount", mObbState.canonicalPath); - if (mForceUnmount) { - cmd.appendArg("force"); - } - mConnector.execute(cmd); - } - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code == VoldResponseCode.OpFailedStorageBusy) { - rc = StorageResultCode.OperationFailedStorageBusy; - } else if (code == VoldResponseCode.OpFailedStorageNotFound) { - // If it's not mounted then we've already won. - rc = StorageResultCode.OperationSucceeded; - } else { - rc = StorageResultCode.OperationFailedInternalError; - } + mVold.unmount(mObbState.volId); + mVold.destroyObb(mObbState.volId); + mObbState.volId = null; } catch (Exception e) { Slog.w(TAG, e); rc = StorageResultCode.OperationFailedInternalError; @@ -4506,18 +3567,6 @@ class StorageManagerService extends IStorageManager.Stub } pw.println(); - pw.println("mConnector:"); - pw.increaseIndent(); - mConnector.dump(fd, pw, args); - pw.decreaseIndent(); - - pw.println(); - pw.println("mCryptConnector:"); - pw.increaseIndent(); - mCryptConnector.dump(fd, pw, args); - pw.decreaseIndent(); - - pw.println(); pw.print("Last maintenance: "); pw.println(TimeUtils.formatForLogging(mLastMaintenance)); } @@ -4525,11 +3574,10 @@ class StorageManagerService extends IStorageManager.Stub /** {@inheritDoc} */ @Override public void monitor() { - if (mConnector != null) { - mConnector.monitor(); - } - if (mCryptConnector != null) { - mCryptConnector.monitor(); + try { + mVold.monitor(); + } catch (Exception e) { + Slog.wtf(TAG, e); } } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index e0cde72ffff2..90ad8a5d0131 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -2162,6 +2162,15 @@ public final class ActiveServices { } } + if (r.fgRequired) { + if (DEBUG_FOREGROUND_SERVICE) { + Slog.v(TAG, "Whitelisting " + UserHandle.formatUid(r.appInfo.uid) + + " for fg-service launch"); + } + mAm.tempWhitelistUidLocked(r.appInfo.uid, + SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch"); + } + if (!mPendingServices.contains(r)) { mPendingServices.add(r); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c8e2dc57e0ed..5d200ae91e25 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -709,7 +709,7 @@ public class ActivityManagerService extends IActivityManager.Stub public boolean canShowErrorDialogs() { return mShowDialogs && !mSleeping && !mShuttingDown - && !mKeyguardController.isKeyguardShowing() + && !mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY) && !(UserManager.isDeviceInDemoMode(mContext) && mUserController.getCurrentUser().isDemo()); } @@ -1648,45 +1648,32 @@ public class ActivityManagerService extends IActivityManager.Stub static final int DISPATCH_PROCESSES_CHANGED_UI_MSG = 31; static final int DISPATCH_PROCESS_DIED_UI_MSG = 32; static final int REPORT_MEM_USAGE_MSG = 33; - static final int REPORT_USER_SWITCH_MSG = 34; - static final int CONTINUE_USER_SWITCH_MSG = 35; - static final int USER_SWITCH_TIMEOUT_MSG = 36; static final int IMMERSIVE_MODE_LOCK_MSG = 37; static final int PERSIST_URI_GRANTS_MSG = 38; static final int REQUEST_ALL_PSS_MSG = 39; - static final int START_PROFILES_MSG = 40; static final int UPDATE_TIME_PREFERENCE_MSG = 41; - static final int SYSTEM_USER_START_MSG = 42; - static final int SYSTEM_USER_CURRENT_MSG = 43; static final int ENTER_ANIMATION_COMPLETE_MSG = 44; static final int FINISH_BOOTING_MSG = 45; - static final int START_USER_SWITCH_UI_MSG = 46; static final int SEND_LOCALE_TO_MOUNT_DAEMON_MSG = 47; static final int DISMISS_DIALOG_UI_MSG = 48; static final int NOTIFY_CLEARTEXT_NETWORK_MSG = 49; static final int POST_DUMP_HEAP_NOTIFICATION_MSG = 50; static final int DELETE_DUMPHEAP_MSG = 51; - static final int FOREGROUND_PROFILE_CHANGED_MSG = 52; static final int DISPATCH_UIDS_CHANGED_UI_MSG = 53; static final int REPORT_TIME_TRACKER_MSG = 54; - static final int REPORT_USER_SWITCH_COMPLETE_MSG = 55; static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 56; static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 57; static final int IDLE_UIDS_MSG = 58; - static final int SYSTEM_USER_UNLOCK_MSG = 59; static final int LOG_STACK_STATE = 60; static final int VR_MODE_CHANGE_MSG = 61; static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 62; static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 63; - static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 64; static final int NOTIFY_VR_SLEEPING_MSG = 65; static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66; static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67; static final int PUSH_TEMP_WHITELIST_UI_MSG = 68; static final int SERVICE_FOREGROUND_CRASH_MSG = 69; static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70; - static final int USER_SWITCH_CALLBACKS_TIMEOUT_MSG = 71; - static final int START_USER_SWITCH_FG_MSG = 712; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -1899,10 +1886,6 @@ public class ActivityManagerService extends IActivityManager.Stub } break; } - case START_USER_SWITCH_UI_MSG: { - mUserController.showUserSwitchDialog((Pair<UserInfo, UserInfo>) msg.obj); - break; - } case DISMISS_DIALOG_UI_MSG: { final Dialog d = (Dialog) msg.obj; d.dismiss(); @@ -2131,26 +2114,6 @@ public class ActivityManagerService extends IActivityManager.Stub thread.start(); break; } - case START_USER_SWITCH_FG_MSG: { - mUserController.startUserInForeground(msg.arg1); - break; - } - case REPORT_USER_SWITCH_MSG: { - mUserController.dispatchUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); - break; - } - case CONTINUE_USER_SWITCH_MSG: { - mUserController.continueUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); - break; - } - case USER_SWITCH_TIMEOUT_MSG: { - mUserController.timeoutUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); - break; - } - case USER_SWITCH_CALLBACKS_TIMEOUT_MSG: { - mUserController.timeoutUserSwitchCallbacks(msg.arg1, msg.arg2); - break; - } case IMMERSIVE_MODE_LOCK_MSG: { final boolean nextState = (msg.arg1 != 0); if (mUpdateLock.isHeld() != nextState) { @@ -2175,12 +2138,6 @@ public class ActivityManagerService extends IActivityManager.Stub } break; } - case START_PROFILES_MSG: { - synchronized (ActivityManagerService.this) { - mUserController.startProfilesLocked(); - } - break; - } case UPDATE_TIME_PREFERENCE_MSG: { // The user's time format preference might have changed. // For convenience we re-use the Intent extra values. @@ -2199,35 +2156,6 @@ public class ActivityManagerService extends IActivityManager.Stub } break; } - case SYSTEM_USER_START_MSG: { - mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START, - Integer.toString(msg.arg1), msg.arg1); - mSystemServiceManager.startUser(msg.arg1); - break; - } - case SYSTEM_USER_UNLOCK_MSG: { - final int userId = msg.arg1; - mSystemServiceManager.unlockUser(userId); - synchronized (ActivityManagerService.this) { - mRecentTasks.loadUserRecentsLocked(userId); - } - if (userId == UserHandle.USER_SYSTEM) { - startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE); - } - installEncryptionUnawareProviders(userId); - mUserController.finishUserUnlocked((UserState) msg.obj); - break; - } - case SYSTEM_USER_CURRENT_MSG: { - mBatteryStatsService.noteEvent( - BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_FINISH, - Integer.toString(msg.arg2), msg.arg2); - mBatteryStatsService.noteEvent( - BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START, - Integer.toString(msg.arg1), msg.arg1); - mSystemServiceManager.switchUser(msg.arg1); - break; - } case ENTER_ANIMATION_COMPLETE_MSG: { synchronized (ActivityManagerService.this) { ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj); @@ -2367,19 +2295,10 @@ public class ActivityManagerService extends IActivityManager.Stub mMemWatchDumpUid = -1; } } break; - case FOREGROUND_PROFILE_CHANGED_MSG: { - mUserController.dispatchForegroundProfileChanged(msg.arg1); - } break; case REPORT_TIME_TRACKER_MSG: { AppTimeTracker tracker = (AppTimeTracker)msg.obj; tracker.deliverResult(mContext); } break; - case REPORT_USER_SWITCH_COMPLETE_MSG: { - mUserController.dispatchUserSwitchComplete(msg.arg1); - } break; - case REPORT_LOCKED_BOOT_COMPLETE_MSG: { - mUserController.dispatchLockedBootComplete(msg.arg1); - } break; case SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG: { IUiAutomationConnection connection = (IUiAutomationConnection) msg.obj; try { @@ -3147,9 +3066,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (mLastResumedActivity != null && r.userId != mLastResumedActivity.userId) { - mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG); - mHandler.obtainMessage( - FOREGROUND_PROFILE_CHANGED_MSG, r.userId, 0).sendToTarget(); + mUserController.sendForegroundProfileChanged(r.userId); } mLastResumedActivity = r; @@ -3869,6 +3786,12 @@ public class ActivityManagerService extends IActivityManager.Stub mNativeDebuggingApp = null; } + if (app.info.isPrivilegedApp() && + !SystemProperties.getBoolean("pm.dexopt.priv-apps", true)) { + runtimeFlags |= Zygote.DISABLE_VERIFIER; + runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES; + } + String invokeWith = null; if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { // Debuggable apps may include a wrapper script with their library directory. @@ -4151,15 +4074,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } - void enforceShellRestriction(String restriction, int userHandle) { - if (Binder.getCallingUid() == SHELL_UID) { - if (userHandle < 0 || mUserController.hasUserRestriction(restriction, userHandle)) { - throw new SecurityException("Shell does not have permission to access user " - + userHandle); - } - } - } - @Override public int getFrontActivityScreenCompatMode() { enforceNotIsolatedCaller("getFrontActivityScreenCompatMode"); @@ -7366,7 +7280,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } }); - scheduleStartProfilesLocked(); + mUserController.scheduleStartProfilesLocked(); } } } @@ -10043,7 +9957,7 @@ public class ActivityManagerService extends IActivityManager.Stub enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, "getTaskDescription()"); final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id, - MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID); + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (tr != null) { return tr.lastTaskDescription; } @@ -10156,7 +10070,7 @@ public class ActivityManagerService extends IActivityManager.Stub public void setTaskResizeable(int taskId, int resizeableMode) { synchronized (this) { final TaskRecord task = mStackSupervisor.anyTaskForIdLocked( - taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID); + taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (task == null) { Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found"); return; @@ -10219,7 +10133,7 @@ public class ActivityManagerService extends IActivityManager.Stub try { synchronized (this) { final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, - MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID); + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (task == null) { Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found"); return rect; @@ -10251,7 +10165,7 @@ public class ActivityManagerService extends IActivityManager.Stub try { synchronized (this) { final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, - MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID); + MATCH_TASK_IN_STACKS_ONLY); if (task == null) { Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found"); return; @@ -10270,7 +10184,7 @@ public class ActivityManagerService extends IActivityManager.Stub try { synchronized (this) { final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, - MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID); + MATCH_TASK_IN_STACKS_ONLY); if (task == null) { Slog.w(TAG, "cancelTaskThumbnailTransition: taskId=" + taskId + " not found"); return; @@ -10290,7 +10204,7 @@ public class ActivityManagerService extends IActivityManager.Stub final TaskRecord task; synchronized (this) { task = mStackSupervisor.anyTaskForIdLocked(taskId, - MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID); + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (task == null) { Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found"); return null; @@ -10604,56 +10518,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } - @Override - public void swapDockedAndFullscreenStack() throws RemoteException { - enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "swapDockedAndFullscreenStack()"); - synchronized (this) { - long ident = Binder.clearCallingIdentity(); - try { - final ActivityStack fullscreenStack = mStackSupervisor.getStack( - FULLSCREEN_WORKSPACE_STACK_ID); - final TaskRecord topTask = fullscreenStack != null ? fullscreenStack.topTask() - : null; - final ActivityStack dockedStack = mStackSupervisor.getStack(DOCKED_STACK_ID); - final ArrayList<TaskRecord> tasks = dockedStack != null ? dockedStack.getAllTasks() - : null; - if (topTask == null || tasks == null || tasks.size() == 0) { - Slog.w(TAG, - "Unable to swap tasks, either docked or fullscreen stack is empty."); - return; - } - - // TODO: App transition - mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_RELAUNCH, false); - - // Defer the resume until we move all the docked tasks to the fullscreen stack below - topTask.reparent(DOCKED_STACK_ID, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, - DEFER_RESUME, "swapDockedAndFullscreenStack - DOCKED_STACK"); - final int size = tasks.size(); - for (int i = 0; i < size; i++) { - final int id = tasks.get(i).taskId; - if (id == topTask.taskId) { - continue; - } - - // Defer the resume until after all the tasks have been moved - tasks.get(i).reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, - REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, DEFER_RESUME, - "swapDockedAndFullscreenStack - FULLSCREEN_STACK"); - } - - // Because we deferred the resume to avoid conflicts with stack switches while - // resuming, we need to do it after all the tasks are moved. - mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - mStackSupervisor.resumeFocusedStackTopActivityLocked(); - - mWindowManager.executeAppTransition(); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - /** * Moves the input task to the docked stack. * @@ -12066,7 +11930,7 @@ public class ActivityManagerService extends IActivityManager.Stub //mUsageStatsService.monitorPackages(); } - private void startPersistentApps(int matchFlags) { + void startPersistentApps(int matchFlags) { if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return; synchronized (this) { @@ -12087,7 +11951,7 @@ public class ActivityManagerService extends IActivityManager.Stub * When a user is unlocked, we need to install encryption-unaware providers * belonging to any running apps. */ - private void installEncryptionUnawareProviders(int userId) { + void installEncryptionUnawareProviders(int userId) { // We're only interested in providers that are encryption unaware, and // we don't care about uninstalled apps, since there's no way they're // running at this point. @@ -12392,19 +12256,14 @@ public class ActivityManagerService extends IActivityManager.Stub void onWakefulnessChanged(int wakefulness) { synchronized(this) { + boolean wasAwake = mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE; + boolean isAwake = wakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE; mWakefulness = wakefulness; - // Also update state in a special way for running foreground services UI. - switch (mWakefulness) { - case PowerManagerInternal.WAKEFULNESS_ASLEEP: - case PowerManagerInternal.WAKEFULNESS_DREAMING: - case PowerManagerInternal.WAKEFULNESS_DOZING: - mServices.updateScreenStateLocked(false /* screenOn */); - break; - case PowerManagerInternal.WAKEFULNESS_AWAKE: - default: - mServices.updateScreenStateLocked(true /* screenOn */); - break; + if (wasAwake != isAwake) { + // Also update state in a special way for running foreground services UI. + mServices.updateScreenStateLocked(isAwake); + sendNotifyVrManagerOfSleepState(!isAwake); } } } @@ -12440,7 +12299,6 @@ public class ActivityManagerService extends IActivityManager.Stub } mStackSupervisor.applySleepTokensLocked(true /* applyToStacks */); if (wasSleeping) { - sendNotifyVrManagerOfSleepState(false); updateOomAdjLocked(); } } else if (!mSleeping && shouldSleep) { @@ -12450,7 +12308,6 @@ public class ActivityManagerService extends IActivityManager.Stub } mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING; mStackSupervisor.goingToSleepLocked(); - sendNotifyVrManagerOfSleepState(true); updateOomAdjLocked(); } } @@ -12544,7 +12401,7 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void setLockScreenShown(boolean showing) { + public void setLockScreenShown(boolean showing, int secondaryDisplayShowing) { if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires permission " @@ -12554,7 +12411,7 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized(this) { long ident = Binder.clearCallingIdentity(); try { - mKeyguardController.setKeyguardShown(showing); + mKeyguardController.setKeyguardShown(showing, secondaryDisplayShowing); } finally { Binder.restoreCallingIdentity(ident); } @@ -23559,54 +23416,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public boolean switchUser(final int targetUserId) { - enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId); - int currentUserId; - UserInfo targetUserInfo; - synchronized (this) { - currentUserId = mUserController.getCurrentUserIdLocked(); - targetUserInfo = mUserController.getUserInfo(targetUserId); - if (targetUserId == currentUserId) { - Slog.i(TAG, "user #" + targetUserId + " is already the current user"); - return true; - } - if (targetUserInfo == null) { - Slog.w(TAG, "No user info for user #" + targetUserId); - return false; - } - if (!targetUserInfo.isDemo() && UserManager.isDeviceInDemoMode(mContext)) { - Slog.w(TAG, "Cannot switch to non-demo user #" + targetUserId - + " when device is in demo mode"); - return false; - } - if (!targetUserInfo.supportsSwitchTo()) { - Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported"); - return false; - } - if (targetUserInfo.isManagedProfile()) { - Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user"); - return false; - } - mUserController.setTargetUserIdLocked(targetUserId); - } - if (mUserController.mUserSwitchUiEnabled) { - UserInfo currentUserInfo = mUserController.getUserInfo(currentUserId); - Pair<UserInfo, UserInfo> userNames = new Pair<>(currentUserInfo, targetUserInfo); - mUiHandler.removeMessages(START_USER_SWITCH_UI_MSG); - mUiHandler.sendMessage(mHandler.obtainMessage( - START_USER_SWITCH_UI_MSG, userNames)); - } else { - mHandler.removeMessages(START_USER_SWITCH_FG_MSG); - mHandler.sendMessage(mHandler.obtainMessage( - START_USER_SWITCH_FG_MSG, targetUserId, 0)); - } - return true; - } - - void scheduleStartProfilesLocked() { - if (!mHandler.hasMessages(START_PROFILES_MSG)) { - mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG), - DateUtils.SECOND_IN_MILLIS); - } + return mUserController.switchUser(targetUserId); } @Override @@ -24018,7 +23828,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void notifyKeyguardTrustedChanged() { synchronized (ActivityManagerService.this) { - if (mKeyguardController.isKeyguardShowing()) { + if (mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)) { mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 6901d2de6f00..0aca9ea6d748 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -75,6 +75,8 @@ import static android.app.ActivityManager.RESIZE_MODE_SYSTEM; import static android.app.ActivityManager.RESIZE_MODE_USER; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; import static com.android.server.am.TaskRecord.INVALID_TASK_ID; @@ -115,7 +117,8 @@ final class ActivityManagerShellCommand extends ShellCommand { private boolean mStreaming; // Streaming the profiling output to a file. private String mAgent; // Agent to attach on startup. private int mDisplayId; - private int mStackId; + private int mWindowingMode; + private int mActivityType; private int mTaskId; private boolean mIsTaskOverlay; @@ -271,7 +274,8 @@ final class ActivityManagerShellCommand extends ShellCommand { mStreaming = false; mUserId = defUser; mDisplayId = INVALID_DISPLAY; - mStackId = INVALID_STACK_ID; + mWindowingMode = WINDOWING_MODE_UNDEFINED; + mActivityType = ACTIVITY_TYPE_UNDEFINED; mTaskId = INVALID_TASK_ID; mIsTaskOverlay = false; @@ -308,8 +312,10 @@ final class ActivityManagerShellCommand extends ShellCommand { mReceiverPermission = getNextArgRequired(); } else if (opt.equals("--display")) { mDisplayId = Integer.parseInt(getNextArgRequired()); - } else if (opt.equals("--stack")) { - mStackId = Integer.parseInt(getNextArgRequired()); + } else if (opt.equals("--windowingMode")) { + mWindowingMode = Integer.parseInt(getNextArgRequired()); + } else if (opt.equals("--activityType")) { + mActivityType = Integer.parseInt(getNextArgRequired()); } else if (opt.equals("--task")) { mTaskId = Integer.parseInt(getNextArgRequired()); } else if (opt.equals("--task-overlay")) { @@ -396,9 +402,17 @@ final class ActivityManagerShellCommand extends ShellCommand { options = ActivityOptions.makeBasic(); options.setLaunchDisplayId(mDisplayId); } - if (mStackId != INVALID_STACK_ID) { - options = ActivityOptions.makeBasic(); - options.setLaunchStackId(mStackId); + if (mWindowingMode != WINDOWING_MODE_UNDEFINED) { + if (options == null) { + options = ActivityOptions.makeBasic(); + } + options.setLaunchWindowingMode(mWindowingMode); + } + if (mActivityType != ACTIVITY_TYPE_UNDEFINED) { + if (options == null) { + options = ActivityOptions.makeBasic(); + } + options.setLaunchActivityType(mActivityType); } if (mTaskId != INVALID_TASK_ID) { options = ActivityOptions.makeBasic(); @@ -2685,7 +2699,8 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" --track-allocation: enable tracking of object allocations"); pw.println(" --user <USER_ID> | current: Specify which user to run as; if not"); pw.println(" specified then run as the current user."); - pw.println(" --stack <STACK_ID>: Specify into which stack should the activity be put."); + pw.println(" --windowingMode <WINDOWING_MODE>: The windowing mode to launch the activity into."); + pw.println(" --activityType <ACTIVITY_TYPE>: The activity type to launch the activity as."); pw.println(" start-service [--user <USER_ID> | current] <INTENT>"); pw.println(" Start a Service. Options are:"); pw.println(" --user <USER_ID> | current: Specify which user to run as; if not"); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 0ccb45f74ec2..49082334db8c 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -17,7 +17,6 @@ package com.android.server.am; import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; -import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; @@ -36,7 +35,6 @@ import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE; import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.activityTypeToString; import static android.content.Intent.ACTION_MAIN; @@ -89,10 +87,8 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SCREENSHOTS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_THUMBNAILS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -1038,7 +1034,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } } else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) { activityType = ACTIVITY_TYPE_RECENTS; - } else if (options != null && options.getLaunchStackId() == ASSISTANT_STACK_ID + } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT && canLaunchAssistActivity(launchedFromPackage)) { activityType = ACTIVITY_TYPE_ASSISTANT; } @@ -1157,8 +1153,15 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo * can be put a secondary screen. */ boolean canBeLaunchedOnDisplay(int displayId) { + final TaskRecord task = getTask(); + + // The resizeability of an Activity's parent task takes precendence over the ActivityInfo. + // This allows for a non resizable activity to be launched into a resizeable task. + final boolean resizeable = + task != null ? task.isResizeable() : supportsResizeableMultiWindow(); + return service.mStackSupervisor.canPlaceEntityOnDisplay(displayId, - supportsResizeableMultiWindow(), launchedFromPid, launchedFromUid, info); + resizeable, launchedFromPid, launchedFromUid, info); } /** diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index a6a702fbfc13..6140c266f96b 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1962,7 +1962,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop) { final boolean isInPinnedStack = r.getStack().getStackId() == PINNED_STACK_ID; - final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing(); + final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing( + mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY); final boolean keyguardLocked = mStackSupervisor.mKeyguardController.isKeyguardLocked(); final boolean showWhenLocked = r.canShowWhenLocked() && !isInPinnedStack; final boolean dismissKeyguard = r.hasDismissKeyguardWindows(); @@ -5194,8 +5195,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai voiceInteractor); // add the task to stack first, mTaskPositioner might need the stack association addTask(task, toTop, "createTaskRecord"); - final boolean isLockscreenShown = - mService.mStackSupervisor.mKeyguardController.isKeyguardShowing(); + final boolean isLockscreenShown = mService.mStackSupervisor.mKeyguardController + .isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY); if (!layoutTaskInStack(task, info.windowLayout) && mBounds != null && task.isResizeable() && !isLockscreenShown) { task.updateOverrideConfiguration(mBounds); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index c8a2a230a7e1..ffe5fd48706a 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -21,6 +21,7 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.START_ANY_ACTIVITY; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.app.ActivityManager.START_TASK_TO_FRONT; +import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID; import static android.app.ActivityManager.StackId.FIRST_STATIC_STACK_ID; @@ -31,13 +32,20 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManager.StackId.RECENTS_STACK_ID; +import static android.app.ActivityManager.StackId.getStackIdForActivityType; +import static android.app.ActivityManager.StackId.getStackIdForWindowingMode; import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY; import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.PowerManager.PARTIAL_WAKE_LOCK; @@ -83,6 +91,7 @@ import static com.android.server.am.ActivityStack.ActivityState.STOPPING; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING; import static com.android.server.am.ActivityStack.STACK_INVISIBLE; import static com.android.server.am.ActivityStack.STACK_VISIBLE; +import static com.android.server.am.TaskRecord.INVALID_TASK_ID; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; @@ -94,6 +103,7 @@ import static java.lang.Integer.MAX_VALUE; import android.Manifest; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; @@ -707,24 +717,26 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } TaskRecord anyTaskForIdLocked(int id) { - return anyTaskForIdLocked(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, - INVALID_STACK_ID); + return anyTaskForIdLocked(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE); + } + + TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode) { + return anyTaskForIdLocked(id, matchMode, null); } /** * Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise. * @param id Id of the task we would like returned. * @param matchMode The mode to match the given task id in. - * @param stackId The stack to restore the task to (default launch stack will be used if - * stackId is {@link android.app.ActivityManager.StackId#INVALID_STACK_ID}). Only - * valid if the matchMode is - * {@link #MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE}. + * @param aOptions The activity options to use for restoration. Can be null. */ - TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode, int stackId) { + TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode, + @Nullable ActivityOptions aOptions) { // If there is a stack id set, ensure that we are attempting to actually restore a task - if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && - stackId != INVALID_STACK_ID) { - throw new IllegalArgumentException("Should not specify stackId for non-restore lookup"); + // TODO: Don't really know if this is needed... + if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) { + throw new IllegalArgumentException("Should not specify activity options for non-restore" + + " lookup"); } int numDisplays = mActivityDisplays.size(); @@ -762,7 +774,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } // Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE - if (!restoreRecentTaskLocked(task, stackId)) { + if (!restoreRecentTaskLocked(task, aOptions)) { if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Couldn't restore task id=" + id + " found in recents"); return null; @@ -857,8 +869,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on. int candidateTaskId = nextTaskIdForUser(currentTaskId, userId); while (mRecentTasks.taskIdTakenForUserLocked(candidateTaskId, userId) - || anyTaskForIdLocked(candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, - INVALID_STACK_ID) != null) { + || anyTaskForIdLocked( + candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) { candidateTaskId = nextTaskIdForUser(candidateTaskId, userId); if (candidateTaskId == currentTaskId) { // Something wrong! @@ -2084,38 +2096,35 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // we'll just indicate that this task returns to the home task. task.setTaskToReturnTo(ACTIVITY_TYPE_HOME); } - ActivityStack currentStack = task.getStack(); + final ActivityStack currentStack = task.getStack(); if (currentStack == null) { Slog.e(TAG, "findTaskToMoveToFrontLocked: can't move task=" + task + " to front. Stack is null"); return; } - if (task.isResizeable() && options != null) { - int stackId = options.getLaunchStackId(); - if (canUseActivityOptionsLaunchBounds(options, stackId)) { - final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds()); - task.updateOverrideConfiguration(bounds); - if (stackId == INVALID_STACK_ID) { - stackId = task.getLaunchStackId(); - } - if (stackId != currentStack.mStackId) { - task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE, - DEFER_RESUME, "findTaskToMoveToFrontLocked"); - stackId = currentStack.mStackId; - // moveTaskToStackUncheckedLocked() should already placed the task on top, - // still need moveTaskToFrontLocked() below for any transition settings. - } - if (StackId.resizeStackWithLaunchBounds(stackId)) { - resizeStackLocked(stackId, bounds, - null /* tempTaskBounds */, null /* tempTaskInsetBounds */, - !PRESERVE_WINDOWS, true /* allowResizeInDockedMode */, !DEFER_RESUME); - } else { - // WM resizeTask must be done after the task is moved to the correct stack, - // because Task's setBounds() also updates dim layer's bounds, but that has - // dependency on the stack. - task.resizeWindowContainer(); - } + if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) { + final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds()); + task.updateOverrideConfiguration(bounds); + + int stackId = getLaunchStackId(null, options, task); + + if (stackId != currentStack.mStackId) { + task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE, + DEFER_RESUME, "findTaskToMoveToFrontLocked"); + stackId = currentStack.mStackId; + // moveTaskToStackUncheckedLocked() should already placed the task on top, + // still need moveTaskToFrontLocked() below for any transition settings. + } + if (StackId.resizeStackWithLaunchBounds(stackId)) { + resizeStackLocked(stackId, bounds, + null /* tempTaskBounds */, null /* tempTaskInsetBounds */, + !PRESERVE_WINDOWS, true /* allowResizeInDockedMode */, !DEFER_RESUME); + } else { + // WM resizeTask must be done after the task is moved to the correct stack, + // because Task's setBounds() also updates dim layer's bounds, but that has + // dependency on the stack. + task.resizeWindowContainer(); } } @@ -2126,17 +2135,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (DEBUG_STACK) Slog.d(TAG_STACK, "findTaskToMoveToFront: moved to front of stack=" + currentStack); - handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, DEFAULT_DISPLAY, + handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, currentStack.mStackId, forceNonResizeable); } - boolean canUseActivityOptionsLaunchBounds(ActivityOptions options, int launchStackId) { + boolean canUseActivityOptionsLaunchBounds(ActivityOptions options) { // We use the launch bounds in the activity options is the device supports freeform // window management or is launching into the pinned stack. - if (options.getLaunchBounds() == null) { + if (options == null || options.getLaunchBounds() == null) { return false; } - return (mService.mSupportsPictureInPicture && launchStackId == PINNED_STACK_ID) + return (mService.mSupportsPictureInPicture + && options.getLaunchWindowingMode() == WINDOWING_MODE_PINNED) || mService.mSupportsFreeformWindowManagement; } @@ -2161,6 +2171,179 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return (T) createStackOnDisplay(stackId, DEFAULT_DISPLAY, createOnTop); } + private int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options, + @Nullable TaskRecord task) { + + // First preference if the windowing mode in the activity options if set. + int windowingMode = (options != null) + ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED; + + // If windowing mode is unset, then next preference is the candidate task, then the + // activity record. + if (windowingMode == WINDOWING_MODE_UNDEFINED) { + if (task != null) { + windowingMode = task.getWindowingMode(); + } + if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) { + windowingMode = r.getWindowingMode(); + } + } + + // Make sure the windowing mode we are trying to use makes sense for what is supported. + if (!mService.mSupportsMultiWindow && windowingMode != WINDOWING_MODE_FULLSCREEN) { + windowingMode = WINDOWING_MODE_FULLSCREEN; + } + + if (!mService.mSupportsSplitScreenMultiWindow + && (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY + || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)) { + windowingMode = WINDOWING_MODE_FULLSCREEN; + } + + if (windowingMode == WINDOWING_MODE_FREEFORM + && !mService.mSupportsFreeformWindowManagement) { + windowingMode = WINDOWING_MODE_FULLSCREEN; + } + + return windowingMode; + } + + private int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options, + @Nullable TaskRecord task) { + // First preference if the activity type in the activity options if set. + int activityType = (options != null) + ? options.getLaunchActivityType() : ACTIVITY_TYPE_UNDEFINED; + + if (activityType != ACTIVITY_TYPE_UNDEFINED) { + return activityType; + } + + // If activity type is unset, then next preference is the task, then the activity record. + if (task != null) { + activityType = task.getActivityType(); + } + if (activityType == ACTIVITY_TYPE_UNDEFINED && r != null) { + activityType = r.getActivityType(); + } + return activityType; + } + + int getLaunchStackId(@Nullable ActivityRecord r, @Nullable ActivityOptions options, + @Nullable TaskRecord candidateTask) { + return getLaunchStackId(r, options, candidateTask, INVALID_DISPLAY); + } + + /** + * Returns the right stack to use for launching factoring in all the input parameters. + * + * @param r The activity we are trying to launch. Can be null. + * @param options The activity options used to the launch. Can be null. + * @param candidateTask The possible task the activity might be launched in. Can be null. + * + * @return The stack to use for the launch or INVALID_STACK_ID. + */ + int getLaunchStackId(@Nullable ActivityRecord r, @Nullable ActivityOptions options, + @Nullable TaskRecord candidateTask, int candidateDisplayId) { + int taskId = INVALID_TASK_ID; + int displayId = INVALID_DISPLAY; + //Rect bounds = null; + + // We give preference to the launch preference in activity options. + if (options != null) { + taskId = options.getLaunchTaskId(); + displayId = options.getLaunchDisplayId(); + // TODO: Need to work this into the equation... + //bounds = options.getLaunchBounds(); + } + + // First preference for stack goes to the task Id set in the activity options. Use the stack + // associated with that if possible. + if (taskId != INVALID_TASK_ID) { + // Temporarily set the task id to invalid in case in re-entry. + options.setLaunchTaskId(INVALID_TASK_ID); + final TaskRecord task = anyTaskForIdLocked(taskId, + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options); + options.setLaunchTaskId(taskId); + if (task != null) { + return task.getStack().mStackId; + } + } + + final int windowingMode = resolveWindowingMode(r, options, candidateTask); + final int activityType = resolveActivityType(r, options, candidateTask); + ActivityStack stack = null; + + // Next preference for stack goes to the display Id set in the activity options or the + // candidate display. + if (displayId == INVALID_DISPLAY) { + displayId = candidateDisplayId; + } + if (displayId != INVALID_DISPLAY) { + if (r != null) { + // TODO: This should also take in the windowing mode and activity type into account. + stack = getValidLaunchStackOnDisplay(displayId, r); + if (stack != null) { + return stack.mStackId; + } + } + final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId); + if (display != null) { + for (int i = display.mStacks.size() - 1; i >= 0; --i) { + stack = display.mStacks.get(i); + if (stack.getWindowingMode() == windowingMode + && stack.getActivityType() == activityType) { + return stack.mStackId; + } + } + // TODO: We should create the stack we want on the display at this point. + } + } + + // Give preference to the stack and display of the input task and activity if they match the + // mode we want to launch into. + if (candidateTask != null) { + stack = candidateTask.getStack(); + } + if (stack == null && r != null) { + stack = r.getStack(); + } + if (stack != null) { + if (stack.getWindowingMode() == windowingMode + && stack.getActivityType() == activityType) { + return stack.mStackId; + } + ActivityDisplay display = stack.getDisplay(); + + if (display != null) { + for (int i = display.mStacks.size() - 1; i >= 0; --i) { + stack = display.mStacks.get(i); + if (stack.getWindowingMode() == windowingMode + && stack.getActivityType() == activityType) { + return stack.mStackId; + } + } + } + } + + // Give preference to the type of activity we are trying to launch followed by the windowing + // mode. + int stackId = getStackIdForActivityType(activityType); + if (stackId != INVALID_STACK_ID) { + return stackId; + } + stackId = getStackIdForWindowingMode(windowingMode); + if (stackId != INVALID_STACK_ID) { + return stackId; + } + + // Whatever...return some default for now. + if (candidateTask != null && candidateTask.mBounds != null + && mService.mSupportsFreeformWindowManagement) { + return FREEFORM_WORKSPACE_STACK_ID; + } + return FULLSCREEN_WORKSPACE_STACK_ID; + } + /** * Get a topmost stack on the display, that is a valid launch stack for specified activity. * If there is no such stack, new dynamic stack can be created. @@ -2178,7 +2361,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Return the topmost valid stack on the display. for (int i = activityDisplay.mStacks.size() - 1; i >= 0; --i) { final ActivityStack stack = activityDisplay.mStacks.get(i); - if (mService.mActivityStarter.isValidLaunchStackId(stack.mStackId, displayId, r)) { + if (isValidLaunchStackId(stack.mStackId, displayId, r)) { return stack; } } @@ -2186,7 +2369,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // If there is no valid stack on the external display - check if new dynamic stack will do. if (displayId != Display.DEFAULT_DISPLAY) { final int newDynamicStackId = getNextStackId(); - if (mService.mActivityStarter.isValidLaunchStackId(newDynamicStackId, displayId, r)) { + if (isValidLaunchStackId(newDynamicStackId, displayId, r)) { return createStackOnDisplay(newDynamicStackId, displayId, true /*onTop*/); } } @@ -2195,6 +2378,32 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return null; } + boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) { + switch (stackId) { + case INVALID_STACK_ID: + case HOME_STACK_ID: + return false; + case FULLSCREEN_WORKSPACE_STACK_ID: + return true; + case FREEFORM_WORKSPACE_STACK_ID: + return r.supportsFreeform(); + case DOCKED_STACK_ID: + return r.supportsSplitScreen(); + case PINNED_STACK_ID: + return r.supportsPictureInPicture(); + case RECENTS_STACK_ID: + return r.isActivityTypeRecents(); + case ASSISTANT_STACK_ID: + return r.isActivityTypeAssistant(); + default: + if (StackId.isDynamicStack(stackId)) { + return r.canBeLaunchedOnDisplay(displayId); + } + Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId); + return false; + } + } + ArrayList<ActivityStack> getStacks() { ArrayList<ActivityStack> allStacks = new ArrayList<>(); for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { @@ -2345,8 +2554,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D continueUpdateBounds(RECENTS_STACK_ID); for (int i = mResizingTasksDuringAnimation.size() - 1; i >= 0; i--) { final int taskId = mResizingTasksDuringAnimation.valueAt(i); - final TaskRecord task = - anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID); + final TaskRecord task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_ONLY); if (task != null) { task.setTaskDockedResizing(false); } @@ -2641,8 +2849,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D */ boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents, boolean pauseImmediately) { - final TaskRecord tr = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, - INVALID_STACK_ID); + final TaskRecord tr = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (tr != null) { tr.removeTaskActivitiesLocked(pauseImmediately); cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents); @@ -2741,23 +2948,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** * Restores a recent task to a stack * @param task The recent task to be restored. - * @param stackId The stack to restore the task to (default launch stack will be used - * if stackId is {@link android.app.ActivityManager.StackId#INVALID_STACK_ID} - * or is not a static stack). + * @param aOptions The activity options to use for restoration. * @return true if the task has been restored successfully. */ - boolean restoreRecentTaskLocked(TaskRecord task, int stackId) { - if (!StackId.isStaticStack(stackId)) { - // If stack is not static (or stack id is invalid) - use the default one. - // This means that tasks that were on external displays will be restored on the - // primary display. - stackId = task.getLaunchStackId(); - } else if (stackId == DOCKED_STACK_ID && !task.supportsSplitScreen()) { - // Preferred stack is the docked stack, but the task can't go in the docked stack. - // Put it in the fullscreen stack. - stackId = FULLSCREEN_WORKSPACE_STACK_ID; - } - + boolean restoreRecentTaskLocked(TaskRecord task, ActivityOptions aOptions) { + final int stackId = getLaunchStackId(null, aOptions, task); final ActivityStack currentStack = task.getStack(); if (currentStack != null) { // Task has already been restored once. See if we need to do anything more @@ -2770,15 +2965,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D currentStack.removeTask(task, "restoreRecentTaskLocked", REMOVE_TASK_MODE_MOVING); } - final ActivityStack stack = - getStack(stackId, CREATE_IF_NEEDED, !ON_TOP); - - if (stack == null) { - // What does this mean??? Not sure how we would get here... - if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, - "Unable to find/create stack to restore recent task=" + task); - return false; - } + final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, !ON_TOP); stack.addTask(task, false /* toTop */, "restoreRecentTask"); // TODO: move call for creation here and other place into Stack.addTask() @@ -4015,21 +4202,20 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return list; } - void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredStackId, + void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode, int preferredDisplayId, int actualStackId) { - handleNonResizableTaskIfNeeded(task, preferredStackId, preferredDisplayId, actualStackId, - false /* forceNonResizable */); + handleNonResizableTaskIfNeeded(task, preferredWindowingMode, preferredDisplayId, + actualStackId, false /* forceNonResizable */); } - void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredStackId, + void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode, int preferredDisplayId, int actualStackId, boolean forceNonResizable) { final boolean isSecondaryDisplayPreferred = - (preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY) - || StackId.isDynamicStack(preferredStackId); + (preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY); final ActivityStack actualStack = getStack(actualStackId); final boolean inSplitScreenMode = actualStack != null && actualStack.inSplitScreenWindowingMode(); - if (((!inSplitScreenMode && preferredStackId != DOCKED_STACK_ID) + if (((!inSplitScreenMode && preferredWindowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) && !isSecondaryDisplayPreferred) || task.isActivityTypeHome()) { return; } @@ -4424,18 +4610,22 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final String callingPackage; final Intent intent; final int userId; + int activityType = ACTIVITY_TYPE_UNDEFINED; + int windowingMode = WINDOWING_MODE_UNDEFINED; final ActivityOptions activityOptions = (bOptions != null) ? new ActivityOptions(bOptions) : null; - final int launchStackId = (activityOptions != null) - ? activityOptions.getLaunchStackId() : INVALID_STACK_ID; - if (StackId.isHomeOrRecentsStack(launchStackId)) { + if (activityOptions != null) { + activityType = activityOptions.getLaunchActivityType(); + windowingMode = activityOptions.getLaunchWindowingMode(); + } + if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) { throw new IllegalArgumentException("startActivityFromRecentsInner: Task " + taskId + " can't be launch in the home/recents stack."); } mWindowManager.deferSurfaceLayout(); try { - if (launchStackId == DOCKED_STACK_ID) { + if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { mWindowManager.setDockedStackCreateState( activityOptions.getDockCreateMode(), null /* initialBounds */); @@ -4447,7 +4637,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, - launchStackId); + activityOptions); if (task == null) { continueUpdateBounds(RECENTS_STACK_ID); mWindowManager.executeAppTransition(); @@ -4458,14 +4648,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Since we don't have an actual source record here, we assume that the currently // focused activity was the source. final ActivityStack focusedStack = getFocusedStack(); - final ActivityRecord sourceRecord = - focusedStack != null ? focusedStack.topActivity() : null; + final ActivityRecord sourceRecord = focusedStack != null + ? focusedStack.topActivity() : null; + final int stackId = getLaunchStackId(null, activityOptions, task); - if (launchStackId != INVALID_STACK_ID) { - if (task.getStackId() != launchStackId) { - task.reparent(launchStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, - DEFER_RESUME, "startActivityFromRecents"); - } + if (stackId != INVALID_STACK_ID && task.getStackId() != stackId) { + task.reparent(stackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME, + "startActivityFromRecents"); } // If the user must confirm credentials (e.g. when first launching a work app and the @@ -4484,7 +4673,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // If we are launching the task in the docked stack, put it into resizing mode so // the window renders full-screen with the background filling the void. Also only // call this at the end to make sure that tasks exists on the window manager side. - if (launchStackId == DOCKED_STACK_ID) { + if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { setResizingDuringAnimation(task); } @@ -4502,7 +4691,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D userId = task.userId; int result = mService.startActivityInPackage(callingUid, callingPackage, intent, null, null, null, 0, 0, bOptions, userId, task, "startActivityFromRecents"); - if (launchStackId == DOCKED_STACK_ID) { + if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { setResizingDuringAnimation(task); } return result; diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 16abcfb620d9..d94e866b312b 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -39,6 +39,8 @@ import static android.app.ActivityManager.StackId.isDynamicStack; import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; @@ -1024,10 +1026,12 @@ class ActivityStarter { ActivityRecord reusedActivity = getReusableIntentActivity(); - final int preferredLaunchStackId = - (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID; - final int preferredLaunchDisplayId = - (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY; + int preferredWindowingMode = WINDOWING_MODE_UNDEFINED; + int preferredLaunchDisplayId = DEFAULT_DISPLAY; + if (mOptions != null) { + preferredWindowingMode = mOptions.getLaunchWindowingMode(); + preferredLaunchDisplayId = mOptions.getLaunchDisplayId(); + } if (reusedActivity != null) { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but @@ -1158,7 +1162,7 @@ class ActivityStarter { // Don't use mStartActivity.task to show the toast. We're not starting a new activity // but reusing 'top'. Fields in mStartActivity may not be fully initialized. - mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId, + mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode, preferredLaunchDisplayId, topStack.mStackId); return START_DELIVERED_TO_TOP; @@ -1173,8 +1177,7 @@ class ActivityStarter { if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; - result = setTaskFromReuseOrCreateNewTask( - taskToAffiliate, preferredLaunchStackId, topStack); + result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack); } else if (mSourceRecord != null) { result = setTaskFromSourceRecord(); } else if (mInTask != null) { @@ -1241,7 +1244,7 @@ class ActivityStarter { } mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); - mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId, + mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode, preferredLaunchDisplayId, mTargetStack.mStackId); return START_SUCCESS; @@ -1654,8 +1657,8 @@ class ActivityStarter { mTargetStack.moveToFront("intentActivityFound"); } - mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID, - DEFAULT_DISPLAY, mTargetStack.mStackId); + mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), + WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack.mStackId); // If the caller has requested that the target task be reset, then do so. if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { @@ -1675,8 +1678,7 @@ class ActivityStarter { // Task will be launched over the home stack, so return home. task.setTaskToReturnTo(ACTIVITY_TYPE_HOME); return; - } else if (focusedStack != null && focusedStack != task.getStack() && - focusedStack.isActivityTypeAssistant()) { + } else if (focusedStack != task.getStack() && focusedStack.isActivityTypeAssistant()) { // Task was launched over the assistant stack, so return there task.setTaskToReturnTo(ACTIVITY_TYPE_ASSISTANT); return; @@ -1779,7 +1781,7 @@ class ActivityStarter { } private int setTaskFromReuseOrCreateNewTask( - TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) { + TaskRecord taskToAffiliate, ActivityStack topStack) { mTargetStack = computeStackFocus( mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions); @@ -1821,8 +1823,10 @@ class ActivityStarter { // If stack id is specified in activity options, usually it means that activity is // launched not from currently focused stack (e.g. from SysUI or from shell) - in // that case we check the target stack. + // TODO: Not sure I understand the value or use of the commented out code and the + // comment above. See if this causes any issues and why... updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags, - preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack); + /*preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : */topStack); } if (mDoResume) { mTargetStack.moveToFront("reuseOrNewTask"); @@ -1964,7 +1968,8 @@ class ActivityStarter { if (mLaunchBounds != null) { mInTask.updateOverrideConfiguration(mLaunchBounds); - int stackId = mInTask.getLaunchStackId(); + // TODO: Shouldn't we already know what stack to use by the time we get here? + int stackId = mSupervisor.getLaunchStackId(null, null, mInTask); if (stackId != mInTask.getStackId()) { mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE, DEFER_RESUME, "inTaskToFront"); @@ -2102,9 +2107,10 @@ class ActivityStarter { } } // If there is no suitable dynamic stack then we figure out which static stack to use. - final int stackId = task != null ? task.getLaunchStackId() : - bounds != null ? FREEFORM_WORKSPACE_STACK_ID : - FULLSCREEN_WORKSPACE_STACK_ID; + final int stackId = task != null ? mSupervisor.getLaunchStackId(r, aOptions, task) + // TODO: This should go in mSupervisor.getLaunchStackId method... + : bounds != null && mService.mSupportsFreeformWindowManagement + ? FREEFORM_WORKSPACE_STACK_ID : FULLSCREEN_WORKSPACE_STACK_ID; stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP); } if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r=" @@ -2165,18 +2171,16 @@ class ActivityStarter { return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP); } - final int launchDisplayId = - (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY; - - final int launchStackId = - (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID; - - if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) { - throw new IllegalArgumentException( - "Stack and display id can't be set at the same time."); + int launchDisplayId = INVALID_DISPLAY; + int launchStackId = INVALID_STACK_ID; + if (aOptions != null) { + launchDisplayId = aOptions.getLaunchDisplayId(); + final int vrDisplayId = mUsingVr2dDisplay ? mSourceDisplayId : INVALID_DISPLAY; + launchStackId = mSupervisor.getLaunchStackId(r, aOptions, task, vrDisplayId); } - if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) { + // TODO: Will no longer be needed once we are on longer using static stack ids. + if (mSupervisor.isValidLaunchStackId(launchStackId, launchDisplayId, r)) { return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP); } if (launchStackId == DOCKED_STACK_ID) { @@ -2184,12 +2188,14 @@ class ActivityStarter { // for this activity, so we put the activity in the fullscreen stack. return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP); } + // TODO: Can probably be removed since ASS.getLaunchStackId() does display resolution. if (launchDisplayId != INVALID_DISPLAY) { // Stack id has higher priority than display id. return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r); } // If we are using Vr2d display, find the virtual display stack. + // TODO: Can be removed. if (mUsingVr2dDisplay) { ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r); if (DEBUG_STACK) { @@ -2240,39 +2246,11 @@ class ActivityStarter { } } - boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) { - switch (stackId) { - case INVALID_STACK_ID: - case HOME_STACK_ID: - return false; - case FULLSCREEN_WORKSPACE_STACK_ID: - return true; - case FREEFORM_WORKSPACE_STACK_ID: - return r.supportsFreeform(); - case DOCKED_STACK_ID: - return r.supportsSplitScreen(); - case PINNED_STACK_ID: - return r.supportsPictureInPicture(); - case RECENTS_STACK_ID: - return r.isActivityTypeRecents(); - case ASSISTANT_STACK_ID: - return r.isActivityTypeAssistant(); - default: - if (StackId.isDynamicStack(stackId)) { - return r.canBeLaunchedOnDisplay(displayId); - } - Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId); - return false; - } - } - - Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) { + private Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) { Rect newBounds = null; - if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) { - if (mSupervisor.canUseActivityOptionsLaunchBounds( - options, options.getLaunchStackId())) { - newBounds = TaskRecord.validateBounds(options.getLaunchBounds()); - } + if (mSupervisor.canUseActivityOptionsLaunchBounds(options) + && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) { + newBounds = TaskRecord.validateBounds(options.getLaunchBounds()); } return newBounds; } diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index cea80c8d0e9d..85961135d84f 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -19,6 +19,7 @@ package com.android.server.am; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS; import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; @@ -66,6 +67,7 @@ class KeyguardController { private int mBeforeUnoccludeTransit; private int mVisibilityTransactionDepth; private SleepToken mSleepToken; + private int mSecondaryDisplayShowing = INVALID_DISPLAY; KeyguardController(ActivityManagerService service, ActivityStackSupervisor stackSupervisor) { @@ -78,10 +80,12 @@ class KeyguardController { } /** - * @return true if Keyguard is showing, not going away, and not being occluded, false otherwise + * @return true if Keyguard is showing, not going away, and not being occluded on the given + * display, false otherwise */ - boolean isKeyguardShowing() { - return mKeyguardShowing && !mKeyguardGoingAway && !mOccluded; + boolean isKeyguardShowing(int displayId) { + return mKeyguardShowing && !mKeyguardGoingAway && + (displayId == DEFAULT_DISPLAY ? !mOccluded : displayId == mSecondaryDisplayShowing); } /** @@ -94,15 +98,19 @@ class KeyguardController { /** * Update the Keyguard showing state. */ - void setKeyguardShown(boolean showing) { - if (showing == mKeyguardShowing) { + void setKeyguardShown(boolean showing, int secondaryDisplayShowing) { + boolean showingChanged = showing != mKeyguardShowing; + if (!showingChanged && secondaryDisplayShowing == mSecondaryDisplayShowing) { return; } mKeyguardShowing = showing; - dismissDockedStackIfNeeded(); - if (showing) { - setKeyguardGoingAway(false); - mDismissalRequested = false; + mSecondaryDisplayShowing = secondaryDisplayShowing; + if (showingChanged) { + dismissDockedStackIfNeeded(); + if (showing) { + setKeyguardGoingAway(false); + mDismissalRequested = false; + } } mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); updateKeyguardSleepToken(); @@ -337,9 +345,9 @@ class KeyguardController { } private void updateKeyguardSleepToken() { - if (mSleepToken == null && isKeyguardShowing()) { + if (mSleepToken == null && isKeyguardShowing(DEFAULT_DISPLAY)) { mSleepToken = mService.acquireSleepToken("Keyguard", DEFAULT_DISPLAY); - } else if (mSleepToken != null && !isKeyguardShowing()) { + } else if (mSleepToken != null && !isKeyguardShowing(DEFAULT_DISPLAY)) { mSleepToken.release(); mSleepToken = null; } diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java index 241e58391144..72b5de88e50f 100644 --- a/services/core/java/com/android/server/am/LockTaskController.java +++ b/services/core/java/com/android/server/am/LockTaskController.java @@ -25,6 +25,7 @@ import static android.app.StatusBarManager.DISABLE_HOME; import static android.app.StatusBarManager.DISABLE_MASK; import static android.app.StatusBarManager.DISABLE_NONE; import static android.app.StatusBarManager.DISABLE_RECENT; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.Context.DEVICE_POLICY_SERVICE; import static android.content.Context.STATUS_BAR_SERVICE; import static android.os.UserHandle.USER_ALL; @@ -431,8 +432,8 @@ public class LockTaskController { mSupervisor.resumeFocusedStackTopActivityLocked(); mWindowManager.executeAppTransition(); } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) { - mSupervisor.handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, DEFAULT_DISPLAY, - task.getStackId(), true /* forceNonResizable */); + mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED, + DEFAULT_DISPLAY, task.getStackId(), true /* forceNonResizable */); } } diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java index 74c4826f583b..f6e20cd2e1b4 100644 --- a/services/core/java/com/android/server/am/TaskPersister.java +++ b/services/core/java/com/android/server/am/TaskPersister.java @@ -472,8 +472,7 @@ public class TaskPersister { final int taskId = task.taskId; if (mStackSupervisor.anyTaskForIdLocked(taskId, - MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, - INVALID_STACK_ID) != null) { + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) { // Should not happen. Slog.wtf(TAG, "Existing task with taskId " + taskId + "found"); } else if (userId != task.userId) { diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 48da6555e75c..28b71d9c978d 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -26,6 +26,7 @@ import static android.app.ActivityManager.StackId.HOME_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManager.StackId.RECENTS_STACK_ID; +import static android.app.ActivityManager.StackId.getWindowingModeForStackId; import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; @@ -507,8 +508,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi updateOverrideConfiguration(bounds); if (getStackId() != FREEFORM_WORKSPACE_STACK_ID) { // re-restore the task so it can have the proper stack association. - mService.mStackSupervisor.restoreRecentTaskLocked(this, - FREEFORM_WORKSPACE_STACK_ID); + mService.mStackSupervisor.restoreRecentTaskLocked(this, null); } return true; } @@ -729,7 +729,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi } // TODO: Handle incorrect request to move before the actual move, not after. - supervisor.handleNonResizableTaskIfNeeded(this, preferredStackId, DEFAULT_DISPLAY, stackId); + supervisor.handleNonResizableTaskIfNeeded(this, getWindowingModeForStackId(preferredStackId, + supervisor.getStack(DOCKED_STACK_ID) != null), DEFAULT_DISPLAY, stackId); boolean successful = (preferredStackId == stackId); if (successful && stackId == DOCKED_STACK_ID) { @@ -2079,27 +2080,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi } } - /** - * Returns the correct stack to use based on task type and currently set bounds, - * regardless of the focused stack and current stack association of the task. - * The task will be moved (and stack focus changed) later if necessary. - */ - int getLaunchStackId() { - if (isActivityTypeRecents()) { - return RECENTS_STACK_ID; - } - if (isActivityTypeHome()) { - return HOME_STACK_ID; - } - if (isActivityTypeAssistant()) { - return ASSISTANT_STACK_ID; - } - if (mBounds != null) { - return FREEFORM_WORKSPACE_STACK_ID; - } - return FULLSCREEN_WORKSPACE_STACK_ID; - } - /** Returns the bounds that should be used to launch this task. */ private Rect getLaunchBounds() { if (mStack == null) { diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index db6bb7d8e653..f2e294217999 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -22,6 +22,7 @@ import static android.app.ActivityManager.USER_OP_ERROR_IS_SYSTEM; import static android.app.ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP; import static android.app.ActivityManager.USER_OP_IS_CURRENT; import static android.app.ActivityManager.USER_OP_SUCCESS; +import static android.os.Process.SHELL_UID; import static android.os.Process.SYSTEM_UID; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; @@ -30,14 +31,6 @@ import static com.android.server.am.ActivityManagerService.ALLOW_FULL_ONLY; import static com.android.server.am.ActivityManagerService.ALLOW_NON_FULL; import static com.android.server.am.ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE; import static com.android.server.am.ActivityManagerService.MY_PID; -import static com.android.server.am.ActivityManagerService.REPORT_LOCKED_BOOT_COMPLETE_MSG; -import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_COMPLETE_MSG; -import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MSG; -import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG; -import static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG; -import static com.android.server.am.ActivityManagerService.SYSTEM_USER_UNLOCK_MSG; -import static com.android.server.am.ActivityManagerService.USER_SWITCH_CALLBACKS_TIMEOUT_MSG; -import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG; import static com.android.server.am.UserState.STATE_BOOTING; import static com.android.server.am.UserState.STATE_RUNNING_LOCKED; import static com.android.server.am.UserState.STATE_RUNNING_UNLOCKED; @@ -68,6 +61,7 @@ import android.os.IBinder; import android.os.IProgressListener; import android.os.IRemoteCallback; import android.os.IUserManager; +import android.os.Message; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -78,6 +72,7 @@ import android.os.UserManager; import android.os.UserManagerInternal; import android.os.storage.IStorageManager; import android.os.storage.StorageManager; +import android.text.format.DateUtils; import android.util.ArraySet; import android.util.IntArray; import android.util.Pair; @@ -93,6 +88,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; +import com.android.server.SystemServiceManager; import com.android.server.pm.UserManagerService; import com.android.server.wm.WindowManagerService; @@ -108,7 +104,7 @@ import java.util.concurrent.atomic.AtomicInteger; /** * Helper class for {@link ActivityManagerService} responsible for multi-user functionality. */ -class UserController { +class UserController implements Handler.Callback { private static final String TAG = TAG_WITH_CLASS_NAME ? "UserController" : TAG_AM; // Maximum number of users we allow to be running at a time. @@ -118,6 +114,23 @@ class UserController { // giving up on them and unfreezing the screen. static final int USER_SWITCH_TIMEOUT_MS = 3 * 1000; + // ActivityManager thread message constants + static final int REPORT_USER_SWITCH_MSG = 10; + static final int CONTINUE_USER_SWITCH_MSG = 20; + static final int USER_SWITCH_TIMEOUT_MSG = 30; + static final int START_PROFILES_MSG = 40; + static final int SYSTEM_USER_START_MSG = 50; + static final int SYSTEM_USER_CURRENT_MSG = 60; + static final int FOREGROUND_PROFILE_CHANGED_MSG = 70; + static final int REPORT_USER_SWITCH_COMPLETE_MSG = 80; + static final int USER_SWITCH_CALLBACKS_TIMEOUT_MSG = 90; + static final int SYSTEM_USER_UNLOCK_MSG = 100; + static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 110; + static final int START_USER_SWITCH_FG_MSG = 120; + + // UI thread message constants + static final int START_USER_SWITCH_UI_MSG = 1000; + // If a callback wasn't called within USER_SWITCH_CALLBACKS_TIMEOUT_MS after // USER_SWITCH_TIMEOUT_MS, an error is reported. Usually it indicates a problem in the observer // when it never calls back. @@ -126,6 +139,7 @@ class UserController { private final Object mLock; private final Injector mInjector; private final Handler mHandler; + private final Handler mUiHandler; // Holds the current foreground user's id. Use mLock when updating @GuardedBy("mLock") @@ -193,7 +207,8 @@ class UserController { UserController(Injector injector) { mInjector = injector; mLock = injector.getLock(); - mHandler = injector.getHandler(); + mHandler = mInjector.getHandler(this); + mUiHandler = mInjector.getUiHandler(this); // User 0 is the first and only user that runs at boot. final UserState uss = new UserState(UserHandle.SYSTEM); mStartedUsers.put(UserHandle.USER_SYSTEM, uss); @@ -499,7 +514,7 @@ class UserController { if (userId < 0 || userId == UserHandle.USER_SYSTEM) { throw new IllegalArgumentException("Can't stop system user " + userId); } - mInjector.enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId); + enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId); synchronized (mLock) { return stopUsersLocked(userId, force, callback); } @@ -635,7 +650,7 @@ class UserController { mInjector.batteryStatsServiceNoteEvent( BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH, Integer.toString(userId), userId); - mInjector.systemServiceManagerStopUser(userId); + mInjector.getSystemServiceManager().stopUser(userId); synchronized (mLock) { mInjector.broadcastIntentLocked(shutdownIntent, @@ -765,6 +780,13 @@ class UserController { } } + void scheduleStartProfilesLocked() { + if (!mHandler.hasMessages(START_PROFILES_MSG)) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG), + DateUtils.SECOND_IN_MILLIS); + } + } + void startProfilesLocked() { if (DEBUG_MU) Slog.i(TAG, "startProfilesLocked"); List<UserInfo> profiles = mInjector.getUserManager().getProfiles( @@ -1080,6 +1102,50 @@ class UserController { return true; } + boolean switchUser(final int targetUserId) { + enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId); + int currentUserId; + UserInfo targetUserInfo; + synchronized (mLock) { + currentUserId = getCurrentUserIdLocked(); + targetUserInfo = getUserInfo(targetUserId); + if (targetUserId == currentUserId) { + Slog.i(TAG, "user #" + targetUserId + " is already the current user"); + return true; + } + if (targetUserInfo == null) { + Slog.w(TAG, "No user info for user #" + targetUserId); + return false; + } + if (!targetUserInfo.isDemo() && UserManager.isDeviceInDemoMode(mInjector.getContext())) { + Slog.w(TAG, "Cannot switch to non-demo user #" + targetUserId + + " when device is in demo mode"); + return false; + } + if (!targetUserInfo.supportsSwitchTo()) { + Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported"); + return false; + } + if (targetUserInfo.isManagedProfile()) { + Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user"); + return false; + } + setTargetUserIdLocked(targetUserId); + } + if (mUserSwitchUiEnabled) { + UserInfo currentUserInfo = getUserInfo(currentUserId); + Pair<UserInfo, UserInfo> userNames = new Pair<>(currentUserInfo, targetUserInfo); + mUiHandler.removeMessages(START_USER_SWITCH_UI_MSG); + mUiHandler.sendMessage(mHandler.obtainMessage( + START_USER_SWITCH_UI_MSG, userNames)); + } else { + mHandler.removeMessages(START_USER_SWITCH_FG_MSG); + mHandler.sendMessage(mHandler.obtainMessage( + START_USER_SWITCH_FG_MSG, targetUserId, 0)); + } + return true; + } + void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) { // The dialog will show and then initiate the user switch by calling startUserInForeground mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second); @@ -1215,7 +1281,7 @@ class UserController { void sendContinueUserSwitchLocked(UserState uss, int oldUserId, int newUserId) { mCurWaitingUserSwitchCallbacks = null; mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG); - mHandler.sendMessage(mHandler.obtainMessage(ActivityManagerService.CONTINUE_USER_SWITCH_MSG, + mHandler.sendMessage(mHandler.obtainMessage(CONTINUE_USER_SWITCH_MSG, oldUserId, newUserId, uss)); } @@ -1395,6 +1461,11 @@ class UserController { mUserSwitchObservers.register(observer, name); } + void sendForegroundProfileChanged(int userId) { + mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG); + mHandler.obtainMessage(FOREGROUND_PROFILE_CHANGED_MSG, userId, 0).sendToTarget(); + } + void unregisterUserSwitchObserver(IUserSwitchObserver observer) { mUserSwitchObservers.unregister(observer); } @@ -1575,6 +1646,15 @@ class UserController { return mInjector.getUserManager().exists(userId); } + void enforceShellRestriction(String restriction, int userHandle) { + if (Binder.getCallingUid() == SHELL_UID) { + if (userHandle < 0 || hasUserRestriction(restriction, userHandle)) { + throw new SecurityException("Shell does not have permission to access user " + + userHandle); + } + } + } + boolean hasUserRestriction(String restriction, int userId) { return mInjector.getUserManager().hasUserRestriction(restriction, userId); } @@ -1667,6 +1747,72 @@ class UserController { } } + public boolean handleMessage(Message msg) { + switch (msg.what) { + case START_USER_SWITCH_FG_MSG: + startUserInForeground(msg.arg1); + break; + case REPORT_USER_SWITCH_MSG: + dispatchUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); + break; + case CONTINUE_USER_SWITCH_MSG: + continueUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); + break; + case USER_SWITCH_TIMEOUT_MSG: + timeoutUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); + break; + case USER_SWITCH_CALLBACKS_TIMEOUT_MSG: + timeoutUserSwitchCallbacks(msg.arg1, msg.arg2); + break; + case START_PROFILES_MSG: + synchronized (mLock) { + startProfilesLocked(); + } + break; + case SYSTEM_USER_START_MSG: + mInjector.batteryStatsServiceNoteEvent( + BatteryStats.HistoryItem.EVENT_USER_RUNNING_START, + Integer.toString(msg.arg1), msg.arg1); + mInjector.getSystemServiceManager().startUser(msg.arg1); + break; + case SYSTEM_USER_UNLOCK_MSG: + final int userId = msg.arg1; + mInjector.getSystemServiceManager().unlockUser(userId); + synchronized (mLock) { + mInjector.loadUserRecentsLocked(userId); + } + if (userId == UserHandle.USER_SYSTEM) { + mInjector.startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE); + } + mInjector.installEncryptionUnawareProviders(userId); + finishUserUnlocked((UserState) msg.obj); + break; + case SYSTEM_USER_CURRENT_MSG: + mInjector.batteryStatsServiceNoteEvent( + BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_FINISH, + Integer.toString(msg.arg2), msg.arg2); + mInjector.batteryStatsServiceNoteEvent( + BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START, + Integer.toString(msg.arg1), msg.arg1); + + mInjector.getSystemServiceManager().switchUser(msg.arg1); + break; + case FOREGROUND_PROFILE_CHANGED_MSG: + dispatchForegroundProfileChanged(msg.arg1); + break; + case REPORT_USER_SWITCH_COMPLETE_MSG: + dispatchUserSwitchComplete(msg.arg1); + break; + case REPORT_LOCKED_BOOT_COMPLETE_MSG: + dispatchLockedBootComplete(msg.arg1); + break; + case START_USER_SWITCH_UI_MSG: + showUserSwitchDialog((Pair<UserInfo, UserInfo>) msg.obj); + break; + } + return false; + } + @VisibleForTesting static class Injector { private final ActivityManagerService mService; @@ -1681,8 +1827,12 @@ class UserController { return mService; } - protected Handler getHandler() { - return mService.mHandler; + protected Handler getHandler(Handler.Callback callback) { + return new Handler(mService.mHandlerThread.getLooper(), callback); + } + + protected Handler getUiHandler(Handler.Callback callback) { + return new Handler(mService.mUiHandler.getLooper(), callback); } protected Context getContext() { @@ -1740,14 +1890,14 @@ class UserController { mService.mBatteryStatsService.noteEvent(code, name, uid); } - void systemServiceManagerStopUser(int userId) { - mService.mSystemServiceManager.stopUser(userId); - } - boolean isRuntimeRestarted() { return mService.mSystemServiceManager.isRuntimeRestarted(); } + SystemServiceManager getSystemServiceManager() { + return mService.mSystemServiceManager; + } + boolean isFirstBootOrUpgrade() { IPackageManager pm = AppGlobals.getPackageManager(); try { @@ -1788,8 +1938,16 @@ class UserController { mService.clearBroadcastQueueForUserLocked(userId); } - void enforceShellRestriction(String restriction, int userId) { - mService.enforceShellRestriction(restriction, userId); + void loadUserRecentsLocked(int userId) { + mService.mRecentTasks.loadUserRecentsLocked(userId); + } + + void startPersistentApps(int matchFlags) { + mService.startPersistentApps(matchFlags); + } + + void installEncryptionUnawareProviders(int userId) { + mService.installEncryptionUnawareProviders(userId); } void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser) { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 91b15912fcb5..11d0470ee8e5 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -6134,12 +6134,12 @@ public class AudioService extends IAudioService.Stub private int mSafeMediaVolumeIndex; // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index // corresponding to a gain of -30 dBFS in audio flinger mixer. - // We remove -15 dBs from the theoretical -15dB to account for the EQ boost when bands are set - // to max gain. + // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost + // amplification when both effects are on with all band gains at maximum. // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when // the headset is compliant to EN 60950 with a max loudness of 100dB SPL. private int mSafeUsbMediaVolumeIndex; - private static final float SAFE_VOLUME_GAIN_DBFS = -30.0f; + private static final float SAFE_VOLUME_GAIN_DBFS = -37.0f; // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced, private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java index 22330e66e126..67e72167faa7 100644 --- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java +++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java @@ -126,7 +126,7 @@ final public class IpConnectivityEventBuilder { wakeupStats.systemWakeups = in.systemWakeups; wakeupStats.nonApplicationWakeups = in.nonApplicationWakeups; wakeupStats.applicationWakeups = in.applicationWakeups; - wakeupStats.unroutedWakeups = in.unroutedWakeups; + wakeupStats.noUidWakeups = in.noUidWakeups; final IpConnectivityEvent out = buildEvent(0, 0, in.iface); out.setWakeupStats(wakeupStats); return out; diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java index 6f7ace2f6527..25dba3570e20 100644 --- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java +++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java @@ -170,11 +170,11 @@ public class NetdEventListenerService extends INetdEventListener.Stub { timestampMs = System.currentTimeMillis(); } - addWakupEvent(iface, timestampMs, uid); + addWakeupEvent(iface, timestampMs, uid); } @GuardedBy("this") - private void addWakupEvent(String iface, long timestampMs, int uid) { + private void addWakeupEvent(String iface, long timestampMs, int uid) { int index = wakeupEventIndex(mWakeupEventCursor); mWakeupEventCursor++; WakeupEvent event = new WakeupEvent(); diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java index aafc6317bfae..9cf136720881 100644 --- a/services/core/java/com/android/server/display/NightDisplayService.java +++ b/services/core/java/com/android/server/display/NightDisplayService.java @@ -48,8 +48,10 @@ import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightState; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.Calendar; import java.util.TimeZone; import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY; @@ -306,7 +308,7 @@ public final class NightDisplayService extends SystemService } @Override - public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) { + public void onCustomStartTimeChanged(LocalTime startTime) { Slog.d(TAG, "onCustomStartTimeChanged: startTime=" + startTime); if (mAutoMode != null) { @@ -315,7 +317,7 @@ public final class NightDisplayService extends SystemService } @Override - public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) { + public void onCustomEndTimeChanged(LocalTime endTime) { Slog.d(TAG, "onCustomEndTimeChanged: endTime=" + endTime); if (mAutoMode != null) { @@ -414,6 +416,36 @@ public final class NightDisplayService extends SystemService outTemp[10] = blue; } + /** + * Returns the first date time corresponding to the local time that occurs before the + * provided date time. + * + * @param compareTime the LocalDateTime to compare against + * @return the prior LocalDateTime corresponding to this local time + */ + public static LocalDateTime getDateTimeBefore(LocalTime localTime, LocalDateTime compareTime) { + final LocalDateTime ldt = LocalDateTime.of(compareTime.getYear(), compareTime.getMonth(), + compareTime.getDayOfMonth(), localTime.getHour(), localTime.getMinute()); + + // Check if the local time has passed, if so return the same time yesterday. + return ldt.isAfter(compareTime) ? ldt.minusDays(1) : ldt; + } + + /** + * Returns the first date time corresponding to this local time that occurs after the + * provided date time. + * + * @param compareTime the LocalDateTime to compare against + * @return the next LocalDateTime corresponding to this local time + */ + public static LocalDateTime getDateTimeAfter(LocalTime localTime, LocalDateTime compareTime) { + final LocalDateTime ldt = LocalDateTime.of(compareTime.getYear(), compareTime.getMonth(), + compareTime.getDayOfMonth(), localTime.getHour(), localTime.getMinute()); + + // Check if the local time has passed, if so return the same time tomorrow. + return ldt.isBefore(compareTime) ? ldt.plusDays(1) : ldt; + } + private abstract class AutoMode implements NightDisplayController.Callback { public abstract void onStart(); @@ -425,10 +457,10 @@ public final class NightDisplayService extends SystemService private final AlarmManager mAlarmManager; private final BroadcastReceiver mTimeChangedReceiver; - private NightDisplayController.LocalTime mStartTime; - private NightDisplayController.LocalTime mEndTime; + private LocalTime mStartTime; + private LocalTime mEndTime; - private Calendar mLastActivatedTime; + private LocalDateTime mLastActivatedTime; CustomAutoMode() { mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); @@ -441,31 +473,15 @@ public final class NightDisplayService extends SystemService } private void updateActivated() { - final Calendar now = Calendar.getInstance(); - final Calendar startTime = mStartTime.getDateTimeBefore(now); - final Calendar endTime = mEndTime.getDateTimeAfter(startTime); + final LocalDateTime now = LocalDateTime.now(); + final LocalDateTime start = getDateTimeBefore(mStartTime, now); + final LocalDateTime end = getDateTimeAfter(mEndTime, start); + boolean activate = now.isBefore(end); - boolean activate = now.before(endTime); if (mLastActivatedTime != null) { - // Convert mLastActivatedTime to the current timezone if needed. - final TimeZone currentTimeZone = now.getTimeZone(); - if (!currentTimeZone.equals(mLastActivatedTime.getTimeZone())) { - final int year = mLastActivatedTime.get(Calendar.YEAR); - final int dayOfYear = mLastActivatedTime.get(Calendar.DAY_OF_YEAR); - final int hourOfDay = mLastActivatedTime.get(Calendar.HOUR_OF_DAY); - final int minute = mLastActivatedTime.get(Calendar.MINUTE); - - mLastActivatedTime.setTimeZone(currentTimeZone); - mLastActivatedTime.set(Calendar.YEAR, year); - mLastActivatedTime.set(Calendar.DAY_OF_YEAR, dayOfYear); - mLastActivatedTime.set(Calendar.HOUR_OF_DAY, hourOfDay); - mLastActivatedTime.set(Calendar.MINUTE, minute); - } - // Maintain the existing activated state if within the current period. - if (mLastActivatedTime.before(now) - && mLastActivatedTime.after(startTime) - && (mLastActivatedTime.after(endTime) || now.before(endTime))) { + if (mLastActivatedTime.isBefore(now) && mLastActivatedTime.isAfter(start) + && (mLastActivatedTime.isAfter(end) || now.isBefore(end))) { activate = mController.isActivated(); } } @@ -473,14 +489,16 @@ public final class NightDisplayService extends SystemService if (mIsActivated == null || mIsActivated != activate) { mController.setActivated(activate); } + updateNextAlarm(mIsActivated, now); } - private void updateNextAlarm(@Nullable Boolean activated, @NonNull Calendar now) { + private void updateNextAlarm(@Nullable Boolean activated, @NonNull LocalDateTime now) { if (activated != null) { - final Calendar next = activated ? mEndTime.getDateTimeAfter(now) - : mStartTime.getDateTimeAfter(now); - mAlarmManager.setExact(AlarmManager.RTC, next.getTimeInMillis(), TAG, this, null); + final LocalDateTime next = activated ? getDateTimeAfter(mEndTime, now) + : getDateTimeAfter(mStartTime, now); + final long millis = next.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + mAlarmManager.setExact(AlarmManager.RTC, millis, TAG, this, null); } } @@ -510,18 +528,18 @@ public final class NightDisplayService extends SystemService @Override public void onActivated(boolean activated) { mLastActivatedTime = mController.getLastActivatedTime(); - updateNextAlarm(activated, Calendar.getInstance()); + updateNextAlarm(activated, LocalDateTime.now()); } @Override - public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) { + public void onCustomStartTimeChanged(LocalTime startTime) { mStartTime = startTime; mLastActivatedTime = null; updateActivated(); } @Override - public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) { + public void onCustomEndTimeChanged(LocalTime endTime) { mEndTime = endTime; mLastActivatedTime = null; updateActivated(); @@ -550,15 +568,14 @@ public final class NightDisplayService extends SystemService } boolean activate = state.isNight(); - final Calendar lastActivatedTime = mController.getLastActivatedTime(); + final LocalDateTime lastActivatedTime = mController.getLastActivatedTime(); if (lastActivatedTime != null) { - final Calendar now = Calendar.getInstance(); - final Calendar sunrise = state.sunrise(); - final Calendar sunset = state.sunset(); - + final LocalDateTime now = LocalDateTime.now(); + final LocalDateTime sunrise = state.sunrise(); + final LocalDateTime sunset = state.sunset(); // Maintain the existing activated state if within the current period. - if (lastActivatedTime.before(now) - && (lastActivatedTime.after(sunrise) ^ lastActivatedTime.after(sunset))) { + if (lastActivatedTime.isBefore(now) && (lastActivatedTime.isBefore(sunrise) + ^ lastActivatedTime.isBefore(sunset))) { activate = mController.isActivated(); } } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 0f580d818f91..4fafe34b3063 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -438,16 +438,7 @@ public class PackageDexOptimizer { PackageDexUsage.DexUseInfo dexUseInfo = e.getValue(); pw.println(dex); pw.increaseIndent(); - for (String isa : dexUseInfo.getLoaderIsas()) { - String status = null; - try { - status = DexFile.getDexFileStatus(path, isa); - } catch (IOException ioe) { - status = "[Exception]: " + ioe.getMessage(); - } - pw.println(isa + ": " + status); - } - + // TODO(calin): get the status of the oat file (needs installd call) pw.println("class loader context: " + dexUseInfo.getClassLoaderContext()); if (dexUseInfo.isUsedByOtherApps()) { pw.println("used be other apps: " + dexUseInfo.getLoadingPackages()); @@ -474,8 +465,9 @@ public class PackageDexOptimizer { } if (isProfileGuidedCompilerFilter(targetCompilerFilter) && isUsedByOtherApps) { - // If the dex files is used by other apps, we cannot use profile-guided compilation. - return getNonProfileGuidedCompilerFilter(targetCompilerFilter); + // If the dex files is used by other apps, apply the shared filter. + return PackageManagerServiceCompilerMapping.getCompilerFilterForReason( + PackageManagerService.REASON_SHARED); } return targetCompilerFilter; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ff52e0ebbbb9..8852a4db0cfe 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -578,8 +578,9 @@ public class PackageManagerService extends IPackageManager.Stub public static final int REASON_BACKGROUND_DEXOPT = 3; public static final int REASON_AB_OTA = 4; public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 5; + public static final int REASON_SHARED = 6; - public static final int REASON_LAST = REASON_INACTIVE_PACKAGE_DOWNGRADE; + public static final int REASON_LAST = REASON_SHARED; /** All dangerous permission names in the same order as the events in MetricsEvent */ private static final List<String> ALL_DANGEROUS_PERMISSIONS = Arrays.asList( @@ -9819,19 +9820,6 @@ public class PackageManagerService extends IPackageManager.Stub compilerFilter, dexoptFlags)); - if (pkg.isSystemApp()) { - // Only dexopt shared secondary dex files belonging to system apps to not slow down - // too much boot after an OTA. - int secondaryDexoptFlags = dexoptFlags | - DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX | - DexoptOptions.DEXOPT_ONLY_SHARED_DEX; - mDexManager.dexoptSecondaryDex(new DexoptOptions( - pkg.packageName, - compilerFilter, - secondaryDexoptFlags)); - } - - // TODO(shubhamajmera): Record secondary dexopt stats. switch (primaryDexOptStaus) { case PackageDexOptimizer.DEX_OPT_PERFORMED: numberOfPackagesOptimized++; diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java index 1a97a72cf2b3..19b0d9bc4b90 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java @@ -26,14 +26,19 @@ import dalvik.system.DexFile; public class PackageManagerServiceCompilerMapping { // Names for compilation reasons. static final String REASON_STRINGS[] = { - "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "inactive" + "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "inactive", "shared" }; + static final int REASON_SHARED_INDEX = 6; + // Static block to ensure the strings array is of the right length. static { if (PackageManagerService.REASON_LAST + 1 != REASON_STRINGS.length) { throw new IllegalStateException("REASON_STRINGS not correct"); } + if (!"shared".equals(REASON_STRINGS[REASON_SHARED_INDEX])) { + throw new IllegalStateException("REASON_STRINGS not correct because of shared index"); + } } private static String getSystemPropertyName(int reason) { @@ -52,11 +57,18 @@ public class PackageManagerServiceCompilerMapping { !DexFile.isValidCompilerFilter(sysPropValue)) { throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid " + "(reason " + REASON_STRINGS[reason] + ")"); + } else if (!isFilterAllowedForReason(reason, sysPropValue)) { + throw new IllegalStateException("Value \"" + sysPropValue +"\" not allowed " + + "(reason " + REASON_STRINGS[reason] + ")"); } return sysPropValue; } + private static boolean isFilterAllowedForReason(int reason, String filter) { + return reason != REASON_SHARED_INDEX || !DexFile.isProfileGuidedCompilerFilter(filter); + } + // Check that the properties are set and valid. // Note: this is done in a separate method so this class can be statically initialized. static void checkProperties() { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 1d7f66f54faf..d19bf445ef04 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -198,6 +198,7 @@ import android.util.EventLog; import android.util.Log; import android.util.LongSparseArray; import android.util.MutableBoolean; +import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; import android.util.proto.ProtoOutputStream; @@ -296,13 +297,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int LONG_PRESS_POWER_SHUT_OFF = 2; static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3; - static final int LONG_PRESS_BACK_NOTHING = 0; - static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1; - static final int MULTI_PRESS_POWER_NOTHING = 0; static final int MULTI_PRESS_POWER_THEATER_MODE = 1; static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2; + static final int LONG_PRESS_BACK_NOTHING = 0; + static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1; + // Number of presses needed before we induce panic press behavior on the back button static final int PANIC_PRESS_BACK_COUNT = 4; static final int PANIC_PRESS_BACK_NOTHING = 0; @@ -565,7 +566,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLongPressOnBackBehavior; int mPanicPressOnBackBehavior; int mShortPressOnSleepBehavior; - int mShortPressWindowBehavior; + int mShortPressOnWindowBehavior; volatile boolean mAwake; boolean mScreenOnEarly; boolean mScreenOnFully; @@ -2180,9 +2181,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING; } - mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING; + mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_NOTHING; if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { - mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE; + mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE; } mNavBarOpacityMode = res.getInteger( @@ -6276,7 +6277,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; } case KeyEvent.KEYCODE_WINDOW: { - if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { + if (mShortPressOnWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { if (mPictureInPictureVisible) { // Consumes the key only if picture-in-picture is visible to show // picture-in-picture control menu. This gives a chance to the foreground @@ -8323,9 +8324,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); pw.print(" mSystemReady="); pw.print(mSystemReady); pw.print(" mSystemBooted="); pw.println(mSystemBooted); - pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); - pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); - pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); + pw.print(prefix); pw.print("mLidState="); + pw.print(WindowManagerFuncs.lidStateToString(mLidState)); + pw.print(" mLidOpenRotation="); + pw.println(Surface.rotationToString(mLidOpenRotation)); + pw.print(prefix); pw.print("mCameraLensCoverState="); + pw.print(WindowManagerFuncs.cameraLensStateToString(mCameraLensCoverState)); pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 || mForceClearedSystemUiFlags != 0) { @@ -8343,16 +8347,24 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); pw.println(mWakeGestureEnabledSetting); - pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); - pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); - pw.print(" mDockMode="); pw.print(mDockMode); - pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); - pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); - pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); - pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); - pw.print(" mUserRotation="); pw.print(mUserRotation); - pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); - pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); + pw.print(prefix); + pw.print("mSupportAutoRotation="); pw.print(mSupportAutoRotation); + pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled); + pw.print(prefix); pw.print("mUiMode="); pw.print(Configuration.uiModeToString(mUiMode)); + pw.print(" mDockMode="); pw.println(Intent.dockStateToString(mDockMode)); + pw.print(prefix); pw.print("mEnableCarDockHomeCapture="); + pw.print(mEnableCarDockHomeCapture); + pw.print(" mCarDockRotation="); + pw.print(Surface.rotationToString(mCarDockRotation)); + pw.print(" mDeskDockRotation="); + pw.println(Surface.rotationToString(mDeskDockRotation)); + pw.print(prefix); pw.print("mUserRotationMode="); + pw.print(WindowManagerPolicy.userRotationModeToString(mUserRotationMode)); + pw.print(" mUserRotation="); pw.print(Surface.rotationToString(mUserRotation)); + pw.print(" mAllowAllRotations="); + pw.println(allowAllRotationsToString(mAllowAllRotations)); + pw.print(prefix); pw.print("mCurrentAppOrientation="); + pw.println(ActivityInfo.screenOrientationToString(mCurrentAppOrientation)); pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); pw.print(mCarDockEnablesAccelerometer); pw.print(" mDeskDockEnablesAccelerometer="); @@ -8361,23 +8373,54 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(mLidKeyboardAccessibility); pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); - pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); + pw.print(prefix); pw.print("mLidControlsSleep="); pw.println(mLidControlsSleep); + pw.print(prefix); + pw.print("mLongPressOnBackBehavior="); + pw.println(longPressOnBackBehaviorToString(mLongPressOnBackBehavior)); + pw.print(prefix); + pw.print("mPanicPressOnBackBehavior="); + pw.println(panicPressOnBackBehaviorToString(mPanicPressOnBackBehavior)); + pw.print(prefix); + pw.print("mLongPressOnHomeBehavior="); + pw.println(longPressOnHomeBehaviorToString(mLongPressOnHomeBehavior)); + pw.print(prefix); + pw.print("mDoubleTapOnHomeBehavior="); + pw.println(doubleTapOnHomeBehaviorToString(mDoubleTapOnHomeBehavior)); + pw.print(prefix); + pw.print("mShortPressOnPowerBehavior="); + pw.println(shortPressOnPowerBehaviorToString(mShortPressOnPowerBehavior)); pw.print(prefix); - pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); + pw.print("mLongPressOnPowerBehavior="); + pw.println(longPressOnPowerBehaviorToString(mLongPressOnPowerBehavior)); pw.print(prefix); - pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); - pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); + pw.print("mDoublePressOnPowerBehavior="); + pw.println(multiPressOnPowerBehaviorToString(mDoublePressOnPowerBehavior)); pw.print(prefix); - pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); - pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); - pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); - pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); - pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); + pw.print("mTriplePressOnPowerBehavior="); + pw.println(multiPressOnPowerBehaviorToString(mTriplePressOnPowerBehavior)); + pw.print(prefix); + pw.print("mShortPressOnSleepBehavior="); + pw.println(shortPressOnSleepBehaviorToString(mShortPressOnSleepBehavior)); + pw.print(prefix); + pw.print("mShortPressOnWindowBehavior="); + pw.println(shortPressOnWindowBehaviorToString(mShortPressOnWindowBehavior)); + pw.print(prefix); + pw.print("mHasSoftInput="); pw.print(mHasSoftInput); + pw.print(" mDismissImeOnBackKeyPressed="); pw.println(mDismissImeOnBackKeyPressed); + pw.print(prefix); + pw.print("mIncallPowerBehavior="); + pw.print(incallPowerBehaviorToString(mIncallPowerBehavior)); + pw.print(" mIncallBackBehavior="); + pw.print(incallBackBehaviorToString(mIncallBackBehavior)); + pw.print(" mEndcallBehavior="); + pw.println(endcallBehaviorToString(mEndcallBehavior)); + pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed); + pw.print(prefix); + pw.print("mAwake="); pw.print(mAwake); + pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); - pw.print(prefix); pw.print("mOrientationSensorEnabled="); - pw.println(mOrientationSensorEnabled); pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); pw.print(","); pw.print(mOverscanScreenTop); pw.print(") "); pw.print(mOverscanScreenWidth); @@ -8443,8 +8486,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); pw.println(mLastInputMethodTargetWindow); } - pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed="); - pw.println(mDismissImeOnBackKeyPressed); if (mStatusBar != null) { pw.print(prefix); pw.print("mStatusBar="); pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); @@ -8477,26 +8518,28 @@ public class PhoneWindowManager implements WindowManagerPolicy { } pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded); - pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged); + pw.print(prefix); + pw.print("mKeyguardOccludedChanged="); pw.print(mKeyguardOccludedChanged); pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded); pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); pw.print(" mForceStatusBarFromKeyguard="); pw.println(mForceStatusBarFromKeyguard); - pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed); pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); - pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); - pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); - pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior); - pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); - pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); - pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); - pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); - pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); - pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); + pw.print(prefix); pw.print("mLandscapeRotation="); + pw.print(Surface.rotationToString(mLandscapeRotation)); + pw.print(" mSeascapeRotation="); + pw.println(Surface.rotationToString(mSeascapeRotation)); + pw.print(prefix); pw.print("mPortraitRotation="); + pw.print(Surface.rotationToString(mPortraitRotation)); + pw.print(" mUpsideDownRotation="); + pw.println(Surface.rotationToString(mUpsideDownRotation)); + pw.print(prefix); pw.print("mDemoHdmiRotation="); + pw.print(Surface.rotationToString(mDemoHdmiRotation)); pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); - pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); + pw.print(prefix); pw.print("mUndockedHdmiRotation="); + pw.println(Surface.rotationToString(mUndockedHdmiRotation)); if (mHasFeatureLeanback) { pw.print(prefix); pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed); @@ -8523,5 +8566,169 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mKeyguardDelegate != null) { mKeyguardDelegate.dump(prefix, pw); } + + pw.print(prefix); pw.println("Looper state:"); + mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + " "); + } + + private static String allowAllRotationsToString(int allowAll) { + switch (allowAll) { + case -1: + return "unknown"; + case 0: + return "false"; + case 1: + return "true"; + default: + return Integer.toString(allowAll); + } + } + + private static String endcallBehaviorToString(int behavior) { + StringBuilder sb = new StringBuilder(); + if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0 ) { + sb.append("home|"); + } + if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { + sb.append("sleep|"); + } + + final int N = sb.length(); + if (N == 0) { + return "<nothing>"; + } else { + // Chop off the trailing '|' + return sb.substring(0, N - 1); + } + } + + private static String incallPowerBehaviorToString(int behavior) { + if ((behavior & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0) { + return "hangup"; + } else { + return "sleep"; + } + } + + private static String incallBackBehaviorToString(int behavior) { + if ((behavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0) { + return "hangup"; + } else { + return "<nothing>"; + } + } + + private static String longPressOnBackBehaviorToString(int behavior) { + switch (behavior) { + case LONG_PRESS_BACK_NOTHING: + return "LONG_PRESS_BACK_NOTHING"; + case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST: + return "LONG_PRESS_BACK_GO_TO_VOICE_ASSIST"; + default: + return Integer.toString(behavior); + } + } + + private static String panicPressOnBackBehaviorToString(int behavior) { + switch (behavior) { + case PANIC_PRESS_BACK_NOTHING: + return "PANIC_PRESS_BACK_NOTHING"; + case PANIC_PRESS_BACK_HOME: + return "PANIC_PRESS_BACK_HOME"; + default: + return Integer.toString(behavior); + } + } + + private static String longPressOnHomeBehaviorToString(int behavior) { + switch (behavior) { + case LONG_PRESS_HOME_NOTHING: + return "LONG_PRESS_HOME_NOTHING"; + case LONG_PRESS_HOME_ALL_APPS: + return "LONG_PRESS_HOME_ALL_APPS"; + case LONG_PRESS_HOME_ASSIST: + return "LONG_PRESS_HOME_ASSIST"; + default: + return Integer.toString(behavior); + } + } + + private static String doubleTapOnHomeBehaviorToString(int behavior) { + switch (behavior) { + case DOUBLE_TAP_HOME_NOTHING: + return "DOUBLE_TAP_HOME_NOTHING"; + case DOUBLE_TAP_HOME_RECENT_SYSTEM_UI: + return "DOUBLE_TAP_HOME_RECENT_SYSTEM_UI"; + default: + return Integer.toString(behavior); + } + } + + private static String shortPressOnPowerBehaviorToString(int behavior) { + switch (behavior) { + case SHORT_PRESS_POWER_NOTHING: + return "SHORT_PRESS_POWER_NOTHING"; + case SHORT_PRESS_POWER_GO_TO_SLEEP: + return "SHORT_PRESS_POWER_GO_TO_SLEEP"; + case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP: + return "SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP"; + case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME: + return "SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME"; + case SHORT_PRESS_POWER_GO_HOME: + return "SHORT_PRESS_POWER_GO_HOME"; + case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: + return "SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME"; + default: + return Integer.toString(behavior); + } + } + + private static String longPressOnPowerBehaviorToString(int behavior) { + switch (behavior) { + case LONG_PRESS_POWER_NOTHING: + return "LONG_PRESS_POWER_NOTHING"; + case LONG_PRESS_POWER_GLOBAL_ACTIONS: + return "LONG_PRESS_POWER_GLOBAL_ACTIONS"; + case LONG_PRESS_POWER_SHUT_OFF: + return "LONG_PRESS_POWER_SHUT_OFF"; + case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM: + return "LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM"; + default: + return Integer.toString(behavior); + } + } + private static String multiPressOnPowerBehaviorToString(int behavior) { + switch (behavior) { + case MULTI_PRESS_POWER_NOTHING: + return "MULTI_PRESS_POWER_NOTHING"; + case MULTI_PRESS_POWER_THEATER_MODE: + return "MULTI_PRESS_POWER_THEATER_MODE"; + case MULTI_PRESS_POWER_BRIGHTNESS_BOOST: + return "MULTI_PRESS_POWER_BRIGHTNESS_BOOST"; + default: + return Integer.toString(behavior); + } + } + + private static String shortPressOnSleepBehaviorToString(int behavior) { + switch (behavior) { + case SHORT_PRESS_SLEEP_GO_TO_SLEEP: + return "SHORT_PRESS_SLEEP_GO_TO_SLEEP"; + case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME: + return "SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME"; + default: + return Integer.toString(behavior); + } + } + + private static String shortPressOnWindowBehaviorToString(int behavior) { + switch (behavior) { + case SHORT_PRESS_WINDOW_NOTHING: + return "SHORT_PRESS_WINDOW_NOTHING"; + case SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE: + return "SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE"; + default: + return Integer.toString(behavior); + } } } diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java index 64f64c0d45d6..169fd278f665 100644 --- a/services/core/java/com/android/server/policy/WindowOrientationListener.java +++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java @@ -26,6 +26,7 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.text.TextUtils; import android.util.Slog; +import android.view.Surface; import java.io.PrintWriter; import java.util.Arrays; @@ -236,7 +237,7 @@ public abstract class WindowOrientationListener { pw.println(prefix + TAG); prefix += " "; pw.println(prefix + "mEnabled=" + mEnabled); - pw.println(prefix + "mCurrentRotation=" + mCurrentRotation); + pw.println(prefix + "mCurrentRotation=" + Surface.rotationToString(mCurrentRotation)); pw.println(prefix + "mSensorType=" + mSensorType); pw.println(prefix + "mSensor=" + mSensor); pw.println(prefix + "mRate=" + mRate); @@ -1026,8 +1027,9 @@ public abstract class WindowOrientationListener { public void dumpLocked(PrintWriter pw, String prefix) { pw.println(prefix + "OrientationSensorJudge"); prefix += " "; - pw.println(prefix + "mDesiredRotation=" + mDesiredRotation); - pw.println(prefix + "mProposedRotation=" + mProposedRotation); + pw.println(prefix + "mDesiredRotation=" + Surface.rotationToString(mDesiredRotation)); + pw.println(prefix + "mProposedRotation=" + + Surface.rotationToString(mProposedRotation)); pw.println(prefix + "mTouching=" + mTouching); pw.println(prefix + "mTouchEndedTimestampNanos=" + mTouchEndedTimestampNanos); } diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java index 50e5e7bd2312..70cd54ffd09d 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java @@ -1,5 +1,7 @@ package com.android.server.policy.keyguard; +import static android.view.Display.INVALID_DISPLAY; + import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; @@ -13,6 +15,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.util.Slog; +import android.view.WindowManagerPolicy; import android.view.WindowManagerPolicy.OnKeyguardExitResult; import com.android.internal.policy.IKeyguardDismissCallback; @@ -201,7 +204,10 @@ public class KeyguardServiceDelegate { mKeyguardState.reset(); mHandler.post(() -> { try { - ActivityManager.getService().setLockScreenShown(true); + // There are no longer any keyguard windows on secondary displays, so pass + // INVALID_DISPLAY. All that means is that showWhenLocked activities on + // secondary displays now get to show. + ActivityManager.getService().setLockScreenShown(true, INVALID_DISPLAY); } catch (RemoteException e) { // Local call. } @@ -412,13 +418,45 @@ public class KeyguardServiceDelegate { pw.println(prefix + "systemIsReady=" + mKeyguardState.systemIsReady); pw.println(prefix + "deviceHasKeyguard=" + mKeyguardState.deviceHasKeyguard); pw.println(prefix + "enabled=" + mKeyguardState.enabled); - pw.println(prefix + "offReason=" + mKeyguardState.offReason); + pw.println(prefix + "offReason=" + + WindowManagerPolicy.offReasonToString(mKeyguardState.offReason)); pw.println(prefix + "currentUser=" + mKeyguardState.currentUser); pw.println(prefix + "bootCompleted=" + mKeyguardState.bootCompleted); - pw.println(prefix + "screenState=" + mKeyguardState.screenState); - pw.println(prefix + "interactiveState=" + mKeyguardState.interactiveState); + pw.println(prefix + "screenState=" + screenStateToString(mKeyguardState.screenState)); + pw.println(prefix + "interactiveState=" + + interactiveStateToString(mKeyguardState.interactiveState)); if (mKeyguardService != null) { mKeyguardService.dump(prefix, pw); } } + + private static String screenStateToString(int screen) { + switch (screen) { + case SCREEN_STATE_OFF: + return "SCREEN_STATE_OFF"; + case SCREEN_STATE_TURNING_ON: + return "SCREEN_STATE_TURNING_ON"; + case SCREEN_STATE_ON: + return "SCREEN_STATE_ON"; + case SCREEN_STATE_TURNING_OFF: + return "SCREEN_STATE_TURNING_OFF"; + default: + return Integer.toString(screen); + } + } + + private static String interactiveStateToString(int interactive) { + switch (interactive) { + case INTERACTIVE_STATE_SLEEP: + return "INTERACTIVE_STATE_SLEEP"; + case INTERACTIVE_STATE_WAKING: + return "INTERACTIVE_STATE_WAKING"; + case INTERACTIVE_STATE_AWAKE: + return "INTERACTIVE_STATE_AWAKE"; + case INTERACTIVE_STATE_GOING_TO_SLEEP: + return "INTERACTIVE_STATE_GOING_TO_SLEEP"; + default: + return Integer.toString(interactive); + } + } } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 3b701302aae1..12ca89a93d02 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -120,7 +120,7 @@ public final class PowerManagerService extends SystemService implements Watchdog.Monitor { private static final String TAG = "PowerManagerService"; - private static final boolean DEBUG = false; + private static final boolean DEBUG = true; private static final boolean DEBUG_SPEW = DEBUG && true; // Message: Sent when a user activity timeout occurs to update the power state. @@ -1569,12 +1569,15 @@ public final class PowerManagerService extends SystemService return true; } - private void setWakefulnessLocked(int wakefulness, int reason) { + @VisibleForTesting + void setWakefulnessLocked(int wakefulness, int reason) { if (mWakefulness != wakefulness) { mWakefulness = wakefulness; mWakefulnessChanging = true; mDirty |= DIRTY_WAKEFULNESS; - mNotifier.onWakefulnessChangeStarted(wakefulness, reason); + if (mNotifier != null) { + mNotifier.onWakefulnessChangeStarted(wakefulness, reason); + } } } @@ -2432,11 +2435,8 @@ public final class PowerManagerService extends SystemService return value >= -1.0f && value <= 1.0f; } - private int getDesiredScreenPolicyLocked() { - if (mIsVrModeEnabled) { - return DisplayPowerRequest.POLICY_VR; - } - + @VisibleForTesting + int getDesiredScreenPolicyLocked() { if (mWakefulness == WAKEFULNESS_ASLEEP || sQuiescent) { return DisplayPowerRequest.POLICY_OFF; } @@ -2452,6 +2452,13 @@ public final class PowerManagerService extends SystemService // doze after screen off. This causes the screen off transition to be skipped. } + // It is important that POLICY_VR check happens after the wakefulness checks above so + // that VR-mode does not prevent displays from transitioning to the correct state when + // dozing or sleeping. + if (mIsVrModeEnabled) { + return DisplayPowerRequest.POLICY_VR; + } + if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0 || (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0 || !mBootCompleted @@ -3113,6 +3120,11 @@ public final class PowerManagerService extends SystemService } } + @VisibleForTesting + void setVrModeEnabled(boolean enabled) { + mIsVrModeEnabled = enabled; + } + private void powerHintInternal(int hintId, int data) { nativeSendPowerHint(hintId, data); } @@ -3810,7 +3822,7 @@ public final class PowerManagerService extends SystemService synchronized (mLock) { if (mIsVrModeEnabled != enabled) { - mIsVrModeEnabled = enabled; + setVrModeEnabled(enabled); mDirty |= DIRTY_VR_MODE_CHANGED; updatePowerStateLocked(); } diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java new file mode 100644 index 000000000000..5b77b1ed5269 --- /dev/null +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.stats; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Binder; +import android.os.IStatsCompanionService; +import android.os.IStatsManager; +import android.os.Process; +import android.os.ServiceManager; +import android.util.Slog; + +import com.android.server.SystemService; + +/** + * Helper service for statsd (the native stats management service in cmds/statsd/). + * Used for registering and receiving alarms on behalf of statsd. + */ +public class StatsCompanionService extends IStatsCompanionService.Stub { + static final String TAG = "StatsCompanionService"; + static final boolean DEBUG = true; + + private final Context mContext; + private final AlarmManager mAlarmManager; + private final IStatsManager mStatsd; + + private final PendingIntent mAnomalyAlarmIntent; + private final PendingIntent mPollingAlarmIntent; + + public final static class AnomalyAlarmReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + Slog.i(TAG, "StatsCompanionService believes an anomaly has occurred."); + // TODO: mStatsd.informAlarm(); // should be twoway so device won't sleep before acting? + // AlarmManager releases its own wakelock here. + } + }; + + public final static class PollingAlarmReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (DEBUG) Slog.d(TAG, "Time to poll something."); + // TODO: mStatsd.poll(); // should be twoway so device won't sleep before acting? + // AlarmManager releases its own wakelock here. + } + }; + + public StatsCompanionService(Context context) { + super(); + mContext = context; + mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); + + mAnomalyAlarmIntent = PendingIntent.getBroadcast(mContext, 0, + new Intent(mContext, AnomalyAlarmReceiver.class), 0); + mPollingAlarmIntent = PendingIntent.getBroadcast(mContext, 0, + new Intent(mContext, PollingAlarmReceiver.class), 0); + + mStatsd = getStatsdService(); + } + + /** Returns the statsd IBinder service */ + public static IStatsManager getStatsdService() { + return IStatsManager.Stub.asInterface(ServiceManager.getService("statsd")); + } + + public static final class Lifecycle extends SystemService { + private StatsCompanionService mStatsCompanionService; + + public Lifecycle(Context context) { + super(context); + } + + @Override + public void onStart() { + mStatsCompanionService = new StatsCompanionService(getContext()); + try { + publishBinderService(Context.STATS_COMPANION_SERVICE, mStatsCompanionService); + if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_COMPANION_SERVICE); + } catch (Exception e) { + Slog.e(TAG, "Failed to publishBinderService", e); + } + } + } + + @Override // Binder call + public void setAnomalyAlarm(long timestampMs) { + enforceCallingPermission(); + if (DEBUG) Slog.d(TAG, "Setting anomaly alarm for " + timestampMs); + final long callingToken = Binder.clearCallingIdentity(); + try { + // using RTC, not RTC_WAKEUP, so if device is asleep, will only fire when it awakens. + // This alarm is inexact, leaving its exactness completely up to the OS optimizations. + // AlarmManager will automatically cancel any previous mAnomalyAlarmIntent alarm. + mAlarmManager.set(AlarmManager.RTC, timestampMs, mAnomalyAlarmIntent); + } finally { + Binder.restoreCallingIdentity(callingToken); + } + } + + @Override // Binder call + public void cancelAnomalyAlarm() { + enforceCallingPermission(); + if (DEBUG) Slog.d(TAG, "Cancelling anomaly alarm"); + final long callingToken = Binder.clearCallingIdentity(); + try { + mAlarmManager.cancel(mAnomalyAlarmIntent); + } finally { + Binder.restoreCallingIdentity(callingToken); + } + } + + @Override // Binder call + public void setPollingAlarms(long timestampMs, long intervalMs) { + enforceCallingPermission(); + if (DEBUG) Slog.d(TAG, "Setting polling alarm for " + timestampMs + + " every " + intervalMs + "ms"); + final long callingToken = Binder.clearCallingIdentity(); + try { + // using RTC, not RTC_WAKEUP, so if device is asleep, will only fire when it awakens. + // This alarm is inexact, leaving its exactness completely up to the OS optimizations. + // TODO: totally inexact means that stats per bucket could be quite off. Is this okay? + mAlarmManager.setRepeating(AlarmManager.RTC, timestampMs, intervalMs, + mPollingAlarmIntent); + } finally { + Binder.restoreCallingIdentity(callingToken); + } + } + + @Override // Binder call + public void cancelPollingAlarms() { + enforceCallingPermission(); + if (DEBUG) Slog.d(TAG, "Cancelling polling alarm"); + final long callingToken = Binder.clearCallingIdentity(); + try { + mAlarmManager.cancel(mPollingAlarmIntent); + } finally { + Binder.restoreCallingIdentity(callingToken); + } + } + + private void enforceCallingPermission() { + if (Binder.getCallingPid() == Process.myPid()) { + return; + } + mContext.enforceCallingPermission(android.Manifest.permission.STATSCOMPANION, null); + } + +} diff --git a/services/core/java/com/android/server/timezone/IntentHelper.java b/services/core/java/com/android/server/timezone/IntentHelper.java index 0cb90657480e..5de543213009 100644 --- a/services/core/java/com/android/server/timezone/IntentHelper.java +++ b/services/core/java/com/android/server/timezone/IntentHelper.java @@ -23,15 +23,22 @@ package com.android.server.timezone; */ interface IntentHelper { - void initialize(String updateAppPackageName, String dataAppPackageName, Listener listener); + void initialize(String updateAppPackageName, String dataAppPackageName, + PackageTracker packageTracker); void sendTriggerUpdateCheck(CheckToken checkToken); - void enableReliabilityTriggering(); + /** + * Schedule a "reliability trigger" after at least minimumDelayMillis, replacing any existing + * scheduled one. A reliability trigger ensures that the {@link PackageTracker} can pick up + * reliably if a previous update check did not complete for some reason. It can happen when + * the device is idle. The trigger is expected to call + * {@link PackageTracker#triggerUpdateIfNeeded(boolean)} with a {@code false} value. + */ + void scheduleReliabilityTrigger(long minimumDelayMillis); - void disableReliabilityTriggering(); - - interface Listener { - void triggerUpdateIfNeeded(boolean packageUpdated); - } + /** + * Make sure there is no reliability trigger scheduled. No-op if there wasn't one. + */ + void unscheduleReliabilityTrigger(); } diff --git a/services/core/java/com/android/server/timezone/IntentHelperImpl.java b/services/core/java/com/android/server/timezone/IntentHelperImpl.java index 6db70cd870db..bc0f6e4b283b 100644 --- a/services/core/java/com/android/server/timezone/IntentHelperImpl.java +++ b/services/core/java/com/android/server/timezone/IntentHelperImpl.java @@ -36,16 +36,13 @@ final class IntentHelperImpl implements IntentHelper { private final Context mContext; private String mUpdaterAppPackageName; - private boolean mReliabilityReceiverEnabled; - private Receiver mReliabilityReceiver; - IntentHelperImpl(Context context) { mContext = context; } @Override - public void initialize( - String updaterAppPackageName, String dataAppPackageName, Listener listener) { + public void initialize(String updaterAppPackageName, String dataAppPackageName, + PackageTracker packageTracker) { mUpdaterAppPackageName = updaterAppPackageName; // Register for events of interest. @@ -78,10 +75,8 @@ final class IntentHelperImpl implements IntentHelper { // We do not register for ACTION_PACKAGE_DATA_CLEARED because the updater / data apps are // not expected to need local data. - Receiver packageUpdateReceiver = new Receiver(listener, true /* packageUpdated */); + Receiver packageUpdateReceiver = new Receiver(packageTracker); mContext.registerReceiver(packageUpdateReceiver, packageIntentFilter); - - mReliabilityReceiver = new Receiver(listener, false /* packageUpdated */); } /** Sends an intent to trigger an update check. */ @@ -93,39 +88,26 @@ final class IntentHelperImpl implements IntentHelper { } @Override - public synchronized void enableReliabilityTriggering() { - if (!mReliabilityReceiverEnabled) { - // The intent filter that exists to make updates reliable in the event of failures / - // reboots. - IntentFilter reliabilityIntentFilter = new IntentFilter(); - reliabilityIntentFilter.addAction(Intent.ACTION_IDLE_MAINTENANCE_START); - mContext.registerReceiver(mReliabilityReceiver, reliabilityIntentFilter); - mReliabilityReceiverEnabled = true; - } + public synchronized void scheduleReliabilityTrigger(long minimumDelayMillis) { + TimeZoneUpdateIdler.schedule(mContext, minimumDelayMillis); } @Override - public synchronized void disableReliabilityTriggering() { - if (mReliabilityReceiverEnabled) { - mContext.unregisterReceiver(mReliabilityReceiver); - mReliabilityReceiverEnabled = false; - } + public synchronized void unscheduleReliabilityTrigger() { + TimeZoneUpdateIdler.unschedule(mContext); } private static class Receiver extends BroadcastReceiver { - private final Listener mListener; - private final boolean mPackageUpdated; + private final PackageTracker mPackageTracker; - private Receiver(Listener listener, boolean packageUpdated) { - mListener = listener; - mPackageUpdated = packageUpdated; + private Receiver(PackageTracker packageTracker) { + mPackageTracker = packageTracker; } @Override public void onReceive(Context context, Intent intent) { Slog.d(TAG, "Received intent: " + intent.toString()); - mListener.triggerUpdateIfNeeded(mPackageUpdated); + mPackageTracker.triggerUpdateIfNeeded(true /* packageChanged */); } } - } diff --git a/services/core/java/com/android/server/timezone/PackageTracker.java b/services/core/java/com/android/server/timezone/PackageTracker.java index 24e0fe4841bc..f0306b9b0c38 100644 --- a/services/core/java/com/android/server/timezone/PackageTracker.java +++ b/services/core/java/com/android/server/timezone/PackageTracker.java @@ -51,7 +51,7 @@ import java.io.PrintWriter; */ // Also made non-final so it can be mocked. @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) -public class PackageTracker implements IntentHelper.Listener { +public class PackageTracker { private static final String TAG = "timezone.PackageTracker"; private final PackageManagerHelper mPackageManagerHelper; @@ -72,6 +72,13 @@ public class PackageTracker implements IntentHelper.Listener { // The number of failed checks in a row before reliability checks should stop happening. private long mFailedCheckRetryCount; + /* + * The minimum delay between a successive reliability triggers / other operations. Should to be + * larger than mCheckTimeAllowedMillis to avoid reliability triggers happening during package + * update checks. + */ + private int mDelayBeforeReliabilityCheckMillis; + // Reliability check state: If a check was triggered but not acknowledged within // mCheckTimeAllowedMillis then another one can be triggered. private Long mLastTriggerTimestamp = null; @@ -122,6 +129,7 @@ public class PackageTracker implements IntentHelper.Listener { mDataAppPackageName = mConfigHelper.getDataAppPackageName(); mCheckTimeAllowedMillis = mConfigHelper.getCheckTimeAllowedMillis(); mFailedCheckRetryCount = mConfigHelper.getFailedCheckRetryCount(); + mDelayBeforeReliabilityCheckMillis = mCheckTimeAllowedMillis + (60 * 1000); // Validate the device configuration including the application packages. // The manifest entries in the apps themselves are not validated until use as they can @@ -135,9 +143,10 @@ public class PackageTracker implements IntentHelper.Listener { // Initialize the intent helper. mIntentHelper.initialize(mUpdateAppPackageName, mDataAppPackageName, this); - // Enable the reliability triggering so we will have at least one reliability trigger if - // a package isn't updated. - mIntentHelper.enableReliabilityTriggering(); + // Schedule a reliability trigger so we will have at least one after boot. This will allow + // us to catch if a package updated wasn't handled to completion. There's no hurry: it's ok + // to delay for a while before doing this even if idle. + mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis); Slog.i(TAG, "Time zone updater / data package tracking enabled"); } @@ -195,7 +204,6 @@ public class PackageTracker implements IntentHelper.Listener { * @param packageChanged true if this method was called because a known packaged definitely * changed, false if the cause is a reliability trigger */ - @Override public synchronized void triggerUpdateIfNeeded(boolean packageChanged) { if (!mTrackingEnabled) { throw new IllegalStateException("Unexpected call. Tracking is disabled."); @@ -212,8 +220,8 @@ public class PackageTracker implements IntentHelper.Listener { + " updaterApp=" + updaterAppManifestValid + ", dataApp=" + dataAppManifestValid); - // There's no point in doing reliability checks if the current packages are bad. - mIntentHelper.disableReliabilityTriggering(); + // There's no point in doing any reliability triggers if the current packages are bad. + mIntentHelper.unscheduleReliabilityTrigger(); return; } @@ -238,7 +246,8 @@ public class PackageTracker implements IntentHelper.Listener { Slog.d(TAG, "triggerUpdateIfNeeded: checkComplete call is not yet overdue." + " Not triggering."); - // Not doing any work, but also not disabling future reliability triggers. + // Don't do any work now but we do schedule a future reliability trigger. + mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis); return; } } else if (mCheckFailureCount > mFailedCheckRetryCount) { @@ -247,13 +256,13 @@ public class PackageTracker implements IntentHelper.Listener { Slog.i(TAG, "triggerUpdateIfNeeded: number of allowed consecutive check failures" + " exceeded. Stopping reliability triggers until next reboot or package" + " update."); - mIntentHelper.disableReliabilityTriggering(); + mIntentHelper.unscheduleReliabilityTrigger(); return; } else if (mCheckFailureCount == 0) { // Case 4. Slog.i(TAG, "triggerUpdateIfNeeded: No reliability check required. Last check was" + " successful."); - mIntentHelper.disableReliabilityTriggering(); + mIntentHelper.unscheduleReliabilityTrigger(); return; } } @@ -263,7 +272,7 @@ public class PackageTracker implements IntentHelper.Listener { if (currentInstalledVersions == null) { // This should not happen if the device is configured in a valid way. Slog.e(TAG, "triggerUpdateIfNeeded: currentInstalledVersions was null"); - mIntentHelper.disableReliabilityTriggering(); + mIntentHelper.unscheduleReliabilityTrigger(); return; } @@ -288,7 +297,7 @@ public class PackageTracker implements IntentHelper.Listener { // The last check succeeded and nothing has changed. Do nothing and disable // reliability checks. Slog.i(TAG, "triggerUpdateIfNeeded: Prior check succeeded. No need to trigger."); - mIntentHelper.disableReliabilityTriggering(); + mIntentHelper.unscheduleReliabilityTrigger(); return; } } @@ -299,6 +308,8 @@ public class PackageTracker implements IntentHelper.Listener { if (checkToken == null) { Slog.w(TAG, "triggerUpdateIfNeeded: Unable to generate check token." + " Not sending check request."); + // Trigger again later: perhaps we'll have better luck. + mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis); return; } @@ -309,9 +320,9 @@ public class PackageTracker implements IntentHelper.Listener { // Update the reliability check state in case the update fails. setCheckInProgress(); - // Enable reliability triggering in case the check doesn't succeed and there is no - // response at all. Enabling reliability triggering is idempotent. - mIntentHelper.enableReliabilityTriggering(); + // Schedule a reliability trigger in case the update check doesn't succeed and there is no + // response at all. It will be cancelled if the check is successful in recordCheckResult. + mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis); } /** @@ -370,9 +381,9 @@ public class PackageTracker implements IntentHelper.Listener { + " storage state."); mPackageStatusStorage.resetCheckState(); - // Enable reliability triggering and reset the failure count so we know that the + // Schedule a reliability trigger and reset the failure count so we know that the // next reliability trigger will do something. - mIntentHelper.enableReliabilityTriggering(); + mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis); mCheckFailureCount = 0; } else { // This is the expected case when tracking is enabled: a check was triggered and it has @@ -385,13 +396,13 @@ public class PackageTracker implements IntentHelper.Listener { setCheckComplete(); if (success) { - // Since the check was successful, no more reliability checks are required until + // Since the check was successful, no reliability trigger is required until // there is a package change. - mIntentHelper.disableReliabilityTriggering(); + mIntentHelper.unscheduleReliabilityTrigger(); mCheckFailureCount = 0; } else { - // Enable reliability triggering to potentially check again in future. - mIntentHelper.enableReliabilityTriggering(); + // Enable schedule a reliability trigger to check again in future. + mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis); mCheckFailureCount++; } } else { @@ -400,8 +411,8 @@ public class PackageTracker implements IntentHelper.Listener { Slog.i(TAG, "recordCheckResult: could not update token=" + checkToken + " with success=" + success + ". Optimistic lock failure"); - // Enable reliability triggering to potentially try again in future. - mIntentHelper.enableReliabilityTriggering(); + // Schedule a reliability trigger to potentially try again in future. + mIntentHelper.scheduleReliabilityTrigger(mDelayBeforeReliabilityCheckMillis); mCheckFailureCount++; } } @@ -515,6 +526,7 @@ public class PackageTracker implements IntentHelper.Listener { ", mUpdateAppPackageName='" + mUpdateAppPackageName + '\'' + ", mDataAppPackageName='" + mDataAppPackageName + '\'' + ", mCheckTimeAllowedMillis=" + mCheckTimeAllowedMillis + + ", mDelayBeforeReliabilityCheckMillis=" + mDelayBeforeReliabilityCheckMillis + ", mFailedCheckRetryCount=" + mFailedCheckRetryCount + ", mLastTriggerTimestamp=" + mLastTriggerTimestamp + ", mCheckTriggered=" + mCheckTriggered + diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java index 3ad4419c7273..6824a597a5f8 100644 --- a/services/core/java/com/android/server/timezone/RulesManagerService.java +++ b/services/core/java/com/android/server/timezone/RulesManagerService.java @@ -69,18 +69,22 @@ public final class RulesManagerService extends IRulesManager.Stub { DistroVersion.CURRENT_FORMAT_MINOR_VERSION); public static class Lifecycle extends SystemService { - private RulesManagerService mService; - public Lifecycle(Context context) { super(context); } @Override public void onStart() { - mService = RulesManagerService.create(getContext()); - mService.start(); + RulesManagerService service = RulesManagerService.create(getContext()); + service.start(); + + // Publish the binder service so it can be accessed from other (appropriately + // permissioned) processes. + publishBinderService(Context.TIME_ZONE_RULES_MANAGER_SERVICE, service); - publishBinderService(Context.TIME_ZONE_RULES_MANAGER_SERVICE, mService); + // Publish the service instance locally so we can use it directly from within the system + // server from TimeZoneUpdateIdler. + publishLocalService(RulesManagerService.class, service); } } @@ -496,6 +500,16 @@ public final class RulesManagerService extends IRulesManager.Stub { mPackageTracker.dump(pw); } + /** + * Called when the device is considered idle. + */ + void notifyIdle() { + // No package has changed: we are just triggering because the device is idle and there + // *might* be work to do. + final boolean packageChanged = false; + mPackageTracker.triggerUpdateIfNeeded(packageChanged); + } + @Override public String toString() { return "RulesManagerService{" + diff --git a/services/core/java/com/android/server/timezone/TimeZoneUpdateIdler.java b/services/core/java/com/android/server/timezone/TimeZoneUpdateIdler.java new file mode 100644 index 000000000000..a7767a4fbd66 --- /dev/null +++ b/services/core/java/com/android/server/timezone/TimeZoneUpdateIdler.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.timezone; + +import com.android.server.LocalServices; + +import android.app.job.JobInfo; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.app.job.JobService; +import android.content.ComponentName; +import android.content.Context; +import android.util.Slog; + +/** + * A JobService used to trigger time zone rules update work when a device falls idle. + */ +public final class TimeZoneUpdateIdler extends JobService { + + private static final String TAG = "timezone.TimeZoneUpdateIdler"; + + /** The static job ID used to handle on-idle work. */ + // Must be unique within UID (system service) + private static final int TIME_ZONE_UPDATE_IDLE_JOB_ID = 27042305; + + @Override + public boolean onStartJob(JobParameters params) { + RulesManagerService rulesManagerService = + LocalServices.getService(RulesManagerService.class); + + Slog.d(TAG, "onStartJob() called"); + + // Note: notifyIdle() explicitly handles canceling / re-scheduling so no need to reschedule + // here. + rulesManagerService.notifyIdle(); + + // Everything is handled synchronously. We are done. + return false; + } + + @Override + public boolean onStopJob(JobParameters params) { + // Reschedule if stopped unless it was cancelled due to unschedule(). + boolean reschedule = params.getStopReason() != JobParameters.REASON_CANCELED; + Slog.d(TAG, "onStopJob() called: Reschedule=" + reschedule); + return reschedule; + } + + /** + * Schedules the TimeZoneUpdateIdler job service to run once. + * + * @param context Context to use to get a job scheduler. + */ + public static void schedule(Context context, long minimumDelayMillis) { + // Request that the JobScheduler tell us when the device falls idle. + JobScheduler jobScheduler = + (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); + + // The TimeZoneUpdateIdler will send an intent that will trigger the Receiver. + ComponentName idlerJobServiceName = + new ComponentName(context, TimeZoneUpdateIdler.class); + + // We require the device is idle, but also that it is charging to be as non-invasive as + // we can. + JobInfo.Builder jobInfoBuilder = + new JobInfo.Builder(TIME_ZONE_UPDATE_IDLE_JOB_ID, idlerJobServiceName) + .setRequiresDeviceIdle(true) + .setRequiresCharging(true) + .setMinimumLatency(minimumDelayMillis); + + Slog.d(TAG, "schedule() called: minimumDelayMillis=" + minimumDelayMillis); + jobScheduler.schedule(jobInfoBuilder.build()); + } + + /** + * Unschedules the TimeZoneUpdateIdler job service. + * + * @param context Context to use to get a job scheduler. + */ + public static void unschedule(Context context) { + JobScheduler jobScheduler = + (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); + Slog.d(TAG, "unschedule() called"); + jobScheduler.cancel(TIME_ZONE_UPDATE_IDLE_JOB_ID); + } +} diff --git a/services/core/java/com/android/server/twilight/TwilightState.java b/services/core/java/com/android/server/twilight/TwilightState.java index 30a8cccb6ad5..71304a7a4701 100644 --- a/services/core/java/com/android/server/twilight/TwilightState.java +++ b/services/core/java/com/android/server/twilight/TwilightState.java @@ -18,7 +18,10 @@ package com.android.server.twilight; import android.text.format.DateFormat; -import java.util.Calendar; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.TimeZone; /** * The twilight state, consisting of the sunrise and sunset times (in millis) for the current @@ -45,12 +48,11 @@ public final class TwilightState { } /** - * Returns a new {@link Calendar} instance initialized to {@link #sunriseTimeMillis()}. + * Returns a new {@link LocalDateTime} instance initialized to {@link #sunriseTimeMillis()}. */ - public Calendar sunrise() { - final Calendar sunrise = Calendar.getInstance(); - sunrise.setTimeInMillis(mSunriseTimeMillis); - return sunrise; + public LocalDateTime sunrise() { + final ZoneId zoneId = TimeZone.getDefault().toZoneId(); + return LocalDateTime.ofInstant(Instant.ofEpochMilli(mSunriseTimeMillis), zoneId); } /** @@ -62,12 +64,11 @@ public final class TwilightState { } /** - * Returns a new {@link Calendar} instance initialized to {@link #sunsetTimeMillis()}. + * Returns a new {@link LocalDateTime} instance initialized to {@link #sunsetTimeMillis()}. */ - public Calendar sunset() { - final Calendar sunset = Calendar.getInstance(); - sunset.setTimeInMillis(mSunsetTimeMillis); - return sunset; + public LocalDateTime sunset() { + final ZoneId zoneId = TimeZone.getDefault().toZoneId(); + return LocalDateTime.ofInstant(Instant.ofEpochMilli(mSunsetTimeMillis), zoneId); } /** diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java index bf769ed46bc1..1e334b83d8b0 100644 --- a/services/core/java/com/android/server/webkit/SystemImpl.java +++ b/services/core/java/com/android/server/webkit/SystemImpl.java @@ -304,6 +304,6 @@ public class SystemImpl implements SystemInterface { // flags declaring we want extra info from the package manager for webview providers private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA - | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING - | PackageManager.MATCH_ANY_USER; + | PackageManager.GET_SIGNATURES | PackageManager.GET_SHARED_LIBRARY_FILES + | PackageManager.MATCH_DEBUG_TRIAGED_MISSING | PackageManager.MATCH_ANY_USER; } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 817a01c5c8d7..98a1bd359b55 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1722,21 +1722,22 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo out.set(mContentRect); } - TaskStack addStackToDisplay(int stackId, boolean onTop) { + TaskStack addStackToDisplay(int stackId, boolean onTop, StackWindowController controller) { if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" + mDisplayId); TaskStack stack = getStackById(stackId); if (stack != null) { - // It's already attached to the display...clear mDeferRemoval and move stack to - // appropriate z-order on display as needed. + // It's already attached to the display...clear mDeferRemoval, set controller, and move + // stack to appropriate z-order on display as needed. stack.mDeferRemoval = false; + stack.setController(controller); // We're not moving the display to front when we're adding stacks, only when // requested to change the position of stack explicitly. mTaskStackContainers.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, stack, false /* includingParents */); } else { - stack = new TaskStack(mService, stackId); + stack = new TaskStack(mService, stackId, controller); mTaskStackContainers.addStackToDisplay(stack, onTop); } diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java index a50ed71afdb1..c0a4cb72a348 100644 --- a/services/core/java/com/android/server/wm/StackWindowController.java +++ b/services/core/java/com/android/server/wm/StackWindowController.java @@ -18,8 +18,6 @@ package com.android.server.wm; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; -import android.app.ActivityManager.StackId; -import android.app.WindowConfiguration; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Handler; @@ -76,8 +74,7 @@ public class StackWindowController + " to unknown displayId=" + displayId); } - final TaskStack stack = dc.addStackToDisplay(stackId, onTop); - stack.setController(this); + dc.addStackToDisplay(stackId, onTop, this); getRawBounds(outBounds); } } diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index 463240228fb6..751769a63d62 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -297,7 +297,7 @@ class TaskSnapshotController { return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(), topChild.getConfiguration().orientation, mainWindow.mStableInsets, - false /* reduced */, 1.0f /* scale */); + ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */); } /** diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 126d820e69b6..7cb90de49b1a 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -149,9 +149,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye Rect mPreAnimationBounds = new Rect(); - TaskStack(WindowManagerService service, int stackId) { + TaskStack(WindowManagerService service, int stackId, StackWindowController controller) { mService = service; mStackId = stackId; + setController(controller); mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.docked_stack_minimize_thickness); EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 57271fa10950..948c028d46ca 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -103,6 +103,7 @@ import com.android.server.restrictions.RestrictionsManagerService; import com.android.server.security.KeyAttestationApplicationIdProviderService; import com.android.server.security.KeyChainSystemService; import com.android.server.soundtrigger.SoundTriggerService; +import com.android.server.stats.StatsCompanionService; import com.android.server.statusbar.StatusBarManagerService; import com.android.server.storage.DeviceStorageMonitorService; import com.android.server.telecom.TelecomLoaderService; @@ -1146,20 +1147,6 @@ public final class SystemServer { traceEnd(); } - /* - * StorageManagerService has a few dependencies: Notification Manager and - * AppWidget Provider. Make sure StorageManagerService is completely started - * first before continuing. - */ - if (storageManager != null && !mOnlyCore) { - traceBeginAndSlog("WaitForAsecScan"); - try { - storageManager.waitForAsecScan(); - } catch (RemoteException ignored) { - } - traceEnd(); - } - traceBeginAndSlog("StartNotificationManager"); mSystemServiceManager.startService(NotificationManagerService.class); SystemNotificationChannels.createAll(context); @@ -1209,18 +1196,6 @@ public final class SystemServer { traceEnd(); } - // timezone.RulesManagerService will prevent a device starting up if the chain of trust - // required for safe time zone updates might be broken. RuleManagerService cannot do - // this check when mOnlyCore == true, so we don't enable the service in this case. - final boolean startRulesManagerService = - !mOnlyCore && context.getResources().getBoolean( - R.bool.config_enableUpdateableTimeZoneRules); - if (startRulesManagerService) { - traceBeginAndSlog("StartTimeZoneRulesManagerService"); - mSystemServiceManager.startService(TIME_ZONE_RULES_MANAGER_SERVICE_CLASS); - traceEnd(); - } - traceBeginAndSlog("StartAudioService"); mSystemServiceManager.startService(AudioService.Lifecycle.class); traceEnd(); @@ -1361,6 +1336,19 @@ public final class SystemServer { } traceEnd(); + // timezone.RulesManagerService will prevent a device starting up if the chain of trust + // required for safe time zone updates might be broken. RuleManagerService cannot do + // this check when mOnlyCore == true, so we don't enable the service in this case. + // This service requires that JobSchedulerService is already started when it starts. + final boolean startRulesManagerService = + !mOnlyCore && context.getResources().getBoolean( + R.bool.config_enableUpdateableTimeZoneRules); + if (startRulesManagerService) { + traceBeginAndSlog("StartTimeZoneRulesManagerService"); + mSystemServiceManager.startService(TIME_ZONE_RULES_MANAGER_SERVICE_CLASS); + traceEnd(); + } + if (!disableNetwork && !disableNetworkTime) { traceBeginAndSlog("StartNetworkTimeUpdateService"); try { @@ -1536,6 +1524,11 @@ public final class SystemServer { traceEnd(); } + // Statsd helper + traceBeginAndSlog("StartStatsCompanionService"); + mSystemServiceManager.startService(StatsCompanionService.Lifecycle.class); + traceEnd(); + // Before things start rolling, be sure we have decided whether // we are in safe mode. final boolean safeMode = wm.detectSafeMode(); diff --git a/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java index 58a4456ff4d7..3a92d638fb02 100644 --- a/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NightDisplayServiceTest.java @@ -30,13 +30,14 @@ import android.support.test.runner.AndroidJUnit4; import android.test.mock.MockContentResolver; import com.android.internal.app.NightDisplayController; -import com.android.internal.app.NightDisplayController.LocalTime; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.display.DisplayTransformManager; import com.android.server.display.NightDisplayService; import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightState; +import java.time.LocalDateTime; +import java.time.ZoneId; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -45,6 +46,7 @@ import org.mockito.Mockito; import java.util.Calendar; import java.util.HashMap; +import java.time.LocalTime; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -926,11 +928,10 @@ public class NightDisplayServiceTest { */ private void setActivated(boolean activated, int lastActivatedTimeOffset) { mNightDisplayController.setActivated(activated); - - final Calendar c = Calendar.getInstance(); - c.add(Calendar.MINUTE, lastActivatedTimeOffset); - Secure.putLongForUser(mContext.getContentResolver(), - Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, c.getTimeInMillis(), mUserId); + Secure.putStringForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, + LocalDateTime.now().plusMinutes(lastActivatedTimeOffset).toString(), + mUserId); } /** @@ -969,7 +970,7 @@ public class NightDisplayServiceTest { private static LocalTime getLocalTimeRelativeToNow(int offsetMinutes) { final Calendar c = Calendar.getInstance(); c.add(Calendar.MINUTE, offsetMinutes); - return new LocalTime(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE)); + return LocalTime.of(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE)); } /** @@ -984,13 +985,27 @@ public class NightDisplayServiceTest { final LocalTime sunset = getLocalTimeRelativeToNow(sunsetOffset); final LocalTime sunrise = getLocalTimeRelativeToNow(sunriseOffset); - final Calendar now = Calendar.getInstance(); - long sunsetMillis = sunset.getDateTimeBefore(now).getTimeInMillis(); - long sunriseMillis = sunrise.getDateTimeBefore(now).getTimeInMillis(); + final LocalDateTime now = LocalDateTime.now(); + final ZoneId zoneId = ZoneId.systemDefault(); + + long sunsetMillis = NightDisplayService.getDateTimeBefore(sunset, now) + .atZone(zoneId) + .toInstant() + .toEpochMilli(); + long sunriseMillis = NightDisplayService.getDateTimeBefore(sunrise, now) + .atZone(zoneId) + .toInstant() + .toEpochMilli(); if (sunsetMillis < sunriseMillis) { - sunsetMillis = sunset.getDateTimeAfter(now).getTimeInMillis(); + sunsetMillis = NightDisplayService.getDateTimeAfter(sunset, now) + .atZone(zoneId) + .toInstant() + .toEpochMilli(); } else { - sunriseMillis = sunrise.getDateTimeAfter(now).getTimeInMillis(); + sunriseMillis = NightDisplayService.getDateTimeAfter(sunrise, now) + .atZone(zoneId) + .toInstant() + .toEpochMilli(); } return new TwilightState(sunriseMillis, sunsetMillis); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java index 47a3a7242a44..526f81572b07 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java @@ -20,15 +20,19 @@ import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM; import static android.view.WindowManagerPolicy.NAV_BAR_LEFT; import static android.view.WindowManagerPolicy.NAV_BAR_RIGHT; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; import android.content.ComponentName; +import android.content.pm.ActivityInfo; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.support.test.filters.MediumTest; import android.support.test.runner.AndroidJUnit4; +import android.view.Display; import org.junit.runner.RunWith; import org.junit.Test; @@ -46,6 +50,8 @@ public class ActivityRecordTests extends ActivityTestsBase { private final ComponentName testActivityComponent = ComponentName.unflattenFromString("com.foo/.BarActivity"); + private final ComponentName secondaryActivityComponent = + ComponentName.unflattenFromString("com.foo/.BarActivity2"); @Test public void testStackCleanupOnClearingTask() throws Exception { final ActivityManagerService service = createActivityManagerService(); @@ -131,4 +137,45 @@ public class ActivityRecordTests extends ActivityTestsBase { record.ensureActivityConfigurationLocked(0 /* globalChanges */, false /* preserveWindow */); assertEquals(expectedActivityBounds, record.getBounds()); } + + + @Test + public void testCanBeLaunchedOnDisplay() throws Exception { + testSupportsLaunchingResizeable(false /*taskPresent*/, true /*taskResizeable*/, + true /*activityResizeable*/, true /*expected*/); + + testSupportsLaunchingResizeable(false /*taskPresent*/, true /*taskResizeable*/, + false /*activityResizeable*/, false /*expected*/); + + testSupportsLaunchingResizeable(true /*taskPresent*/, false /*taskResizeable*/, + true /*activityResizeable*/, false /*expected*/); + + testSupportsLaunchingResizeable(true /*taskPresent*/, true /*taskResizeable*/, + false /*activityResizeable*/, true /*expected*/); + } + + private void testSupportsLaunchingResizeable(boolean taskPresent, boolean taskResizeable, + boolean activityResizeable, boolean expected) { + final ActivityManagerService service = createActivityManagerService(); + service.mSupportsMultiWindow = true; + + + final TaskRecord task = taskPresent + ? createTask(service, testActivityComponent, TEST_STACK_ID) : null; + + if (task != null) { + task.setResizeMode(taskResizeable ? ActivityInfo.RESIZE_MODE_RESIZEABLE + : ActivityInfo.RESIZE_MODE_UNRESIZEABLE); + } + + final ActivityRecord record = createActivity(service, secondaryActivityComponent, + task); + record.info.resizeMode = activityResizeable ? ActivityInfo.RESIZE_MODE_RESIZEABLE + : ActivityInfo.RESIZE_MODE_UNRESIZEABLE; + + record.canBeLaunchedOnDisplay(Display.DEFAULT_DISPLAY); + + assertEquals(((TestActivityStackSupervisor) service.mStackSupervisor) + .getLastResizeableFromCanPlaceEntityOnDisplay(), expected); + } } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java index 661dd4fc828c..cd1843b37ae2 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java @@ -17,7 +17,10 @@ package com.android.server.am; import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; +import static android.app.ActivityManager.StackId.HOME_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -60,7 +63,7 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { public void testRestoringInvalidTask() throws Exception { final ActivityManagerService service = createActivityManagerService(); TaskRecord task = service.mStackSupervisor.anyTaskForIdLocked(0 /*taskId*/, - MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, 0 /*stackId*/); + MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null); assertNull(task); } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index b5345444f8cc..0cf1df84c073 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -163,6 +163,7 @@ public class ActivityTestsBase { */ protected static class TestActivityStackSupervisor extends ActivityStackSupervisor { private final ActivityDisplay mDisplay; + private boolean mLastResizeable; public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) { super(service, looper); @@ -170,6 +171,22 @@ public class ActivityTestsBase { mDisplay = new ActivityDisplay(); } + // TODO: Use Mockito spy instead. Currently not possible due to TestActivityStackSupervisor + // access to ActivityDisplay + @Override + boolean canPlaceEntityOnDisplay(int displayId, boolean resizeable, int callingPid, + int callingUid, ActivityInfo activityInfo) { + mLastResizeable = resizeable; + return super.canPlaceEntityOnDisplay(displayId, resizeable, callingPid, callingUid, + activityInfo); + } + + // TODO: remove and use Mockito verify once {@link #canPlaceEntityOnDisplay} override is + // removed. + public boolean getLastResizeableFromCanPlaceEntityOnDisplay() { + return mLastResizeable; + } + // No home stack is set. @Override void moveHomeStackToFront(String reason) { diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java index 4475de5aa14e..419a161669aa 100644 --- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java @@ -48,13 +48,13 @@ import java.util.List; import java.util.Set; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static com.android.server.am.ActivityManagerService.CONTINUE_USER_SWITCH_MSG; -import static com.android.server.am.ActivityManagerService.REPORT_LOCKED_BOOT_COMPLETE_MSG; -import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_COMPLETE_MSG; -import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MSG; -import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG; -import static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG; -import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG; +import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG; +import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG; +import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG; +import static com.android.server.am.UserController.REPORT_USER_SWITCH_MSG; +import static com.android.server.am.UserController.SYSTEM_USER_CURRENT_MSG; +import static com.android.server.am.UserController.SYSTEM_USER_START_MSG; +import static com.android.server.am.UserController.USER_SWITCH_TIMEOUT_MSG; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; @@ -309,6 +309,7 @@ public class UserControllerTest extends AndroidTestCase { private static class TestInjector extends UserController.Injector { final Object lock = new Object(); TestHandler handler; + TestHandler uiHandler; HandlerThread handlerThread; UserManagerService userManagerMock; UserManagerInternal userManagerInternalMock; @@ -324,6 +325,7 @@ public class UserControllerTest extends AndroidTestCase { handlerThread = new HandlerThread(TAG); handlerThread.start(); handler = new TestHandler(handlerThread.getLooper()); + uiHandler = new TestHandler(handlerThread.getLooper()); userManagerMock = mock(UserManagerService.class); userManagerInternalMock = mock(UserManagerInternal.class); windowManagerMock = mock(WindowManagerService.class); @@ -337,11 +339,16 @@ public class UserControllerTest extends AndroidTestCase { } @Override - protected Handler getHandler() { + protected Handler getHandler(Handler.Callback callback) { return handler; } @Override + protected Handler getUiHandler(Handler.Callback callback) { + return uiHandler; + } + + @Override protected UserManagerService getUserManager() { return userManagerMock; } diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index 14b1ce1662c7..4559660351b0 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -33,6 +33,10 @@ import org.junit.rules.TemporaryFolder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP; +import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE; +import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING; +import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.eq; @@ -83,4 +87,33 @@ public class PowerManagerServiceTest extends AndroidTestCase { SystemProperties.set(TEST_LAST_REBOOT_PROPERTY, ""); assertThat(reason).isEqualTo(PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN); } + + @SmallTest + public void testGetDesiredScreenPolicy_WithVR() throws Exception { + // Brighten up the screen + mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, 0); + assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo( + DisplayPowerRequest.POLICY_BRIGHT); + + // Move to VR + mService.setVrModeEnabled(true); + assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo( + DisplayPowerRequest.POLICY_VR); + + // Then take a nap + mService.setWakefulnessLocked(WAKEFULNESS_ASLEEP, 0); + assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo( + DisplayPowerRequest.POLICY_OFF); + + // Wake up to VR + mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, 0); + assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo( + DisplayPowerRequest.POLICY_VR); + + // And back to normal + mService.setVrModeEnabled(false); + assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo( + DisplayPowerRequest.POLICY_BRIGHT); + + } } diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java index 38142d3681b6..7d73e82eaf76 100644 --- a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java @@ -107,7 +107,7 @@ public class PackageTrackerTest { mFakeIntentHelper.assertNotInitialized(); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); } @Test @@ -119,7 +119,7 @@ public class PackageTrackerTest { mPackageTracker.start(); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); try { // This call should also not be allowed and will throw an exception if tracking is @@ -129,7 +129,7 @@ public class PackageTrackerTest { } catch (IllegalStateException expected) {} // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); } @Test @@ -141,14 +141,14 @@ public class PackageTrackerTest { mPackageTracker.start(); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); // Receiving a check result when tracking is disabled should cause the storage to be // reset. mPackageTracker.recordCheckResult(null /* checkToken */, true /* success */); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); // Assert the storage was reset. checkPackageStorageStatusIsInitialOrReset(); @@ -166,13 +166,13 @@ public class PackageTrackerTest { mPackageTracker.start(); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); // Receiving a check result when tracking is disabled should cause the storage to be reset. mPackageTracker.recordCheckResult(createArbitraryCheckToken(), true /* success */); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); // Assert the storage was reset. checkPackageStorageStatusIsInitialOrReset(); @@ -195,7 +195,7 @@ public class PackageTrackerTest { mFakeIntentHelper.assertNotInitialized(); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); } @Test @@ -215,7 +215,7 @@ public class PackageTrackerTest { mFakeIntentHelper.assertNotInitialized(); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); } @Test @@ -235,7 +235,7 @@ public class PackageTrackerTest { mFakeIntentHelper.assertNotInitialized(); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); } @Test @@ -255,7 +255,7 @@ public class PackageTrackerTest { mFakeIntentHelper.assertNotInitialized(); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); } @Test @@ -289,7 +289,7 @@ public class PackageTrackerTest { mFakeIntentHelper.assertUpdateNotTriggered(); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); // Assert the storage was not touched. checkPackageStorageStatusIsInitialOrReset(); @@ -325,7 +325,7 @@ public class PackageTrackerTest { mFakeIntentHelper.assertUpdateNotTriggered(); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); // Assert the storage was not touched. checkPackageStorageStatusIsInitialOrReset(); @@ -416,7 +416,7 @@ public class PackageTrackerTest { mPackageTracker.recordCheckResult(null /* checkToken */, success); // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringEnabled(); + mFakeIntentHelper.assertReliabilityTriggerScheduled(); // Assert the storage was reset. checkPackageStorageStatusIsInitialOrReset(); @@ -627,7 +627,7 @@ public class PackageTrackerTest { mPackageTracker.recordCheckResult(token1, true /* success */); // Reliability triggering should still be enabled. - mFakeIntentHelper.assertReliabilityTriggeringEnabled(); + mFakeIntentHelper.assertReliabilityTriggerScheduled(); // Check the expected storage state. checkPackageStorageStatus(PackageStatus.CHECK_STARTED, packageVersions2); @@ -743,7 +743,7 @@ public class PackageTrackerTest { // Under the covers we expect it to fail to update because the storage should recognize that // the token is no longer valid. - mFakeIntentHelper.assertReliabilityTriggeringEnabled(); + mFakeIntentHelper.assertReliabilityTriggerScheduled(); // Peek inside the package tracker to make sure it is tracking failure counts properly. assertEquals(1, mPackageTracker.getCheckFailureCountForTests()); @@ -766,7 +766,7 @@ public class PackageTrackerTest { checkPackageStorageStatusIsInitialOrReset(); // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Assert the PackageTracker did trigger an update. checkUpdateCheckTriggered(packageVersions); @@ -803,7 +803,7 @@ public class PackageTrackerTest { checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions); // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Assert the PackageTracker did not attempt to trigger an update. mFakeIntentHelper.assertUpdateNotTriggered(); @@ -843,7 +843,7 @@ public class PackageTrackerTest { checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Assert the PackageTracker did trigger an update. checkUpdateCheckTriggered(currentPackageVersions); @@ -890,7 +890,7 @@ public class PackageTrackerTest { for (int i = 0; i < retriesAllowed + 1; i++) { // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Assert the PackageTracker did trigger an update. checkUpdateCheckTriggered(currentPackageVersions); @@ -912,9 +912,9 @@ public class PackageTrackerTest { // Check reliability triggering is in the correct state. if (i <= retriesAllowed) { - mFakeIntentHelper.assertReliabilityTriggeringEnabled(); + mFakeIntentHelper.assertReliabilityTriggerScheduled(); } else { - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); } } } @@ -950,7 +950,7 @@ public class PackageTrackerTest { // Fail (retries - 1) times. for (int i = 0; i < retriesAllowed - 1; i++) { // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Assert the PackageTracker did trigger an update. checkUpdateCheckTriggered(currentPackageVersions); @@ -971,11 +971,11 @@ public class PackageTrackerTest { currentPackageVersions); // Check reliability triggering is still enabled. - mFakeIntentHelper.assertReliabilityTriggeringEnabled(); + mFakeIntentHelper.assertReliabilityTriggerScheduled(); } // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Assert the PackageTracker did trigger an update. checkUpdateCheckTriggered(currentPackageVersions); @@ -1023,7 +1023,7 @@ public class PackageTrackerTest { checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, oldPackageVersions); // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Assert the PackageTracker did trigger an update. checkUpdateCheckTriggered(currentPackageVersions); @@ -1033,18 +1033,18 @@ public class PackageTrackerTest { mFakeClock.incrementClock(checkDelayMillis - 1); // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Assert the PackageTracker did not trigger an update. mFakeIntentHelper.assertUpdateNotTriggered(); checkPackageStorageStatus(PackageStatus.CHECK_STARTED, currentPackageVersions); - mFakeIntentHelper.assertReliabilityTriggeringEnabled(); + mFakeIntentHelper.assertReliabilityTriggerScheduled(); // Increment the clock slightly more. Should now consider the response overdue. mFakeClock.incrementClock(2); // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Triggering should have happened. checkUpdateCheckTriggered(currentPackageVersions); @@ -1096,7 +1096,7 @@ public class PackageTrackerTest { mFakeClock.incrementClock(checkDelayMillis + 1); // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Assert the PackageTracker triggered an update. checkUpdateCheckTriggered(newPackageVersions); @@ -1154,18 +1154,18 @@ public class PackageTrackerTest { mFakeClock.incrementClock(checkDelayMillis - 1); // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Assert the PackageTracker did not trigger an update. mFakeIntentHelper.assertUpdateNotTriggered(); checkPackageStorageStatus(PackageStatus.CHECK_STARTED, newPackageVersions); - mFakeIntentHelper.assertReliabilityTriggeringEnabled(); + mFakeIntentHelper.assertReliabilityTriggerScheduled(); // Increment the clock slightly more. Should now consider the response overdue. mFakeClock.incrementClock(2); // Simulate a reliability trigger. - mFakeIntentHelper.simulateReliabilityTrigger(); + mPackageTracker.triggerUpdateIfNeeded(false /* packageChanged */); // Triggering should have happened. checkUpdateCheckTriggered(newPackageVersions); @@ -1202,7 +1202,7 @@ public class PackageTrackerTest { // If an update check was triggered reliability triggering should always be enabled to // ensure that it can be completed if it fails. - mFakeIntentHelper.assertReliabilityTriggeringEnabled(); + mFakeIntentHelper.assertReliabilityTriggerScheduled(); // Check the expected storage state. checkPackageStorageStatus(PackageStatus.CHECK_STARTED, packageVersions); @@ -1210,7 +1210,7 @@ public class PackageTrackerTest { private void checkUpdateCheckFailed(PackageVersions packageVersions) { // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringEnabled(); + mFakeIntentHelper.assertReliabilityTriggerScheduled(); // Assert the storage was updated. checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, packageVersions); @@ -1218,7 +1218,7 @@ public class PackageTrackerTest { private void checkUpdateCheckSuccessful(PackageVersions packageVersions) { // Check reliability triggering state. - mFakeIntentHelper.assertReliabilityTriggeringDisabled(); + mFakeIntentHelper.assertReliabilityTriggerNotScheduled(); // Assert the storage was updated. checkPackageStorageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions); @@ -1345,7 +1345,7 @@ public class PackageTrackerTest { mFakeIntentHelper.assertInitialized(UPDATE_APP_PACKAGE_NAME, DATA_APP_PACKAGE_NAME); // Assert that reliability tracking is always enabled after initialization. - mFakeIntentHelper.assertReliabilityTriggeringEnabled(); + mFakeIntentHelper.assertReliabilityTriggerScheduled(); } private void checkPackageStorageStatus( @@ -1368,34 +1368,34 @@ public class PackageTrackerTest { */ private static class FakeIntentHelper implements IntentHelper { - private Listener mListener; + private PackageTracker mPackageTracker; private String mUpdateAppPackageName; private String mDataAppPackageName; private CheckToken mLastToken; - private boolean mReliabilityTriggeringEnabled; + private boolean mReliabilityTriggerScheduled; @Override public void initialize(String updateAppPackageName, String dataAppPackageName, - Listener listener) { + PackageTracker packageTracker) { assertNotNull(updateAppPackageName); assertNotNull(dataAppPackageName); - assertNotNull(listener); - mListener = listener; + assertNotNull(packageTracker); + mPackageTracker = packageTracker; mUpdateAppPackageName = updateAppPackageName; mDataAppPackageName = dataAppPackageName; } public void assertInitialized( String expectedUpdateAppPackageName, String expectedDataAppPackageName) { - assertNotNull(mListener); + assertNotNull(mPackageTracker); assertEquals(expectedUpdateAppPackageName, mUpdateAppPackageName); assertEquals(expectedDataAppPackageName, mDataAppPackageName); } public void assertNotInitialized() { - assertNull(mListener); + assertNull(mPackageTracker); } @Override @@ -1407,21 +1407,21 @@ public class PackageTrackerTest { } @Override - public void enableReliabilityTriggering() { - mReliabilityTriggeringEnabled = true; + public void scheduleReliabilityTrigger(long minimumDelayMillis) { + mReliabilityTriggerScheduled = true; } @Override - public void disableReliabilityTriggering() { - mReliabilityTriggeringEnabled = false; + public void unscheduleReliabilityTrigger() { + mReliabilityTriggerScheduled = false; } - public void assertReliabilityTriggeringEnabled() { - assertTrue(mReliabilityTriggeringEnabled); + public void assertReliabilityTriggerScheduled() { + assertTrue(mReliabilityTriggerScheduled); } - public void assertReliabilityTriggeringDisabled() { - assertFalse(mReliabilityTriggeringEnabled); + public void assertReliabilityTriggerNotScheduled() { + assertFalse(mReliabilityTriggerScheduled); } public void assertUpdateTriggered() { @@ -1440,11 +1440,7 @@ public class PackageTrackerTest { } public void simulatePackageUpdatedEvent() { - mListener.triggerUpdateIfNeeded(true); - } - - public void simulateReliabilityTrigger() { - mListener.triggerUpdateIfNeeded(false); + mPackageTracker.triggerUpdateIfNeeded(true /* packageChanged */); } } diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java index e39cccab7bad..5d2bb4d92620 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java @@ -102,7 +102,7 @@ public class WindowFrameTests extends WindowTestsBase { sWm.mSystemDecorLayer = 10000; mWindowToken = new WindowTestUtils.TestAppWindowToken(sWm.getDefaultDisplayContentLocked()); - mStubStack = new TaskStack(sWm, 0); + mStubStack = new TaskStack(sWm, 0, null); } public void assertRect(Rect rect, int left, int top, int right, int bottom) { diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java index 2ae10aadb10c..0315c8d6f9ba 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java @@ -78,7 +78,7 @@ public class WindowTestUtils { */ public static class TestTaskStack extends TaskStack { TestTaskStack(WindowManagerService service, int stackId) { - super(service, stackId); + super(service, stackId, null); } @Override diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index 3788cf331600..b040a6324dbb 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -20,6 +20,7 @@ import static android.app.ActivityManager.START_ASSISTANT_HIDDEN_SESSION; import static android.app.ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION; import static android.app.ActivityManager.START_VOICE_HIDDEN_SESSION; import static android.app.ActivityManager.START_VOICE_NOT_ACTIVE_SESSION; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import android.app.ActivityManager; import android.app.ActivityManager.StackId; @@ -222,8 +223,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne } intent = new Intent(intent); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchStackId(StackId.ASSISTANT_STACK_ID); + final ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchActivityType(ACTIVITY_TYPE_ASSISTANT); return mAm.startAssistantActivity(mComponent.getPackageName(), callingPid, callingUid, intent, resolvedType, options.toBundle(), mUser); } catch (RemoteException e) { diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index d5ff1adb607d..ff6711632252 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -77,9 +77,28 @@ public class PhoneNumberUtils public static final int TOA_International = 0x91; public static final int TOA_Unknown = 0x81; + /* + * The BCD extended type used to determine the extended char for the digit which is greater than + * 9. + * + * see TS 51.011 section 10.5.1 EF_ADN(Abbreviated dialling numbers) + */ + public static final int BCD_EXTENDED_TYPE_EF_ADN = 1; + + /* + * The BCD extended type used to determine the extended char for the digit which is greater than + * 9. + * + * see TS 24.008 section 10.5.4.7 Called party BCD number + */ + public static final int BCD_EXTENDED_TYPE_CALLED_PARTY = 2; + static final String LOG_TAG = "PhoneNumberUtils"; private static final boolean DBG = false; + private static final String BCD_EF_ADN_EXTENDED = "*#,N;"; + private static final String BCD_CALLED_PARTY_EXTENDED = "*#abc"; + /* * global-phone-number = ["+"] 1*( DIGIT / written-sep ) * written-sep = ("-"/".") @@ -799,11 +818,33 @@ public class PhoneNumberUtils * * @return partial string on invalid decode * - * FIXME(mkf) support alphanumeric address type - * currently implemented in SMSMessage.getAddress() + * @deprecated use {@link #calledPartyBCDToString(byte[], int, int, int)} instead. Calling this + * method is equivalent to calling {@link #calledPartyBCDToString(byte[], int, int)} with + * {@link #BCD_EXTENDED_TYPE_EF_ADN} as the extended type. */ - public static String - calledPartyBCDToString (byte[] bytes, int offset, int length) { + @Deprecated + public static String calledPartyBCDToString(byte[] bytes, int offset, int length) { + return calledPartyBCDToString(bytes, offset, length, BCD_EXTENDED_TYPE_EF_ADN); + } + + /** + * 3GPP TS 24.008 10.5.4.7 + * Called Party BCD Number + * + * See Also TS 51.011 10.5.1 "dialing number/ssc string" + * and TS 11.11 "10.3.1 EF adn (Abbreviated dialing numbers)" + * + * @param bytes the data buffer + * @param offset should point to the TOA (aka. TON/NPI) octet after the length byte + * @param length is the number of bytes including TOA byte + * and must be at least 2 + * @param bcdExtType used to determine the extended bcd coding + * @see #BCD_EXTENDED_TYPE_EF_ADN + * @see #BCD_EXTENDED_TYPE_CALLED_PARTY + * + */ + public static String calledPartyBCDToString( + byte[] bytes, int offset, int length, int bcdExtType) { boolean prependPlus = false; StringBuilder ret = new StringBuilder(1 + length * 2); @@ -817,7 +858,7 @@ public class PhoneNumberUtils } internalCalledPartyBCDFragmentToString( - ret, bytes, offset + 1, length - 1); + ret, bytes, offset + 1, length - 1, bcdExtType); if (prependPlus && ret.length() == 0) { // If the only thing there is a prepended plus, return "" @@ -902,14 +943,13 @@ public class PhoneNumberUtils return ret.toString(); } - private static void - internalCalledPartyBCDFragmentToString( - StringBuilder sb, byte [] bytes, int offset, int length) { + private static void internalCalledPartyBCDFragmentToString( + StringBuilder sb, byte [] bytes, int offset, int length, int bcdExtType) { for (int i = offset ; i < length + offset ; i++) { byte b; char c; - c = bcdToChar((byte)(bytes[i] & 0xf)); + c = bcdToChar((byte)(bytes[i] & 0xf), bcdExtType); if (c == 0) { return; @@ -930,7 +970,7 @@ public class PhoneNumberUtils break; } - c = bcdToChar(b); + c = bcdToChar(b, bcdExtType); if (c == 0) { return; } @@ -943,49 +983,65 @@ public class PhoneNumberUtils /** * Like calledPartyBCDToString, but field does not start with a * TOA byte. For example: SIM ADN extension fields + * + * @deprecated use {@link #calledPartyBCDFragmentToString(byte[], int, int, int)} instead. + * Calling this method is equivalent to calling + * {@link #calledPartyBCDFragmentToString(byte[], int, int, int)} with + * {@link #BCD_EXTENDED_TYPE_EF_ADN} as the extended type. */ + @Deprecated + public static String calledPartyBCDFragmentToString(byte[] bytes, int offset, int length) { + return calledPartyBCDFragmentToString(bytes, offset, length, BCD_EXTENDED_TYPE_EF_ADN); + } - public static String - calledPartyBCDFragmentToString(byte [] bytes, int offset, int length) { + /** + * Like calledPartyBCDToString, but field does not start with a + * TOA byte. For example: SIM ADN extension fields + */ + public static String calledPartyBCDFragmentToString( + byte[] bytes, int offset, int length, int bcdExtType) { StringBuilder ret = new StringBuilder(length * 2); - - internalCalledPartyBCDFragmentToString(ret, bytes, offset, length); - + internalCalledPartyBCDFragmentToString(ret, bytes, offset, length, bcdExtType); return ret.toString(); } - /** returns 0 on invalid value */ - private static char - bcdToChar(byte b) { + /** + * Returns the correspond character for given {@code b} based on {@code bcdExtType}, or 0 on + * invalid code. + */ + private static char bcdToChar(byte b, int bcdExtType) { if (b < 0xa) { - return (char)('0' + b); - } else switch (b) { - case 0xa: return '*'; - case 0xb: return '#'; - case 0xc: return PAUSE; - case 0xd: return WILD; + return (char) ('0' + b); + } - default: return 0; + String extended = null; + if (BCD_EXTENDED_TYPE_EF_ADN == bcdExtType) { + extended = BCD_EF_ADN_EXTENDED; + } else if (BCD_EXTENDED_TYPE_CALLED_PARTY == bcdExtType) { + extended = BCD_CALLED_PARTY_EXTENDED; } + if (extended == null || b - 0xa >= extended.length()) { + return 0; + } + + return extended.charAt(b - 0xa); } - private static int - charToBCD(char c) { - if (c >= '0' && c <= '9') { + private static int charToBCD(char c, int bcdExtType) { + if ('0' <= c && c <= '9') { return c - '0'; - } else if (c == '*') { - return 0xa; - } else if (c == '#') { - return 0xb; - } else if (c == PAUSE) { - return 0xc; - } else if (c == WILD) { - return 0xd; - } else if (c == WAIT) { - return 0xe; - } else { - throw new RuntimeException ("invalid char for BCD " + c); } + + String extended = null; + if (BCD_EXTENDED_TYPE_EF_ADN == bcdExtType) { + extended = BCD_EF_ADN_EXTENDED; + } else if (BCD_EXTENDED_TYPE_CALLED_PARTY == bcdExtType) { + extended = BCD_CALLED_PARTY_EXTENDED; + } + if (extended == null || extended.indexOf(c) == -1) { + throw new RuntimeException("invalid char for BCD " + c); + } + return 0xa + extended.indexOf(c); } /** @@ -1034,40 +1090,60 @@ public class PhoneNumberUtils * * Returns null if network portion is empty. */ - public static byte[] - networkPortionToCalledPartyBCD(String s) { + public static byte[] networkPortionToCalledPartyBCD(String s) { String networkPortion = extractNetworkPortion(s); - return numberToCalledPartyBCDHelper(networkPortion, false); + return numberToCalledPartyBCDHelper( + networkPortion, false, BCD_EXTENDED_TYPE_EF_ADN); } /** * Same as {@link #networkPortionToCalledPartyBCD}, but includes a * one-byte length prefix. */ - public static byte[] - networkPortionToCalledPartyBCDWithLength(String s) { + public static byte[] networkPortionToCalledPartyBCDWithLength(String s) { String networkPortion = extractNetworkPortion(s); - return numberToCalledPartyBCDHelper(networkPortion, true); + return numberToCalledPartyBCDHelper( + networkPortion, true, BCD_EXTENDED_TYPE_EF_ADN); + } + + /** + * Convert a dialing number to BCD byte array + * + * @param number dialing number string. If the dialing number starts with '+', set to + * international TOA + * + * @return BCD byte array + * + * @deprecated use {@link #numberToCalledPartyBCD(String, int)} instead. Calling this method + * is equivalent to calling {@link #numberToCalledPartyBCD(String, int)} with + * {@link #BCD_EXTENDED_TYPE_EF_ADN} as the extended type. + */ + @Deprecated + public static byte[] numberToCalledPartyBCD(String number) { + return numberToCalledPartyBCD(number, BCD_EXTENDED_TYPE_EF_ADN); } /** * Convert a dialing number to BCD byte array * - * @param number dialing number string - * if the dialing number starts with '+', set to international TOA + * @param number dialing number string. If the dialing number starts with '+', set to + * international TOA + * @param bcdExtType used to determine the extended bcd coding + * @see #BCD_EXTENDED_TYPE_EF_ADN + * @see #BCD_EXTENDED_TYPE_CALLED_PARTY + * * @return BCD byte array */ - public static byte[] - numberToCalledPartyBCD(String number) { - return numberToCalledPartyBCDHelper(number, false); + public static byte[] numberToCalledPartyBCD(String number, int bcdExtType) { + return numberToCalledPartyBCDHelper(number, false, bcdExtType); } /** * If includeLength is true, prepend a one-byte length value to * the return array. */ - private static byte[] - numberToCalledPartyBCDHelper(String number, boolean includeLength) { + private static byte[] numberToCalledPartyBCDHelper( + String number, boolean includeLength, int bcdExtType) { int numberLenReal = number.length(); int numberLenEffective = numberLenReal; boolean hasPlus = number.indexOf('+') != -1; @@ -1087,7 +1163,8 @@ public class PhoneNumberUtils char c = number.charAt(i); if (c == '+') continue; int shift = ((digitCount & 0x01) == 1) ? 4 : 0; - result[extraBytes + (digitCount >> 1)] |= (byte)((charToBCD(c) & 0x0F) << shift); + result[extraBytes + (digitCount >> 1)] |= + (byte)((charToBCD(c, bcdExtType) & 0x0F) << shift); digitCount++; } diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java index 36abfc9d288e..489c208a0d46 100644 --- a/telephony/java/com/android/ims/ImsCallProfile.java +++ b/telephony/java/com/android/ims/ImsCallProfile.java @@ -19,7 +19,9 @@ package com.android.ims; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.os.PersistableBundle; import android.telecom.VideoProfile; +import android.util.Log; import com.android.internal.telephony.PhoneConstants; @@ -216,6 +218,29 @@ public class ImsCallProfile implements Parcelable { public int mServiceType; public int mCallType; public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE; + + /** + * Extras associated with this {@link ImsCallProfile}. + * <p> + * Valid data types include: + * <ul> + * <li>{@link Integer} (and int)</li> + * <li>{@link Long} (and long)</li> + * <li>{@link Double} (and double)</li> + * <li>{@link String}</li> + * <li>{@code int[]}</li> + * <li>{@code long[]}</li> + * <li>{@code double[]}</li> + * <li>{@code String[]}</li> + * <li>{@link PersistableBundle}</li> + * <li>{@link Boolean} (and boolean)</li> + * <li>{@code boolean[]}</li> + * <li>Other {@link Parcelable} classes in the {@code android.*} namespace.</li> + * </ul> + * <p> + * Invalid types will be removed when the {@link ImsCallProfile} is parceled for transmit across + * a {@link android.os.Binder}. + */ public Bundle mCallExtras; public ImsStreamMediaProfile mMediaProfile; @@ -315,16 +340,17 @@ public class ImsCallProfile implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { + Bundle filteredExtras = maybeCleanseExtras(mCallExtras); out.writeInt(mServiceType); out.writeInt(mCallType); - out.writeParcelable(mCallExtras, 0); + out.writeBundle(filteredExtras); out.writeParcelable(mMediaProfile, 0); } private void readFromParcel(Parcel in) { mServiceType = in.readInt(); mCallType = in.readInt(); - mCallExtras = in.readParcelable(null); + mCallExtras = in.readBundle(); mMediaProfile = in.readParcelable(null); } @@ -465,6 +491,31 @@ public class ImsCallProfile implements Parcelable { } /** + * Cleanses a {@link Bundle} to ensure that it contains only data of type: + * 1. Primitive data types (e.g. int, bool, and other values determined by + * {@link android.os.PersistableBundle#isValidType(Object)}). + * 2. Other Bundles. + * 3. {@link Parcelable} objects in the {@code android.*} namespace. + * @param extras the source {@link Bundle} + * @return where all elements are valid types the source {@link Bundle} is returned unmodified, + * otherwise a copy of the {@link Bundle} with the invalid elements is returned. + */ + private Bundle maybeCleanseExtras(Bundle extras) { + if (extras == null) { + return null; + } + + int startSize = extras.size(); + Bundle filtered = extras.filterValues(); + int endSize = filtered.size(); + if (startSize != endSize) { + Log.i(TAG, "maybeCleanseExtras: " + (startSize - endSize) + " extra values were " + + "removed - only primitive types and system parcelables are permitted."); + } + return filtered; + } + + /** * Determines if a video state is set in a video state bit-mask. * * @param videoState The video state bit mask. diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 629173dfa23b..7a53ef63e2a8 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -161,7 +161,7 @@ public class SmsMessage extends SmsMessageBase { // Second byte is the MSG_LEN, length of the message // See 3GPP2 C.S0023 3.4.27 - int size = data[1]; + int size = data[1] & 0xFF; // Note: Data may include trailing FF's. That's OK; message // should still parse correctly. diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java index 2fbf7ed5648c..bd8c83e63055 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java @@ -17,6 +17,7 @@ package com.android.internal.telephony.gsm; import android.telephony.PhoneNumberUtils; + import java.text.ParseException; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.SmsAddress; @@ -71,8 +72,11 @@ public class GsmSmsAddress extends SmsAddress { // Make sure the final unused BCD digit is 0xf origBytes[length - 1] |= 0xf0; } - address = PhoneNumberUtils.calledPartyBCDToString(origBytes, - OFFSET_TOA, length - OFFSET_TOA); + address = PhoneNumberUtils.calledPartyBCDToString( + origBytes, + OFFSET_TOA, + length - OFFSET_TOA, + PhoneNumberUtils.BCD_EXTENDED_TYPE_CALLED_PARTY); // And restore origBytes origBytes[length - 1] = lastByte; diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index d4098d94ba6c..1ca19e01d6c8 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -535,8 +535,8 @@ public class SmsMessage extends SmsMessageBase { } else { // SC address try { - ret = PhoneNumberUtils - .calledPartyBCDToString(mPdu, mCur, len); + ret = PhoneNumberUtils.calledPartyBCDToString( + mPdu, mCur, len, PhoneNumberUtils.BCD_EXTENDED_TYPE_CALLED_PARTY); } catch (RuntimeException tr) { Rlog.d(LOG_TAG, "invalid SC address: ", tr); ret = null; diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java index f72a1c638ed5..262417620ca2 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java @@ -512,7 +512,7 @@ public class IpConnectivityEventBuilderTest { stats.nonApplicationWakeups = 1; stats.rootWakeups = 2; stats.systemWakeups = 3; - stats.unroutedWakeups = 3; + stats.noUidWakeups = 3; IpConnectivityEvent got = IpConnectivityEventBuilder.toProto(stats); String want = String.join("\n", @@ -526,11 +526,11 @@ public class IpConnectivityEventBuilderTest { " wakeup_stats <", " application_wakeups: 5", " duration_sec: 0", + " no_uid_wakeups: 3", " non_application_wakeups: 1", " root_wakeups: 2", " system_wakeups: 3", " total_wakeups: 14", - " unrouted_wakeups: 3", " >", ">", "version: 2\n"); diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java index ede5988cdc6d..a395c480f57a 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java @@ -423,11 +423,11 @@ public class IpConnectivityMetricsTest { " wakeup_stats <", " application_wakeups: 2", " duration_sec: 0", + " no_uid_wakeups: 0", " non_application_wakeups: 0", " root_wakeups: 0", " system_wakeups: 1", " total_wakeups: 3", - " unrouted_wakeups: 0", " >", ">", "events <", @@ -439,11 +439,11 @@ public class IpConnectivityMetricsTest { " wakeup_stats <", " application_wakeups: 1", " duration_sec: 0", + " no_uid_wakeups: 1", " non_application_wakeups: 0", " root_wakeups: 0", " system_wakeups: 2", " total_wakeups: 4", - " unrouted_wakeups: 1", " >", ">", "version: 2\n"); diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index 2b105e5c92ee..6723601fc5c3 100644 --- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java @@ -163,11 +163,11 @@ public class NetdEventListenerServiceTest { " wakeup_stats <", " application_wakeups: 3", " duration_sec: 0", + " no_uid_wakeups: 0", " non_application_wakeups: 0", " root_wakeups: 0", " system_wakeups: 2", " total_wakeups: 5", - " unrouted_wakeups: 0", " >", ">", "events <", @@ -179,11 +179,11 @@ public class NetdEventListenerServiceTest { " wakeup_stats <", " application_wakeups: 2", " duration_sec: 0", + " no_uid_wakeups: 2", " non_application_wakeups: 1", " root_wakeups: 2", " system_wakeups: 3", " total_wakeups: 10", - " unrouted_wakeups: 2", " >", ">", "version: 2\n"); |