diff options
184 files changed, 3201 insertions, 1010 deletions
diff --git a/Android.mk b/Android.mk index 7e2f4726d8ea..a78a01a1600f 100644 --- a/Android.mk +++ b/Android.mk @@ -827,35 +827,35 @@ include $(BUILD_STATIC_JAVA_LIBRARY) # ==== hiddenapi lists ======================================= -# Copy light greylist and dark greylist over into the build folder. +# Copy blacklist and light greylist over into the build folder. # This is for ART buildbots which need to mock these lists and have alternative # rules for building them. Other rules in the build system should depend on the # files in the build folder. +$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-blacklist.txt,\ + $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST))) $(eval $(call copy-one-file,frameworks/base/config/hiddenapi-light-greylist.txt,\ $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST))) -$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-dark-greylist.txt,\ - $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST))) - -# Generate blacklist as private API minus (light greylist plus dark greylist). - -$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) -$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): LIGHT_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) -$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): DARK_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) -$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \ - $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \ - $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) - if [ ! -z "`comm -12 <(sort $(LIGHT_GREYLIST)) <(sort $(DARK_GREYLIST))`" ]; then \ - echo "There should be no overlap between $(LIGHT_GREYLIST) and $(DARK_GREYLIST)" 1>&2; \ + +# Generate dark greylist as private API minus (blacklist plus light greylist). + +$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) +$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): BLACKLIST := $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) +$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): LIGHT_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) +$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \ + $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) \ + $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) + if [ ! -z "`comm -12 <(sort $(BLACKLIST)) <(sort $(LIGHT_GREYLIST))`" ]; then \ + echo "There should be no overlap between $(BLACKLIST) and $(LIGHT_GREYLIST)" 1>&2; \ exit 1; \ + elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST))`" ]; then \ + echo "$(BLACKLIST) must be a subset of $(PRIVATE_API)" 1>&2; \ + exit 2; \ elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(LIGHT_GREYLIST))`" ]; then \ echo "$(LIGHT_GREYLIST) must be a subset of $(PRIVATE_API)" 1>&2; \ - exit 2; \ - elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(DARK_GREYLIST))`" ]; then \ - echo "$(DARK_GREYLIST) must be a subset of $(PRIVATE_API)" 1>&2; \ exit 3; \ fi - comm -23 <(sort $(PRIVATE_API)) <(sort $(LIGHT_GREYLIST) $(DARK_GREYLIST)) > $@ + comm -23 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST) $(LIGHT_GREYLIST)) > $@ # Include subdirectory makefiles # ============================================================ diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutMultithreadPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutMultithreadPerfTest.java new file mode 100644 index 000000000000..60c6d89b39ce --- /dev/null +++ b/apct-tests/perftests/core/src/android/text/StaticLayoutMultithreadPerfTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package android.text; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; + +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.TimeUnit; + +@LargeTest +@RunWith(AndroidJUnit4.class) +public class StaticLayoutMultithreadPerfTest { + private static final int WORD_LENGTH = 9; // Random word has 9 characters. + private static final int WORDS_IN_LINE = 8; // Roughly, 8 words in a line. + private static final boolean NO_STYLE_TEXT = false; + + private static TextPaint PAINT = new TextPaint(); + private static final int TEXT_WIDTH = WORDS_IN_LINE * WORD_LENGTH * (int) PAINT.getTextSize(); + + public StaticLayoutMultithreadPerfTest() {} + + @Rule + public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + private CountDownLatch mStartLatch; + private AtomicBoolean mThreadState; // True for running, False for stopped. + + private static final long TIMEOUT_MS = 5000; + + private Thread[] startBackgroundThread(int numOfThreads) { + mStartLatch = new CountDownLatch(numOfThreads); + mThreadState = new AtomicBoolean(true); + + Thread[] threads = new Thread[numOfThreads]; + for (int i = 0; i < numOfThreads; ++i) { + final int seed = i + 1; + threads[i] = new Thread(new Runnable() { + @Override + public void run() { + final TextPerfUtils util = new TextPerfUtils(); + util.resetRandom(seed); + + mStartLatch.countDown(); + while (mThreadState.get()) { + final CharSequence text = util.nextRandomParagraph( + WORD_LENGTH, NO_STYLE_TEXT); + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .build(); + } + } + }); + } + + for (int i = 0; i < numOfThreads; ++i) { + threads[i].start(); + } + + try { + mStartLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return threads; + } + + private void finishThreads(Thread[] threads) { + mThreadState.set(false); + for (Thread thread : threads) { + try { + thread.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + mStartLatch = null; + mThreadState = null; + } + + private void runRandomTest(int numOfTotalThreads) { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final TextPerfUtils util = new TextPerfUtils(); + Thread[] threads = startBackgroundThread(numOfTotalThreads - 1); + while (state.keepRunning()) { + state.pauseTiming(); + final CharSequence text = util.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); + state.resumeTiming(); + + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) + .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) + .build(); + } + finishThreads(threads); + } + + @Test + public void testCreate_RandomText_Thread_1() { + runRandomTest(1); + } + + @Test + public void testCreate_RandomText_Thread_2() { + runRandomTest(2); + } + + @Test + public void testCreate_RandomText_Thread_4() { + runRandomTest(4); + } +} diff --git a/api/system-current.txt b/api/system-current.txt index 32d235d47279..6a6d6672cacf 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -361,6 +361,7 @@ package android.app { } public final class StatsManager { + method public boolean addConfiguration(long, byte[], java.lang.String, java.lang.String); method public boolean addConfiguration(long, byte[]); method public byte[] getData(long); method public byte[] getMetadata(); @@ -688,6 +689,12 @@ package android.app.usage { field public static final java.lang.String SERVICE_INTERFACE = "android.app.usage.CacheQuotaService"; } + public static final class UsageEvents.Event { + method public int getStandbyBucket(); + field public static final int NOTIFICATION_SEEN = 10; // 0xa + field public static final int STANDBY_BUCKET_CHANGED = 11; // 0xb + } + public final class UsageStatsManager { method public int getAppStandbyBucket(java.lang.String); method public java.util.Map<java.lang.String, java.lang.Integer> getAppStandbyBuckets(); @@ -792,7 +799,7 @@ package android.content { field public static final java.lang.String STATS_MANAGER = "stats"; field public static final java.lang.String SYSTEM_UPDATE_SERVICE = "system_update"; field public static final java.lang.String VR_SERVICE = "vrmanager"; - field public static final java.lang.String WIFI_RTT_SERVICE = "rttmanager"; + field public static final deprecated java.lang.String WIFI_RTT_SERVICE = "rttmanager"; field public static final java.lang.String WIFI_SCANNING_SERVICE = "wifiscanner"; } @@ -3092,7 +3099,7 @@ package android.net.http { package android.net.wifi { - public class RttManager { + public deprecated class RttManager { method public void disableResponder(android.net.wifi.RttManager.ResponderCallback); method public void enableResponder(android.net.wifi.RttManager.ResponderCallback); method public deprecated android.net.wifi.RttManager.Capabilities getCapabilities(); @@ -3168,22 +3175,22 @@ package android.net.wifi { field public int supportedType; } - public static class RttManager.ParcelableRttParams implements android.os.Parcelable { + public static deprecated class RttManager.ParcelableRttParams implements android.os.Parcelable { field public android.net.wifi.RttManager.RttParams[] mParams; } - public static class RttManager.ParcelableRttResults implements android.os.Parcelable { + public static deprecated class RttManager.ParcelableRttResults implements android.os.Parcelable { ctor public RttManager.ParcelableRttResults(android.net.wifi.RttManager.RttResult[]); field public android.net.wifi.RttManager.RttResult[] mResults; } - public static abstract class RttManager.ResponderCallback { + public static abstract deprecated class RttManager.ResponderCallback { ctor public RttManager.ResponderCallback(); method public abstract void onResponderEnableFailure(int); method public abstract void onResponderEnabled(android.net.wifi.RttManager.ResponderConfig); } - public static class RttManager.ResponderConfig implements android.os.Parcelable { + public static deprecated class RttManager.ResponderConfig implements android.os.Parcelable { ctor public RttManager.ResponderConfig(); method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); @@ -3196,7 +3203,7 @@ package android.net.wifi { field public int preamble; } - public static class RttManager.RttCapabilities implements android.os.Parcelable { + public static deprecated class RttManager.RttCapabilities implements android.os.Parcelable { ctor public RttManager.RttCapabilities(); field public int bwSupported; field public boolean lciSupported; @@ -3211,13 +3218,13 @@ package android.net.wifi { field public boolean twoSided11McRttSupported; } - public static abstract interface RttManager.RttListener { + public static abstract deprecated interface RttManager.RttListener { method public abstract void onAborted(); method public abstract void onFailure(int, java.lang.String); method public abstract void onSuccess(android.net.wifi.RttManager.RttResult[]); } - public static class RttManager.RttParams { + public static deprecated class RttManager.RttParams { ctor public RttManager.RttParams(); field public boolean LCIRequest; field public boolean LCRRequest; @@ -3241,7 +3248,7 @@ package android.net.wifi { field public boolean secure; } - public static class RttManager.RttResult { + public static deprecated class RttManager.RttResult { ctor public RttManager.RttResult(); field public android.net.wifi.RttManager.WifiInformationElement LCI; field public android.net.wifi.RttManager.WifiInformationElement LCR; @@ -3278,7 +3285,7 @@ package android.net.wifi { field public deprecated int tx_rate; } - public static class RttManager.WifiInformationElement { + public static deprecated class RttManager.WifiInformationElement { ctor public RttManager.WifiInformationElement(); field public byte[] data; field public byte id; diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index e610fd757723..7662c4025c42 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include "statslog.h" @@ -32,6 +32,7 @@ #include <log/log_event_list.h> #include <utils/Errors.h> +#include <utils/SystemClock.h> using namespace android; using android::base::StringPrintf; @@ -60,6 +61,8 @@ const int FIELD_ID_ID = 2; // for ConfigMetricsReport const int FIELD_ID_METRICS = 1; const int FIELD_ID_UID_MAP = 2; +const int FIELD_ID_LAST_REPORT_NANOS = 3; +const int FIELD_ID_CURRENT_REPORT_NANOS = 4; #define STATS_DATA_DIR "/data/misc/stats-data" @@ -166,7 +169,7 @@ void StatsLogProcessor::OnLogEvent(LogEvent* event) { void StatsLogProcessor::OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config) { std::lock_guard<std::mutex> lock(mMetricsMutex); - ALOGD("Updated configuration for key %s", key.ToString().c_str()); + VLOG("Updated configuration for key %s", key.ToString().c_str()); sp<MetricsManager> newMetricsManager = new MetricsManager(key, config, mTimeBaseSec, mUidMap); auto it = mMetricsManagers.find(key); if (it == mMetricsManagers.end() && mMetricsManagers.size() > StatsdStats::kMaxConfigCount) { @@ -264,6 +267,12 @@ void StatsLogProcessor::onDumpReportLocked(const ConfigKey& key, vector<uint8_t> uidMap.SerializeToArray(&uidMapBuffer[0], uidMapSize); proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP, uidMapBuffer, uidMapSize); + // Fill in the timestamps. + proto.write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_NANOS, + (long long)it->second->getLastReportTimeNs()); + proto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_NANOS, + (long long)::android::elapsedRealtimeNano()); + // End of ConfigMetricsReport (reports). proto.end(reportsToken); diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index 183a99501024..c24efec4c4fc 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include "StatsService.h" diff --git a/cmds/statsd/src/anomaly/AnomalyMonitor.cpp b/cmds/statsd/src/anomaly/AnomalyMonitor.cpp index 4912648b648d..72d29d03c863 100644 --- a/cmds/statsd/src/anomaly/AnomalyMonitor.cpp +++ b/cmds/statsd/src/anomaly/AnomalyMonitor.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true +#define DEBUG false #include "Log.h" #include "anomaly/AnomalyMonitor.h" @@ -36,10 +36,10 @@ void AnomalyMonitor::setStatsCompanionService(sp<IStatsCompanionService> statsCo sp<IStatsCompanionService> tmpForLock = mStatsCompanionService; mStatsCompanionService = statsCompanionService; if (statsCompanionService == nullptr) { - if (DEBUG) ALOGD("Erasing link to statsCompanionService"); + VLOG("Erasing link to statsCompanionService"); return; } - if (DEBUG) ALOGD("Creating link to statsCompanionService"); + VLOG("Creating link to statsCompanionService"); const sp<const AnomalyAlarm> top = mPq.top(); if (top != nullptr) { updateRegisteredAlarmTime_l(top->timestampSec); @@ -58,7 +58,7 @@ void AnomalyMonitor::add(sp<const AnomalyAlarm> alarm) { return; } // TODO: Ensure that refractory period is respected. - if (DEBUG) ALOGD("Adding alarm with time %u", alarm->timestampSec); + VLOG("Adding alarm with time %u", alarm->timestampSec); mPq.push(alarm); if (mRegisteredAlarmTimeSec < 1 || alarm->timestampSec + mMinUpdateTimeSec < mRegisteredAlarmTimeSec) { @@ -72,16 +72,16 @@ void AnomalyMonitor::remove(sp<const AnomalyAlarm> alarm) { ALOGW("Asked to remove a null alarm."); return; } - if (DEBUG) ALOGD("Removing alarm with time %u", alarm->timestampSec); + VLOG("Removing alarm with time %u", alarm->timestampSec); bool wasPresent = mPq.remove(alarm); if (!wasPresent) return; if (mPq.empty()) { - if (DEBUG) ALOGD("Queue is empty. Cancel any alarm."); + VLOG("Queue is empty. Cancel any alarm."); cancelRegisteredAlarmTime_l(); return; } uint32_t soonestAlarmTimeSec = mPq.top()->timestampSec; - if (DEBUG) ALOGD("Soonest alarm is %u", soonestAlarmTimeSec); + VLOG("Soonest alarm is %u", soonestAlarmTimeSec); if (soonestAlarmTimeSec > mRegisteredAlarmTimeSec + mMinUpdateTimeSec) { updateRegisteredAlarmTime_l(soonestAlarmTimeSec); } @@ -91,7 +91,7 @@ void AnomalyMonitor::remove(sp<const AnomalyAlarm> alarm) { // updates to the registered alarm. unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> AnomalyMonitor::popSoonerThan( uint32_t timestampSec) { - if (DEBUG) ALOGD("Removing alarms with time <= %u", timestampSec); + VLOG("Removing alarms with time <= %u", timestampSec); unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> oldAlarms; std::lock_guard<std::mutex> lock(mLock); @@ -103,7 +103,7 @@ unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> AnomalyMonitor::popS // Always update registered alarm time (if anything has changed). if (!oldAlarms.empty()) { if (mPq.empty()) { - if (DEBUG) ALOGD("Queue is empty. Cancel any alarm."); + VLOG("Queue is empty. Cancel any alarm."); cancelRegisteredAlarmTime_l(); } else { // Always update the registered alarm in this case (unlike remove()). @@ -114,7 +114,7 @@ unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> AnomalyMonitor::popS } void AnomalyMonitor::updateRegisteredAlarmTime_l(uint32_t timestampSec) { - if (DEBUG) ALOGD("Updating reg alarm time to %u", timestampSec); + VLOG("Updating reg alarm time to %u", timestampSec); mRegisteredAlarmTimeSec = timestampSec; if (mStatsCompanionService != nullptr) { mStatsCompanionService->setAnomalyAlarm(secToMs(mRegisteredAlarmTimeSec)); @@ -123,7 +123,7 @@ void AnomalyMonitor::updateRegisteredAlarmTime_l(uint32_t timestampSec) { } void AnomalyMonitor::cancelRegisteredAlarmTime_l() { - if (DEBUG) ALOGD("Cancelling reg alarm."); + VLOG("Cancelling reg alarm."); mRegisteredAlarmTimeSec = 0; if (mStatsCompanionService != nullptr) { mStatsCompanionService->cancelAnomalyAlarm(); diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp index 7c5e45e100a5..63f6e2acd9df 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp +++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include "AnomalyTracker.h" diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp index e459f7681f26..fa0bc0c400b0 100644 --- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp +++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include "DurationAnomalyTracker.h" diff --git a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp index a75127324745..d0d2f938cf0c 100644 --- a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp +++ b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include <fstream> diff --git a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp index e7ea4b9abf0c..d9aeb4656bfe 100644 --- a/cmds/statsd/src/external/CpuTimePerUidPuller.cpp +++ b/cmds/statsd/src/external/CpuTimePerUidPuller.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include <fstream> diff --git a/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp b/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp index 7a2d1991a538..0e126e7a4b44 100644 --- a/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp +++ b/cmds/statsd/src/external/KernelUidCpuActiveTimeReader.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include <fstream> diff --git a/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp b/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp index 7426e743c40f..7684ed4eb44b 100644 --- a/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp +++ b/cmds/statsd/src/external/KernelUidCpuClusterTimeReader.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include <fstream> diff --git a/cmds/statsd/src/external/Perfetto.cpp b/cmds/statsd/src/external/Perfetto.cpp index 1d8a96850c4b..b09d373a5f3b 100644 --- a/cmds/statsd/src/external/Perfetto.cpp +++ b/cmds/statsd/src/external/Perfetto.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#define DEBUG false // STOPSHIP if true #include "Log.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert @@ -36,7 +37,7 @@ namespace os { namespace statsd { bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config) { - ALOGD("Starting trace collection through perfetto"); + VLOG("Starting trace collection through perfetto"); if (!config.has_trace_config()) { ALOGE("The perfetto trace config is empty, aborting"); @@ -118,7 +119,7 @@ bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config) { return false; } - ALOGD("CollectPerfettoTraceAndUploadToDropbox() succeeded"); + VLOG("CollectPerfettoTraceAndUploadToDropbox() succeeded"); return true; } diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp index b955f1cdaf5a..8210c8dcd63d 100644 --- a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp +++ b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true +#define DEBUG false #include "Log.h" #include <android/os/IStatsCompanionService.h> @@ -64,7 +64,7 @@ bool StatsCompanionServicePuller::PullInternal(vector<shared_ptr<LogEvent> >* da std::copy(it.bytes.begin(), it.bytes.end(), tmp.buf + kLogMsgHeaderSize); data->push_back(make_shared<LogEvent>(tmp)); } - ALOGD("StatsCompanionServicePuller::pull succeeded for %d", mTagId); + VLOG("StatsCompanionServicePuller::pull succeeded for %d", mTagId); return true; } else { ALOGW("statsCompanion not found!"); diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp index 0b772b3752de..4c676a70363f 100644 --- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp +++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp @@ -48,116 +48,73 @@ namespace os { namespace statsd { const std::map<int, PullAtomInfo> StatsPullerManagerImpl::kAllPullAtomInfo = { - // wifi_bytes_transfer - {android::util::WIFI_BYTES_TRANSFER, - {{2, 3, 4, 5}, - {}, - 1, - new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}}, - // wifi_bytes_transfer_by_fg_bg - {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG, - {{3, 4, 5, 6}, - {2}, - 1, - new StatsCompanionServicePuller( - android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}}, - // mobile_bytes_transfer - {android::util::MOBILE_BYTES_TRANSFER, - {{2, 3, 4, 5}, - {}, - 1, - new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}}, - // mobile_bytes_transfer_by_fg_bg - {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG, - {{3, 4, 5, 6}, - {2}, - 1, - new StatsCompanionServicePuller( - android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}}, - // bluetooth_bytes_transfer - {android::util::BLUETOOTH_BYTES_TRANSFER, - {{2, 3}, - {}, - 1, - new StatsCompanionServicePuller( - android::util::BLUETOOTH_BYTES_TRANSFER)}}, - // kernel_wakelock - {android::util::KERNEL_WAKELOCK, - {{}, - {}, - 1, - new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}}, - // subsystem_sleep_state - {android::util::SUBSYSTEM_SLEEP_STATE, - {{}, - {}, - 1, - new StatsCompanionServicePuller(android::util::SUBSYSTEM_SLEEP_STATE)}}, - // cpu_time_per_freq - {android::util::CPU_TIME_PER_FREQ, - {{3}, - {2}, - 1, - new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}}, - // cpu_time_per_uid - {android::util::CPU_TIME_PER_UID, - {{2, 3}, {}, 1, new CpuTimePerUidPuller()}}, - // cpu_time_per_uid_freq - {android::util::CPU_TIME_PER_UID_FREQ, - {{3}, {2}, 1, new CpuTimePerUidFreqPuller()}}, - // wifi_activity_energy_info - {android::util::WIFI_ACTIVITY_ENERGY_INFO, - {{}, - {}, - 1, - new StatsCompanionServicePuller( - android::util::WIFI_ACTIVITY_ENERGY_INFO)}}, - // modem_activity_info - {android::util::MODEM_ACTIVITY_INFO, - {{}, - {}, - 1, - new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}}, - // bluetooth_activity_info - {android::util::BLUETOOTH_ACTIVITY_INFO, - {{}, - {}, - 1, - new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}}, - // system_elapsed_realtime - {android::util::SYSTEM_ELAPSED_REALTIME, - {{}, - {}, - 1, - new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME)}}, - // system_uptime - {android::util::SYSTEM_UPTIME, - {{}, - {}, - 1, - new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}}, - // cpu_active_time - {android::util::CPU_ACTIVE_TIME, - {{3}, {2}, 1, new KernelUidCpuActiveTimeReader()}}, - // cpu_cluster_time - {android::util::CPU_CLUSTER_TIME, - {{3}, {2}, 1, new KernelUidCpuClusterTimeReader()}}, - // disk_space - {android::util::DISK_SPACE, - {{}, {}, 1, new StatsCompanionServicePuller(android::util::DISK_SPACE)}}, - // remaining_battery_capacity - {android::util::REMAINING_BATTERY_CAPACITY, - {{}, - {}, - 1, - new ResourceHealthManagerPuller( - android::util::REMAINING_BATTERY_CAPACITY)}}, - // full_battery_capacity - {android::util::FULL_BATTERY_CAPACITY, - {{}, - {}, - 1, - new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}}}; + // wifi_bytes_transfer + {android::util::WIFI_BYTES_TRANSFER, + {{2, 3, 4, 5}, + {}, + 1, + new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}}, + // wifi_bytes_transfer_by_fg_bg + {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG, + {{3, 4, 5, 6}, + {2}, + 1, + new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}}, + // mobile_bytes_transfer + {android::util::MOBILE_BYTES_TRANSFER, + {{2, 3, 4, 5}, + {}, + 1, + new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}}, + // mobile_bytes_transfer_by_fg_bg + {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG, + {{3, 4, 5, 6}, + {2}, + 1, + new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}}, + // bluetooth_bytes_transfer + {android::util::BLUETOOTH_BYTES_TRANSFER, + {{2, 3}, {}, 1, new StatsCompanionServicePuller(android::util::BLUETOOTH_BYTES_TRANSFER)}}, + // kernel_wakelock + {android::util::KERNEL_WAKELOCK, + {{}, {}, 1, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}}, + // subsystem_sleep_state + {android::util::SUBSYSTEM_SLEEP_STATE, {{}, {}, 1, new SubsystemSleepStatePuller()}}, + // cpu_time_per_freq + {android::util::CPU_TIME_PER_FREQ, + {{3}, {2}, 1, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}}, + // cpu_time_per_uid + {android::util::CPU_TIME_PER_UID, {{2, 3}, {}, 1, new CpuTimePerUidPuller()}}, + // cpu_time_per_uid_freq + {android::util::CPU_TIME_PER_UID_FREQ, {{3}, {2}, 1, new CpuTimePerUidFreqPuller()}}, + // wifi_activity_energy_info + {android::util::WIFI_ACTIVITY_ENERGY_INFO, + {{}, {}, 1, new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_ENERGY_INFO)}}, + // modem_activity_info + {android::util::MODEM_ACTIVITY_INFO, + {{}, {}, 1, new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}}, + // bluetooth_activity_info + {android::util::BLUETOOTH_ACTIVITY_INFO, + {{}, {}, 1, new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}}, + // system_elapsed_realtime + {android::util::SYSTEM_ELAPSED_REALTIME, + {{}, {}, 1, new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME)}}, + // system_uptime + {android::util::SYSTEM_UPTIME, + {{}, {}, 1, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}}, + // cpu_active_time + {android::util::CPU_ACTIVE_TIME, {{3}, {2}, 1, new KernelUidCpuActiveTimeReader()}}, + // cpu_cluster_time + {android::util::CPU_CLUSTER_TIME, {{3}, {2}, 1, new KernelUidCpuClusterTimeReader()}}, + // disk_space + {android::util::DISK_SPACE, + {{}, {}, 1, new StatsCompanionServicePuller(android::util::DISK_SPACE)}}, + // remaining_battery_capacity + {android::util::REMAINING_BATTERY_CAPACITY, + {{}, {}, 1, new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}}, + // full_battery_capacity + {android::util::FULL_BATTERY_CAPACITY, + {{}, {}, 1, new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}}}; StatsPullerManagerImpl::StatsPullerManagerImpl() : mCurrentPullingInterval(LONG_MAX) { @@ -165,14 +122,14 @@ StatsPullerManagerImpl::StatsPullerManagerImpl() } bool StatsPullerManagerImpl::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) { - if (DEBUG) ALOGD("Initiating pulling %d", tagId); + VLOG("Initiating pulling %d", tagId); if (kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end()) { - bool ret = kAllPullAtomInfo.find(tagId)->second.puller->Pull(data); - ALOGD("pulled %d items", (int)data->size()); - return ret; + bool ret = kAllPullAtomInfo.find(tagId)->second.puller->Pull(data); + VLOG("pulled %d items", (int)data->size()); + return ret; } else { - ALOGD("Unknown tagId %d", tagId); + VLOG("Unknown tagId %d", tagId); return false; // Return early since we don't know what to pull. } } @@ -183,7 +140,7 @@ StatsPullerManagerImpl& StatsPullerManagerImpl::GetInstance() { } bool StatsPullerManagerImpl::PullerForMatcherExists(int tagId) const { - return kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end(); + return kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end(); } void StatsPullerManagerImpl::RegisterReceiver(int tagId, wp<PullDataReceiver> receiver, diff --git a/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp b/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp index 550a06497b84..65a1df0eda20 100644 --- a/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp +++ b/cmds/statsd/src/external/SubsystemSleepStatePuller.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include <android/hardware/power/1.0/IPower.h> diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp index e1947c4a5fe8..01c75873fdf9 100644 --- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp +++ b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include <sstream> @@ -63,7 +63,7 @@ std::string dumpMemInfo(size_t limit) { size_t count; if (info == nullptr || overallSize == 0 || infoSize == 0 || (count = overallSize / infoSize) == 0) { - ALOGD("no malloc info, libc.debug.malloc.program property should be set"); + VLOG("no malloc info, libc.debug.malloc.program property should be set"); return std::string(); } diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp index 77f54569cb47..06c5b0049a3b 100644 --- a/cmds/statsd/src/guardrail/StatsdStats.cpp +++ b/cmds/statsd/src/guardrail/StatsdStats.cpp @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include "StatsdStats.h" diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp index c8857aa9102f..e1ab5d529370 100644 --- a/cmds/statsd/src/logd/LogEvent.cpp +++ b/cmds/statsd/src/logd/LogEvent.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "logd/LogEvent.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp index 5b5b57b61302..5a042b63c675 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.cpp +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -45,8 +45,6 @@ namespace statsd { // for StatsLogReport const int FIELD_ID_ID = 1; -const int FIELD_ID_START_REPORT_NANOS = 2; -const int FIELD_ID_END_REPORT_NANOS = 3; const int FIELD_ID_COUNT_METRICS = 5; // for CountMetricDataWrapper const int FIELD_ID_DATA = 1; @@ -97,7 +95,6 @@ void CountMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventT void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) { flushIfNeededLocked(dumpTimeNs); report->set_metric_id(mMetricId); - report->set_start_report_nanos(mStartTimeNs); auto count_metrics = report->mutable_count_metrics(); for (const auto& counter : mPastBuckets) { @@ -123,7 +120,6 @@ void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, } protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs); long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_COUNT_METRICS); VLOG("metric %lld dump report now...",(long long)mMetricId); @@ -167,7 +163,6 @@ void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, } protoOutput->end(protoToken); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs); mPastBuckets.clear(); diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp index 2400eba19de9..65cbc4afdad4 100644 --- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp +++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp @@ -44,8 +44,6 @@ namespace statsd { // for StatsLogReport const int FIELD_ID_ID = 1; -const int FIELD_ID_START_REPORT_NANOS = 2; -const int FIELD_ID_END_REPORT_NANOS = 3; const int FIELD_ID_DURATION_METRICS = 6; // for DurationMetricDataWrapper const int FIELD_ID_DATA = 1; @@ -179,7 +177,6 @@ void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet, void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) { flushIfNeededLocked(dumpTimeNs); report->set_metric_id(mMetricId); - report->set_start_report_nanos(mStartTimeNs); auto duration_metrics = report->mutable_duration_metrics(); for (const auto& pair : mPastBuckets) { @@ -205,7 +202,6 @@ void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, } protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs); long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DURATION_METRICS); VLOG("metric %lld dump report now...", (long long)mMetricId); @@ -250,7 +246,6 @@ void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, } protoOutput->end(protoToken); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs); mPastBuckets.clear(); } diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp index a021e0a4d6c8..0578e0682687 100644 --- a/cmds/statsd/src/metrics/EventMetricProducer.cpp +++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp @@ -42,8 +42,6 @@ namespace statsd { // for StatsLogReport const int FIELD_ID_ID = 1; -const int FIELD_ID_START_REPORT_NANOS = 2; -const int FIELD_ID_END_REPORT_NANOS = 3; const int FIELD_ID_EVENT_METRICS = 4; // for EventMetricDataWrapper const int FIELD_ID_DATA = 1; @@ -106,8 +104,6 @@ void EventMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, return; } protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs); size_t bufferSize = mProto->size(); VLOG("metric %lld dump report now... proto size: %zu ", diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index 4190f0048cc2..62ee6ef17d5c 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -45,8 +45,6 @@ namespace statsd { // for StatsLogReport const int FIELD_ID_ID = 1; -const int FIELD_ID_START_REPORT_NANOS = 2; -const int FIELD_ID_END_REPORT_NANOS = 3; const int FIELD_ID_GAUGE_METRICS = 8; // for GaugeMetricDataWrapper const int FIELD_ID_DATA = 1; @@ -134,7 +132,6 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, } protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs); long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_GAUGE_METRICS); for (const auto& pair : mPastBuckets) { @@ -188,7 +185,6 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, protoOutput->end(wrapperToken); } protoOutput->end(protoToken); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs); mPastBuckets.clear(); // TODO: Clear mDimensionKeyMap once the report is dumped. diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index 6573a898c55d..6c21b052e807 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include "MetricsManager.h" #include "statslog.h" @@ -29,6 +29,7 @@ #include <log/logprint.h> #include <private/android_filesystem_config.h> +#include <utils/SystemClock.h> using android::util::FIELD_COUNT_REPEATED; using android::util::FIELD_TYPE_MESSAGE; @@ -48,7 +49,7 @@ const int FIELD_ID_METRICS = 1; MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config, const long timeBaseSec, sp<UidMap> uidMap) - : mConfigKey(key), mUidMap(uidMap) { + : mConfigKey(key), mUidMap(uidMap), mLastReportTimeNs(0) { mConfigValid = initStatsdConfig(key, config, *uidMap, timeBaseSec, mTagIds, mAllAtomMatchers, mAllConditionTrackers, mAllMetricProducers, mAllAnomalyTrackers, mConditionToMetricMap, @@ -184,6 +185,7 @@ void MetricsManager::onDumpReport(ProtoOutputStream* protoOutput) { protoOutput->end(token); } } + mLastReportTimeNs = ::android::elapsedRealtimeNano(); VLOG("=========================Metric Reports End=========================="); } diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 9cae70a9de80..2b30f44d345a 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -64,6 +64,11 @@ public: void dumpStates(FILE* out, bool verbose); + // Returns the elapsed realtime when this metric manager last reported metrics. + uint64_t getLastReportTimeNs() { + return mLastReportTimeNs; + }; + // Config source owner can call onDumpReport() to get all the metrics collected. virtual void onDumpReport(android::util::ProtoOutputStream* protoOutput); virtual void onDumpReport(const uint64_t& dumpTimeStampNs, ConfigMetricsReport* report); @@ -78,6 +83,8 @@ private: bool mConfigValid = false; + uint64_t mLastReportTimeNs; + // The uid log sources from StatsdConfig. std::vector<int32_t> mAllowedUid; diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index 31d9ff8455c8..7b1944c595e5 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -48,8 +48,6 @@ namespace statsd { // for StatsLogReport const int FIELD_ID_ID = 1; -const int FIELD_ID_START_REPORT_NANOS = 2; -const int FIELD_ID_END_REPORT_NANOS = 3; const int FIELD_ID_VALUE_METRICS = 7; // for ValueMetricDataWrapper const int FIELD_ID_DATA = 1; @@ -122,7 +120,6 @@ void ValueMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventT void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, StatsLogReport* report) { flushIfNeededLocked(dumpTimeNs); report->set_metric_id(mMetricId); - report->set_start_report_nanos(mStartTimeNs); auto value_metrics = report->mutable_value_metrics(); for (const auto& pair : mPastBuckets) { ValueMetricData* metricData = value_metrics->add_data(); @@ -147,7 +144,6 @@ void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, return; } protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs); long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_VALUE_METRICS); for (const auto& pair : mPastBuckets) { @@ -186,7 +182,6 @@ void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs, protoOutput->end(wrapperToken); } protoOutput->end(protoToken); - protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs); VLOG("metric %lld dump report now...", (long long)mMetricId); mPastBuckets.clear(); diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp index a0173ee9922f..205c8e4b22cd 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include "../condition/CombinationConditionTracker.h" @@ -541,7 +541,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, ALOGE("initLogMatchingTrackers failed"); return false; } - ALOGD("initLogMatchingTrackers succeed..."); + VLOG("initLogMatchingTrackers succeed..."); if (!initConditions(key, config, logTrackerMap, conditionTrackerMap, allConditionTrackers, trackerToConditionMap)) { diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp index 691423e054b2..0d7b722c40bc 100644 --- a/cmds/statsd/src/packages/UidMap.cpp +++ b/cmds/statsd/src/packages/UidMap.cpp @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include "guardrail/StatsdStats.h" diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index af21ca4d82e8..b56cffb40806 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -143,9 +143,7 @@ message UidMapping { message StatsLogReport { optional int64 metric_id = 1; - optional int64 start_report_nanos = 2; - - optional int64 end_report_nanos = 3; + // Fields 2 and 3 are reserved. message EventMetricDataWrapper { repeated EventMetricData data = 1; @@ -177,6 +175,10 @@ message ConfigMetricsReport { repeated StatsLogReport metrics = 1; optional UidMapping uid_map = 2; + + optional int64 last_report_nanos = 3; + + optional int64 current_report_nanos = 4; } message ConfigMetricsReportList { diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp index 00d86582951f..23bd55616be2 100644 --- a/cmds/statsd/src/storage/StorageManager.cpp +++ b/cmds/statsd/src/storage/StorageManager.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define DEBUG true // STOPSHIP if true +#define DEBUG false // STOPSHIP if true #include "Log.h" #include "android-base/stringprintf.h" diff --git a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java index 33c8abf03462..03e5fef5d717 100644 --- a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java +++ b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java @@ -32,11 +32,13 @@ public class DisplayProtoUtils { for (StatsLog.ConfigMetricsReport report : reports.getReportsList()) { sb.append("StatsLogReport size: ").append(report.getMetricsCount()).append("\n"); + sb.append("Last report time:").append(getDateStr(report.getLastReportNanos())). + append("\n"); + sb.append("Current report time:").append(getDateStr(report.getCurrentReportNanos())). + append("\n"); for (StatsLog.StatsLogReport log : report.getMetricsList()) { sb.append("\n\n"); sb.append("metric id: ").append(log.getMetricId()).append("\n"); - sb.append("start time:").append(getDateStr(log.getStartReportNanos())).append("\n"); - sb.append("end time:").append(getDateStr(log.getEndReportNanos())).append("\n"); switch (log.getDataCase()) { case DURATION_METRICS: diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java index 75489ade6432..87b82c261bf1 100644 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java +++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java @@ -36,6 +36,10 @@ public class DisplayProtoUtils { int numMetrics = 0; for (StatsLog.ConfigMetricsReport report : reports.getReportsList()) { sb.append("StatsLogReport size: ").append(report.getMetricsCount()).append("\n"); + sb.append("Last report time:").append(getDateStr(report.getLastReportNanos())). + append("\n"); + sb.append("Current report time:").append(getDateStr(report.getCurrentReportNanos())). + append("\n"); for (StatsLog.StatsLogReport log : report.getMetricsList()) { numMetrics++; if (numMetrics > MAX_NUM_METRICS_TO_DISPLAY) { @@ -45,8 +49,6 @@ public class DisplayProtoUtils { } sb.append("\n"); sb.append("metric id: ").append(log.getMetricId()).append("\n"); - sb.append("start time:").append(getDateStr(log.getStartReportNanos())).append("\n"); - sb.append("end time:").append(getDateStr(log.getEndReportNanos())).append("\n"); switch (log.getDataCase()) { case DURATION_METRICS: diff --git a/config/hiddenapi-blacklist.txt b/config/hiddenapi-blacklist.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/config/hiddenapi-blacklist.txt diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt index 54e971fc5ee9..71de479b5530 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-light-greylist.txt @@ -7,15 +7,18 @@ Landroid/app/Activity;->convertToTranslucent(Landroid/app/Activity$TranslucentCo Landroid/app/Activity;->getActivityOptions()Landroid/app/ActivityOptions; Landroid/app/Activity;->getActivityToken()Landroid/os/IBinder; Landroid/app/Activity;->mActivityInfo:Landroid/content/pm/ActivityInfo; +Landroid/app/ActivityManager;->addOnUidImportanceListener(Landroid/app/ActivityManager$OnUidImportanceListener;I)V Landroid/app/ActivityManager;->clearApplicationUserData(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)Z Landroid/app/ActivityManager;->forceStopPackage(Ljava/lang/String;)V Landroid/app/ActivityManager;->getCurrentUser()I +Landroid/app/ActivityManager;->getPackageImportance(Ljava/lang/String;)I Landroid/app/ActivityManager;->isLowRamDeviceStatic()Z Landroid/app/ActivityManager;->isUserRunning(I)Z Landroid/app/ActivityManager;->mContext:Landroid/content/Context; Landroid/app/ActivityManagerNative;->getDefault()Landroid/app/IActivityManager; Landroid/app/ActivityManager;->PROCESS_STATE_TOP:I Landroid/app/ActivityManager$RecentTaskInfo;->firstActiveTime:J +Landroid/app/ActivityManager;->removeOnUidImportanceListener(Landroid/app/ActivityManager$OnUidImportanceListener;)V Landroid/app/ActivityManager$RunningAppProcessInfo;->flags:I Landroid/app/ActivityManager$RunningAppProcessInfo;->processState:I Landroid/app/Activity;->mApplication:Landroid/app/Application; @@ -43,7 +46,6 @@ Landroid/app/ActivityThread$H;->BIND_SERVICE:I Landroid/app/ActivityThread$H;->CREATE_SERVICE:I Landroid/app/ActivityThread$H;->EXIT_APPLICATION:I Landroid/app/ActivityThread$H;->RECEIVER:I -Landroid/app/ActivityThread$H;->RELAUNCH_ACTIVITY:I Landroid/app/ActivityThread$H;->REMOVE_PROVIDER:I Landroid/app/ActivityThread$H;->SERVICE_ARGS:I Landroid/app/ActivityThread$H;->STOP_SERVICE:I @@ -58,6 +60,9 @@ Landroid/app/ActivityThread;->mNumVisibleActivities:I Landroid/app/ActivityThread;->mPackages:Landroid/util/ArrayMap; Landroid/app/ActivityThread;->performStopActivity(Landroid/os/IBinder;ZLjava/lang/String;)V Landroid/app/ActivityThread;->sPackageManager:Landroid/content/pm/IPackageManager; +Landroid/app/admin/DevicePolicyManager;->getDeviceOwnerComponentOnAnyUser()Landroid/content/ComponentName; +Landroid/app/admin/DevicePolicyManager;->getDeviceOwner()Ljava/lang/String; +Landroid/app/admin/DevicePolicyManager;->getProfileOwner()Landroid/content/ComponentName; Landroid/app/admin/DevicePolicyManager;->getTrustAgentConfiguration(Landroid/content/ComponentName;Landroid/content/ComponentName;I)Ljava/util/List; Landroid/app/admin/DevicePolicyManager;->notifyPendingSystemUpdate(J)V Landroid/app/admin/DevicePolicyManager;->notifyPendingSystemUpdate(JZ)V @@ -69,6 +74,8 @@ Landroid/app/AlarmManager;->FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED:I Landroid/app/AlarmManager;->FLAG_IDLE_UNTIL:I Landroid/app/AlarmManager;->FLAG_STANDALONE:I Landroid/app/AlarmManager;->FLAG_WAKE_FROM_IDLE:I +Landroid/app/AlarmManager;->set(IJJJLandroid/app/AlarmManager$OnAlarmListener;Landroid/os/Handler;Landroid/os/WorkSource;)V +Landroid/app/AlarmManager;->set(IJJJLandroid/app/PendingIntent;Landroid/os/WorkSource;)V Landroid/app/AlarmManager;->WINDOW_EXACT:J Landroid/app/AlarmManager;->WINDOW_HEURISTIC:J Landroid/app/AlertDialog$Builder;->P:Lcom/android/internal/app/AlertController$AlertParams; @@ -92,9 +99,32 @@ Landroid/app/AppOpsManager;->OP_WIFI_SCAN:I Landroid/app/AppOpsManager;->OP_WRITE_SMS:I Landroid/app/AppOpsManager;->setMode(IILjava/lang/String;I)V Landroid/app/AppOpsManager;->strOpToOp(Ljava/lang/String;)I +Landroid/app/backup/BackupDataInput;-><init>(Ljava/io/FileDescriptor;)V Landroid/app/backup/BackupDataInputStream;->dataSize:I Landroid/app/backup/BackupDataInputStream;->key:Ljava/lang/String; +Landroid/app/backup/BackupDataOutput;-><init>(Ljava/io/FileDescriptor;)V +Landroid/app/backup/BackupManager;->backupNow()V +Landroid/app/backup/BackupManager;->beginRestoreSession()Landroid/app/backup/RestoreSession; +Landroid/app/backup/BackupManager;->cancelBackups()V +Landroid/app/backup/BackupManager;->getAvailableRestoreToken(Ljava/lang/String;)J +Landroid/app/backup/BackupManager;->getCurrentTransport()Ljava/lang/String; +Landroid/app/backup/BackupManager;->isBackupEnabled()Z +Landroid/app/backup/BackupManager;->listAllTransports()[Ljava/lang/String; +Landroid/app/backup/BackupManagerMonitor;-><init>()V +Landroid/app/backup/BackupManager;->requestBackup([Ljava/lang/String;Landroid/app/backup/BackupObserver;Landroid/app/backup/BackupManagerMonitor;I)I +Landroid/app/backup/BackupManager;->selectBackupTransport(Landroid/content/ComponentName;Landroid/app/backup/SelectBackupTransportCallback;)V +Landroid/app/backup/BackupManager;->selectBackupTransport(Ljava/lang/String;)Ljava/lang/String; +Landroid/app/backup/BackupManager;->setAutoRestore(Z)V +Landroid/app/backup/BackupManager;->setBackupEnabled(Z)V +Landroid/app/backup/BackupObserver;-><init>()V +Landroid/app/backup/BackupTransport;-><init>()V Landroid/app/backup/FullBackup;->backupToTar(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/backup/FullBackupDataOutput;)I +Landroid/app/backup/RestoreDescription;-><init>(Ljava/lang/String;I)V +Landroid/app/backup/RestoreSession;->endRestoreSession()V +Landroid/app/backup/RestoreSession;->getAvailableRestoreSets(Landroid/app/backup/RestoreObserver;)I +Landroid/app/backup/RestoreSession;->restoreAll(JLandroid/app/backup/RestoreObserver;)I +Landroid/app/backup/RestoreSet;-><init>(Ljava/lang/String;Ljava/lang/String;J)V +Landroid/app/backup/SelectBackupTransportCallback;-><init>()V Landroid/app/ContextImpl;->createActivityContext(Landroid/app/ActivityThread;Landroid/app/LoadedApk;Landroid/content/pm/ActivityInfo;Landroid/os/IBinder;ILandroid/content/res/Configuration;)Landroid/app/ContextImpl; Landroid/app/ContextImpl;->getActivityToken()Landroid/os/IBinder; Landroid/app/ContextImpl;->mMainThread:Landroid/app/ActivityThread; @@ -113,6 +143,8 @@ Landroid/app/IActivityManager;->forceStopPackage(Ljava/lang/String;I)V Landroid/app/IActivityManager;->getLaunchedFromPackage(Landroid/os/IBinder;)Ljava/lang/String; Landroid/app/IActivityManager;->resumeAppSwitches()V Landroid/app/IApplicationThread;->scheduleTrimMemory(I)V +Landroid/app/InstantAppResolverService;-><init>()V +Landroid/app/InstantAppResolverService$InstantAppResolutionCallback;->onInstantAppResolveInfo(Ljava/util/List;)V Landroid/app/IntentService;->mServiceHandler:Landroid/app/IntentService$ServiceHandler; Landroid/app/IWallpaperManager;->getWallpaper(Ljava/lang/String;Landroid/app/IWallpaperManagerCallback;ILandroid/os/Bundle;I)Landroid/os/ParcelFileDescriptor; Landroid/app/LoadedApk;->mApplication:Landroid/app/Application; @@ -139,6 +171,9 @@ Landroid/app/StatusBarManager;->expandNotificationsPanel()V Landroid/app/StatusBarManager;->expandSettingsPanel(Ljava/lang/String;)V Landroid/app/StatusBarManager;->expandSettingsPanel()V Landroid/app/TimePickerDialog;->mTimePicker:Landroid/widget/TimePicker; +Landroid/app/usage/UsageStatsManager;->getAppStandbyBuckets()Ljava/util/Map; +Landroid/app/usage/UsageStatsManager;->setAppStandbyBuckets(Ljava/util/Map;)V +Landroid/app/usage/UsageStatsManager;->whitelistAppTemporarily(Ljava/lang/String;JLandroid/os/UserHandle;)V Landroid/app/WallpaperColors;->getColorHints()I Landroid/app/WallpaperManager;->getBitmap()Landroid/graphics/Bitmap; Landroid/app/WallpaperManager;->getBitmap(Z)Landroid/graphics/Bitmap; @@ -150,9 +185,13 @@ Landroid/appwidget/AppWidgetManager;->bindAppWidgetIdIfAllowed(IILandroid/conten Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;Landroid/os/Bundle;)V Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;)V Landroid/bluetooth/BluetoothA2dp;->connect(Landroid/bluetooth/BluetoothDevice;)Z +Landroid/bluetooth/BluetoothAdapter;->disableBLE()Z Landroid/bluetooth/BluetoothAdapter;->disable(Z)Z +Landroid/bluetooth/BluetoothAdapter;->enableBLE()Z Landroid/bluetooth/BluetoothAdapter;->enableNoAutoConnect()Z Landroid/bluetooth/BluetoothAdapter;->getDiscoverableTimeout()I +Landroid/bluetooth/BluetoothAdapter;->isBleScanAlwaysAvailable()Z +Landroid/bluetooth/BluetoothAdapter;->isLeEnabled()Z Landroid/bluetooth/BluetoothAdapter;->setScanMode(II)Z Landroid/bluetooth/BluetoothAdapter;->setScanMode(I)Z Landroid/bluetooth/BluetoothDevice;->cancelBondProcess()Z @@ -171,6 +210,8 @@ Landroid/bluetooth/BluetoothHeadset;->close()V Landroid/bluetooth/BluetoothHeadset;->setPriority(Landroid/bluetooth/BluetoothDevice;I)Z Landroid/bluetooth/BluetoothUuid;->RESERVED_UUIDS:[Landroid/os/ParcelUuid; Landroid/bluetooth/IBluetooth$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetooth; +Landroid/bluetooth/le/BluetoothLeScanner;->startScanFromSource(Ljava/util/List;Landroid/bluetooth/le/ScanSettings;Landroid/os/WorkSource;Landroid/bluetooth/le/ScanCallback;)V +Landroid/bluetooth/le/ScanSettings$Builder;->setScanResultType(I)Landroid/bluetooth/le/ScanSettings$Builder; Landroid/content/AsyncTaskLoader;->mExecutor:Ljava/util/concurrent/Executor; Landroid/content/ContentProviderOperation;->mSelection:Ljava/lang/String; Landroid/content/ContentProviderOperation;->mType:I @@ -178,13 +219,17 @@ Landroid/content/ContentResolver;->getContentService()Landroid/content/IContentS Landroid/content/ContentResolver;->getSyncStatus(Landroid/accounts/Account;Ljava/lang/String;)Landroid/content/SyncStatusInfo; Landroid/content/ContentResolver;->mContext:Landroid/content/Context; Landroid/content/ContentValues;->mValues:Ljava/util/HashMap; +Landroid/content/Context;->bindServiceAsUser(Landroid/content/Intent;Landroid/content/ServiceConnection;ILandroid/os/UserHandle;)Z +Landroid/content/Context;->createCredentialProtectedStorageContext()Landroid/content/Context; Landroid/content/Context;->createPackageContextAsUser(Ljava/lang/String;ILandroid/os/UserHandle;)Landroid/content/Context; Landroid/content/Context;->getSharedPrefsFile(Ljava/lang/String;)Ljava/io/File; Landroid/content/Context;->getThemeResId()I +Landroid/content/Context;->isCredentialProtectedStorage()Z Landroid/content/Context;->sendBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;I)V Landroid/content/Context;->sendBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;Landroid/os/Bundle;)V Landroid/content/Context;->sendOrderedBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;ILandroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V Landroid/content/Context;->sendOrderedBroadcastAsUser(Landroid/content/Intent;Landroid/os/UserHandle;Ljava/lang/String;ILandroid/os/Bundle;Landroid/content/BroadcastReceiver;Landroid/os/Handler;ILjava/lang/String;Landroid/os/Bundle;)V +Landroid/content/ContextWrapper;->createCredentialProtectedStorageContext()Landroid/content/Context; Landroid/content/ContextWrapper;->mBase:Landroid/content/Context; Landroid/content/CursorLoader;->mCancellationSignal:Landroid/os/CancellationSignal; Landroid/content/CursorLoader;->mObserver:Landroid/content/Loader$ForceLoadContentObserver; @@ -192,6 +237,7 @@ Landroid/content/IContentService;->cancelSync(Landroid/accounts/Account;Ljava/la Landroid/content/IContentService;->getMasterSyncAutomatically()Z Landroid/content/IContentService;->setMasterSyncAutomatically(Z)V Landroid/content/Intent;->ACTION_ALARM_CHANGED:Ljava/lang/String; +Landroid/content/IntentFilter;->setOrder(I)V Landroid/content/Intent;->putExtra(Ljava/lang/String;Landroid/os/IBinder;)Landroid/content/Intent; Landroid/content/pm/ApplicationInfo;->installLocation:I Landroid/content/pm/ApplicationInfo;->isForwardLocked()Z @@ -200,12 +246,19 @@ Landroid/content/pm/ApplicationInfo;->isPrivilegedApp()Z Landroid/content/pm/ApplicationInfo;->primaryCpuAbi:Ljava/lang/String; Landroid/content/pm/ApplicationInfo;->privateFlags:I Landroid/content/pm/ApplicationInfo;->targetSandboxVersion:I +Landroid/content/pm/InstantAppIntentFilter;-><init>(Ljava/lang/String;Ljava/util/List;)V +Landroid/content/pm/InstantAppResolveInfo;->getPackageName()Ljava/lang/String; +Landroid/content/pm/InstantAppResolveInfo;-><init>(Landroid/content/pm/InstantAppResolveInfo$InstantAppDigest;Ljava/lang/String;Ljava/util/List;I)V +Landroid/content/pm/InstantAppResolveInfo$InstantAppDigest;->getDigestPrefix()[I +Landroid/content/pm/InstantAppResolveInfo$InstantAppDigest;-><init>(Ljava/lang/String;)V Landroid/content/pm/IPackageManager;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo; Landroid/content/pm/IPackageManager;->setLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;ILandroid/content/IntentFilter;ILandroid/content/ComponentName;)V +Landroid/content/pm/IPackageStatsObserver$Stub;-><init>()V Landroid/content/pm/LauncherApps;->mPm:Landroid/content/pm/PackageManager; Landroid/content/pm/LauncherApps;->startShortcut(Ljava/lang/String;Ljava/lang/String;Landroid/graphics/Rect;Landroid/os/Bundle;I)V Landroid/content/pm/PackageInstaller$SessionParams;->setGrantedRuntimePermissions([Ljava/lang/String;)V Landroid/content/pm/PackageInstaller$SessionParams;->setInstallAsInstantApp(Z)V +Landroid/content/pm/PackageManager;->addOnPermissionsChangeListener(Landroid/content/pm/PackageManager$OnPermissionsChangedListener;)V Landroid/content/pm/PackageManager;->freeStorageAndNotify(JLandroid/content/pm/IPackageDataObserver;)V Landroid/content/pm/PackageManager;->freeStorageAndNotify(Ljava/lang/String;JLandroid/content/pm/IPackageDataObserver;)V Landroid/content/pm/PackageManager;->freeStorage(JLandroid/content/IntentSender;)V @@ -217,6 +270,8 @@ Landroid/content/pm/PackageManager;->getPackageSizeInfo(Ljava/lang/String;Landro Landroid/content/pm/PackageManager;->getResourcesForApplicationAsUser(Ljava/lang/String;I)Landroid/content/res/Resources; Landroid/content/pm/PackageManager;->movePackage(Ljava/lang/String;Landroid/os/storage/VolumeInfo;)I Landroid/content/pm/PackageManager;->queryBroadcastReceivers(Landroid/content/Intent;II)Ljava/util/List; +Landroid/content/pm/PackageManager;->removeOnPermissionsChangeListener(Landroid/content/pm/PackageManager$OnPermissionsChangedListener;)V +Landroid/content/pm/PackageManager;->verifyIntentFilter(IILjava/util/List;)V Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Ljava/io/File;Z)V Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Z)V Landroid/content/pm/PackageParser;->generatePackageInfo(Landroid/content/pm/PackageParser$Package;[IIJJLjava/util/Set;Landroid/content/pm/PackageUserState;I)Landroid/content/pm/PackageInfo; @@ -306,18 +361,64 @@ Landroid/graphics/Typeface;->setDefault(Landroid/graphics/Typeface;)V Landroid/graphics/Typeface;->sSystemFontMap:Ljava/util/Map; Landroid/hardware/Camera;->addCallbackBuffer([BI)V Landroid/hardware/Camera;->openLegacy(II)Landroid/hardware/Camera; +Landroid/hardware/display/DisplayManager;->getStableDisplaySize()Landroid/graphics/Point; Landroid/hardware/display/WifiDisplayStatus;->mActiveDisplay:Landroid/hardware/display/WifiDisplay; Landroid/hardware/display/WifiDisplayStatus;->mDisplays:[Landroid/hardware/display/WifiDisplay; Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager; Landroid/hardware/input/InputManager;->getInstance()Landroid/hardware/input/InputManager; Landroid/hardware/input/InputManager;->mIm:Landroid/hardware/input/IInputManager; +Landroid/hardware/location/ContextHubInfo;->getId()I +Landroid/hardware/location/ContextHubInfo;->getMaxPacketLengthBytes()I +Landroid/hardware/location/ContextHubManager$Callback;-><init>()V +Landroid/hardware/location/ContextHubManager;->findNanoAppOnHub(ILandroid/hardware/location/NanoAppFilter;)[I +Landroid/hardware/location/ContextHubManager;->getContextHubHandles()[I +Landroid/hardware/location/ContextHubManager;->getContextHubInfo(I)Landroid/hardware/location/ContextHubInfo; +Landroid/hardware/location/ContextHubManager;->getNanoAppInstanceInfo(I)Landroid/hardware/location/NanoAppInstanceInfo; +Landroid/hardware/location/ContextHubManager;->loadNanoApp(ILandroid/hardware/location/NanoApp;)I +Landroid/hardware/location/ContextHubManager;->registerCallback(Landroid/hardware/location/ContextHubManager$Callback;)I +Landroid/hardware/location/ContextHubManager;->sendMessage(IILandroid/hardware/location/ContextHubMessage;)I +Landroid/hardware/location/ContextHubManager;->unloadNanoApp(I)I +Landroid/hardware/location/ContextHubMessage;->getData()[B +Landroid/hardware/location/ContextHubMessage;->getMsgType()I +Landroid/hardware/location/ContextHubMessage;->getVersion()I +Landroid/hardware/location/ContextHubMessage;-><init>(II[B)V +Landroid/hardware/location/GeofenceHardware;->addGeofence(IILandroid/hardware/location/GeofenceHardwareRequest;Landroid/hardware/location/GeofenceHardwareCallback;)Z +Landroid/hardware/location/GeofenceHardwareCallback;-><init>()V +Landroid/hardware/location/GeofenceHardwareCallback;->onGeofenceAdd(II)V +Landroid/hardware/location/GeofenceHardwareCallback;->onGeofenceRemove(II)V +Landroid/hardware/location/GeofenceHardwareCallback;->onGeofenceTransition(IILandroid/location/Location;JI)V +Landroid/hardware/location/GeofenceHardware;->getMonitoringTypes()[I +Landroid/hardware/location/GeofenceHardware;->getStatusOfMonitoringType(I)I +Landroid/hardware/location/GeofenceHardwareMonitorCallback;-><init>()V +Landroid/hardware/location/GeofenceHardwareMonitorCallback;->onMonitoringSystemChange(IZLandroid/location/Location;)V +Landroid/hardware/location/GeofenceHardware;->registerForMonitorStateChangeCallback(ILandroid/hardware/location/GeofenceHardwareMonitorCallback;)Z +Landroid/hardware/location/GeofenceHardware;->removeGeofence(II)Z +Landroid/hardware/location/GeofenceHardwareRequest;->createCircularGeofence(DDD)Landroid/hardware/location/GeofenceHardwareRequest; +Landroid/hardware/location/GeofenceHardwareRequest;->setLastTransition(I)V +Landroid/hardware/location/GeofenceHardwareRequest;->setMonitorTransitions(I)V +Landroid/hardware/location/GeofenceHardwareRequest;->setNotificationResponsiveness(I)V +Landroid/hardware/location/GeofenceHardwareRequest;->setUnknownTimer(I)V +Landroid/hardware/location/NanoAppFilter;-><init>(JIIJ)V +Landroid/hardware/location/NanoApp;-><init>(J[B)V +Landroid/hardware/location/NanoAppInstanceInfo;->getAppId()J +Landroid/hardware/location/NanoAppInstanceInfo;->getAppVersion()I +Landroid/hardware/location/NanoAppInstanceInfo;->getHandle()I +Landroid/hardware/location/NanoAppInstanceInfo;->getName()Ljava/lang/String; Landroid/hardware/usb/UsbManager;->setCurrentFunction(Ljava/lang/String;Z)V +Landroid/location/GeocoderParams;->getClientPackage()Ljava/lang/String; +Landroid/location/GeocoderParams;->getLocale()Ljava/util/Locale; +Landroid/location/LocationManager;->requestLocationUpdates(Landroid/location/LocationRequest;Landroid/location/LocationListener;Landroid/os/Looper;)V Landroid/location/LocationRequest;->createFromDeprecatedProvider(Ljava/lang/String;JFZ)Landroid/location/LocationRequest; +Landroid/location/LocationRequest;->setHideFromAppOps(Z)V Landroid/location/LocationRequest;->setWorkSource(Landroid/os/WorkSource;)V Landroid/location/Location;->setIsFromMockProvider(Z)V Landroid/media/AudioAttributes$Builder;->setInternalCapturePreset(I)Landroid/media/AudioAttributes$Builder; +Landroid/media/AudioFocusInfo;->getClientId()Ljava/lang/String; +Landroid/media/AudioFocusInfo;->getClientUid()I +Landroid/media/AudioFocusInfo;->getLossReceived()I Landroid/media/AudioManager;->abandonAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;)I Landroid/media/AudioManager;->mAudioFocusIdListenerMap:Ljava/util/concurrent/ConcurrentHashMap; +Landroid/media/AudioManager;->registerAudioPolicy(Landroid/media/audiopolicy/AudioPolicy;)I Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioFocusRequest;Landroid/media/audiopolicy/AudioPolicy;)I Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;II)I Landroid/media/AudioManager;->requestAudioFocus(Landroid/media/AudioManager$OnAudioFocusChangeListener;Landroid/media/AudioAttributes;IILandroid/media/audiopolicy/AudioPolicy;)I @@ -325,6 +426,21 @@ Landroid/media/AudioManager;->setMasterMute(ZI)V Landroid/media/AudioManager;->STREAM_BLUETOOTH_SCO:I Landroid/media/AudioManager;->STREAM_SYSTEM_ENFORCED:I Landroid/media/AudioManager;->STREAM_TTS:I +Landroid/media/AudioManager;->unregisterAudioPolicyAsync(Landroid/media/audiopolicy/AudioPolicy;)V +Landroid/media/audiopolicy/AudioMix$Builder;->build()Landroid/media/audiopolicy/AudioMix; +Landroid/media/audiopolicy/AudioMix$Builder;-><init>(Landroid/media/audiopolicy/AudioMixingRule;)V +Landroid/media/audiopolicy/AudioMix$Builder;->setFormat(Landroid/media/AudioFormat;)Landroid/media/audiopolicy/AudioMix$Builder; +Landroid/media/audiopolicy/AudioMix$Builder;->setRouteFlags(I)Landroid/media/audiopolicy/AudioMix$Builder; +Landroid/media/audiopolicy/AudioMixingRule$Builder;->addRule(Landroid/media/AudioAttributes;I)Landroid/media/audiopolicy/AudioMixingRule$Builder; +Landroid/media/audiopolicy/AudioMixingRule$Builder;->build()Landroid/media/audiopolicy/AudioMixingRule; +Landroid/media/audiopolicy/AudioMixingRule$Builder;-><init>()V +Landroid/media/audiopolicy/AudioPolicy$AudioPolicyFocusListener;-><init>()V +Landroid/media/audiopolicy/AudioPolicy$Builder;->addMix(Landroid/media/audiopolicy/AudioMix;)Landroid/media/audiopolicy/AudioPolicy$Builder; +Landroid/media/audiopolicy/AudioPolicy$Builder;->build()Landroid/media/audiopolicy/AudioPolicy; +Landroid/media/audiopolicy/AudioPolicy$Builder;-><init>(Landroid/content/Context;)V +Landroid/media/audiopolicy/AudioPolicy$Builder;->setAudioPolicyFocusListener(Landroid/media/audiopolicy/AudioPolicy$AudioPolicyFocusListener;)V +Landroid/media/audiopolicy/AudioPolicy$Builder;->setLooper(Landroid/os/Looper;)Landroid/media/audiopolicy/AudioPolicy$Builder; +Landroid/media/audiopolicy/AudioPolicy;->createAudioRecordSink(Landroid/media/audiopolicy/AudioMix;)Landroid/media/AudioRecord; Landroid/media/AudioSystem;->setDeviceConnectionState(IILjava/lang/String;Ljava/lang/String;)I Landroid/media/AudioTrack;->getLatency()I Landroid/media/IAudioService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IAudioService; @@ -354,6 +470,19 @@ Landroid/media/Ringtone;->setLooping(Z)V Landroid/media/Ringtone;->setVolume(F)V Landroid/media/SubtitleController;->mHandler:Landroid/os/Handler; Landroid/media/ThumbnailUtils;->createImageThumbnail(Ljava/lang/String;I)Landroid/graphics/Bitmap; +Landroid/metrics/LogMaker;->getCategory()I +Landroid/metrics/LogMaker;->getCounterBucket()J +Landroid/metrics/LogMaker;->getCounterName()Ljava/lang/String; +Landroid/metrics/LogMaker;->getCounterValue()I +Landroid/metrics/LogMaker;->getTimestamp()J +Landroid/metrics/LogMaker;->isLongCounterBucket()Z +Landroid/metrics/LogMaker;->serialize()[Ljava/lang/Object; +Landroid/metrics/MetricsReader;->checkpoint()V +Landroid/metrics/MetricsReader;->hasNext()Z +Landroid/metrics/MetricsReader;-><init>()V +Landroid/metrics/MetricsReader;->next()Landroid/metrics/LogMaker; +Landroid/metrics/MetricsReader;->read(J)V +Landroid/metrics/MetricsReader;->reset()V Landroid/net/ConnectivityManager;->ACTION_TETHER_STATE_CHANGED:Ljava/lang/String; Landroid/net/ConnectivityManager;->EXTRA_ACTIVE_TETHER:Ljava/lang/String; Landroid/net/ConnectivityManager;->getActiveLinkProperties()Landroid/net/LinkProperties; @@ -366,11 +495,20 @@ Landroid/net/ConnectivityManager;->isNetworkSupported(I)Z Landroid/net/ConnectivityManager;->isNetworkTypeMobile(I)Z Landroid/net/ConnectivityManager;->isTetheringSupported()Z Landroid/net/ConnectivityManager;->mService:Landroid/net/IConnectivityManager; +Landroid/net/ConnectivityManager$OnStartTetheringCallback;-><init>()V Landroid/net/ConnectivityManager;->requestRouteToHostAddress(ILjava/net/InetAddress;)Z Landroid/net/ConnectivityManager;->requestRouteToHost(II)Z +Landroid/net/ConnectivityManager;->startTethering(IZLandroid/net/ConnectivityManager$OnStartTetheringCallback;Landroid/os/Handler;)V +Landroid/net/ConnectivityManager;->startTethering(IZLandroid/net/ConnectivityManager$OnStartTetheringCallback;)V +Landroid/net/ConnectivityManager;->stopTethering(I)V Landroid/net/INetworkStatsService$Stub$Proxy;->getMobileIfaces()[Ljava/lang/String; Landroid/net/LinkProperties;->setHttpProxy(Landroid/net/ProxyInfo;)V +Landroid/net/NetworkKey;-><init>(Landroid/net/WifiKey;)V Landroid/net/NetworkPolicyManager;->mService:Landroid/net/INetworkPolicyManager; +Landroid/net/NetworkRecommendationProvider;-><init>(Landroid/content/Context;Ljava/util/concurrent/Executor;)V +Landroid/net/NetworkScoreManager;->clearScores()Z +Landroid/net/NetworkScoreManager;->getActiveScorerPackage()Ljava/lang/String; +Landroid/net/NetworkScoreManager;->updateScores([Landroid/net/ScoredNetwork;)Z Landroid/net/NetworkStats;->capacity:I Landroid/net/NetworkStats;->defaultNetwork:[I Landroid/net/NetworkStats;->iface:[Ljava/lang/String; @@ -385,37 +523,90 @@ Landroid/net/NetworkStats;->tag:[I Landroid/net/NetworkStats;->txBytes:[J Landroid/net/NetworkStats;->txPackets:[J Landroid/net/NetworkStats;->uid:[I +Landroid/net/RssiCurve;-><init>(II[BI)V +Landroid/net/RssiCurve;-><init>(II[B)V +Landroid/net/RssiCurve;->lookupScore(IZ)B +Landroid/net/ScoredNetwork;-><init>(Landroid/net/NetworkKey;Landroid/net/RssiCurve;)V +Landroid/net/ScoredNetwork;-><init>(Landroid/net/NetworkKey;Landroid/net/RssiCurve;ZLandroid/os/Bundle;)V +Landroid/net/ScoredNetwork;-><init>(Landroid/net/NetworkKey;Landroid/net/RssiCurve;Z)V +Landroid/net/SSLCertificateSocketFactory;->castToOpenSSLSocket(Ljava/net/Socket;)Lcom/android/org/conscrypt/OpenSSLSocketImpl; +Landroid/net/SSLCertificateSocketFactory;->getAlpnSelectedProtocol(Ljava/net/Socket;)[B +Landroid/net/SSLCertificateSocketFactory;->getDelegate()Ljavax/net/ssl/SSLSocketFactory; Landroid/net/SSLCertificateSocketFactory;->getHttpSocketFactory(ILandroid/net/SSLSessionCache;)Lorg/apache/http/conn/ssl/SSLSocketFactory; +Landroid/net/SSLCertificateSocketFactory;-><init>(ILandroid/net/SSLSessionCache;Z)V +Landroid/net/SSLCertificateSocketFactory;->INSECURE_TRUST_MANAGER:[Ljavax/net/ssl/TrustManager; +Landroid/net/SSLCertificateSocketFactory;->isSslCheckRelaxed()Z +Landroid/net/SSLCertificateSocketFactory;->makeSocketFactory([Ljavax/net/ssl/KeyManager;[Ljavax/net/ssl/TrustManager;)Ljavax/net/ssl/SSLSocketFactory; +Landroid/net/SSLCertificateSocketFactory;->mAlpnProtocols:[B +Landroid/net/SSLCertificateSocketFactory;->mChannelIdPrivateKey:Ljava/security/PrivateKey; +Landroid/net/SSLCertificateSocketFactory;->mHandshakeTimeoutMillis:I +Landroid/net/SSLCertificateSocketFactory;->mInsecureFactory:Ljavax/net/ssl/SSLSocketFactory; +Landroid/net/SSLCertificateSocketFactory;->mKeyManagers:[Ljavax/net/ssl/KeyManager; +Landroid/net/SSLCertificateSocketFactory;->mNpnProtocols:[B +Landroid/net/SSLCertificateSocketFactory;->mSecureFactory:Ljavax/net/ssl/SSLSocketFactory; +Landroid/net/SSLCertificateSocketFactory;->mSecure:Z +Landroid/net/SSLCertificateSocketFactory;->mSessionCache:Lcom/android/org/conscrypt/SSLClientSessionCache; +Landroid/net/SSLCertificateSocketFactory;->mTrustManagers:[Ljavax/net/ssl/TrustManager; +Landroid/net/SSLCertificateSocketFactory;->setAlpnProtocols([[B)V +Landroid/net/SSLCertificateSocketFactory;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V +Landroid/net/SSLCertificateSocketFactory;->setSoWriteTimeout(Ljava/net/Socket;I)V +Landroid/net/SSLCertificateSocketFactory;->TAG:Ljava/lang/String; +Landroid/net/SSLCertificateSocketFactory;->toLengthPrefixedList([[[B)[B +Landroid/net/SSLCertificateSocketFactory;->verifyHostname(Ljava/net/Socket;Ljava/lang/String;)V Landroid/net/TrafficStats;->getStatsService()Landroid/net/INetworkStatsService; +Landroid/net/TrafficStats;->setThreadStatsTagBackup()V +Landroid/net/TrafficStats;->setThreadStatsTagRestore()V +Landroid/net/TrafficStats;->setThreadStatsUid(I)V +Landroid/net/WifiKey;-><init>(Ljava/lang/String;Ljava/lang/String;)V Landroid/net/wifi/p2p/WifiP2pGroup;->getNetworkId()I Landroid/net/wifi/p2p/WifiP2pGroupList;->getGroupList()Ljava/util/Collection; Landroid/net/wifi/p2p/WifiP2pManager;->deletePersistentGroup(Landroid/net/wifi/p2p/WifiP2pManager$Channel;ILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V Landroid/net/wifi/p2p/WifiP2pManager;->requestPersistentGroupInfo(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/p2p/WifiP2pManager$PersistentGroupInfoListener;)V Landroid/net/wifi/p2p/WifiP2pManager;->setDeviceName(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Ljava/lang/String;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V +Landroid/net/wifi/RttManager;->getRttCapabilities()Landroid/net/wifi/RttManager$RttCapabilities; +Landroid/net/wifi/RttManager$RttParams;-><init>()V +Landroid/net/wifi/RttManager;->startRanging([Landroid/net/wifi/RttManager$RttParams;Landroid/net/wifi/RttManager$RttListener;)V Landroid/net/wifi/WifiConfiguration;->apBand:I Landroid/net/wifi/WifiConfiguration;->apChannel:I Landroid/net/wifi/WifiConfiguration;->hasNoInternetAccess()Z +Landroid/net/wifi/WifiConfiguration;->isEphemeral()Z +Landroid/net/wifi/WifiConfiguration;->isNoInternetAccessExpected()Z Landroid/net/wifi/WifiConfiguration;->mIpConfiguration:Landroid/net/IpConfiguration; Landroid/net/wifi/WifiConfiguration;->validatedInternetAccess:Z Landroid/net/wifi/WifiManager;->connect(ILandroid/net/wifi/WifiManager$ActionListener;)V Landroid/net/wifi/WifiManager;->connect(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V Landroid/net/wifi/WifiManager;->EXTRA_WIFI_AP_STATE:Ljava/lang/String; Landroid/net/wifi/WifiManager;->forget(ILandroid/net/wifi/WifiManager$ActionListener;)V +Landroid/net/wifi/WifiManager;->getPrivilegedConfiguredNetworks()Ljava/util/List; Landroid/net/wifi/WifiManager;->getWifiApConfiguration()Landroid/net/wifi/WifiConfiguration; Landroid/net/wifi/WifiManager;->getWifiApState()I Landroid/net/wifi/WifiManager;->isDualBandSupported()Z Landroid/net/wifi/WifiManager;->isWifiApEnabled()Z +Landroid/net/wifi/WifiManager;->isWifiScannerSupported()Z Landroid/net/wifi/WifiManager;->mService:Landroid/net/wifi/IWifiManager; Landroid/net/wifi/WifiManager;->save(Landroid/net/wifi/WifiConfiguration;Landroid/net/wifi/WifiManager$ActionListener;)V Landroid/net/wifi/WifiManager;->setWifiApConfiguration(Landroid/net/wifi/WifiConfiguration;)Z +Landroid/net/wifi/WifiManager;->startScan(Landroid/os/WorkSource;)Z Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_CHANGED_ACTION:Ljava/lang/String; Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_DISABLED:I Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_DISABLING:I Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_ENABLED:I Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_ENABLING:I Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_FAILED:I +Landroid/net/wifi/WifiScanner;->getScanResults()Z +Landroid/net/wifi/WifiScanner$ScanData;->getResults()[Landroid/net/wifi/ScanResult; +Landroid/net/wifi/WifiScanner$ScanSettings;-><init>()V +Landroid/net/wifi/WifiScanner;->startBackgroundScan(Landroid/net/wifi/WifiScanner$ScanSettings;Landroid/net/wifi/WifiScanner$ScanListener;)V +Landroid/net/wifi/WifiScanner;->startScan(Landroid/net/wifi/WifiScanner$ScanSettings;Landroid/net/wifi/WifiScanner$ScanListener;Landroid/os/WorkSource;)V +Landroid/net/wifi/WifiScanner;->startScan(Landroid/net/wifi/WifiScanner$ScanSettings;Landroid/net/wifi/WifiScanner$ScanListener;)V +Landroid/net/wifi/WifiScanner;->stopBackgroundScan(Landroid/net/wifi/WifiScanner$ScanListener;)V +Landroid/nfc/NfcAdapter;->addNfcUnlockHandler(Landroid/nfc/NfcAdapter$NfcUnlockHandler;[Ljava/lang/String;)Z +Landroid/nfc/NfcAdapter;->disable()Z +Landroid/nfc/NfcAdapter;->enable()Z Landroid/nfc/NfcAdapter;->getDefaultAdapter()Landroid/nfc/NfcAdapter; +Landroid/nfc/NfcAdapter;->removeNfcUnlockHandler(Landroid/nfc/NfcAdapter$NfcUnlockHandler;)Z Landroid/nfc/NfcAdapter;->setNdefPushMessageCallback(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;I)V +Landroid/nfc/NfcAdapter;->setNdefPushMessage(Landroid/nfc/NdefMessage;Landroid/app/Activity;I)V Landroid/opengl/GLSurfaceView$EglHelper;->mEglContext:Ljavax/microedition/khronos/egl/EGLContext; Landroid/opengl/GLSurfaceView$GLThread;->mEglHelper:Landroid/opengl/GLSurfaceView$EglHelper; Landroid/opengl/GLSurfaceView;->mGLThread:Landroid/opengl/GLSurfaceView$GLThread; @@ -543,7 +734,11 @@ Landroid/os/Trace;->TRACE_TAG_VIEW:J Landroid/os/UpdateEngine;->applyPayload(Ljava/lang/String;JJ[Ljava/lang/String;)V Landroid/os/UpdateEngine;->bind(Landroid/os/UpdateEngineCallback;Landroid/os/Handler;)Z Landroid/os/UpdateEngine;->bind(Landroid/os/UpdateEngineCallback;)Z +Landroid/os/UpdateEngineCallback;-><init>()V +Landroid/os/UpdateEngineCallback;->onPayloadApplicationComplete(I)V +Landroid/os/UpdateEngineCallback;->onStatusUpdate(IF)V Landroid/os/UpdateEngine;->cancel()V +Landroid/os/UpdateEngine;-><init>()V Landroid/os/UpdateEngine;->resetStatus()V Landroid/os/UpdateLock;->acquire()V Landroid/os/UpdateLock;->isHeld()Z @@ -567,10 +762,12 @@ Landroid/os/UserManager;->getProfiles(I)Ljava/util/List; Landroid/os/UserManager;->getUserHandle()I Landroid/os/UserManager;->getUserHandle(I)I Landroid/os/UserManager;->getUserInfo(I)Landroid/content/pm/UserInfo; +Landroid/os/UserManager;->getUserRestrictionSource(Ljava/lang/String;Landroid/os/UserHandle;)I Landroid/os/UserManager;->getUserSerialNumber(I)I Landroid/os/UserManager;->getUsers()Ljava/util/List; Landroid/os/UserManager;->hasBaseUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z Landroid/os/UserManager;->isLinkedUser()Z +Landroid/os/UserManager;->isManagedProfile()Z Landroid/os/UserManager;->isUserUnlocked(I)Z Landroid/os/WorkSource;->add(ILjava/lang/String;)Z Landroid/os/WorkSource;->add(I)Z @@ -645,10 +842,39 @@ Landroid/service/media/IMediaBrowserServiceCallbacks;->onConnect(Ljava/lang/Stri Landroid/service/media/IMediaBrowserServiceCallbacks;->onLoadChildren(Ljava/lang/String;Landroid/content/pm/ParceledListSlice;)V Landroid/service/media/IMediaBrowserServiceCallbacks;->onLoadChildrenWithOptions(Ljava/lang/String;Landroid/content/pm/ParceledListSlice;Landroid/os/Bundle;)V Landroid/service/media/MediaBrowserService;->KEY_MEDIA_ITEM:Ljava/lang/String; +Landroid/service/media/MediaBrowserService$Result;->mFlags:I Landroid/service/notification/NotificationListenerService;->registerAsSystemService(Landroid/content/Context;Landroid/content/ComponentName;I)V Landroid/service/notification/NotificationListenerService;->unregisterAsSystemService()V +Landroid/service/persistentdata/PersistentDataBlockManager;->getMaximumDataBlockSize()J +Landroid/service/persistentdata/PersistentDataBlockManager;->read()[B +Landroid/service/persistentdata/PersistentDataBlockManager;->write([B)I +Landroid/service/resolver/ResolverRankerService;-><init>()V +Landroid/service/resolver/ResolverTarget;->getChooserScore()F +Landroid/service/resolver/ResolverTarget;->getLaunchScore()F +Landroid/service/resolver/ResolverTarget;->getRecencyScore()F +Landroid/service/resolver/ResolverTarget;->getSelectProbability()F +Landroid/service/resolver/ResolverTarget;->getTimeSpentScore()F +Landroid/service/resolver/ResolverTarget;->setSelectProbability(F)V +Landroid/service/trust/TrustAgentService;-><init>()V +Landroid/service/voice/VoiceInteractionService;->isKeyphraseAndLocaleSupportedForHotword(Ljava/lang/String;Ljava/util/Locale;)Z Landroid/service/wallpaper/WallpaperService$Engine;->setFixedSizeAllowed(Z)V Landroid/speech/tts/TextToSpeech;->getCurrentEngine()Ljava/lang/String; +Landroid/telecom/AudioState;->getRoute()I +Landroid/telecom/AudioState;->getSupportedRouteMask()I +Landroid/telecom/AudioState;->isMuted()Z +Landroid/telecom/Call;->addListener(Landroid/telecom/Call$Listener;)V +Landroid/telecom/Call$Listener;-><init>()V +Landroid/telecom/Call;->removeListener(Landroid/telecom/Call$Listener;)V +Landroid/telecom/Phone;->addListener(Landroid/telecom/Phone$Listener;)V +Landroid/telecom/Phone;->getAudioState()Landroid/telecom/AudioState; +Landroid/telecom/Phone;->getCallAudioState()Landroid/telecom/CallAudioState; +Landroid/telecom/Phone;->getCalls()Ljava/util/List; +Landroid/telecom/Phone$Listener;-><init>()V +Landroid/telecom/Phone;->removeListener(Landroid/telecom/Phone$Listener;)V +Landroid/telecom/Phone;->setAudioRoute(I)V +Landroid/telecom/Phone;->setMuted(Z)V +Landroid/telecom/TelecomManager;->endCall()Z +Landroid/telecom/TelecomManager;->EXTRA_IS_HANDOVER:Ljava/lang/String; Landroid/telephony/PhoneStateListener;->mSubId:Ljava/lang/Integer; Landroid/telephony/ServiceState;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/ServiceState; Landroid/telephony/SignalStrength;->getCdmaLevel()I @@ -661,10 +887,12 @@ Landroid/telephony/SmsMessage;->getSubId()I Landroid/telephony/SmsMessage;->mWrappedSmsMessage:Lcom/android/internal/telephony/SmsMessageBase; Landroid/telephony/SubscriptionManager;->getDefaultSmsPhoneId()I Landroid/telephony/SubscriptionManager;->getPhoneId(I)I +Landroid/telephony/SubscriptionManager;->getSlotIndex(I)I Landroid/telephony/SubscriptionManager;->getSubId(I)[I Landroid/telephony/SubscriptionManager;->setDefaultSmsSubId(I)V Landroid/telephony/TelephonyManager;->checkCarrierPrivilegesForPackage(Ljava/lang/String;)I Landroid/telephony/TelephonyManager;->from(Landroid/content/Context;)Landroid/telephony/TelephonyManager; +Landroid/telephony/TelephonyManager;->getCarrierPackageNamesForIntent(Landroid/content/Intent;)Ljava/util/List; Landroid/telephony/TelephonyManager;->getCurrentPhoneType()I Landroid/telephony/TelephonyManager;->getCurrentPhoneType(I)I Landroid/telephony/TelephonyManager;->getDataEnabled(I)Z @@ -695,6 +923,36 @@ Landroid/text/SpannableStringBuilder;->mSpanEnds:[I Landroid/text/SpannableStringBuilder;->mSpanFlags:[I Landroid/text/SpannableStringBuilder;->mSpans:[Ljava/lang/Object; Landroid/text/SpannableStringBuilder;->mSpanStarts:[I +Landroid/text/SpannableStringInternal;->charAt(I)C +Landroid/text/SpannableStringInternal;->checkRange(Ljava/lang/String;II)V +Landroid/text/SpannableStringInternal;->COLUMNS:I +Landroid/text/SpannableStringInternal;->copySpans(Landroid/text/SpannableStringInternal;II)V +Landroid/text/SpannableStringInternal;->copySpans(Landroid/text/Spanned;II)V +Landroid/text/SpannableStringInternal;->EMPTY:[Ljava/lang/Object; +Landroid/text/SpannableStringInternal;->END:I +Landroid/text/SpannableStringInternal;->FLAGS:I +Landroid/text/SpannableStringInternal;->getChars(II[CI)V +Landroid/text/SpannableStringInternal;->getSpanEnd(Ljava/lang/Object;)I +Landroid/text/SpannableStringInternal;->getSpanFlags(Ljava/lang/Object;)I +Landroid/text/SpannableStringInternal;->getSpans(IILjava/lang/Class;)[Ljava/lang/Object; +Landroid/text/SpannableStringInternal;->getSpanStart(Ljava/lang/Object;)I +Landroid/text/SpannableStringInternal;-><init>(Ljava/lang/CharSequence;II)V +Landroid/text/SpannableStringInternal;->isIndexFollowsNextLine(I)Z +Landroid/text/SpannableStringInternal;->isOutOfCopyRange(IIII)Z +Landroid/text/SpannableStringInternal;->length()I +Landroid/text/SpannableStringInternal;->mSpanCount:I +Landroid/text/SpannableStringInternal;->mSpanData:[I +Landroid/text/SpannableStringInternal;->mSpans:[Ljava/lang/Object; +Landroid/text/SpannableStringInternal;->mText:Ljava/lang/String; +Landroid/text/SpannableStringInternal;->nextSpanTransition(IILjava/lang/Class;)I +Landroid/text/SpannableStringInternal;->region(II)Ljava/lang/String; +Landroid/text/SpannableStringInternal;->removeSpan(Ljava/lang/Object;)V +Landroid/text/SpannableStringInternal;->sendSpanAdded(Ljava/lang/Object;II)V +Landroid/text/SpannableStringInternal;->sendSpanChanged(Ljava/lang/Object;IIII)V +Landroid/text/SpannableStringInternal;->sendSpanRemoved(Ljava/lang/Object;II)V +Landroid/text/SpannableStringInternal;->setSpan(Ljava/lang/Object;III)V +Landroid/text/SpannableStringInternal;->setSpan(Ljava/lang/Object;IIIZ)V +Landroid/text/SpannableStringInternal;->START:I Landroid/text/StaticLayout;->mColumns:I Landroid/text/StaticLayout;->mLineCount:I Landroid/text/StaticLayout;->mLines:[I @@ -736,6 +994,8 @@ Landroid/view/IWindowManager;->setAnimationScale(IF)V Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V Landroid/view/IWindowManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowManager; Landroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I +Landroid/view/LayoutInflater;->createViewFromTag(Landroid/view/View;Ljava/lang/String;Landroid/content/Context;Landroid/util/AttributeSet;)Landroid/view/View; +Landroid/view/LayoutInflater;->createViewFromTag(Landroid/view/View;Ljava/lang/String;Landroid/content/Context;Landroid/util/AttributeSet;Z)Landroid/view/View; Landroid/view/LayoutInflater;->mConstructorArgs:[Ljava/lang/Object; Landroid/view/LayoutInflater;->mFactory2:Landroid/view/LayoutInflater$Factory2; Landroid/view/LayoutInflater;->mFactory:Landroid/view/LayoutInflater$Factory; @@ -1113,6 +1373,9 @@ Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([B)V Ldalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String; Ldalvik/system/BaseDexClassLoader;->pathList:Ldalvik/system/DexPathList; +Ldalvik/system/BlockGuard;->getThreadPolicy()Ldalvik/system/BlockGuard$Policy; +Ldalvik/system/BlockGuard$Policy;->onNetwork()V +Ldalvik/system/CloseGuard;->close()V Ldalvik/system/CloseGuard;->get()Ldalvik/system/CloseGuard; Ldalvik/system/CloseGuard;->open(Ljava/lang/String;)V Ldalvik/system/CloseGuard;->warnIfOpen()V diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 3d088ff9e5c3..ff970bf82a7a 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -113,6 +113,7 @@ import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; import android.util.LogPrinter; +import android.util.MergedConfiguration; import android.util.Pair; import android.util.PrintWriterPrinter; import android.util.Slog; @@ -204,7 +205,7 @@ public final class ActivityThread extends ClientTransactionHandler { private static final boolean DEBUG_SERVICE = false; public static final boolean DEBUG_MEMORY_TRIM = false; private static final boolean DEBUG_PROVIDER = false; - private static final boolean DEBUG_ORDER = false; + public static final boolean DEBUG_ORDER = false; private static final long MIN_TIME_BETWEEN_GCS = 5*1000; private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; private static final int LOG_AM_ON_PAUSE_CALLED = 30021; @@ -398,7 +399,6 @@ public final class ActivityThread extends ClientTransactionHandler { boolean startsNotResumed; public final boolean isForward; int pendingConfigChanges; - boolean onlyLocalRequest; Window mPendingRemoveWindow; WindowManager mPendingRemoveWindowManager; @@ -520,7 +520,6 @@ public final class ActivityThread extends ClientTransactionHandler { sb.append(", startsNotResumed=").append(startsNotResumed); sb.append(", isForward=").append(isForward); sb.append(", pendingConfigChanges=").append(pendingConfigChanges); - sb.append(", onlyLocalRequest=").append(onlyLocalRequest); sb.append(", preserveWindow=").append(mPreserveWindow); if (activity != null) { sb.append(", Activity{"); @@ -765,15 +764,6 @@ public final class ActivityThread extends ClientTransactionHandler { sendMessage(H.SLEEPING, token, sleeping ? 1 : 0); } - @Override - public final void scheduleRelaunchActivity(IBinder token, - List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, - int configChanges, boolean notResumed, Configuration config, - Configuration overrideConfig, boolean preserveWindow) { - requestRelaunchActivity(token, pendingResults, pendingNewIntents, - configChanges, notResumed, config, overrideConfig, true, preserveWindow); - } - public final void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, boolean sync, int sendingUser, int processState) { @@ -1531,7 +1521,6 @@ public final class ActivityThread extends ClientTransactionHandler { public static final int UNBIND_SERVICE = 122; public static final int DUMP_SERVICE = 123; public static final int LOW_MEMORY = 124; - public static final int RELAUNCH_ACTIVITY = 126; public static final int PROFILER_CONTROL = 127; public static final int CREATE_BACKUP_AGENT = 128; public static final int DESTROY_BACKUP_AGENT = 129; @@ -1577,7 +1566,6 @@ public final class ActivityThread extends ClientTransactionHandler { case UNBIND_SERVICE: return "UNBIND_SERVICE"; case DUMP_SERVICE: return "DUMP_SERVICE"; case LOW_MEMORY: return "LOW_MEMORY"; - case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; case PROFILER_CONTROL: return "PROFILER_CONTROL"; case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT"; case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT"; @@ -1611,12 +1599,6 @@ public final class ActivityThread extends ClientTransactionHandler { public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { - case RELAUNCH_ACTIVITY: { - Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart"); - ActivityClientRecord r = (ActivityClientRecord)msg.obj; - handleRelaunchActivity(r); - Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); - } break; case BIND_APPLICATION: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); AppBindData data = (AppBindData)msg.obj; @@ -3726,20 +3708,6 @@ public final class ActivityThread extends ClientTransactionHandler { } r.activity.performResume(r.startsNotResumed); - synchronized (mResourcesManager) { - // If there is a pending local relaunch that was requested when the activity was - // paused, it will put the activity into paused state when it finally happens. - // Since the activity resumed before being relaunched, we don't want that to - // happen, so we need to clear the request to relaunch paused. - for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) { - final ActivityClientRecord relaunching = mRelaunchingActivities.get(i); - if (relaunching.token == r.token - && relaunching.onlyLocalRequest && relaunching.startsNotResumed) { - relaunching.startsNotResumed = false; - } - } - } - EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(), r.activity.getComponentName().getClassName(), reason); @@ -3888,14 +3856,12 @@ public final class ActivityThread extends ClientTransactionHandler { } } - if (!r.onlyLocalRequest) { - r.nextIdle = mNewActivities; - mNewActivities = r; - if (localLOGV) Slog.v( - TAG, "Scheduling idle handler for " + r); - Looper.myQueue().addIdleHandler(new Idler()); + r.nextIdle = mNewActivities; + mNewActivities = r; + if (localLOGV) { + Slog.v(TAG, "Scheduling idle handler for " + r); } - r.onlyLocalRequest = false; + Looper.myQueue().addIdleHandler(new Idler()); } else { // If an exception was thrown when trying to resume, then // just end this activity. @@ -4586,15 +4552,12 @@ public final class ActivityThread extends ClientTransactionHandler { mSomeActivitiesChanged = true; } - /** - * @param preserveWindow Whether the activity should try to reuse the window it created, - * including the decor view after the relaunch. - */ - public final void requestRelaunchActivity(IBinder token, + @Override + public ActivityClientRecord prepareRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, - int configChanges, boolean notResumed, Configuration config, - Configuration overrideConfig, boolean fromServer, boolean preserveWindow) { + int configChanges, MergedConfiguration config, boolean preserveWindow) { ActivityClientRecord target = null; + boolean scheduleRelaunch = false; synchronized (mResourcesManager) { for (int i=0; i<mRelaunchingActivities.size(); i++) { @@ -4616,57 +4579,31 @@ public final class ActivityThread extends ClientTransactionHandler { r.pendingIntents = pendingNewIntents; } } - - // For each relaunch request, activity manager expects an answer - if (!r.onlyLocalRequest && fromServer) { - try { - ActivityManager.getService().activityRelaunched(token); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } break; } } if (target == null) { - if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null, fromServer:" - + fromServer); + if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null"); target = new ActivityClientRecord(); target.token = token; target.pendingResults = pendingResults; target.pendingIntents = pendingNewIntents; target.mPreserveWindow = preserveWindow; - if (!fromServer) { - final ActivityClientRecord existing = mActivities.get(token); - if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + existing); - if (existing != null) { - if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: paused= " - + existing.paused);; - target.startsNotResumed = existing.paused; - target.overrideConfig = existing.overrideConfig; - } - target.onlyLocalRequest = true; - } mRelaunchingActivities.add(target); - sendMessage(H.RELAUNCH_ACTIVITY, target); - } - - if (fromServer) { - target.startsNotResumed = notResumed; - target.onlyLocalRequest = false; - } - if (config != null) { - target.createdConfig = config; - } - if (overrideConfig != null) { - target.overrideConfig = overrideConfig; + scheduleRelaunch = true; } + target.createdConfig = config.getGlobalConfiguration(); + target.overrideConfig = config.getOverrideConfiguration(); target.pendingConfigChanges |= configChanges; } + + return scheduleRelaunch ? target : null; } - private void handleRelaunchActivity(ActivityClientRecord tmp) { + @Override + public void handleRelaunchActivity(ActivityClientRecord tmp, + PendingTransactionActions pendingActions) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); @@ -4735,18 +4672,10 @@ public final class ActivityThread extends ClientTransactionHandler { ActivityClientRecord r = mActivities.get(tmp.token); if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r); if (r == null) { - if (!tmp.onlyLocalRequest) { - try { - ActivityManager.getService().activityRelaunched(tmp.token); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } return; } r.activity.mConfigChangeFlags |= configChanges; - r.onlyLocalRequest = tmp.onlyLocalRequest; r.mPreserveWindow = tmp.mPreserveWindow; r.activity.mChangingConfigurations = true; @@ -4763,9 +4692,9 @@ public final class ActivityThread extends ClientTransactionHandler { // preserved by the server, so we want to notify it that we are preparing to replace // everything try { - if (r.mPreserveWindow || r.onlyLocalRequest) { + if (r.mPreserveWindow) { WindowManagerGlobal.getWindowSession().prepareToReplaceWindows( - r.token, !r.onlyLocalRequest); + r.token, true /* childrenOnly */); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -4804,24 +4733,22 @@ public final class ActivityThread extends ClientTransactionHandler { r.startsNotResumed = tmp.startsNotResumed; r.overrideConfig = tmp.overrideConfig; - // TODO(lifecycler): Move relaunch to lifecycler. - PendingTransactionActions pendingActions = new PendingTransactionActions(); handleLaunchActivity(r, pendingActions); - handleStartActivity(r, pendingActions); - handleResumeActivity(r.token, false /* clearHide */, r.isForward, "relaunch"); - if (r.startsNotResumed) { - performPauseActivity(r, false /* finished */, "relaunch", pendingActions); - } + // Only report a successful relaunch to WindowManager. + pendingActions.setReportRelaunchToWindowManager(true); + } - if (!tmp.onlyLocalRequest) { - try { - ActivityManager.getService().activityRelaunched(r.token); - if (r.window != null) { - r.window.reportActivityRelaunched(); - } - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + @Override + public void reportRelaunch(IBinder token, PendingTransactionActions pendingActions) { + try { + ActivityManager.getService().activityRelaunched(token); + final ActivityClientRecord r = mActivities.get(token); + if (pendingActions.shouldReportRelaunchToWindowManager() && r != null + && r.window != null) { + r.window.reportActivityRelaunched(); } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -5890,21 +5817,23 @@ public final class ActivityThread extends ClientTransactionHandler { // Preload fonts resources FontsContract.setApplicationContextForResources(appContext); - try { - final ApplicationInfo info = - getPackageManager().getApplicationInfo( - data.appInfo.packageName, - PackageManager.GET_META_DATA /*flags*/, - UserHandle.myUserId()); - if (info.metaData != null) { - final int preloadedFontsResource = info.metaData.getInt( - ApplicationInfo.METADATA_PRELOADED_FONTS, 0); - if (preloadedFontsResource != 0) { - data.info.getResources().preloadFonts(preloadedFontsResource); + if (!Process.isIsolated()) { + try { + final ApplicationInfo info = + getPackageManager().getApplicationInfo( + data.appInfo.packageName, + PackageManager.GET_META_DATA /*flags*/, + UserHandle.myUserId()); + if (info.metaData != null) { + final int preloadedFontsResource = info.metaData.getInt( + ApplicationInfo.METADATA_PRELOADED_FONTS, 0); + if (preloadedFontsResource != 0) { + data.info.getResources().preloadFonts(preloadedFontsResource); + } } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); } } diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java index 5b61fdf8677f..114d18b9a996 100644 --- a/core/java/android/app/ClientTransactionHandler.java +++ b/core/java/android/app/ClientTransactionHandler.java @@ -21,6 +21,7 @@ import android.content.pm.ApplicationInfo; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.os.IBinder; +import android.util.MergedConfiguration; import com.android.internal.content.ReferrerIntent; @@ -124,6 +125,39 @@ public abstract class ClientTransactionHandler { public abstract ActivityThread.ActivityClientRecord getActivityClient(IBinder token); /** + * Prepare activity relaunch to update internal bookkeeping. This is used to track multiple + * relaunch and config update requests. + * @param token Activity token. + * @param pendingResults Activity results to be delivered. + * @param pendingNewIntents New intent messages to be delivered. + * @param configChanges Mask of configuration changes that have occurred. + * @param config New configuration applied to the activity. + * @param preserveWindow Whether the activity should try to reuse the window it created, + * including the decor view after the relaunch. + * @return An initialized instance of {@link ActivityThread.ActivityClientRecord} to use during + * relaunch, or {@code null} if relaunch cancelled. + */ + public abstract ActivityThread.ActivityClientRecord prepareRelaunchActivity(IBinder token, + List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, + int configChanges, MergedConfiguration config, boolean preserveWindow); + + /** + * Perform activity relaunch. + * @param r Activity client record prepared for relaunch. + * @param pendingActions Pending actions to be used on later stages of activity transaction. + * */ + public abstract void handleRelaunchActivity(ActivityThread.ActivityClientRecord r, + PendingTransactionActions pendingActions); + + /** + * Report that relaunch request was handled. + * @param token Target activity token. + * @param pendingActions Pending actions initialized on earlier stages of activity transaction. + * Used to check if we should report relaunch to WM. + * */ + public abstract void reportRelaunch(IBinder token, PendingTransactionActions pendingActions); + + /** * Debugging output. * @param pw {@link PrintWriter} to write logs to. * @param prefix Prefix to prepend to output. diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 4a9b2bcb16ed..a1ba13d9512c 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -409,6 +409,7 @@ class ContextImpl extends Context { return sp; } + @GuardedBy("ContextImpl.class") private ArrayMap<File, SharedPreferencesImpl> getSharedPreferencesCacheLocked() { if (sSharedPrefsCache == null) { sSharedPrefsCache = new ArrayMap<>(); diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index 9e99a78ccfbd..ae9b83ec0122 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -83,9 +83,6 @@ oneway interface IApplicationThread { int resultCode, in String data, in Bundle extras, boolean ordered, boolean sticky, int sendingUser, int processState); void scheduleLowMemory(); - void scheduleRelaunchActivity(IBinder token, in List<ResultInfo> pendingResults, - in List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed, - in Configuration config, in Configuration overrideConfig, boolean preserveWindow); void scheduleSleeping(IBinder token, boolean sleeping); void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType); void setSchedulingGroup(int group); diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java index 88e42d58e476..c2c91c2bcbd6 100644 --- a/core/java/android/app/StatsManager.java +++ b/core/java/android/app/StatsManager.java @@ -33,6 +33,7 @@ import android.util.Slog; public final class StatsManager { IStatsManager mService; private static final String TAG = "StatsManager"; + private static final boolean DEBUG = false; /** * Long extra of uid that added the relevant stats config. @@ -74,6 +75,14 @@ public final class StatsManager { } /** + * Temporary. Will be deleted. + */ + @RequiresPermission(Manifest.permission.DUMP) + public boolean addConfiguration(long configKey, byte[] config, String a, String b) { + return addConfiguration(configKey, config); + } + + /** * Clients can send a configuration and simultaneously registers the name of a broadcast * receiver that listens for when it should request data. * @@ -88,12 +97,12 @@ public final class StatsManager { try { IStatsManager service = getIStatsManagerLocked(); if (service == null) { - Slog.d(TAG, "Failed to find statsd when adding configuration"); + if (DEBUG) Slog.d(TAG, "Failed to find statsd when adding configuration"); return false; } return service.addConfiguration(configKey, config); } catch (RemoteException e) { - Slog.d(TAG, "Failed to connect to statsd when adding configuration"); + if (DEBUG) Slog.d(TAG, "Failed to connect to statsd when adding configuration"); return false; } } @@ -111,12 +120,12 @@ public final class StatsManager { try { IStatsManager service = getIStatsManagerLocked(); if (service == null) { - Slog.d(TAG, "Failed to find statsd when removing configuration"); + if (DEBUG) Slog.d(TAG, "Failed to find statsd when removing configuration"); return false; } return service.removeConfiguration(configKey); } catch (RemoteException e) { - Slog.d(TAG, "Failed to connect to statsd when removing configuration"); + if (DEBUG) Slog.d(TAG, "Failed to connect to statsd when removing configuration"); return false; } } @@ -225,12 +234,12 @@ public final class StatsManager { try { IStatsManager service = getIStatsManagerLocked(); if (service == null) { - Slog.d(TAG, "Failed to find statsd when getting data"); + if (DEBUG) Slog.d(TAG, "Failed to find statsd when getting data"); return null; } return service.getData(configKey); } catch (RemoteException e) { - Slog.d(TAG, "Failed to connecto statsd when getting data"); + if (DEBUG) Slog.d(TAG, "Failed to connecto statsd when getting data"); return null; } } @@ -249,12 +258,12 @@ public final class StatsManager { try { IStatsManager service = getIStatsManagerLocked(); if (service == null) { - Slog.d(TAG, "Failed to find statsd when getting metadata"); + if (DEBUG) Slog.d(TAG, "Failed to find statsd when getting metadata"); return null; } return service.getMetadata(); } catch (RemoteException e) { - Slog.d(TAG, "Failed to connecto statsd when getting metadata"); + if (DEBUG) Slog.d(TAG, "Failed to connecto statsd when getting metadata"); return null; } } diff --git a/core/java/android/app/servertransaction/ActivityRelaunchItem.java b/core/java/android/app/servertransaction/ActivityRelaunchItem.java new file mode 100644 index 000000000000..d8a7463cb086 --- /dev/null +++ b/core/java/android/app/servertransaction/ActivityRelaunchItem.java @@ -0,0 +1,176 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.servertransaction; + +import static android.app.ActivityThread.DEBUG_ORDER; + +import android.app.ActivityThread; +import android.app.ClientTransactionHandler; +import android.app.ResultInfo; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Trace; +import android.util.MergedConfiguration; +import android.util.Slog; + +import com.android.internal.content.ReferrerIntent; + +import java.util.List; +import java.util.Objects; + +/** + * Activity relaunch callback. + * @hide + */ +public class ActivityRelaunchItem extends ClientTransactionItem { + + private static final String TAG = "ActivityRelaunchItem"; + + private List<ResultInfo> mPendingResults; + private List<ReferrerIntent> mPendingNewIntents; + private int mConfigChanges; + private MergedConfiguration mConfig; + private boolean mPreserveWindow; + + /** + * A record that was properly configured for relaunch. Execution will be cancelled if not + * initialized after {@link #preExecute(ClientTransactionHandler, IBinder)}. + */ + private ActivityThread.ActivityClientRecord mActivityClientRecord; + + @Override + public void preExecute(ClientTransactionHandler client, IBinder token) { + mActivityClientRecord = client.prepareRelaunchActivity(token, mPendingResults, + mPendingNewIntents, mConfigChanges, mConfig, mPreserveWindow); + } + + @Override + public void execute(ClientTransactionHandler client, IBinder token, + PendingTransactionActions pendingActions) { + if (mActivityClientRecord == null) { + if (DEBUG_ORDER) Slog.d(TAG, "Activity relaunch cancelled"); + return; + } + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart"); + client.handleRelaunchActivity(mActivityClientRecord, pendingActions); + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + } + + @Override + public void postExecute(ClientTransactionHandler client, IBinder token, + PendingTransactionActions pendingActions) { + client.reportRelaunch(token, pendingActions); + } + + // ObjectPoolItem implementation + + private ActivityRelaunchItem() {} + + /** Obtain an instance initialized with provided params. */ + public static ActivityRelaunchItem obtain(List<ResultInfo> pendingResults, + List<ReferrerIntent> pendingNewIntents, int configChanges, MergedConfiguration config, + boolean preserveWindow) { + ActivityRelaunchItem instance = ObjectPool.obtain(ActivityRelaunchItem.class); + if (instance == null) { + instance = new ActivityRelaunchItem(); + } + instance.mPendingResults = pendingResults; + instance.mPendingNewIntents = pendingNewIntents; + instance.mConfigChanges = configChanges; + instance.mConfig = config; + instance.mPreserveWindow = preserveWindow; + + return instance; + } + + @Override + public void recycle() { + mPendingResults = null; + mPendingNewIntents = null; + mConfigChanges = 0; + mConfig = null; + mPreserveWindow = false; + mActivityClientRecord = null; + ObjectPool.recycle(this); + } + + + // Parcelable implementation + + /** Write to Parcel. */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeTypedList(mPendingResults, flags); + dest.writeTypedList(mPendingNewIntents, flags); + dest.writeInt(mConfigChanges); + dest.writeTypedObject(mConfig, flags); + dest.writeBoolean(mPreserveWindow); + } + + /** Read from Parcel. */ + private ActivityRelaunchItem(Parcel in) { + mPendingResults = in.createTypedArrayList(ResultInfo.CREATOR); + mPendingNewIntents = in.createTypedArrayList(ReferrerIntent.CREATOR); + mConfigChanges = in.readInt(); + mConfig = in.readTypedObject(MergedConfiguration.CREATOR); + mPreserveWindow = in.readBoolean(); + } + + public static final Creator<ActivityRelaunchItem> CREATOR = + new Creator<ActivityRelaunchItem>() { + public ActivityRelaunchItem createFromParcel(Parcel in) { + return new ActivityRelaunchItem(in); + } + + public ActivityRelaunchItem[] newArray(int size) { + return new ActivityRelaunchItem[size]; + } + }; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final ActivityRelaunchItem other = (ActivityRelaunchItem) o; + return Objects.equals(mPendingResults, other.mPendingResults) + && Objects.equals(mPendingNewIntents, other.mPendingNewIntents) + && mConfigChanges == other.mConfigChanges && Objects.equals(mConfig, other.mConfig) + && mPreserveWindow == other.mPreserveWindow; + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + Objects.hashCode(mPendingResults); + result = 31 * result + Objects.hashCode(mPendingNewIntents); + result = 31 * result + mConfigChanges; + result = 31 * result + Objects.hashCode(mConfig); + result = 31 * result + (mPreserveWindow ? 1 : 0); + return result; + } + + @Override + public String toString() { + return "ActivityRelaunchItem{pendingResults=" + mPendingResults + + ",pendingNewIntents=" + mPendingNewIntents + ",configChanges=" + mConfigChanges + + ",config=" + mConfig + ",preserveWindow" + mPreserveWindow + "}"; + } +} diff --git a/core/java/android/app/servertransaction/PendingTransactionActions.java b/core/java/android/app/servertransaction/PendingTransactionActions.java index 073d28cfa27f..af7b7a21a582 100644 --- a/core/java/android/app/servertransaction/PendingTransactionActions.java +++ b/core/java/android/app/servertransaction/PendingTransactionActions.java @@ -44,6 +44,7 @@ public class PendingTransactionActions { private boolean mCallOnPostCreate; private Bundle mOldState; private StopInfo mStopInfo; + private boolean mReportRelaunchToWM; public PendingTransactionActions() { clear(); @@ -91,6 +92,24 @@ public class PendingTransactionActions { mStopInfo = stopInfo; } + /** + * Check if we should report an activity relaunch to WindowManager. We report back for every + * relaunch request to ActivityManager, but only for those that were actually finished to we + * report to WindowManager. + */ + public boolean shouldReportRelaunchToWindowManager() { + return mReportRelaunchToWM; + } + + /** + * Set if we should report an activity relaunch to WindowManager. We report back for every + * relaunch request to ActivityManager, but only for those that were actually finished we report + * to WindowManager. + */ + public void setReportRelaunchToWindowManager(boolean reportToWm) { + mReportRelaunchToWM = reportToWm; + } + /** Reports to server about activity stop. */ public static class StopInfo implements Runnable { private static final String TAG = "ActivityStopInfo"; diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index edb992bd265c..6b573e99f1fa 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -16,6 +16,7 @@ package android.app.usage; import android.annotation.IntDef; +import android.annotation.SystemApi; import android.content.res.Configuration; import android.os.Parcel; import android.os.Parcelable; @@ -104,12 +105,14 @@ public final class UsageEvents implements Parcelable { * An event type denoting that a notification was viewed by the user. * @hide */ + @SystemApi public static final int NOTIFICATION_SEEN = 10; /** * An event type denoting a change in App Standby Bucket. * @hide */ + @SystemApi public static final int STANDBY_BUCKET_CHANGED = 11; /** @hide */ @@ -257,6 +260,17 @@ public final class UsageEvents implements Parcelable { return mShortcutId; } + /** + * Returns the standby bucket of the app, if the event is of type + * {@link #STANDBY_BUCKET_CHANGED}, otherwise returns 0. + * @return the standby bucket associated with the event. + * @hide + */ + @SystemApi + public int getStandbyBucket() { + return mBucket; + } + /** @hide */ public Event getObfuscatedIfInstantApp() { if ((mFlags & FLAG_IS_PACKAGE_INSTANT_APP) == 0) { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index b85a3199881c..15f3777b99cc 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -560,6 +560,7 @@ public abstract class Context { * * @param resId Resource id for the CharSequence text */ + @NonNull public final CharSequence getText(@StringRes int resId) { return getResources().getText(resId); } @@ -616,12 +617,11 @@ public abstract class Context { * @param id The desired resource identifier, as generated by the aapt * tool. This integer encodes the package, type, and resource * entry. The value 0 is an invalid identifier. - * @return An object that can be used to draw this resource, or - * {@code null} if the resource could not be resolved. + * @return An object that can be used to draw this resource. * @throws android.content.res.Resources.NotFoundException if the given ID * does not exist. */ - @Nullable + @NonNull public final Drawable getDrawable(@DrawableRes int id) { return getResources().getDrawable(id, getTheme()); } @@ -633,12 +633,11 @@ public abstract class Context { * @param id The desired resource identifier, as generated by the aapt * tool. This integer encodes the package, type, and resource * entry. The value 0 is an invalid identifier. - * @return A color state list, or {@code null} if the resource could not be - * resolved. + * @return A color state list. * @throws android.content.res.Resources.NotFoundException if the given ID * does not exist. */ - @Nullable + @NonNull public final ColorStateList getColorStateList(@ColorRes int id) { return getResources().getColorStateList(id, getTheme()); } @@ -3539,6 +3538,7 @@ public abstract class Context { * @hide */ @SystemApi + @Deprecated public static final String WIFI_RTT_SERVICE = "rttmanager"; /** diff --git a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java index 02d0a6d8bd36..79bc9a30b1e2 100644 --- a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java +++ b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java @@ -274,6 +274,7 @@ public final class RuntimePermissionPresenter { } } + @GuardedBy("mLock") private void scheduleNextMessageIfNeededLocked() { if (mBound && mRemoteInstance != null && !mPendingWork.isEmpty()) { Message nextMessage = mPendingWork.remove(0); diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index 24116b42bc7b..bb907005b680 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -143,6 +143,7 @@ public final class AssetManager implements AutoCloseable { /** * This must be called from Zygote so that system assets are shared by all applications. */ + @GuardedBy("sSync") private static void createSystemAssetsInZygoteLocked() { if (sSystem != null) { return; @@ -366,6 +367,7 @@ public final class AssetManager implements AutoCloseable { * The AssetManager may have been closed, but references to it still exist * and therefore the native implementation is not destroyed. */ + @GuardedBy("this") private void ensureValidLocked() { if (mObject == 0) { throw new RuntimeException("AssetManager has been destroyed"); @@ -376,6 +378,7 @@ public final class AssetManager implements AutoCloseable { * Ensures that the AssetManager has not been explicitly closed. If this method passes, * then this implies that ensureValidLocked() also passes. */ + @GuardedBy("this") private void ensureOpenLocked() { // If mOpen is true, this implies that mObject != 0. if (!mOpen) { @@ -1189,6 +1192,7 @@ public final class AssetManager implements AutoCloseable { } } + @GuardedBy("this") private void incRefsLocked(long id) { if (DEBUG_REFS) { if (mRefStacks == null) { @@ -1201,6 +1205,7 @@ public final class AssetManager implements AutoCloseable { mNumRefs++; } + @GuardedBy("this") private void decRefsLocked(long id) { if (DEBUG_REFS && mRefStacks != null) { mRefStacks.remove(id); diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 8f58891ed556..d8133824f757 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -867,8 +867,9 @@ public class Resources { * @param theme The theme used to style the drawable attributes, may be {@code null}. * @return Drawable An object that can be used to draw this resource. * @throws NotFoundException Throws NotFoundException if the given ID does - * not exist. + * not exist, or cannot be decoded. */ + @NonNull public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) { final TypedValue value = obtainTempTypedValue(); try { @@ -980,7 +981,7 @@ public class Resources { * or multiple colors that can be selected based on a state. * @deprecated Use {@link #getColorStateList(int, Theme)} instead. */ - @Nullable + @NonNull @Deprecated public ColorStateList getColorStateList(@ColorRes int id) throws NotFoundException { final ColorStateList csl = getColorStateList(id, null); @@ -1011,7 +1012,7 @@ public class Resources { * @return A themed ColorStateList object containing either a single solid * color or multiple colors that can be selected based on a state. */ - @Nullable + @NonNull public ColorStateList getColorStateList(@ColorRes int id, @Nullable Theme theme) throws NotFoundException { final TypedValue value = obtainTempTypedValue(); @@ -1024,7 +1025,7 @@ public class Resources { } } - @Nullable + @NonNull ColorStateList loadColorStateList(@NonNull TypedValue value, int id, @Nullable Theme theme) throws NotFoundException { return mResourcesImpl.loadColorStateList(this, value, id, theme); @@ -1033,7 +1034,7 @@ public class Resources { /** * @hide */ - @Nullable + @NonNull public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, @Nullable Theme theme) { return mResourcesImpl.loadComplexColor(this, value, id, theme); } @@ -1139,6 +1140,7 @@ public class Resources { * * @see #getXml */ + @NonNull public XmlResourceParser getLayout(@LayoutRes int id) throws NotFoundException { return loadXmlResourceParser(id, "layout"); } @@ -1163,6 +1165,7 @@ public class Resources { * * @see #getXml */ + @NonNull public XmlResourceParser getAnimation(@AnimatorRes @AnimRes int id) throws NotFoundException { return loadXmlResourceParser(id, "anim"); } @@ -1188,6 +1191,7 @@ public class Resources { * * @see android.util.AttributeSet */ + @NonNull public XmlResourceParser getXml(@XmlRes int id) throws NotFoundException { return loadXmlResourceParser(id, "xml"); } @@ -1203,8 +1207,8 @@ public class Resources { * @return InputStream Access to the resource data. * * @throws NotFoundException Throws NotFoundException if the given ID does not exist. - * */ + @NonNull public InputStream openRawResource(@RawRes int id) throws NotFoundException { final TypedValue value = obtainTempTypedValue(); try { @@ -1261,6 +1265,7 @@ public class Resources { * * @throws NotFoundException Throws NotFoundException if the given ID does not exist. */ + @NonNull public InputStream openRawResource(@RawRes int id, TypedValue value) throws NotFoundException { return mResourcesImpl.openRawResource(id, value); diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java index 80e3860bfb9e..08a161347e59 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -27,11 +27,9 @@ import android.annotation.StyleRes; import android.annotation.StyleableRes; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo.Config; -import android.content.res.AssetManager.AssetInputStream; import android.content.res.Configuration.NativeConfig; import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; -import android.graphics.ImageDecoder; import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -544,7 +542,7 @@ public class ResourcesImpl { } } - @Nullable + @NonNull Drawable loadDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, int id, int density, @Nullable Resources.Theme theme) throws NotFoundException { @@ -628,7 +626,7 @@ public class ResourcesImpl { } else if (isColorDrawable) { dr = new ColorDrawable(value.data); } else { - dr = loadDrawableForCookie(wrapper, value, id, density, null); + dr = loadDrawableForCookie(wrapper, value, id, density); } // DrawableContainer' constant state has drawables instances. In order to leave the // constant state intact in the cache, we need to create a new DrawableContainer after @@ -755,8 +753,9 @@ public class ResourcesImpl { /** * Loads a drawable from XML or resources stream. */ + @NonNull private Drawable loadDrawableForCookie(@NonNull Resources wrapper, @NonNull TypedValue value, - int id, int density, @Nullable Resources.Theme theme) { + int id, int density) { if (value.string == null) { throw new NotFoundException("Resource \"" + getResourceName(id) + "\" (" + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value); @@ -775,22 +774,23 @@ public class ResourcesImpl { } } - // For prelaod tracing. + // For preload tracing. long startTime = 0; int startBitmapCount = 0; long startBitmapSize = 0; - int startDrwableCount = 0; + int startDrawableCount = 0; if (TRACE_FOR_DETAILED_PRELOAD) { startTime = System.nanoTime(); startBitmapCount = Bitmap.sPreloadTracingNumInstantiatedBitmaps; startBitmapSize = Bitmap.sPreloadTracingTotalBitmapsSize; - startDrwableCount = sPreloadTracingNumLoadedDrawables; + startDrawableCount = sPreloadTracingNumLoadedDrawables; } if (DEBUG_LOAD) { Log.v(TAG, "Loading drawable for cookie " + value.assetCookie + ": " + file); } + final Drawable dr; Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file); @@ -805,18 +805,13 @@ public class ResourcesImpl { if (file.endsWith(".xml")) { final XmlResourceParser rp = loadXmlResourceParser( file, id, value.assetCookie, "drawable"); - dr = Drawable.createFromXmlForDensity(wrapper, rp, density, theme); + dr = Drawable.createFromXmlForDensity(wrapper, rp, density, null); rp.close(); } else { final InputStream is = mAssets.openNonAsset( value.assetCookie, file, AssetManager.ACCESS_STREAMING); - AssetInputStream ais = (AssetInputStream) is; - // ImageDecoder will close the input stream. - ImageDecoder.Source src = new ImageDecoder.AssetInputStreamSource(ais, - wrapper, value); - dr = ImageDecoder.decodeDrawable(src, (decoder, info, s) -> { - decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); - }); + dr = Drawable.createFromResourceStream(wrapper, value, is, file, null); + is.close(); } } finally { stack.pop(); @@ -840,7 +835,7 @@ public class ResourcesImpl { final long loadedBitmapSize = Bitmap.sPreloadTracingTotalBitmapsSize - startBitmapSize; final int loadedDrawables = - sPreloadTracingNumLoadedDrawables - startDrwableCount; + sPreloadTracingNumLoadedDrawables - startDrawableCount; sPreloadTracingNumLoadedDrawables++; @@ -916,6 +911,7 @@ public class ResourcesImpl { * first try to load CSL from the cache. If not found, try to get from the constant state. * Last, parse the XML and generate the CSL. */ + @NonNull private ComplexColor loadComplexColorFromName(Resources wrapper, Resources.Theme theme, TypedValue value, int id) { final long key = (((long) value.assetCookie) << 32) | value.data; @@ -935,17 +931,15 @@ public class ResourcesImpl { complexColor = loadComplexColorForCookie(wrapper, value, id, theme); } - if (complexColor != null) { - complexColor.setBaseChangingConfigurations(value.changingConfigurations); + complexColor.setBaseChangingConfigurations(value.changingConfigurations); - if (mPreloading) { - if (verifyPreloadConfig(complexColor.getChangingConfigurations(), - 0, value.resourceId, "color")) { - sPreloadedComplexColors.put(key, complexColor.getConstantState()); - } - } else { - cache.put(key, theme, complexColor.getConstantState()); + if (mPreloading) { + if (verifyPreloadConfig(complexColor.getChangingConfigurations(), + 0, value.resourceId, "color")) { + sPreloadedComplexColors.put(key, complexColor.getConstantState()); } + } else { + cache.put(key, theme, complexColor.getConstantState()); } return complexColor; } @@ -991,7 +985,7 @@ public class ResourcesImpl { return complexColor; } - @Nullable + @NonNull ColorStateList loadColorStateList(Resources wrapper, TypedValue value, int id, Resources.Theme theme) throws NotFoundException { @@ -1051,7 +1045,7 @@ public class ResourcesImpl { * * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content. */ - @Nullable + @NonNull private ComplexColor loadComplexColorForCookie(Resources wrapper, TypedValue value, int id, Resources.Theme theme) { if (value.string == null) { diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java index b211700328b9..dc60612451d4 100644 --- a/core/java/android/database/sqlite/SQLiteConnectionPool.java +++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java @@ -422,6 +422,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Can't throw. + @GuardedBy("mLock") private boolean recycleConnectionLocked(SQLiteConnection connection, AcquiredConnectionStatus status) { if (status == AcquiredConnectionStatus.RECONFIGURE) { @@ -531,6 +532,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Can't throw. + @GuardedBy("mLock") private void closeAvailableConnectionsAndLogExceptionsLocked() { closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked(); @@ -541,6 +543,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Can't throw. + @GuardedBy("mLock") private boolean closeAvailableConnectionLocked(int connectionId) { final int count = mAvailableNonPrimaryConnections.size(); for (int i = count - 1; i >= 0; i--) { @@ -562,6 +565,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Can't throw. + @GuardedBy("mLock") private void closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked() { final int count = mAvailableNonPrimaryConnections.size(); for (int i = 0; i < count; i++) { @@ -581,6 +585,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Can't throw. + @GuardedBy("mLock") private void closeExcessConnectionsAndLogExceptionsLocked() { int availableCount = mAvailableNonPrimaryConnections.size(); while (availableCount-- > mMaxConnectionPoolSize - 1) { @@ -591,6 +596,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Can't throw. + @GuardedBy("mLock") private void closeConnectionAndLogExceptionsLocked(SQLiteConnection connection) { try { connection.close(); // might throw @@ -609,6 +615,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Can't throw. + @GuardedBy("mLock") private void reconfigureAllConnectionsLocked() { if (mAvailablePrimaryConnection != null) { try { @@ -776,6 +783,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Can't throw. + @GuardedBy("mLock") private void cancelConnectionWaiterLocked(ConnectionWaiter waiter) { if (waiter.mAssignedConnection != null || waiter.mException != null) { // Waiter is done waiting but has not woken up yet. @@ -848,6 +856,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Can't throw. + @GuardedBy("mLock") private void wakeConnectionWaitersLocked() { // Unpark all waiters that have requests that we can fulfill. // This method is designed to not throw runtime exceptions, although we might send @@ -910,6 +919,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Might throw. + @GuardedBy("mLock") private SQLiteConnection tryAcquirePrimaryConnectionLocked(int connectionFlags) { // If the primary connection is available, acquire it now. SQLiteConnection connection = mAvailablePrimaryConnection; @@ -935,6 +945,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Might throw. + @GuardedBy("mLock") private SQLiteConnection tryAcquireNonPrimaryConnectionLocked( String sql, int connectionFlags) { // Try to acquire the next connection in the queue. @@ -974,6 +985,7 @@ public final class SQLiteConnectionPool implements Closeable { } // Might throw. + @GuardedBy("mLock") private void finishAcquireConnectionLocked(SQLiteConnection connection, int connectionFlags) { try { final boolean readOnly = (connectionFlags & CONNECTION_FLAG_READ_ONLY) != 0; diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java index a734719afa5d..8b4f02efd153 100644 --- a/core/java/android/os/BatteryManager.java +++ b/core/java/android/os/BatteryManager.java @@ -323,4 +323,16 @@ public class BatteryManager { public long getLongProperty(int id) { return queryProperty(id); } + + /** + * Return true if the plugType given is wired + * @param plugType {@link #BATTERY_PLUGGED_AC}, {@link #BATTERY_PLUGGED_USB}, + * or {@link #BATTERY_PLUGGED_WIRELESS} + * + * @return true if plugType is wired + * @hide + */ + public static boolean isPlugWired(int plugType) { + return plugType == BATTERY_PLUGGED_USB || plugType == BATTERY_PLUGGED_AC; + } } diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java index 12a495bf2821..fb22194098b6 100644 --- a/core/java/android/os/VintfObject.java +++ b/core/java/android/os/VintfObject.java @@ -80,4 +80,11 @@ public class VintfObject { * ("28", ["libjpeg.so", "libbase.so"])] */ public static native Map<String, String[]> getVndkSnapshots(); + + /** + * @return target FCM version, a number specified in the device manifest + * indicating the FCM version that the device manifest implements. Null if + * device manifest doesn't specify this number (for legacy devices). + */ + public static native Long getTargetFrameworkCompatibilityMatrixVersion(); } diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index b7b2b2de35e5..422e36baee70 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -1343,6 +1343,7 @@ public abstract class NotificationListenerService extends Service { /** * @hide */ + @GuardedBy("mLock") public final void applyUpdateLocked(NotificationRankingUpdate update) { mRankingMap = new RankingMap(update); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 0910c117c17c..5de25bae6a3e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -4806,6 +4806,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M; Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O; + Canvas.setCompatibilityVersion(targetSdkVersion); // In M and newer, our widgets can pass a "hint" value in the size // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 5131a8ad4bf0..8b64bad8fe62 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -619,6 +619,7 @@ public final class AutofillManager { /** * @hide */ + @GuardedBy("mLock") public boolean isCompatibilityModeEnabledLocked() { return mCompatibilityBridge != null; } @@ -709,6 +710,7 @@ public final class AutofillManager { notifyViewEntered(view, 0); } + @GuardedBy("mLock") private boolean shouldIgnoreViewEnteredLocked(@NonNull View view, int flags) { if (isDisabledByServiceLocked()) { if (sVerbose) { @@ -749,6 +751,7 @@ public final class AutofillManager { } /** Returns AutofillCallback if need fire EVENT_INPUT_UNAVAILABLE */ + @GuardedBy("mLock") private AutofillCallback notifyViewEnteredLocked(@NonNull View view, int flags) { if (shouldIgnoreViewEnteredLocked(view, flags)) return null; @@ -792,6 +795,7 @@ public final class AutofillManager { } } + @GuardedBy("mLock") void notifyViewExitedLocked(@NonNull View view) { ensureServiceClientAddedIfNeededLocked(); @@ -893,6 +897,7 @@ public final class AutofillManager { } /** Returns AutofillCallback if need fire EVENT_INPUT_UNAVAILABLE */ + @GuardedBy("mLock") private AutofillCallback notifyViewEnteredLocked(View view, int virtualId, Rect bounds, int flags) { AutofillCallback callback = null; @@ -936,6 +941,7 @@ public final class AutofillManager { } } + @GuardedBy("mLock") private void notifyViewExitedLocked(@NonNull View view, int virtualId) { ensureServiceClientAddedIfNeededLocked(); @@ -1087,6 +1093,7 @@ public final class AutofillManager { } } + @GuardedBy("mLock") private void commitLocked() { if (!mEnabled && !isActiveLocked()) { return; @@ -1115,6 +1122,7 @@ public final class AutofillManager { } } + @GuardedBy("mLock") private void cancelLocked() { if (!mEnabled && !isActiveLocked()) { return; @@ -1378,6 +1386,7 @@ public final class AutofillManager { return new AutofillId(parent.getAutofillViewId(), virtualId); } + @GuardedBy("mLock") private void startSessionLocked(@NonNull AutofillId id, @NonNull Rect bounds, @NonNull AutofillValue value, int flags) { if (sVerbose) { @@ -1408,6 +1417,7 @@ public final class AutofillManager { } } + @GuardedBy("mLock") private void finishSessionLocked() { if (sVerbose) Log.v(TAG, "finishSessionLocked(): " + getStateAsStringLocked()); @@ -1422,6 +1432,7 @@ public final class AutofillManager { resetSessionLocked(); } + @GuardedBy("mLock") private void cancelSessionLocked() { if (sVerbose) Log.v(TAG, "cancelSessionLocked(): " + getStateAsStringLocked()); @@ -1436,6 +1447,7 @@ public final class AutofillManager { resetSessionLocked(); } + @GuardedBy("mLock") private void resetSessionLocked() { mSessionId = NO_SESSION; mState = STATE_UNKNOWN; @@ -1444,6 +1456,7 @@ public final class AutofillManager { mSaveTriggerId = null; } + @GuardedBy("mLock") private void updateSessionLocked(AutofillId id, Rect bounds, AutofillValue value, int action, int flags) { if (sVerbose && action != ACTION_VIEW_EXITED) { @@ -1478,6 +1491,7 @@ public final class AutofillManager { } } + @GuardedBy("mLock") private void ensureServiceClientAddedIfNeededLocked() { if (getClient() == null) { return; @@ -1947,6 +1961,7 @@ public final class AutofillManager { pw.print(" verbose: "); pw.println(sVerbose); } + @GuardedBy("mLock") private String getStateAsStringLocked() { switch (mState) { case STATE_UNKNOWN: @@ -1964,14 +1979,17 @@ public final class AutofillManager { } } + @GuardedBy("mLock") private boolean isActiveLocked() { return mState == STATE_ACTIVE; } + @GuardedBy("mLock") private boolean isDisabledByServiceLocked() { return mState == STATE_DISABLED_BY_SERVICE; } + @GuardedBy("mLock") private boolean isFinishedLocked() { return mState == STATE_FINISHED; } @@ -2167,6 +2185,7 @@ public final class AutofillManager { AutofillValue.forText(node.getText())); } + @GuardedBy("mLock") private void updateTrackedViewsLocked() { if (mTrackedViews != null) { mTrackedViews.onVisibleForAutofillChangedLocked(); @@ -2311,6 +2330,7 @@ public final class AutofillManager { * @param id the id of the view/virtual view whose visibility changed. * @param isVisible visible if the view is visible in the view hierarchy. */ + @GuardedBy("mLock") void notifyViewVisibilityChangedLocked(@NonNull AutofillId id, boolean isVisible) { if (sDebug) { Log.d(TAG, "notifyViewVisibilityChangedLocked(): id=" + id + " isVisible=" @@ -2344,6 +2364,7 @@ public final class AutofillManager { * * @see AutofillClient#autofillClientIsVisibleForAutofill() */ + @GuardedBy("mLock") void onVisibleForAutofillChangedLocked() { // The visibility of the views might have changed while the client was not be visible, // hence update the visibility state for all views. diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 467e2a43d3e7..eb58b0919385 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -3828,6 +3828,7 @@ public class BatteryStatsImpl extends BatteryStats { mActiveHistoryStates2 = 0xffffffff; } + @GuardedBy("this") public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime, long realtime) { final boolean screenOff = !isScreenOn(screenState); @@ -3905,6 +3906,7 @@ public class BatteryStatsImpl extends BatteryStats { * This should only be called after the cpu times have been read. * @see #scheduleRemoveIsolatedUidLocked(int, int) */ + @GuardedBy("this") public void removeIsolatedUidLocked(int isolatedUid) { StatsLog.write( StatsLog.ISOLATED_UID_CHANGED, mIsolatedUids.get(isolatedUid, -1), @@ -4734,6 +4736,7 @@ public class BatteryStatsImpl extends BatteryStats { return; } + @GuardedBy("this") public void noteScreenStateLocked(int state) { state = mPretendScreenOff ? Display.STATE_OFF : state; @@ -9650,6 +9653,7 @@ public class BatteryStatsImpl extends BatteryStats { return ps; } + @GuardedBy("mBsi") public void updateUidProcessStateLocked(int procState) { int uidRunningState; // Make special note of Foreground Services @@ -11762,6 +11766,7 @@ public class BatteryStatsImpl extends BatteryStats { * and we are on battery with screen off, we give more of the cpu time to those apps holding * wakelocks. If the screen is on, we just assign the actual cpu time an app used. */ + @GuardedBy("this") public void updateCpuTimeLocked() { if (mPowerProfile == null) { return; @@ -12207,6 +12212,7 @@ public class BatteryStatsImpl extends BatteryStats { return false; } + @GuardedBy("this") protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery, final int oldStatus, final int level, final int chargeUAh) { boolean doWrite = false; @@ -12383,6 +12389,7 @@ public class BatteryStatsImpl extends BatteryStats { // This should probably be exposed in the API, though it's not critical public static final int BATTERY_PLUGGED_NONE = OsProtoEnums.BATTERY_PLUGGED_NONE; // = 0 + @GuardedBy("this") public void setBatteryStateLocked(final int status, final int health, final int plugType, final int level, /* not final */ int temp, final int volt, final int chargeUAh, final int chargeFullUAh) { @@ -13198,6 +13205,7 @@ public class BatteryStatsImpl extends BatteryStats { } } + @GuardedBy("this") public void dumpConstantsLocked(PrintWriter pw) { mConstants.dumpLocked(pw); } diff --git a/core/java/com/android/internal/os/FuseAppLoop.java b/core/java/com/android/internal/os/FuseAppLoop.java index 088e7268b984..12405ebce057 100644 --- a/core/java/com/android/internal/os/FuseAppLoop.java +++ b/core/java/com/android/internal/os/FuseAppLoop.java @@ -283,6 +283,7 @@ public class FuseAppLoop implements Handler.Callback { return -OsConstants.EBADF; } + @GuardedBy("mLock") private CallbackEntry getCallbackEntryOrThrowLocked(long inode) throws ErrnoException { final CallbackEntry entry = mCallbackMap.get(checkInode(inode)); if (entry == null) { @@ -291,12 +292,14 @@ public class FuseAppLoop implements Handler.Callback { return entry; } + @GuardedBy("mLock") private void recycleLocked(Args args) { if (mArgsPool.size() < ARGS_POOL_SIZE) { mArgsPool.add(args); } } + @GuardedBy("mLock") private void replySimpleLocked(long unique, int result) { if (mInstance != 0) { native_replySimple(mInstance, unique, result); diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index f70d3c2a27fd..221bf8823b74 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -35,7 +35,7 @@ oneway interface IStatusBar void animateCollapsePanels(); void togglePanel(); - void showChargingAnimation(int batteryLevel); + void showWirelessChargingAnimation(int batteryLevel); /** * Notifies the status bar of a System UI visibility flag change. diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index b53459e072d4..67dc81af5895 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -551,6 +551,7 @@ public class MenuBuilder implements Menu { mPreventDispatchingItemsChanged = true; clear(); clearHeader(); + mPresenters.clear(); mPreventDispatchingItemsChanged = false; mItemsChangedWhileDispatchPrevented = false; onItemsChanged(true); diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp index f6223fad3dcb..ed032c78f6c7 100644 --- a/core/jni/android/graphics/FontFamily.cpp +++ b/core/jni/android/graphics/FontFamily.cpp @@ -90,7 +90,7 @@ static void FontFamily_unref(jlong familyPtr) { } static bool addSkTypeface(NativeFamilyBuilder* builder, sk_sp<SkData>&& data, int ttcIndex, - jint givenWeight, jint givenItalic) { + jint weight, jint italic) { uirenderer::FatVector<SkFontArguments::Axis, 2> skiaAxes; for (const auto& axis : builder->axes) { skiaAxes.emplace_back(SkFontArguments::Axis{axis.axisTag, axis.value}); @@ -114,27 +114,15 @@ static bool addSkTypeface(NativeFamilyBuilder* builder, sk_sp<SkData>&& data, in std::shared_ptr<minikin::MinikinFont> minikinFont = std::make_shared<MinikinFontSkia>(std::move(face), fontPtr, fontSize, ttcIndex, builder->axes); + minikin::Font::Builder fontBuilder(minikinFont); - int weight = givenWeight; - bool italic = givenItalic == 1; - if (givenWeight == RESOLVE_BY_FONT_TABLE || givenItalic == RESOLVE_BY_FONT_TABLE) { - int os2Weight; - bool os2Italic; - if (!minikin::FontFamily::analyzeStyle(minikinFont, &os2Weight, &os2Italic)) { - ALOGE("analyzeStyle failed. Using default style"); - os2Weight = 400; - os2Italic = false; - } - if (givenWeight == RESOLVE_BY_FONT_TABLE) { - weight = os2Weight; - } - if (givenItalic == RESOLVE_BY_FONT_TABLE) { - italic = os2Italic; - } + if (weight != RESOLVE_BY_FONT_TABLE) { + fontBuilder.setWeight(weight); } - - builder->fonts.push_back(minikin::Font(minikinFont, - minikin::FontStyle(weight, static_cast<minikin::FontStyle::Slant>(italic)))); + if (italic != RESOLVE_BY_FONT_TABLE) { + fontBuilder.setSlant(static_cast<minikin::FontStyle::Slant>(italic != 0)); + } + builder->fonts.push_back(fontBuilder.build()); builder->axes.clear(); return true; } diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index 115d0d5a608b..482d028a67f3 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -576,7 +576,7 @@ namespace PaintGlue { minikin::FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle); float saveSkewX = paint->getTextSkewX(); bool savefakeBold = paint->isFakeBoldText(); - MinikinFontSkia::populateSkPaint(paint, baseFont.font, baseFont.fakery); + MinikinFontSkia::populateSkPaint(paint, baseFont.font->typeface().get(), baseFont.fakery); SkScalar spacing = paint->getFontMetrics(metrics); // The populateSkPaint call may have changed fake bold / text skew // because we want to measure with those effects applied, so now diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp index 6b961f54cf88..06de5daab7d2 100644 --- a/core/jni/android_graphics_Canvas.cpp +++ b/core/jni/android_graphics_Canvas.cpp @@ -573,6 +573,11 @@ static void freeTextLayoutCaches(JNIEnv* env, jobject) { minikin::Layout::purgeCaches(); } +static void setCompatibilityVersion(JNIEnv* env, jobject, jint apiLevel) { + Canvas::setCompatibilityVersion(apiLevel); +} + + }; // namespace CanvasJNI static const JNINativeMethod gMethods[] = { @@ -580,6 +585,7 @@ static const JNINativeMethod gMethods[] = { {"nInitRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster}, {"nFreeCaches", "()V", (void*) CanvasJNI::freeCaches}, {"nFreeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}, + {"nSetCompatibilityVersion", "(I)V", (void*) CanvasJNI::setCompatibilityVersion}, // ------------ @FastNative ---------------- {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap}, diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp index 16591685848e..e8ef349f5b7a 100644 --- a/core/jni/android_os_VintfObject.cpp +++ b/core/jni/android_os_VintfObject.cpp @@ -32,10 +32,13 @@ static jclass gString; static jclass gHashMapClazz; static jmethodID gHashMapInit; static jmethodID gHashMapPut; +static jclass gLongClazz; +static jmethodID gLongValueOf; namespace android { using vintf::HalManifest; +using vintf::Level; using vintf::SchemaType; using vintf::VintfObject; using vintf::XmlConverter; @@ -154,6 +157,14 @@ static jobject android_os_VintfObject_getVndkSnapshots(JNIEnv* env, jclass) { return jMap; } +static jobject android_os_VintfObject_getTargetFrameworkCompatibilityMatrixVersion(JNIEnv* env, jclass) { + std::shared_ptr<const HalManifest> manifest = VintfObject::GetDeviceHalManifest(); + if (manifest == nullptr || manifest->level() == Level::UNSPECIFIED) { + return nullptr; + } + return env->CallStaticObjectMethod(gLongClazz, gLongValueOf, static_cast<jlong>(manifest->level())); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gVintfObjectMethods[] = { @@ -163,6 +174,7 @@ static const JNINativeMethod gVintfObjectMethods[] = { {"getHalNamesAndVersions", "()[Ljava/lang/String;", (void*)android_os_VintfObject_getHalNamesAndVersions}, {"getSepolicyVersion", "()Ljava/lang/String;", (void*)android_os_VintfObject_getSepolicyVersion}, {"getVndkSnapshots", "()Ljava/util/Map;", (void*)android_os_VintfObject_getVndkSnapshots}, + {"getTargetFrameworkCompatibilityMatrixVersion", "()Ljava/lang/Long;", (void*)android_os_VintfObject_getTargetFrameworkCompatibilityMatrixVersion}, }; const char* const kVintfObjectPathName = "android/os/VintfObject"; @@ -175,6 +187,8 @@ int register_android_os_VintfObject(JNIEnv* env) gHashMapInit = GetMethodIDOrDie(env, gHashMapClazz, "<init>", "()V"); gHashMapPut = GetMethodIDOrDie(env, gHashMapClazz, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + gLongClazz = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/Long")); + gLongValueOf = GetStaticMethodIDOrDie(env, gLongClazz, "valueOf", "(J)Ljava/lang/Long;"); return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods, NELEM(gVintfObjectMethods)); diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto index ef777de06163..f8050a15e78e 100644 --- a/core/proto/android/service/package.proto +++ b/core/proto/android/service/package.proto @@ -49,7 +49,8 @@ message PackageServiceDumpProto { option (android.msg_privacy).dest = DEST_AUTOMATIC; optional int32 user_id = 1; - optional string name = 2 [ (android.privacy).dest = DEST_EXPLICIT ]; + // Name of the shared UID. eg: android.uid.bluetooth + optional string name = 2; } // Installed packages. diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml index ce4ac613824a..e80f16c466b3 100644 --- a/core/res/res/values/colors_material.xml +++ b/core/res/res/values/colors_material.xml @@ -79,8 +79,8 @@ <item name="secondary_content_alpha_material_light" format="float" type="dimen">0.54</item> <item name="highlight_alpha_material_light" format="float" type="dimen">0.16</item> - <item name="highlight_alpha_material_dark" format="float" type="dimen">0.32</item> - <item name="highlight_alpha_material_colored" format="float" type="dimen">0.48</item> + <item name="highlight_alpha_material_dark" format="float" type="dimen">0.16</item> + <item name="highlight_alpha_material_colored" format="float" type="dimen">0.16</item> <!-- Primary & accent colors --> <eat-comment /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index c8032a276659..9dffe6906a04 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2486,9 +2486,9 @@ <string-array translatable="false" name="config_globalActionsList"> <item>power</item> <item>restart</item> - <item>screenshot</item> - <item>logout</item> <item>lockdown</item> + <item>logout</item> + <item>screenshot</item> <item>bugreport</item> <item>users</item> </string-array> diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java index aefc47e95512..fb0f5344f643 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java @@ -17,6 +17,7 @@ package android.app.servertransaction; import static android.app.servertransaction.TestUtils.config; +import static android.app.servertransaction.TestUtils.mergedConfig; import static android.app.servertransaction.TestUtils.referrerIntentList; import static android.app.servertransaction.TestUtils.resultInfoList; @@ -151,6 +152,25 @@ public class ObjectPoolTests { } @Test + public void testRecycleActivityRelaunchItem() { + ActivityRelaunchItem emptyItem = ActivityRelaunchItem.obtain(null, null, 0, null, false); + Configuration overrideConfig = new Configuration(); + overrideConfig.assetsSeq = 5; + ActivityRelaunchItem item = ActivityRelaunchItem.obtain(resultInfoList(), + referrerIntentList(), 42, mergedConfig(), true); + assertNotSame(item, emptyItem); + assertFalse(item.equals(emptyItem)); + + item.recycle(); + assertEquals(item, emptyItem); + + ActivityRelaunchItem item2 = ActivityRelaunchItem.obtain(resultInfoList(), + referrerIntentList(), 42, mergedConfig(), true); + assertSame(item, item2); + assertFalse(item2.equals(emptyItem)); + } + + @Test public void testRecycleMoveToDisplayItem() { MoveToDisplayItem emptyItem = MoveToDisplayItem.obtain(0, null); MoveToDisplayItem item = MoveToDisplayItem.obtain(4, config()); diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java index e92351609256..d125fe790eba 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java +++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java @@ -21,6 +21,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import android.app.ResultInfo; import android.content.Intent; import android.content.res.Configuration; +import android.util.MergedConfiguration; import com.android.internal.content.ReferrerIntent; @@ -38,6 +39,15 @@ class TestUtils { return config; } + static MergedConfiguration mergedConfig() { + Configuration config = config(); + Configuration overrideConfig = new Configuration(); + overrideConfig.densityDpi = 30; + overrideConfig.screenWidthDp = 40; + overrideConfig.smallestScreenWidthDp = 15; + return new MergedConfiguration(config, overrideConfig); + } + static List<ResultInfo> resultInfoList() { String resultWho1 = "resultWho1"; int requestCode1 = 7; diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index 77aaa2d7f9ea..0906435db912 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -17,6 +17,7 @@ package android.app.servertransaction; import static android.app.servertransaction.TestUtils.config; +import static android.app.servertransaction.TestUtils.mergedConfig; import static android.app.servertransaction.TestUtils.referrerIntentList; import static android.app.servertransaction.TestUtils.resultInfoList; @@ -27,7 +28,6 @@ import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; -import android.app.ResultInfo; import android.content.ComponentName; import android.content.IIntentReceiver; import android.content.Intent; @@ -53,7 +53,6 @@ import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import com.android.internal.app.IVoiceInteractor; -import com.android.internal.content.ReferrerIntent; import org.junit.Before; import org.junit.Test; @@ -243,6 +242,22 @@ public class TransactionParcelTests { } @Test + public void testRelaunch() { + // Write to parcel + Configuration overrideConfig = new Configuration(); + overrideConfig.assetsSeq = 5; + ActivityRelaunchItem item = ActivityRelaunchItem.obtain(resultInfoList(), + referrerIntentList(), 35, mergedConfig(), true); + writeAndPrepareForReading(item); + + // Read from parcel and assert + ActivityRelaunchItem result = ActivityRelaunchItem.CREATOR.createFromParcel(mParcel); + + assertEquals(item.hashCode(), result.hashCode()); + assertTrue(item.equals(result)); + } + + @Test public void testPause() { // Write to parcel PauseActivityItem item = PauseActivityItem.obtain(true /* finished */, @@ -435,12 +450,6 @@ public class TransactionParcelTests { } @Override - public void scheduleRelaunchActivity(IBinder iBinder, List<ResultInfo> list, - List<ReferrerIntent> list1, int i, boolean b, Configuration configuration, - Configuration configuration1, boolean b1) throws RemoteException { - } - - @Override public void scheduleSleeping(IBinder iBinder, boolean b) throws RemoteException { } diff --git a/core/tests/coretests/src/android/view/menu/ContextMenuTest.java b/core/tests/coretests/src/android/view/menu/ContextMenuTest.java index 59d4e55d8d45..657a7fc7b798 100644 --- a/core/tests/coretests/src/android/view/menu/ContextMenuTest.java +++ b/core/tests/coretests/src/android/view/menu/ContextMenuTest.java @@ -41,6 +41,13 @@ public class ContextMenuTest extends ActivityInstrumentationTestCase<ContextMenu testMenuPosition(getActivity().getTargetRtl()); } + public void testContextMenuPositionRepetitive() throws InterruptedException { + // Regression test for b/72507876 + testMenuPosition(getActivity().getTargetLtr()); + testMenuPosition(getActivity().getTargetRtl()); + testMenuPosition(getActivity().getTargetLtr()); + } + private void testMenuPosition(View target) throws InterruptedException { final int minScreenDimension = getMinScreenDimension(); if (minScreenDimension < 320) { diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index f5bf754ae6ef..7ea35e73619a 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -18,6 +18,8 @@ package android.graphics; import static android.graphics.BitmapFactory.Options.validate; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.res.AssetManager; import android.content.res.Resources; import android.os.Trace; @@ -518,8 +520,9 @@ public class BitmapFactory { * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve} */ - public static Bitmap decodeResourceStream(Resources res, TypedValue value, - InputStream is, Rect pad, Options opts) { + @Nullable + public static Bitmap decodeResourceStream(@Nullable Resources res, @Nullable TypedValue value, + @Nullable InputStream is, @Nullable Rect pad, @Nullable Options opts) { validate(opts); if (opts == null) { opts = new Options(); @@ -707,7 +710,9 @@ public class BitmapFactory { * <code>is.mark(1024)</code> would be called. As of * {@link android.os.Build.VERSION_CODES#KITKAT}, this is no longer the case.</p> */ - public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) { + @Nullable + public static Bitmap decodeStream(@Nullable InputStream is, @Nullable Rect outPadding, + @Nullable Options opts) { // we don't throw in this case, thus allowing the caller to only check // the cache, and not force the image to be decoded. if (is == null) { @@ -742,7 +747,8 @@ public class BitmapFactory { * Private helper function for decoding an InputStream natively. Buffers the input enough to * do a rewind as needed, and supplies temporary storage if necessary. is MUST NOT be null. */ - private static Bitmap decodeStreamInternal(InputStream is, Rect outPadding, Options opts) { + private static Bitmap decodeStreamInternal(@NonNull InputStream is, + @Nullable Rect outPadding, @Nullable Options opts) { // ASSERT(is != null); byte [] tempStorage = null; if (opts != null) tempStorage = opts.inTempStorage; diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index f5e863305766..d925441e3657 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -1219,10 +1219,14 @@ public class Canvas extends BaseCanvas { nFreeTextLayoutCaches(); } + /** @hide */ + public static void setCompatibilityVersion(int apiLevel) { nSetCompatibilityVersion(apiLevel); } + private static native void nFreeCaches(); private static native void nFreeTextLayoutCaches(); private static native long nInitRaster(Bitmap bitmap); private static native long nGetNativeFinalizer(); + private static native void nSetCompatibilityVersion(int apiLevel); // ---------------- @FastNative ------------------- diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index 3cca47b47a59..acefead785c4 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -25,7 +25,7 @@ import android.annotation.Nullable; import android.annotation.RawRes; import android.content.ContentResolver; import android.content.res.AssetFileDescriptor; -import android.content.res.AssetManager.AssetInputStream; +import android.content.res.AssetManager; import android.content.res.Resources; import android.graphics.drawable.AnimatedImageDrawable; import android.graphics.drawable.Drawable; @@ -263,63 +263,6 @@ public final class ImageDecoder implements AutoCloseable { } } - /** - * Takes ownership of the AssetInputStream. - * - * @hide - */ - public static class AssetInputStreamSource extends Source { - public AssetInputStreamSource(@NonNull AssetInputStream ais, - @NonNull Resources res, @NonNull TypedValue value) { - mAssetInputStream = ais; - mResources = res; - - if (value.density == TypedValue.DENSITY_DEFAULT) { - mDensity = DisplayMetrics.DENSITY_DEFAULT; - } else if (value.density != TypedValue.DENSITY_NONE) { - mDensity = value.density; - } else { - mDensity = Bitmap.DENSITY_NONE; - } - } - - private AssetInputStream mAssetInputStream; - private final Resources mResources; - private final int mDensity; - - @Override - public Resources getResources() { return mResources; } - - @Override - public int getDensity() { - return mDensity; - } - - @Override - public ImageDecoder createImageDecoder() throws IOException { - ImageDecoder decoder = null; - synchronized (this) { - if (mAssetInputStream == null) { - throw new IOException("Cannot reuse AssetInputStreamSource"); - } - AssetInputStream ais = mAssetInputStream; - mAssetInputStream = null; - try { - long asset = ais.getNativeAsset(); - decoder = nCreate(asset); - } finally { - if (decoder == null) { - IoUtils.closeQuietly(ais); - } else { - decoder.mInputStream = ais; - decoder.mOwnsInputStream = true; - } - } - return decoder; - } - } - } - private static class ResourceSource extends Source { ResourceSource(@NonNull Resources res, int resId) { mResources = res; @@ -353,7 +296,11 @@ public final class ImageDecoder implements AutoCloseable { mResDensity = value.density; } - long asset = ((AssetInputStream) is).getNativeAsset(); + if (!(is instanceof AssetManager.AssetInputStream)) { + // This should never happen. + throw new RuntimeException("Resource is not an asset?"); + } + long asset = ((AssetManager.AssetInputStream) is).getNativeAsset(); decoder = nCreate(asset); } finally { if (decoder == null) { diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 44ba78557678..8af2fd8bbb5e 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -1174,8 +1174,10 @@ public abstract class Drawable { * * @deprecated Prefer the version without an Options object. */ - public static Drawable createFromResourceStream(Resources res, TypedValue value, - InputStream is, String srcName, BitmapFactory.Options opts) { + @Nullable + public static Drawable createFromResourceStream(@Nullable Resources res, + @Nullable TypedValue value, @Nullable InputStream is, @Nullable String srcName, + @Nullable BitmapFactory.Options opts) { if (is == null) { return null; } @@ -1199,7 +1201,6 @@ public abstract class Drawable { // an application in compatibility mode, without scaling those down // to the compatibility density only to have them scaled back up when // drawn to the screen. - if (opts == null) opts = new BitmapFactory.Options(); opts.inScreenDensity = Drawable.resolveDensity(res, 0); Bitmap bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts); if (bm != null) { diff --git a/graphics/java/android/graphics/drawable/RippleForeground.java b/graphics/java/android/graphics/drawable/RippleForeground.java index 4129868079c7..a8dc34af292b 100644 --- a/graphics/java/android/graphics/drawable/RippleForeground.java +++ b/graphics/java/android/graphics/drawable/RippleForeground.java @@ -110,6 +110,7 @@ class RippleForeground extends RippleComponent { // Take 60% of the maximum of the width and height, then divided half to get the radius. mStartRadius = Math.max(bounds.width(), bounds.height()) * 0.3f; + clampStartingPosition(); } @Override @@ -350,7 +351,7 @@ class RippleForeground extends RippleComponent { final float cY = mBounds.exactCenterY(); final float dX = mStartingX - cX; final float dY = mStartingY - cY; - final float r = mTargetRadius; + final float r = mTargetRadius - mStartRadius; if (dX * dX + dY * dY > r * r) { // Point is outside the circle, clamp to the perimeter. final double angle = Math.atan2(dY, dX); diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp index 1d2c597c4c8c..a65d49b7e32f 100644 --- a/libs/androidfw/LoadedArsc.cpp +++ b/libs/androidfw/LoadedArsc.cpp @@ -409,14 +409,10 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, util::ReadUtf16StringFromDevice(header->name, arraysize(header->name), &loaded_package->package_name_); - // A TypeSpec builder. We use this to accumulate the set of Types - // available for a TypeSpec, and later build a single, contiguous block - // of memory that holds all the Types together with the TypeSpec. - std::unique_ptr<TypeSpecPtrBuilder> types_builder; - - // Keep track of the last seen type index. Since type IDs are 1-based, - // this records their index, which is 0-based (type ID - 1). - uint8_t last_type_idx = 0; + // A map of TypeSpec builders, each associated with an type index. + // We use these to accumulate the set of Types available for a TypeSpec, and later build a single, + // contiguous block of memory that holds all the Types together with the TypeSpec. + std::unordered_map<int, std::unique_ptr<TypeSpecPtrBuilder>> type_builder_map; ChunkIterator iter(chunk.data_ptr(), chunk.data_size()); while (iter.HasNext()) { @@ -450,28 +446,6 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, case RES_TABLE_TYPE_SPEC_TYPE: { ATRACE_NAME("LoadTableTypeSpec"); - // Starting a new TypeSpec, so finish the old one if there was one. - if (types_builder) { - TypeSpecPtr type_spec_ptr = types_builder->Build(); - if (type_spec_ptr == nullptr) { - LOG(ERROR) << "Too many type configurations, overflow detected."; - return {}; - } - - // We only add the type to the package if there is no IDMAP, or if the type is - // overlaying something. - if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) { - // If this is an overlay, insert it at the target type ID. - if (type_spec_ptr->idmap_entries != nullptr) { - last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1; - } - loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); - } - - types_builder = {}; - last_type_idx = 0; - } - const ResTable_typeSpec* type_spec = child_chunk.header<ResTable_typeSpec>(); if (type_spec == nullptr) { LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small."; @@ -506,8 +480,6 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, return {}; } - last_type_idx = type_spec->id - 1; - // If this is an overlay, associate the mapping of this type to the target type // from the IDMAP. const IdmapEntry_header* idmap_entry_header = nullptr; @@ -515,7 +487,13 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, idmap_entry_header = loaded_idmap->GetEntryMapForType(type_spec->id); } - types_builder = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header); + std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1]; + if (builder_ptr == nullptr) { + builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header); + } else { + LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x", + type_spec->id); + } } break; case RES_TABLE_TYPE_TYPE: { @@ -530,12 +508,15 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, } // Type chunks must be preceded by their TypeSpec chunks. - if (!types_builder || type->id - 1 != last_type_idx) { - LOG(ERROR) << "RES_TABLE_TYPE_TYPE found without preceding RES_TABLE_TYPE_SPEC_TYPE."; + std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type->id - 1]; + if (builder_ptr != nullptr) { + builder_ptr->AddType(type); + } else { + LOG(ERROR) << StringPrintf( + "RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE.", + type->id); return {}; } - - types_builder->AddType(type); } break; case RES_TABLE_LIBRARY_TYPE: { @@ -561,7 +542,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, arraysize(entry_iter->packageName), &package_name); if (dtohl(entry_iter->packageId) >= std::numeric_limits<uint8_t>::max()) { - LOG(ERROR) << base::StringPrintf( + LOG(ERROR) << StringPrintf( "Package ID %02x in RES_TABLE_LIBRARY_TYPE too large for package '%s'.", dtohl(entry_iter->packageId), package_name.c_str()); return {}; @@ -574,14 +555,20 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, } break; default: - LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); + LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } - // Finish the last TypeSpec. - if (types_builder) { - TypeSpecPtr type_spec_ptr = types_builder->Build(); + if (iter.HadError()) { + LOG(ERROR) << iter.GetLastError(); + return {}; + } + + // Flatten and construct the TypeSpecs. + for (auto& entry : type_builder_map) { + uint8_t type_idx = static_cast<uint8_t>(entry.first); + TypeSpecPtr type_spec_ptr = entry.second->Build(); if (type_spec_ptr == nullptr) { LOG(ERROR) << "Too many type configurations, overflow detected."; return {}; @@ -592,20 +579,15 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) { // If this is an overlay, insert it at the target type ID. if (type_spec_ptr->idmap_entries != nullptr) { - last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1; + type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1; } - loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); + loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr); } } - if (iter.HadError()) { - LOG(ERROR) << iter.GetLastError(); - return {}; - } return std::move(loaded_package); } - bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool load_as_shared_library) { ATRACE_CALL(); @@ -655,7 +637,7 @@ bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, } break; default: - LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); + LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } @@ -687,7 +669,7 @@ std::unique_ptr<const LoadedArsc> LoadedArsc::Load(const StringPiece& data, break; default: - LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); + LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp index bedebd66cb2f..cae632ddea30 100644 --- a/libs/androidfw/tests/LoadedArsc_test.cpp +++ b/libs/androidfw/tests/LoadedArsc_test.cpp @@ -16,6 +16,7 @@ #include "androidfw/LoadedArsc.h" +#include "android-base/file.h" #include "androidfw/ResourceUtils.h" #include "TestHelpers.h" @@ -29,6 +30,7 @@ namespace basic = com::android::basic; namespace libclient = com::android::libclient; namespace sparse = com::android::sparse; +using ::android::base::ReadFileToString; using ::testing::Eq; using ::testing::Ge; using ::testing::IsNull; @@ -177,6 +179,46 @@ TEST(LoadedArscTest, LoadFeatureSplit) { ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], entry_index), NotNull()); } +// AAPT(2) generates resource tables with chunks in a certain order. The rule is that +// a RES_TABLE_TYPE_TYPE with id `i` must always be preceded by a RES_TABLE_TYPE_SPEC_TYPE with +// id `i`. The RES_TABLE_TYPE_SPEC_TYPE does not need to be directly preceding, however. +// +// AAPT(2) generates something like: +// RES_TABLE_TYPE_SPEC_TYPE id=1 +// RES_TABLE_TYPE_TYPE id=1 +// RES_TABLE_TYPE_SPEC_TYPE id=2 +// RES_TABLE_TYPE_TYPE id=2 +// +// But the following is valid too: +// RES_TABLE_TYPE_SPEC_TYPE id=1 +// RES_TABLE_TYPE_SPEC_TYPE id=2 +// RES_TABLE_TYPE_TYPE id=1 +// RES_TABLE_TYPE_TYPE id=2 +// +TEST(LoadedArscTest, LoadOutOfOrderTypeSpecs) { + std::string contents; + ASSERT_TRUE( + ReadFileFromZipToString(GetTestDataPath() + "/out_of_order_types/out_of_order_types.apk", + "resources.arsc", &contents)); + + std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents)); + ASSERT_THAT(loaded_arsc, NotNull()); + + ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u)); + const auto& package = loaded_arsc->GetPackages()[0]; + ASSERT_THAT(package, NotNull()); + + const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0); + ASSERT_THAT(type_spec, NotNull()); + ASSERT_THAT(type_spec->type_count, Ge(1u)); + ASSERT_THAT(type_spec->types[0], NotNull()); + + type_spec = package->GetTypeSpecByTypeIndex(1); + ASSERT_THAT(type_spec, NotNull()); + ASSERT_THAT(type_spec->type_count, Ge(1u)); + ASSERT_THAT(type_spec->types[0], NotNull()); +} + class MockLoadedIdmap : public LoadedIdmap { public: MockLoadedIdmap() : LoadedIdmap() { diff --git a/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml b/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml new file mode 100644 index 000000000000..34016db8b808 --- /dev/null +++ b/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.app" /> diff --git a/libs/androidfw/tests/data/out_of_order_types/build b/libs/androidfw/tests/data/out_of_order_types/build new file mode 100755 index 000000000000..8496f81038b0 --- /dev/null +++ b/libs/androidfw/tests/data/out_of_order_types/build @@ -0,0 +1,22 @@ +#!/bin/bash +# +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set -e + +aapt2 compile --dir res -o compiled.flata +aapt2 link --manifest AndroidManifest.xml -o out_of_order_types.apk compiled.flata +rm compiled.flata diff --git a/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt b/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt new file mode 100644 index 000000000000..eca8f478c501 --- /dev/null +++ b/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt @@ -0,0 +1,43 @@ +00000000: 0200 0c00 ac02 0000 0100 0000 0100 1c00 ................ +00000010: 1c00 0000 0000 0000 0000 0000 0001 0000 ................ +00000020: 1c00 0000 0000 0000 0002 2001 8402 0000 .......... ..... +00000030: 7f00 0000 6300 6f00 6d00 2e00 6100 6e00 ....c.o.m...a.n. +00000040: 6400 7200 6f00 6900 6400 2e00 6100 7000 d.r.o.i.d...a.p. +00000050: 7000 0000 0000 0000 0000 0000 0000 0000 p............... +00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +000000a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +000000b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +000000c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +000000d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +000000e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +000000f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00000110: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00000120: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00000130: 0000 0000 2001 0000 0000 0000 6401 0000 .... .......d... +00000140: 0000 0000 0000 0000 0100 1c00 4400 0000 ............D... +00000150: 0200 0000 0000 0000 0000 0000 2400 0000 ............$... +00000160: 0000 0000 0000 0000 0c00 0000 0400 6200 ..............b. +00000170: 6f00 6f00 6c00 0000 0700 6900 6e00 7400 o.o.l.....i.n.t. +00000180: 6500 6700 6500 7200 0000 0000 0100 1c00 e.g.e.r......... +00000190: 2800 0000 0100 0000 0000 0000 0001 0000 (............... +000001a0: 2000 0000 0000 0000 0000 0000 0404 7465 .............te +000001b0: 7374 0000 0202 1000 1400 0000 0100 0000 st.............. +000001c0: 0100 0000 0000 0000 0202 1000 1400 0000 +000001d0: 0200 0000 0100 0000 0000 0000 0102 5400 +000001e0: 6800 0000 0100 0000 0100 0000 5800 0000 +000001f0: 4000 0000 0000 0000 0000 0000 0000 0000 +00000200: 0000 0000 0000 0000 0000 0000 0000 0000 +00000210: 0000 0000 0000 0000 0000 0000 0000 0000 +00000220: 0000 0000 0000 0000 0000 0000 0000 0000 +00000230: 0000 0000 0800 0000 0000 0000 0800 0012 +00000240: ffff ffff 0102 5400 6800 0000 0200 0000 ......T.h....... +00000250: 0100 0000 5800 0000 4000 0000 0000 0000 ....X...@....... +00000260: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00000270: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00000280: 0000 0000 0000 0000 0000 0000 0000 0000 ................ +00000290: 0000 0000 0000 0000 0000 0000 0800 0000 ................ +000002a0: 0000 0000 0800 0010 0100 0000 ............ diff --git a/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk b/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk Binary files differnew file mode 100644 index 000000000000..75146e0fc476 --- /dev/null +++ b/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk diff --git a/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml b/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml new file mode 100644 index 000000000000..7c54fbae9f21 --- /dev/null +++ b/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <bool name="test">true</bool> + <integer name="test">1</integer> +</resources> diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 9e0d10d07892..2b0b22df7edf 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -742,6 +742,12 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& p SkPaint paintCopy(paint); paintCopy.setTextAlign(SkPaint::kLeft_Align); SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); + // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and + // older. + if (!mCanvasOwned && sApiLevel <= 27 && paintCopy.getStrokeWidth() <= 0 + && paintCopy.getStyle() == SkPaint::kStroke_Style) { + paintCopy.setStyle(SkPaint::kFill_Style); + } SkRect bounds = SkRect::MakeLTRB(boundsLeft + x, boundsTop + y, boundsRight + x, boundsBottom + y); diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index f118e8d0a53e..f662406bdc38 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -557,13 +557,12 @@ void Tree::Cache::clear() { mAtlasKey = INVALID_ATLAS_KEY; } -void Tree::draw(SkCanvas* canvas) { +void Tree::draw(SkCanvas* canvas, const SkRect& bounds) { SkRect src; sk_sp<SkSurface> vdSurface = mCache.getSurface(&src); if (vdSurface) { canvas->drawImageRect(vdSurface->makeImageSnapshot().get(), src, - mutateProperties()->getBounds(), getPaint(), - SkCanvas::kFast_SrcRectConstraint); + bounds, getPaint(), SkCanvas::kFast_SrcRectConstraint); } else { // Handle the case when VectorDrawableAtlas has been destroyed, because of memory pressure. // We render the VD into a temporary standalone buffer and mark the frame as dirty. Next @@ -575,8 +574,7 @@ void Tree::draw(SkCanvas* canvas) { int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth()); int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight()); canvas->drawBitmapRect(skiaBitmap, SkRect::MakeWH(scaledWidth, scaledHeight), - mutateProperties()->getBounds(), getPaint(), - SkCanvas::kFast_SrcRectConstraint); + bounds, getPaint(), SkCanvas::kFast_SrcRectConstraint); mCache.clear(); markDirty(); } diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index d9cf8ab7eedf..da52a9503377 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -644,7 +644,7 @@ public: * Draws VD cache into a canvas. This should always be called from RT and it works with Skia * pipelines only. */ - void draw(SkCanvas* canvas); + void draw(SkCanvas* canvas, const SkRect& bounds); /** * Draws VD into a GPU backed surface. diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp index 284fd836745c..ad4c8be74d75 100644 --- a/libs/hwui/hwui/Canvas.cpp +++ b/libs/hwui/hwui/Canvas.cpp @@ -225,4 +225,10 @@ void Canvas::drawTextOnPath(const uint16_t* text, int count, minikin::Bidi bidiF MinikinUtils::forFontRun(layout, &paintCopy, f); } +int Canvas::sApiLevel = 1; + +void Canvas::setCompatibilityVersion(int apiLevel) { + sApiLevel = apiLevel; +} + } // namespace android diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index 3ddf1c48b83f..fabb8d2e4549 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -116,6 +116,14 @@ public: static Canvas* create_canvas(SkCanvas* skiaCanvas); /** + * Sets the target SDK version used to build the app. + * + * @param apiLevel API level + * + */ + static void setCompatibilityVersion(int apiLevel); + + /** * Provides a Skia SkCanvas interface that acts as a proxy to this Canvas. * It is useful for testing and clients (e.g. Picture/Movie) that expect to * draw their contents into an SkCanvas. @@ -282,6 +290,8 @@ protected: virtual void drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset, const SkPaint& paint, const SkPath& path, size_t start, size_t end) = 0; + static int sApiLevel; + friend class DrawTextFunctor; friend class DrawTextOnPathFunctor; friend class uirenderer::SkiaCanvasProxy; diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp index 091b5267881d..dca9ef5559a6 100644 --- a/libs/hwui/hwui/Typeface.cpp +++ b/libs/hwui/hwui/Typeface.cpp @@ -132,8 +132,8 @@ Typeface* Typeface::createFromFamilies(std::vector<std::shared_ptr<minikin::Font bool italicFromFont; const minikin::FontStyle defaultStyle; - const minikin::MinikinFont* mf = - families.empty() ? nullptr : families[0]->getClosestMatch(defaultStyle).font; + const minikin::MinikinFont* mf = families.empty() ? nullptr + : families[0]->getClosestMatch(defaultStyle).font->typeface().get(); if (mf != nullptr) { SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface(); const SkFontStyle& style = skTypeface->fontStyle(); @@ -183,7 +183,7 @@ void Typeface::setRobotoTypefaceForTest() { std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>( std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>()); std::vector<minikin::Font> fonts; - fonts.push_back(minikin::Font(std::move(font), minikin::FontStyle())); + fonts.push_back(minikin::Font::Builder(font).build()); std::shared_ptr<minikin::FontCollection> collection = std::make_shared<minikin::FontCollection>( std::make_shared<minikin::FontFamily>(std::move(fonts))); diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index eabe2e87fc49..25c76eb4db3e 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -124,14 +124,19 @@ void SkiaRecordingCanvas::callDrawGLFunction(Functor* functor, class VectorDrawable : public SkDrawable { public: - VectorDrawable(VectorDrawableRoot* tree) : mRoot(tree) {} + VectorDrawable(VectorDrawableRoot* tree) + : mRoot(tree) + , mBounds(tree->stagingProperties()->getBounds()) {} protected: - virtual SkRect onGetBounds() override { return SkRect::MakeLargest(); } - virtual void onDraw(SkCanvas* canvas) override { mRoot->draw(canvas); } + virtual SkRect onGetBounds() override { return mBounds; } + virtual void onDraw(SkCanvas* canvas) override { + mRoot->draw(canvas, mBounds); + } private: sp<VectorDrawableRoot> mRoot; + SkRect mBounds; }; void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp index 2953ea8b21e9..15c0ab1ad8d2 100644 --- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp +++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp @@ -471,6 +471,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(RenderNodeDrawable, projectionHwLayer) { sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; } void onCopyOnWrite(ContentChangeMode) override {} int* mDrawCounter; + void onWritePixels(const SkPixmap&, int x, int y) {} }; auto receiverBackground = TestUtils::createSkiaNode( @@ -1143,4 +1144,47 @@ TEST(ReorderBarrierDrawable, testShadowMatrix) { RenderNodeDrawable drawable(parent.get(), &canvas, false); canvas.drawDrawable(&drawable); EXPECT_EQ(6, canvas.getIndex()); -}
\ No newline at end of file +} + +// Draw a vector drawable twice but with different bounds and verify correct bounds are used. +RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaRecordingCanvas, drawVectorDrawable) { + static const int CANVAS_WIDTH = 100; + static const int CANVAS_HEIGHT = 200; + class VectorDrawableTestCanvas : public TestCanvasBase { + public: + VectorDrawableTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {} + void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, + const SkPaint* paint, SrcRectConstraint constraint) override { + const int index = mDrawCounter++; + switch (index) { + case 0: + EXPECT_EQ(dst, SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT)); + break; + case 1: + EXPECT_EQ(dst, SkRect::MakeWH(CANVAS_WIDTH/2, CANVAS_HEIGHT)); + break; + default: + ADD_FAILURE(); + } + } + }; + + VectorDrawable::Group* group = new VectorDrawable::Group(); + sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group)); + vectorDrawable->mutateStagingProperties()->setScaledSize(CANVAS_WIDTH/10, CANVAS_HEIGHT/10); + + auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, + [&](RenderProperties& props, SkiaRecordingCanvas& canvas) { + vectorDrawable->mutateStagingProperties()->setBounds(SkRect::MakeWH(CANVAS_WIDTH, + CANVAS_HEIGHT)); + canvas.drawVectorDrawable(vectorDrawable.get()); + vectorDrawable->mutateStagingProperties()->setBounds(SkRect::MakeWH(CANVAS_WIDTH/2, + CANVAS_HEIGHT)); + canvas.drawVectorDrawable(vectorDrawable.get()); + }); + + VectorDrawableTestCanvas canvas; + RenderNodeDrawable drawable(node.get(), &canvas, true); + canvas.drawDrawable(&drawable); + EXPECT_EQ(2, canvas.mDrawCounter); +} diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp index 8fdb0e347afa..42a92fcc7d89 100644 --- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp +++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp @@ -250,6 +250,7 @@ public: sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; } T* canvas() { return static_cast<T*>(getCanvas()); } void onCopyOnWrite(ContentChangeMode) override {} + void onWritePixels(const SkPixmap&, int x, int y) override {} }; } diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp index 2232c25de345..e424a266bf72 100644 --- a/libs/hwui/tests/unit/TypefaceTests.cpp +++ b/libs/hwui/tests/unit/TypefaceTests.cpp @@ -57,7 +57,7 @@ std::shared_ptr<minikin::FontFamily> buildFamily(const char* fileName) { std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>( std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>()); std::vector<minikin::Font> fonts; - fonts.push_back(minikin::Font(std::move(font), minikin::FontStyle())); + fonts.push_back(minikin::Font::Builder(font).build()); return std::make_shared<minikin::FontFamily>(std::move(fonts)); } diff --git a/media/java/android/media/MediaDataSource.java b/media/java/android/media/MediaDataSource.java index 948da0b97910..4ba2120f5b09 100644 --- a/media/java/android/media/MediaDataSource.java +++ b/media/java/android/media/MediaDataSource.java @@ -34,8 +34,8 @@ public abstract class MediaDataSource implements Closeable { /** * Called to request data from the given position. * - * Implementations should should write up to {@code size} bytes into - * {@code buffer}, and return the number of bytes written. + * Implementations should fill {@code buffer} with up to {@code size} + * bytes of data, and return the number of valid bytes in the buffer. * * Return {@code 0} if size is zero (thus no bytes are read). * diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index c926e1ff48a7..c1aa2dcfbdb5 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -250,6 +250,19 @@ <item>Best Effort (Adaptive Bit Rate)</item> </string-array> + <!-- TODO: Enable for translation per b/73007419 --> + <!-- Summaries for Bluetooth Audio Active Device status. [CHAR LIMIT=50]--> + <string-array name="bluetooth_audio_active_device_summaries" translatable="false" > + <!-- Status message when the device is not Active. --> + <item></item> + <!-- Status message when the device is Active for Media and Phone. --> + <item>, active</item> + <!-- Status message when the device is Active for Media only. --> + <item>, active(media)</item> + <!-- Status message when the device is Active for Phone only. --> + <item>, active(phone)</item> + </string-array> + <!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] --> <string-array name="select_logd_size_titles"> <item>Off</item> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 1cff59cf9b01..e557c65ca9d3 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -128,27 +128,27 @@ <!-- Bluetooth settings. Message when connecting to a device --> <string name="bluetooth_connecting">Connecting\u2026</string> <!-- Bluetooth settings. Message when connected to a device. [CHAR LIMIT=40] --> - <string name="bluetooth_connected">Connected</string> + <string name="bluetooth_connected">Connected<xliff:g id="active_device">%1$s</xliff:g></string> <!--Bluetooth settings screen, summary text under individual Bluetooth devices when pairing --> <string name="bluetooth_pairing">Pairing\u2026</string> <!-- Bluetooth settings. Message when connected to a device, except for phone audio. [CHAR LIMIT=40] --> - <string name="bluetooth_connected_no_headset">Connected (no phone)</string> + <string name="bluetooth_connected_no_headset">Connected (no phone)<xliff:g id="active_device">%1$s</xliff:g></string> <!-- Bluetooth settings. Message when connected to a device, except for media audio. [CHAR LIMIT=40] --> - <string name="bluetooth_connected_no_a2dp">Connected (no media)</string> + <string name="bluetooth_connected_no_a2dp">Connected (no media)<xliff:g id="active_device">%1$s</xliff:g></string> <!-- Bluetooth settings. Message when connected to a device, except for map. [CHAR LIMIT=40] --> - <string name="bluetooth_connected_no_map">Connected (no message access)</string> + <string name="bluetooth_connected_no_map">Connected (no message access)<xliff:g id="active_device">%1$s</xliff:g></string> <!-- Bluetooth settings. Message when connected to a device, except for phone/media audio. [CHAR LIMIT=40] --> - <string name="bluetooth_connected_no_headset_no_a2dp">Connected (no phone or media)</string> + <string name="bluetooth_connected_no_headset_no_a2dp">Connected (no phone or media)<xliff:g id="active_device">%1$s</xliff:g></string> <!-- Bluetooth settings. Message when connected to a device, showing remote device battery level. [CHAR LIMIT=NONE] --> - <string name="bluetooth_connected_battery_level">Connected, battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g></string> + <string name="bluetooth_connected_battery_level">Connected, battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g><xliff:g id="active_device">%2$s</xliff:g></string> <!-- Bluetooth settings. Message when connected to a device, except for phone audio, showing remote device battery level. [CHAR LIMIT=NONE] --> - <string name="bluetooth_connected_no_headset_battery_level">Connected (no phone), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g></string> + <string name="bluetooth_connected_no_headset_battery_level">Connected (no phone), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g><xliff:g id="active_device">%2$s</xliff:g></string> <!-- Bluetooth settings. Message when connected to a device, except for media audio, showing remote device battery level. [CHAR LIMIT=NONE] --> - <string name="bluetooth_connected_no_a2dp_battery_level">Connected (no media), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g></string> + <string name="bluetooth_connected_no_a2dp_battery_level">Connected (no media), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g><xliff:g id="active_device">%2$s</xliff:g></string> <!-- Bluetooth settings. Message when connected to a device, except for phone/media audio, showing remote device battery level. [CHAR LIMIT=NONE] --> - <string name="bluetooth_connected_no_headset_no_a2dp_battery_level">Connected (no phone or media), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g></string> + <string name="bluetooth_connected_no_headset_no_a2dp_battery_level">Connected (no phone or media), battery <xliff:g id="battery_level_as_percentage">%1$s</xliff:g><xliff:g id="active_device">%2$s</xliff:g></string> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the A2DP profile. --> <string name="bluetooth_profile_a2dp">Media audio</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index fb0f75b522b3..e1ebbc4c166c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -940,60 +940,55 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> com.android.settingslib.Utils.formatPercentage(batteryLevel); } - // TODO: A temporary workaround solution using string description the device is active. - // Issue tracked by b/72317067 . - // An alternative solution would be visual indication. - // Intentionally not adding the strings to strings.xml for now: - // 1) If this is just a short-term solution, no need to waste translation effort - // 2) The number of strings with all possible combinations becomes enormously large. - // If string description becomes part of the final solution, we MUST NOT - // concatenate the strings here: this does not translate well. - String activeString = null; + // Prepare the string for the Active Device summary + String[] activeDeviceStringsArray = mContext.getResources().getStringArray( + R.array.bluetooth_audio_active_device_summaries); + String activeDeviceString = activeDeviceStringsArray[0]; // Default value: not active if (mIsActiveDeviceA2dp && mIsActiveDeviceHeadset) { - activeString = ", active"; + activeDeviceString = activeDeviceStringsArray[1]; // Active for Media and Phone } else { if (mIsActiveDeviceA2dp) { - activeString = ", active(media)"; + activeDeviceString = activeDeviceStringsArray[2]; // Active for Media only } if (mIsActiveDeviceHeadset) { - activeString = ", active(phone)"; + activeDeviceString = activeDeviceStringsArray[3]; // Active for Phone only } } - if (activeString == null) activeString = ""; if (profileConnected) { if (a2dpNotConnected && hfpNotConnected) { if (batteryLevelPercentageString != null) { return mContext.getString( R.string.bluetooth_connected_no_headset_no_a2dp_battery_level, - batteryLevelPercentageString) + activeString; + batteryLevelPercentageString, activeDeviceString); } else { - return mContext.getString(R.string.bluetooth_connected_no_headset_no_a2dp) + - activeString; + return mContext.getString(R.string.bluetooth_connected_no_headset_no_a2dp, + activeDeviceString); } } else if (a2dpNotConnected) { if (batteryLevelPercentageString != null) { return mContext.getString(R.string.bluetooth_connected_no_a2dp_battery_level, - batteryLevelPercentageString) + activeString; + batteryLevelPercentageString, activeDeviceString); } else { - return mContext.getString(R.string.bluetooth_connected_no_a2dp) + activeString; + return mContext.getString(R.string.bluetooth_connected_no_a2dp, + activeDeviceString); } } else if (hfpNotConnected) { if (batteryLevelPercentageString != null) { return mContext.getString(R.string.bluetooth_connected_no_headset_battery_level, - batteryLevelPercentageString) + activeString; + batteryLevelPercentageString, activeDeviceString); } else { - return mContext.getString(R.string.bluetooth_connected_no_headset) - + activeString; + return mContext.getString(R.string.bluetooth_connected_no_headset, + activeDeviceString); } } else { if (batteryLevelPercentageString != null) { return mContext.getString(R.string.bluetooth_connected_battery_level, - batteryLevelPercentageString) + activeString; + batteryLevelPercentageString, activeDeviceString); } else { - return mContext.getString(R.string.bluetooth_connected) + activeString; + return mContext.getString(R.string.bluetooth_connected, activeDeviceString); } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java b/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java index 4e78d9b3d33c..85bf4e83bd55 100644 --- a/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java +++ b/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java @@ -19,6 +19,7 @@ package com.android.settingslib.development; import android.content.Context; import android.content.Intent; import android.os.Build; +import android.os.UserManager; import android.provider.Settings; import android.support.v4.content.LocalBroadcastManager; @@ -27,7 +28,8 @@ public class DevelopmentSettingsEnabler { public static final String DEVELOPMENT_SETTINGS_CHANGED_ACTION = "com.android.settingslib.development.DevelopmentSettingsEnabler.SETTINGS_CHANGED"; - private DevelopmentSettingsEnabler() {} + private DevelopmentSettingsEnabler() { + } public static void setDevelopmentSettingsEnabled(Context context, boolean enable) { Settings.Global.putInt(context.getContentResolver(), @@ -37,8 +39,14 @@ public class DevelopmentSettingsEnabler { } public static boolean isDevelopmentSettingsEnabled(Context context) { - return Settings.Global.getInt(context.getContentResolver(), + final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); + final boolean settingEnabled = Settings.Global.getInt(context.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, Build.TYPE.equals("eng") ? 1 : 0) != 0; + final boolean hasRestriction = um.hasUserRestriction( + UserManager.DISALLOW_DEBUGGING_FEATURES); + final boolean isAdmin = um.isAdminUser(); + + return isAdmin && !hasRestriction && settingEnabled; } } diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java index ed3696cafa45..f7aa29796ce8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java @@ -158,6 +158,9 @@ public class DataUsageController { usage.startDate = start; usage.usageLevel = totalBytes; usage.period = formatDateRange(start, end); + usage.cycleStart = start; + usage.cycleEnd = end; + if (policy != null) { usage.limitLevel = policy.limitBytes > 0 ? policy.limitBytes : 0; usage.warningLevel = policy.warningBytes > 0 ? policy.warningBytes : 0; @@ -245,6 +248,8 @@ public class DataUsageController { public long limitLevel; public long warningLevel; public long usageLevel; + public long cycleStart; + public long cycleEnd; } public interface Callback { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java index 4091ce1f173e..1481161bcb6c 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java @@ -80,22 +80,12 @@ public class CachedBluetoothDeviceTest { doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel(); } - /** - * Test to verify the current test context object works so that we are not checking null - * against null - */ - @Test - public void testContextMock() { - assertThat(mContext.getString(R.string.bluetooth_connected)).isEqualTo("Connected"); - } - @Test public void testGetConnectionSummary_testSingleProfileConnectDisconnect() { // Test without battery level // Set PAN profile to be connected and test connection state summary mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED); - assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( - R.string.bluetooth_connected)); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); // Set PAN profile to be disconnected and test connection state summary mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED); @@ -105,9 +95,7 @@ public class CachedBluetoothDeviceTest { mBatteryLevel = 10; // Set PAN profile to be connected and test connection state summary mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED); - assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( - R.string.bluetooth_connected_battery_level, - com.android.settingslib.Utils.formatPercentage(mBatteryLevel))); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, battery 10%"); // Set PAN profile to be disconnected and test connection state summary mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED); @@ -118,8 +106,7 @@ public class CachedBluetoothDeviceTest { // Set PAN profile to be connected and test connection state summary mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED); - assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( - R.string.bluetooth_connected)); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); // Set PAN profile to be disconnected and test connection state summary mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED); @@ -134,28 +121,23 @@ public class CachedBluetoothDeviceTest { mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED); - assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( - R.string.bluetooth_connected_battery_level, - com.android.settingslib.Utils.formatPercentage(mBatteryLevel))); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, battery 10%"); // Disconnect HFP only and test connection state summary mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED); - assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( - R.string.bluetooth_connected_no_headset_battery_level, - com.android.settingslib.Utils.formatPercentage(mBatteryLevel))); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( + "Connected (no phone), battery 10%"); // Disconnect A2DP only and test connection state summary mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED); - assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( - R.string.bluetooth_connected_no_a2dp_battery_level, - com.android.settingslib.Utils.formatPercentage(mBatteryLevel))); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( + "Connected (no media), battery 10%"); // Disconnect both HFP and A2DP and test connection state summary mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED); - assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( - R.string.bluetooth_connected_no_headset_no_a2dp_battery_level, - com.android.settingslib.Utils.formatPercentage(mBatteryLevel))); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( + "Connected (no phone or media), battery 10%"); // Disconnect all profiles and test connection state summary mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED); @@ -163,6 +145,117 @@ public class CachedBluetoothDeviceTest { } @Test + public void testGetConnectionSummary_testSingleProfileActiveDeviceA2dp() { + // Test without battery level + // Set A2DP profile to be connected and test connection state summary + mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); + + // Set device as Active for A2DP and test connection state summary + mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)"); + + // Test with battery level + mBatteryLevel = 10; + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( + "Connected, battery 10%, active(media)"); + + // Set A2DP profile to be disconnected and test connection state summary + mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED); + assertThat(mCachedDevice.getConnectionSummary()).isNull(); + + // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level + mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN; + // Set A2DP profile to be connected, Active and test connection state summary + mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); + mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)"); + + // Set A2DP profile to be disconnected and test connection state summary + mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED); + assertThat(mCachedDevice.getConnectionSummary()).isNull(); + } + + @Test + public void testGetConnectionSummary_testSingleProfileActiveDeviceHfp() { + // Test without battery level + // Set HFP profile to be connected and test connection state summary + mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); + + // Set device as Active for HFP and test connection state summary + mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)"); + + // Test with battery level + mBatteryLevel = 10; + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( + "Connected, battery 10%, active(phone)"); + + // Set HFP profile to be disconnected and test connection state summary + mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED); + assertThat(mCachedDevice.getConnectionSummary()).isNull(); + + // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level + mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN; + // Set HFP profile to be connected, Active and test connection state summary + mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); + mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)"); + + // Set HFP profile to be disconnected and test connection state summary + mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED); + assertThat(mCachedDevice.getConnectionSummary()).isNull(); + } + + @Test + public void testGetConnectionSummary_testMultipleProfilesActiveDevice() { + // Test without battery level + // Set A2DP and HFP profiles to be connected and test connection state summary + mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); + mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); + + // Set device as Active for A2DP and HFP and test connection state summary + mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); + mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active"); + + // Test with battery level + mBatteryLevel = 10; + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( + "Connected, battery 10%, active"); + + // Disconnect A2DP only and test connection state summary + mCachedDevice.setActiveDevice(false, BluetoothProfile.A2DP); + mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( + "Connected (no media), battery 10%, active(phone)"); + + // Disconnect HFP only and test connection state summary + mCachedDevice.setActiveDevice(false, BluetoothProfile.HEADSET); + mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED); + mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); + mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( + "Connected (no phone), battery 10%, active(media)"); + + // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level + mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN; + // Set A2DP and HFP profiles to be connected, Active and test connection state summary + mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); + mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); + mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); + mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); + assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active"); + + // Set A2DP and HFP profiles to be disconnected and test connection state summary + mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED); + mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED); + assertThat(mCachedDevice.getConnectionSummary()).isNull(); + } + + @Test public void testDeviceName_testAliasNameAvailable() { when(mDevice.getAliasName()).thenReturn(DEVICE_ALIAS); when(mDevice.getName()).thenReturn(DEVICE_NAME); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java index d19d19ab62e9..708353ebb7a0 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java @@ -23,7 +23,9 @@ import android.provider.Settings; import com.android.settingslib.SettingsLibRobolectricTestRunner; import com.android.settingslib.TestConfig; +import com.android.settingslib.testutils.shadow.ShadowUserManager; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -31,7 +33,9 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @RunWith(SettingsLibRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows = { + ShadowUserManager.class +}) public class DevelopmentSettingsEnablerTest { private Context mContext; @@ -39,10 +43,16 @@ public class DevelopmentSettingsEnablerTest { @Before public void setUp() { mContext = RuntimeEnvironment.application; + ShadowUserManager.getShadow().setIsAdminUser(true); + } + + @After + public void tearDown() { + ShadowUserManager.getShadow().reset(); } @Test - public void testEnabling() { + public void isEnabled_settingsOn_noRestriction_isAdmin_shouldReturnTrue() { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0); @@ -54,7 +64,7 @@ public class DevelopmentSettingsEnablerTest { } @Test - public void testDisabling() { + public void isEnabled_settingsOff_noRestriction_isAdmin_shouldReturnFalse() { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1); @@ -64,4 +74,13 @@ public class DevelopmentSettingsEnablerTest { assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse(); } + + @Test + public void isEnabled_settingsOn_noRestriction_notAdmin_shouldReturnFalse() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1); + ShadowUserManager.getShadow().setIsAdminUser(false); + + assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse(); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowUserManager.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowUserManager.java new file mode 100644 index 000000000000..c8b3269da09b --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowUserManager.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.testutils.shadow; + +import android.content.Context; +import android.os.UserManager; + +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; +import org.robolectric.shadow.api.Shadow; + +@Implements(UserManager.class) +public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager { + + private boolean mAdminUser; + + public void setIsAdminUser(boolean isAdminUser) { + mAdminUser = isAdminUser; + } + + @Resetter + public void reset() { + mAdminUser = false; + } + + @Implementation + public boolean isAdminUser() { + return mAdminUser; + } + + @Implementation + public static UserManager get(Context context) { + return (UserManager) context.getSystemService(Context.USER_SERVICE); + } + + public static ShadowUserManager getShadow() { + return (ShadowUserManager) Shadow.extract( + RuntimeEnvironment.application.getSystemService(UserManager.class)); + } +}
\ No newline at end of file diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index e55c65a47f7b..a9021ae674f0 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -901,13 +901,28 @@ <dimen name="fingerprint_dialog_fp_icon_size">60dp</dimen> <dimen name="fingerprint_dialog_animation_translation_offset">350dp</dimen> - <!-- WirelessCharging Animation values --> - <!-- Starting text size of batteryLevel for wireless charging animation --> - <dimen name="config_batteryLevelTextSizeStart" format="float">5.0</dimen> - <!-- Ending text size of batteryLevel for wireless charging animation --> - <dimen name="config_batteryLevelTextSizeEnd" format="float">32.0</dimen> - <!-- Wireless Charging battery level text animation duration --> - <integer name="config_batteryLevelTextAnimationDuration">400</integer> + <!-- Wireless Charging Animation values --> + <dimen name="wireless_charging_dots_radius_start">0dp</dimen> + <dimen name="wireless_charging_dots_radius_end">4dp</dimen> + <dimen name="wireless_charging_circle_radius_start">28dp</dimen> + <dimen name="wireless_charging_circle_radius_end">92dp</dimen> + <integer name="wireless_charging_angle_offset">20</integer> + <integer name="wireless_charging_scale_dots_duration">83</integer> + <integer name="wireless_charging_num_dots">20</integer> + <!-- Starting text size in dp of batteryLevel for wireless charging animation --> + <dimen name="wireless_charging_anim_battery_level_text_size_start">0dp</dimen> + <!-- Ending text size in dp of batteryLevel for wireless charging animation --> + <dimen name="wireless_charging_anim_battery_level_text_size_end">14dp</dimen> + <!-- time until battery info is at full opacity--> + <integer name="wireless_charging_anim_opacity_offset">80</integer> + <!-- duration batteryLevel opacity goes from 0 to 1 duration --> + <integer name="wireless_charging_battery_level_text_opacity_duration">117</integer> + <!-- battery text scale animation duration --> + <integer name="wireless_charging_battery_level_text_scale_animation_duration">367</integer> + <!--time until wireless charging animation starts to fade--> + <integer name="wireless_charging_fade_offset">920</integer> + <!-- duration wireless charging animation takes to full fade to 0 opacity --> + <integer name="wireless_charging_fade_duration">200</integer> <!-- Wired charging on AOD, text animation duration --> <integer name="wired_charging_aod_text_animation_duration_down">500</integer> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl index 64fa9c61280a..cd9e1268f0c7 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl @@ -21,9 +21,40 @@ import com.android.systemui.shared.recents.ISystemUiProxy; oneway interface IOverviewProxy { void onBind(in ISystemUiProxy sysUiProxy); + + /** + * Proxies motion events from the nav bar in SystemUI to the OverviewProxyService. The sender + * guarantees the following order of events: + * + * Normal gesture: DOWN, (MOVE/POINTER_DOWN/POINTER_UP)*, UP + * Quick switch: DOWN, (MOVE/POINTER_DOWN/POINTER_UP)*, SWITCH + * Quick scrub: DOWN, (MOVE/POINTER_DOWN/POINTER_UP)*, SCRUB_START, SCRUB_PROGRESS*, SCRUB_END + * + * Once quick switch/scrub is sent, then no further motion events will be provided. + */ void onMotionEvent(in MotionEvent event); + + /** + * Sent when a user has quickly flinged on the nav bar to switch tasks. Once this event is sent + * the caller will stop sending any motion events. + */ void onQuickSwitch(); + + /** + * Sent when the user starts to actively scrub the nav bar to switch tasks. Once this event is + * sent the caller will stop sending any motion events. + */ void onQuickScrubStart(); + + /** + * Sent when the user stops actively scrubbing the nav bar to switch tasks. Once this event is + * sent the caller will stop sending any motion events. + */ void onQuickScrubEnd(); + + /** + * Sent for each movement over the nav bar while the user is scrubbing it to switch tasks. Once + * this event is sent the caller will stop sending any motion events. + */ void onQuickScrubProgress(float progress); } diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java index 348855bb0440..afc9629ecede 100644 --- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java +++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java @@ -19,7 +19,6 @@ package com.android.systemui.charging; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; -import android.content.res.Configuration; import android.graphics.PixelFormat; import android.os.Handler; import android.os.Looper; @@ -36,13 +35,18 @@ import android.view.WindowManager; */ public class WirelessChargingAnimation { - public static final long DURATION = 1400; + public static final long DURATION = 1133; private static final String TAG = "WirelessChargingView"; private static final boolean LOCAL_LOGV = false; private final WirelessChargingView mCurrentWirelessChargingView; private static WirelessChargingView mPreviousWirelessChargingView; + public interface Callback { + void onAnimationStarting(); + void onAnimationEnded(); + } + /** * Constructs an empty WirelessChargingAnimation object. If looper is null, * Looper.myLooper() is used. Must set @@ -51,9 +55,9 @@ public class WirelessChargingAnimation { * @hide */ public WirelessChargingAnimation(@NonNull Context context, @Nullable Looper looper, int - batteryLevel) { + batteryLevel, Callback callback) { mCurrentWirelessChargingView = new WirelessChargingView(context, looper, - batteryLevel); + batteryLevel, callback); } /** @@ -61,8 +65,8 @@ public class WirelessChargingAnimation { * @hide */ public static WirelessChargingAnimation makeWirelessChargingAnimation(@NonNull Context context, - @Nullable Looper looper, int batteryLevel) { - return new WirelessChargingAnimation(context, looper, batteryLevel); + @Nullable Looper looper, int batteryLevel, Callback callback) { + return new WirelessChargingAnimation(context, looper, batteryLevel, callback); } /** @@ -95,8 +99,11 @@ public class WirelessChargingAnimation { private View mView; private View mNextView; private WindowManager mWM; + private Callback mCallback; - public WirelessChargingView(Context context, @Nullable Looper looper, int batteryLevel) { + public WirelessChargingView(Context context, @Nullable Looper looper, int batteryLevel, + Callback callback) { + mCallback = callback; mNextView = new WirelessChargingLayout(context, batteryLevel); mGravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER; @@ -149,6 +156,8 @@ public class WirelessChargingAnimation { } public void hide(long duration) { + mHandler.removeMessages(HIDE); + if (LOCAL_LOGV) Log.v(TAG, "HIDE: " + this); mHandler.sendMessageDelayed(Message.obtain(mHandler, HIDE), duration); } @@ -169,18 +178,6 @@ public class WirelessChargingAnimation { context = mView.getContext(); } mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - // We can resolve the Gravity here by using the Locale for getting - // the layout direction - final Configuration config = mView.getContext().getResources().getConfiguration(); - final int gravity = Gravity.getAbsoluteGravity(mGravity, - config.getLayoutDirection()); - mParams.gravity = gravity; - if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { - mParams.horizontalWeight = 1.0f; - } - if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) { - mParams.verticalWeight = 1.0f; - } mParams.packageName = packageName; mParams.hideTimeoutMilliseconds = DURATION; @@ -191,6 +188,9 @@ public class WirelessChargingAnimation { if (LOCAL_LOGV) Log.v(TAG, "ADD! " + mView + " in " + this); try { + if (mCallback != null) { + mCallback.onAnimationStarting(); + } mWM.addView(mView, mParams); } catch (WindowManager.BadTokenException e) { Slog.d(TAG, "Unable to add wireless charging view. " + e); @@ -203,6 +203,9 @@ public class WirelessChargingAnimation { if (mView != null) { if (mView.getParent() != null) { if (LOCAL_LOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this); + if (mCallback != null) { + mCallback.onAnimationEnded(); + } mWM.removeViewImmediate(mView); } diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java index c78ea56524cb..8f87d647a0e3 100644 --- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java +++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java @@ -16,13 +16,16 @@ package com.android.systemui.charging; +import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.util.AttributeSet; +import android.view.animation.PathInterpolator; import android.widget.FrameLayout; import android.widget.TextView; +import com.android.systemui.Interpolators; import com.android.systemui.R; import java.text.NumberFormat; @@ -52,10 +55,9 @@ public class WirelessChargingLayout extends FrameLayout { init(c, attrs, -1); } - private void init(Context c, AttributeSet attrs, int batteryLevel) { + private void init(Context context, AttributeSet attrs, int batteryLevel) { final int mBatteryLevel = batteryLevel; - - inflate(c, R.layout.wireless_charging_layout, this); + inflate(context, R.layout.wireless_charging_layout, this); // where the circle animation occurs: final WirelessChargingView mChargingView = findViewById(R.id.wireless_charging_view); @@ -68,14 +70,57 @@ public class WirelessChargingLayout extends FrameLayout { if (batteryLevel != UNKNOWN_BATTERY_LEVEL) { mPercentage.setText(NumberFormat.getPercentInstance().format(mBatteryLevel / 100f)); - - ValueAnimator animator = ObjectAnimator.ofFloat(mPercentage, "textSize", - getContext().getResources().getFloat(R.dimen.config_batteryLevelTextSizeStart), - getContext().getResources().getFloat(R.dimen.config_batteryLevelTextSizeEnd)); - - animator.setDuration((long) getContext().getResources().getInteger( - R.integer.config_batteryLevelTextAnimationDuration)); - animator.start(); + mPercentage.setAlpha(0); } + + final long chargingAnimationFadeStartOffset = (long) context.getResources().getInteger( + R.integer.wireless_charging_fade_offset); + final long chargingAnimationFadeDuration = (long) context.getResources().getInteger( + R.integer.wireless_charging_fade_duration); + final int batteryLevelTextSizeStart = context.getResources().getDimensionPixelSize( + R.dimen.wireless_charging_anim_battery_level_text_size_start); + final int batteryLevelTextSizeEnd = context.getResources().getDimensionPixelSize( + R.dimen.wireless_charging_anim_battery_level_text_size_end); + + // Animation Scale: battery percentage text scales from 0% to 100% + ValueAnimator textSizeAnimator = ObjectAnimator.ofFloat(mPercentage, "textSize", + batteryLevelTextSizeStart, batteryLevelTextSizeEnd); + textSizeAnimator.setInterpolator(new PathInterpolator(0, 0, 0, 1)); + textSizeAnimator.setDuration((long) context.getResources().getInteger( + R.integer.wireless_charging_battery_level_text_scale_animation_duration)); + + // Animation Opacity: battery percentage text transitions from 0 to 1 opacity + ValueAnimator textOpacityAnimator = ObjectAnimator.ofFloat(mPercentage, "alpha", 0, 1); + textOpacityAnimator.setInterpolator(Interpolators.LINEAR); + textOpacityAnimator.setDuration((long) context.getResources().getInteger( + R.integer.wireless_charging_battery_level_text_opacity_duration)); + textOpacityAnimator.setStartDelay((long) context.getResources().getInteger( + R.integer.wireless_charging_anim_opacity_offset)); + + // Animation Opacity: battery percentage text fades from 1 to 0 opacity + ValueAnimator textFadeAnimator = ObjectAnimator.ofFloat(mPercentage, "alpha", 1, 0); + textFadeAnimator.setDuration(chargingAnimationFadeDuration); + textFadeAnimator.setInterpolator(Interpolators.LINEAR); + textFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset); + + // Animation Opacity: wireless charging circle animation fades from 1 to 0 opacity + ValueAnimator circleFadeAnimator = ObjectAnimator.ofFloat(mChargingView, "alpha", + 1, 0); + circleFadeAnimator.setDuration(chargingAnimationFadeDuration); + circleFadeAnimator.setInterpolator(Interpolators.LINEAR); + circleFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset); + + // Animation Opacity: secondary text animation fades from 1 to 0 opacity + ValueAnimator secondaryTextFadeAnimator = ObjectAnimator.ofFloat(mSecondaryText, "alpha", + 1, 0); + circleFadeAnimator.setDuration(chargingAnimationFadeDuration); + secondaryTextFadeAnimator.setInterpolator(Interpolators.LINEAR); + secondaryTextFadeAnimator.setStartDelay(chargingAnimationFadeStartOffset); + + // play all animations together + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator, + circleFadeAnimator, secondaryTextFadeAnimator); + animatorSet.start(); } -} +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java index f5edf5216fa2..19c6dc1ceb1f 100644 --- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java +++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingView.java @@ -21,10 +21,10 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; -import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import com.android.settingslib.Utils; +import com.android.systemui.Interpolators; import com.android.systemui.R; final class WirelessChargingView extends View { @@ -33,21 +33,21 @@ final class WirelessChargingView extends View { private float mPathGone; private float mInterpolatedPathGone; private long mAnimationStartTime; - private long mStartSpinCircleAnimationTime; - private long mAnimationOffset = 500; - private long mTotalAnimationDuration = WirelessChargingAnimation.DURATION - mAnimationOffset; - private long mExpandingCircle = (long) (mTotalAnimationDuration * .9); - private long mSpinCircleAnimationTime = mTotalAnimationDuration - mExpandingCircle; + private long mScaleDotsDuration; - private boolean mFinishedAnimatingSpinningCircles = false; + private boolean mFinishedAnimatingDots = false; + private int mNumDots; - private int mStartAngle = -90; - private int mNumSmallCircles = 20; - private int mSmallCircleRadius = 10; + private double mAngleOffset; + private double mCurrAngleOffset; - private int mMainCircleStartRadius = 100; - private int mMainCircleEndRadius = 230; - private int mMainCircleCurrentRadius = mMainCircleStartRadius; + private int mDotsRadiusStart; + private int mDotsRadiusEnd; + private int mCurrDotRadius; + + private int mMainCircleStartRadius; + private int mMainCircleEndRadius; + private int mMainCircleCurrentRadius; private int mCenterX; private int mCenterY; @@ -72,8 +72,25 @@ final class WirelessChargingView extends View { public void init(Context context, AttributeSet attr) { mContext = context; + + mDotsRadiusStart = context.getResources().getDimensionPixelSize( + R.dimen.wireless_charging_dots_radius_start); + mDotsRadiusEnd = context.getResources().getDimensionPixelSize( + R.dimen.wireless_charging_dots_radius_end); + + mMainCircleStartRadius = context.getResources().getDimensionPixelSize( + R.dimen.wireless_charging_circle_radius_start); + mMainCircleEndRadius = context.getResources().getDimensionPixelSize( + R.dimen.wireless_charging_circle_radius_end); + mMainCircleCurrentRadius = mMainCircleStartRadius; + + mAngleOffset = context.getResources().getInteger(R.integer.wireless_charging_angle_offset); + mScaleDotsDuration = (long) context.getResources().getInteger( + R.integer.wireless_charging_scale_dots_duration); + mNumDots = context.getResources().getInteger(R.integer.wireless_charging_num_dots); + setupPaint(); - mInterpolator = new DecelerateInterpolator(); + mInterpolator = Interpolators.LINEAR_OUT_SLOW_IN; } private void setupPaint() { @@ -92,64 +109,62 @@ final class WirelessChargingView extends View { updateDrawingParameters(); drawCircles(canvas); - if (!mFinishedAnimatingSpinningCircles) { + if (!mFinishedAnimatingDots) { invalidate(); } } /** * Draws a larger circle of radius {@link WirelessChargingView#mMainCircleEndRadius} composed of - * {@link WirelessChargingView#mNumSmallCircles} smaller circles + * {@link WirelessChargingView#mNumDots} smaller circles * @param canvas */ private void drawCircles(Canvas canvas) { mCenterX = canvas.getWidth() / 2; mCenterY = canvas.getHeight() / 2; - // angleOffset makes small circles look like they're moving around the main circle - float angleOffset = mPathGone * 10; - - // draws mNumSmallCircles to compose a larger, main circle - for (int circle = 0; circle < mNumSmallCircles; circle++) { - double angle = ((mStartAngle + angleOffset) * Math.PI / 180) + (circle * ((2 * Math.PI) - / mNumSmallCircles)); + // draws mNumDots to compose a larger, main circle + for (int circle = 0; circle < mNumDots; circle++) { + double angle = ((mCurrAngleOffset) * Math.PI / 180) + (circle * ((2 * Math.PI) + / mNumDots)); int x = (int) (mCenterX + Math.cos(angle) * (mMainCircleCurrentRadius + - mSmallCircleRadius)); + mCurrDotRadius)); int y = (int) (mCenterY + Math.sin(angle) * (mMainCircleCurrentRadius + - mSmallCircleRadius)); - - canvas.drawCircle(x, y, mSmallCircleRadius, mPaint); - } + mCurrDotRadius)); - if (mMainCircleCurrentRadius >= mMainCircleEndRadius && !isSpinCircleAnimationStarted()) { - mStartSpinCircleAnimationTime = System.currentTimeMillis(); + canvas.drawCircle(x, y, mCurrDotRadius, mPaint); } - if (isSpinAnimationFinished()) { - mFinishedAnimatingSpinningCircles = true; + if (mMainCircleCurrentRadius >= mMainCircleEndRadius) { + mFinishedAnimatingDots = true; } } - private boolean isSpinCircleAnimationStarted() { - return mStartSpinCircleAnimationTime != 0; - } - - private boolean isSpinAnimationFinished() { - return isSpinCircleAnimationStarted() && System.currentTimeMillis() - - mStartSpinCircleAnimationTime > mSpinCircleAnimationTime; - } - private void updateDrawingParameters() { - mPathGone = getPathGone(System.currentTimeMillis()); + long now = System.currentTimeMillis(); + long timeSinceStart = now - mAnimationStartTime; + mPathGone = getPathGone(now); mInterpolatedPathGone = mInterpolator.getInterpolation(mPathGone); + // Position Dots: update main circle radius (that the dots compose) if (mPathGone < 1.0f) { mMainCircleCurrentRadius = mMainCircleStartRadius + (int) (mInterpolatedPathGone * (mMainCircleEndRadius - mMainCircleStartRadius)); } else { mMainCircleCurrentRadius = mMainCircleEndRadius; } + + // Scale Dots: update dot radius + if (timeSinceStart < mScaleDotsDuration) { + mCurrDotRadius = mDotsRadiusStart + (int) (mInterpolator.getInterpolation((float) + timeSinceStart / mScaleDotsDuration) * (mDotsRadiusEnd - mDotsRadiusStart)); + } else { + mCurrDotRadius = mDotsRadiusEnd; + } + + // Rotation Dot Group: dots rotate from 0 to 20 degrees + mCurrAngleOffset = mAngleOffset * mPathGone; } /** @@ -158,6 +173,6 @@ final class WirelessChargingView extends View { * For values > 1.0 the larger circle has been drawn and further animation can occur */ private float getPathGone(long now) { - return (float) (now - mAnimationStartTime) / (mExpandingCircle); + return (float) (now - mAnimationStartTime) / (WirelessChargingAnimation.DURATION); } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index ea2a432ea6ca..ac86c8ae097d 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -53,7 +53,6 @@ import com.android.systemui.statusbar.phone.StatusBar; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; -import java.util.concurrent.TimeUnit; public class PowerUI extends SystemUI { static final String TAG = "PowerUI"; @@ -72,10 +71,11 @@ public class PowerUI extends SystemUI { private final Configuration mLastConfiguration = new Configuration(); private int mBatteryLevel = 100; private long mTimeRemaining = Long.MAX_VALUE; - private int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN; private int mPlugType = 0; private int mInvalidCharger = 0; private EnhancedEstimates mEnhancedEstimates; + private boolean mLowWarningShownThisChargeCycle; + private boolean mSevereWarningShownThisChargeCycle; private int mLowBatteryAlertCloseLevel; private final int[] mLowBatteryReminderLevels = new int[2]; @@ -88,6 +88,8 @@ public class PowerUI extends SystemUI { private long mNextLogTime; private IThermalService mThermalService; + @VisibleForTesting int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN; + // by using the same instance (method references are not guaranteed to be the same object // We create a method reference here so that we are guaranteed that we can remove a callback // each time they are created). @@ -218,6 +220,12 @@ public class PowerUI extends SystemUI { final boolean plugged = mPlugType != 0; final boolean oldPlugged = oldPlugType != 0; + // if we are now unplugged but we were previously plugged in we should allow the + // time based trigger again. + if (!plugged && plugged != oldPlugged) { + mLowWarningShownThisChargeCycle = false; + mSevereWarningShownThisChargeCycle = false; + } int oldBucket = findBatteryLevelBucket(oldBatteryLevel); int bucket = findBatteryLevelBucket(mBatteryLevel); @@ -268,7 +276,6 @@ public class PowerUI extends SystemUI { boolean isPowerSaver = mPowerManager.isPowerSaveMode(); // only play SFX when the dialog comes up or the bucket changes final boolean playSound = bucket != oldBucket || oldPlugged; - long oldTimeRemaining = mTimeRemaining; if (mEnhancedEstimates.isHybridNotificationEnabled()) { final Estimate estimate = mEnhancedEstimates.getEstimate(); // Turbo is not always booted once SysUI is running so we have ot make sure we actually @@ -281,10 +288,18 @@ public class PowerUI extends SystemUI { } } - if (shouldShowLowBatteryWarning(plugged, oldPlugged, oldBucket, bucket, oldTimeRemaining, - mTimeRemaining, - isPowerSaver, mBatteryStatus)) { + if (shouldShowLowBatteryWarning(plugged, oldPlugged, oldBucket, bucket, + mTimeRemaining, isPowerSaver, mBatteryStatus)) { mWarnings.showLowBatteryWarning(playSound); + + // mark if we've already shown a warning this cycle. This will prevent the time based + // trigger from spamming users since the time remaining can vary based on current + // device usage. + if (mTimeRemaining < mEnhancedEstimates.getSevereWarningThreshold()) { + mSevereWarningShownThisChargeCycle = true; + } else { + mLowWarningShownThisChargeCycle = true; + } } else if (shouldDismissLowBatteryWarning(plugged, oldBucket, bucket, mTimeRemaining, isPowerSaver)) { mWarnings.dismissLowBatteryWarning(); @@ -295,22 +310,14 @@ public class PowerUI extends SystemUI { @VisibleForTesting boolean shouldShowLowBatteryWarning(boolean plugged, boolean oldPlugged, int oldBucket, - int bucket, long oldTimeRemaining, long timeRemaining, - boolean isPowerSaver, int mBatteryStatus) { + int bucket, long timeRemaining, boolean isPowerSaver, int mBatteryStatus) { return !plugged && !isPowerSaver && (((bucket < oldBucket || oldPlugged) && bucket < 0) - || (mEnhancedEstimates.isHybridNotificationEnabled() - && timeRemaining < mEnhancedEstimates.getLowWarningThreshold() - && isHourLess(oldTimeRemaining, timeRemaining))) + || isTimeBasedTrigger(timeRemaining)) && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN; } - private boolean isHourLess(long oldTimeRemaining, long timeRemaining) { - final long dif = oldTimeRemaining - timeRemaining; - return dif >= TimeUnit.HOURS.toMillis(1); - } - @VisibleForTesting boolean shouldDismissLowBatteryWarning(boolean plugged, int oldBucket, int bucket, long timeRemaining, boolean isPowerSaver) { @@ -323,6 +330,23 @@ public class PowerUI extends SystemUI { || hybridWouldDismiss)); } + private boolean isTimeBasedTrigger(long timeRemaining) { + if (!mEnhancedEstimates.isHybridNotificationEnabled()) { + return false; + } + + // Only show the time based warning once per charge cycle + final boolean canShowWarning = timeRemaining < mEnhancedEstimates.getLowWarningThreshold() + && !mLowWarningShownThisChargeCycle; + + // Only show the severe time based warning once per charge cycle + final boolean canShowSevereWarning = + timeRemaining < mEnhancedEstimates.getSevereWarningThreshold() + && !mSevereWarningShownThisChargeCycle; + + return canShowWarning || canShowSevereWarning; + } + private void initTemperatureWarning() { ContentResolver resolver = mContext.getContentResolver(); Resources resources = mContext.getResources(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java index b8f678413e91..7b1509dcd173 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java @@ -65,8 +65,8 @@ public class QSScrollLayout extends NestedScrollView { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (canScrollVertically(1) || canScrollVertically(-1)) { - return super.onInterceptTouchEvent(ev); + if (!canScrollVertically(1) && !canScrollVertically(-1)) { + return false; } mSwipeDetector.onTouchEvent(ev); return super.onInterceptTouchEvent(ev) || mOverScrollHelper.isInOverScroll(); @@ -74,8 +74,8 @@ public class QSScrollLayout extends NestedScrollView { @Override public boolean onTouchEvent(MotionEvent ev) { - if (canScrollVertically(1) || canScrollVertically(-1)) { - return super.onTouchEvent(ev); + if (!canScrollVertically(1) && !canScrollVertically(-1)) { + return false; } mSwipeDetector.onTouchEvent(ev); return super.onTouchEvent(ev); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 11bdf6b3c72e..fa177f2bb26c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -156,7 +156,7 @@ public class CommandQueue extends IStatusBar.Stub { default void handleShowGlobalActionsMenu() { } default void handleShowShutdownUi(boolean isReboot, String reason) { } - default void showChargingAnimation(int batteryLevel) { } + default void showWirelessChargingAnimation(int batteryLevel) { } default void onRotationProposal(int rotation, boolean isValid) { } @@ -497,7 +497,7 @@ public class CommandQueue extends IStatusBar.Stub { } @Override - public void showChargingAnimation(int batteryLevel) { + public void showWirelessChargingAnimation(int batteryLevel) { mHandler.removeMessages(MSG_SHOW_CHARGING_ANIMATION); mHandler.obtainMessage(MSG_SHOW_CHARGING_ANIMATION, batteryLevel, 0) .sendToTarget(); @@ -784,7 +784,7 @@ public class CommandQueue extends IStatusBar.Stub { break; case MSG_SHOW_CHARGING_ANIMATION: for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).showChargingAnimation(msg.arg1); + mCallbacks.get(i).showWirelessChargingAnimation(msg.arg1); } break; case MSG_SHOW_PINNING_TOAST_ENTER_EXIT: diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java index 7db6e2848b2a..8d14db78fe29 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java @@ -16,37 +16,37 @@ package com.android.systemui.statusbar.phone; +import static android.view.WindowManager.DOCKED_INVALID; +import static android.view.WindowManager.DOCKED_LEFT; +import static android.view.WindowManager.DOCKED_TOP; +import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY; +import static com.android.systemui.OverviewProxyService.TAG_OPS; + import android.app.ActivityManager; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Rect; +import android.os.Handler; import android.os.RemoteException; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; - import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget; import com.android.systemui.Dependency; import com.android.systemui.OverviewProxyService; +import com.android.systemui.OverviewProxyService.OverviewProxyListener; import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.SysUiServiceProvider; import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper; import com.android.systemui.shared.recents.IOverviewProxy; -import com.android.systemui.shared.recents.utilities.Utilities; import com.android.systemui.stackdivider.Divider; import com.android.systemui.tuner.TunerService; -import static android.view.WindowManager.DOCKED_INVALID; -import static android.view.WindowManager.DOCKED_LEFT; -import static android.view.WindowManager.DOCKED_TOP; -import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY; -import static com.android.systemui.OverviewProxyService.TAG_OPS; - /** * Class to detect gestures on the navigation bar. */ @@ -84,8 +84,16 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture private int mTouchDownY; private boolean mDownOnRecents; private VelocityTracker mVelocityTracker; - private OverviewProxyService mOverviewEventSender = Dependency.get(OverviewProxyService.class); + private OverviewProxyService mOverviewProxyService = Dependency.get(OverviewProxyService.class); + private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() { + @Override + public void onRecentsAnimationStarted() { + mRecentsAnimationStarted = true; + mQuickScrubController.cancelQuickSwitch(); + } + }; + private boolean mRecentsAnimationStarted; private boolean mDockWindowEnabled; private boolean mDockWindowTouchSlopExceeded; private int mDragMode; @@ -97,10 +105,12 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance); mQuickScrubController = new QuickScrubController(context); Dependency.get(TunerService.class).addTunable(this, KEY_DOCK_WINDOW_GESTURE); + mOverviewProxyService.addCallback(mOverviewProxyListener); } public void destroy() { Dependency.get(TunerService.class).removeTunable(this); + mOverviewProxyService.removeCallback(mOverviewProxyListener); } public void setComponents(RecentsComponent recentsComponent, Divider divider, @@ -117,7 +127,7 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture } private boolean proxyMotionEvents(MotionEvent event) { - final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy(); + final IOverviewProxy overviewProxy = mOverviewProxyService.getProxy(); if (overviewProxy != null) { mNavigationBarView.requestUnbufferedDispatch(event); event.transform(mTransformGlobalMatrix); @@ -146,6 +156,19 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX); mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix); mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix); + mRecentsAnimationStarted = false; + break; + } + case MotionEvent.ACTION_UP: { + // If the overview proxy service has not started the recents animation then clean up + // after it to ensure that the nav bar buttons still work + if (mOverviewProxyService.getProxy() != null && !mRecentsAnimationStarted) { + try { + ActivityManager.getService().cancelRecentsAnimation(); + } catch (RemoteException e) { + Log.e(TAG, "Could not cancel recents animation", e); + } + } break; } } @@ -154,13 +177,13 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture proxyMotionEvents(event); return false; } - return (mDockWindowEnabled && interceptDockWindowEvent(event)); + return (mDockWindowEnabled && interceptDockWindowEvent(event)) || mRecentsAnimationStarted; } public boolean onTouchEvent(MotionEvent event) { // The same down event was just sent on intercept and therefore can be ignored here boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN - && mOverviewEventSender.getProxy() != null; + && mOverviewProxyService.getProxy() != null; boolean result = mStatusBar.isPresenterFullyCollapsed() && (mQuickScrubController.onTouchEvent(event) || ignoreProxyDownEvent @@ -168,11 +191,11 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture if (mDockWindowEnabled) { result |= handleDockWindowEvent(event); } - return result; + return result || mRecentsAnimationStarted; } public void onDraw(Canvas canvas) { - if (mOverviewEventSender.getProxy() != null) { + if (mOverviewProxyService.getProxy() != null) { mQuickScrubController.onDraw(canvas); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index ad5144e941ad..af0afbdd6782 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -103,7 +103,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav private DeadZone mDeadZone; private final NavigationBarTransitions mBarTransitions; private final OverviewProxyService mOverviewProxyService; - private boolean mRecentsAnimationStarted; // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288) final static boolean WORKAROUND_INVALID_LAYOUT = true; @@ -263,7 +262,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } public void setRecentsAnimationStarted(boolean started) { - mRecentsAnimationStarted = started; if (mRecentsOnboarding != null) { mRecentsOnboarding.onRecentsAnimationStarted(); } @@ -277,22 +275,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav @Override public boolean onInterceptTouchEvent(MotionEvent event) { - int action = event.getActionMasked(); - if (action == MotionEvent.ACTION_DOWN) { - mRecentsAnimationStarted = false; - } else if (action == MotionEvent.ACTION_UP) { - // If the overview proxy service has not started the recents animation then clean up - // after it to ensure that the nav bar buttons still work - if (mOverviewProxyService.getProxy() != null && !mRecentsAnimationStarted) { - try { - ActivityManager.getService().cancelRecentsAnimation(); - } catch (RemoteException e) { - Log.e(TAG, "Could not cancel recents animation"); - } - } - } - - return mGestureHelper.onInterceptTouchEvent(event) || mRecentsAnimationStarted; + return mGestureHelper.onInterceptTouchEvent(event); } @Override @@ -300,7 +283,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav if (mGestureHelper.onTouchEvent(event)) { return true; } - return mRecentsAnimationStarted || super.onTouchEvent(event); + return super.onTouchEvent(event); } public void abortCurrentGesture() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java index 6bfaaf49b65b..dc0835e4371a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java @@ -63,7 +63,7 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene private static final String TAG = "QuickScrubController"; private static final int QUICK_SWITCH_FLING_VELOCITY = 0; private static final int ANIM_DURATION_MS = 200; - private static final long LONG_PRESS_DELAY_MS = 150; + private static final long LONG_PRESS_DELAY_MS = 225; /** * For quick step, set a damping value to allow the button to stick closer its origin position @@ -76,6 +76,7 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene private boolean mDraggingActive; private boolean mQuickScrubActive; + private boolean mAllowQuickSwitch; private float mDownOffset; private float mTranslation; private int mTouchDownX; @@ -95,7 +96,6 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene private final Paint mTrackPaint = new Paint(); private final int mScrollTouchSlop; private final OverviewProxyService mOverviewEventSender; - private final Display mDisplay; private final int mTrackThickness; private final int mTrackPadding; private final ValueAnimator mTrackAnimator; @@ -137,7 +137,8 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene new GestureDetector.SimpleOnGestureListener() { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) { - if (!isQuickScrubEnabled() || mQuickScrubActive) { + if (!isQuickScrubEnabled() || mQuickScrubActive || !mAllowQuickSwitch || + !mHomeButtonRect.contains(mTouchDownX, mTouchDownY)) { return false; } float velocityX = mIsRTL ? -velX : velX; @@ -167,8 +168,6 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene public QuickScrubController(Context context) { mContext = context; mScrollTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); - mDisplay = ((WindowManager) context.getSystemService( - Context.WINDOW_SERVICE)).getDefaultDisplay(); mOverviewEventSender = Dependency.get(OverviewProxyService.class); mGestureDetector = new GestureDetector(mContext, mGestureListener); mTrackThickness = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_thickness); @@ -202,8 +201,24 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene homeButton.setDelayTouchFeedback(false); return false; } + + return handleTouchEvent(event); + } + + /** + * @return true if we want to handle touch events for quick scrub/switch and prevent proxying + * the event to the overview service. + */ + @Override + public boolean onTouchEvent(MotionEvent event) { + return handleTouchEvent(event); + } + + private boolean handleTouchEvent(MotionEvent event) { + final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy(); + final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton(); if (mGestureDetector.onTouchEvent(event)) { - // If the fling has been handled, then skip proxying the UP + // If the fling has been handled on UP, then skip proxying the UP return true; } int action = event.getAction(); @@ -220,6 +235,7 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene homeButton.setDelayTouchFeedback(false); mTouchDownX = mTouchDownY = -1; } + mAllowQuickSwitch = true; break; } case MotionEvent.ACTION_MOVE: { @@ -304,22 +320,6 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene return mDraggingActive || mQuickScrubActive; } - /** - * @return true if we want to handle touch events for quick scrub/switch and prevent proxying - * the event to the overview service. - */ - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mGestureDetector.onTouchEvent(event)) { - // If the fling has been handled, then skip proxying the UP - return true; - } - if (event.getAction() == MotionEvent.ACTION_UP) { - endQuickScrub(); - } - return mDraggingActive || mQuickScrubActive; - } - @Override public void onDraw(Canvas canvas) { int color = (int) mTrackColorEvaluator.evaluate(mDarkIntensity, mLightTrackColor, @@ -420,6 +420,11 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene mDraggingActive = false; } + public void cancelQuickSwitch() { + mAllowQuickSwitch = false; + mHandler.removeCallbacks(mLongPressRunnable); + } + private int getDimensionPixelSize(Context context, @DimenRes int resId) { return context.getResources().getDimensionPixelSize(resId); } 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 3777a6c9409e..8c112a623e18 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -140,7 +140,6 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.ActivityStarterDelegate; import com.android.systemui.AutoReinflateContainer; -import com.android.systemui.charging.WirelessChargingAnimation; import com.android.systemui.DemoMode; import com.android.systemui.Dependency; import com.android.systemui.EventLogTags; @@ -152,6 +151,7 @@ import com.android.systemui.SystemUI; import com.android.systemui.SystemUIFactory; import com.android.systemui.UiOffloadThread; import com.android.systemui.assist.AssistManager; +import com.android.systemui.charging.WirelessChargingAnimation; import com.android.systemui.classifier.FalsingLog; import com.android.systemui.classifier.FalsingManager; import com.android.systemui.colorextraction.SysuiColorExtractor; @@ -181,6 +181,7 @@ import com.android.systemui.stackdivider.WindowManagerProxy; import com.android.systemui.statusbar.ActivatableNotificationView; import com.android.systemui.statusbar.BackDropView; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.DismissView; import com.android.systemui.statusbar.DragDownHelper; import com.android.systemui.statusbar.EmptyShadeView; @@ -2460,14 +2461,25 @@ public class StatusBar extends SystemUI implements DemoMode, } @Override - public void showChargingAnimation(int batteryLevel) { - if (mDozing) { - // ambient - } else if (mKeyguardManager.isKeyguardLocked()) { - // lockscreen + public void showWirelessChargingAnimation(int batteryLevel) { + if (mDozing || mKeyguardManager.isKeyguardLocked()) { + // on ambient or lockscreen, hide notification panel + WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, + batteryLevel, new WirelessChargingAnimation.Callback() { + @Override + public void onAnimationStarting() { + CrossFadeHelper.fadeOut(mNotificationPanel, 1); + } + + @Override + public void onAnimationEnded() { + CrossFadeHelper.fadeIn(mNotificationPanel); + } + }).show(); } else { + // workspace WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, - batteryLevel).show(); + batteryLevel, null).show(); } } @@ -3883,6 +3895,7 @@ public class StatusBar extends SystemUI implements DemoMode, private void instantCollapseNotificationPanel() { mNotificationPanel.instantCollapse(); + runPostCollapseRunnables(); } @Override @@ -5044,6 +5057,8 @@ public class StatusBar extends SystemUI implements DemoMode, } else if (!isPresenterFullyCollapsed()) { instantCollapseNotificationPanel(); visibilityChanged(false); + } else { + runPostCollapseRunnables(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java index 0a51e5a4e389..4b455baee56b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java @@ -155,7 +155,7 @@ public class PowerUITest extends SysuiTestCase { // hybrid but the threshold has been overriden to be too low boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, - ABOVE_WARNING_BUCKET, Long.MAX_VALUE, BELOW_HYBRID_THRESHOLD, + ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); assertFalse(shouldShow); } @@ -172,7 +172,7 @@ public class PowerUITest extends SysuiTestCase { // hybrid since the threshold has been overriden to be much higher boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, - ABOVE_WARNING_BUCKET, Long.MAX_VALUE, ABOVE_HYBRID_THRESHOLD, + ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); assertTrue(shouldShow); } @@ -188,7 +188,7 @@ public class PowerUITest extends SysuiTestCase { // hybrid boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, - ABOVE_WARNING_BUCKET, Long.MAX_VALUE, BELOW_HYBRID_THRESHOLD, + ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); assertTrue(shouldShow); } @@ -203,7 +203,7 @@ public class PowerUITest extends SysuiTestCase { // unplugged device that would show the non-hybrid notification and the hybrid boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, - BELOW_WARNING_BUCKET, Long.MAX_VALUE, BELOW_HYBRID_THRESHOLD, + BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); assertTrue(shouldShow); } @@ -218,7 +218,7 @@ public class PowerUITest extends SysuiTestCase { // unplugged device that would show the non-hybrid but not the hybrid boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, - BELOW_WARNING_BUCKET, Long.MAX_VALUE, ABOVE_HYBRID_THRESHOLD, + BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); assertTrue(shouldShow); } @@ -233,7 +233,7 @@ public class PowerUITest extends SysuiTestCase { // unplugged device that would show the neither due to battery level being good boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, - ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, ABOVE_HYBRID_THRESHOLD, + ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); assertFalse(shouldShow); } @@ -248,7 +248,7 @@ public class PowerUITest extends SysuiTestCase { // plugged device that would show the neither due to being plugged boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(!UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, - BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, BELOW_HYBRID_THRESHOLD, + BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); assertFalse(shouldShow); } @@ -263,7 +263,7 @@ public class PowerUITest extends SysuiTestCase { // Unknown battery status device that would show the neither due boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, - BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, BELOW_HYBRID_THRESHOLD, + BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, !POWER_SAVER_OFF, BatteryManager.BATTERY_STATUS_UNKNOWN); assertFalse(shouldShow); } @@ -278,12 +278,31 @@ public class PowerUITest extends SysuiTestCase { // BatterySaverEnabled device that would show the neither due to battery saver boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, - BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, BELOW_HYBRID_THRESHOLD, + BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, !POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); assertFalse(shouldShow); } @Test + public void testShouldShowLowBatteryWarning_onlyShowsOncePerChargeCycle() { + mPowerUI.start(); + when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true); + when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS); + when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS); + when(mEnhancedEstimates.getEstimate()) + .thenReturn(new Estimate(BELOW_HYBRID_THRESHOLD, true)); + mPowerUI.mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD; + + mPowerUI.maybeShowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, + ABOVE_WARNING_BUCKET); + boolean shouldShow = + mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, + ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, + POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); + assertFalse(shouldShow); + } + + @Test public void testShouldDismissLowBatteryWarning_dismissWhenPowerSaverEnabled() { mPowerUI.start(); when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true); diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java index a70b88e87ae4..c36bb6d2e096 100644 --- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java @@ -901,6 +901,7 @@ class MagnificationController implements Handler.Callback { } } + @GuardedBy("mLock") private void setMagnificationSpecLocked(MagnificationSpec spec) { if (mEnabled) { if (DEBUG_SET_MAGNIFICATION_SPEC) { diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 3b80f555d458..83367f3f83b4 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -1931,6 +1931,7 @@ public class BackupManagerService implements BackupManagerServiceInterface { /** * Remove a package from the full-data queue. */ + @GuardedBy("mQueueLock") private void dequeueFullBackupLocked(String packageName) { final int N = mFullBackupQueue.size(); for (int i = N - 1; i >= 0; i--) { diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 45b2118db1f3..7ab5812fd31a 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -4061,6 +4061,7 @@ class AlarmManagerService extends SystemService { /** * Deliver an alarm and set up the post-delivery handling appropriately */ + @GuardedBy("mLock") public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) { if (alarm.operation != null) { // PendingIntent alarm diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/ForceAppStandbyTracker.java index 100680df637d..b65d126af2b7 100644 --- a/services/core/java/com/android/server/ForceAppStandbyTracker.java +++ b/services/core/java/com/android/server/ForceAppStandbyTracker.java @@ -497,6 +497,7 @@ public class ForceAppStandbyTracker { /** * Update {@link #mRunAnyRestrictedPackages} with the current app ops state. */ + @GuardedBy("mLock") private void refreshForcedAppStandbyUidPackagesLocked() { mRunAnyRestrictedPackages.clear(); final List<PackageOps> ops = mAppOpsManager.getPackagesForOps( @@ -536,6 +537,7 @@ public class ForceAppStandbyTracker { /** * Update {@link #mForceAllAppsStandby} and notifies the listeners. */ + @GuardedBy("mLock") private void toggleForceAllAppsStandbyLocked(boolean enable) { if (enable == mForceAllAppsStandby) { return; @@ -545,6 +547,7 @@ public class ForceAppStandbyTracker { mHandler.notifyForceAllAppsStandbyChanged(); } + @GuardedBy("mLock") private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) { final int size = mRunAnyRestrictedPackages.size(); if (size > 8) { @@ -563,6 +566,7 @@ public class ForceAppStandbyTracker { /** * @return whether a uid package-name pair is in mRunAnyRestrictedPackages. */ + @GuardedBy("mLock") boolean isRunAnyRestrictedLocked(int uid, @NonNull String packageName) { return findForcedAppStandbyUidPackageIndexLocked(uid, packageName) >= 0; } @@ -570,6 +574,7 @@ public class ForceAppStandbyTracker { /** * Add to / remove from {@link #mRunAnyRestrictedPackages}. */ + @GuardedBy("mLock") boolean updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName, boolean restricted) { final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName); diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 93f7f1d12922..bdeb23163e7e 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -1166,6 +1166,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mImePackageAppeared = false; } + @GuardedBy("mMethodMap") private boolean shouldRebuildInputMethodListLocked() { // This method is guaranteed to be called only by getRegisteredHandler(). @@ -1467,6 +1468,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false); } + @GuardedBy("mMethodMap") private void switchUserLocked(int newUserId) { if (DEBUG) Slog.d(TAG, "Switching user stage 1/3. newUserId=" + newUserId + " currentUserId=" + mSettings.getCurrentUserId()); @@ -1817,6 +1819,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return flags; } + @GuardedBy("mMethodMap") @NonNull InputBindResult attachNewInputLocked( /* @InputMethodClient.StartInputReason */ final int startInputReason, boolean initial) { @@ -1846,6 +1849,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber); } + @GuardedBy("mMethodMap") @NonNull InputBindResult startInputLocked( /* @InputMethodClient.StartInputReason */ final int startInputReason, @@ -1889,6 +1893,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub controlFlags, startInputReason); } + @GuardedBy("mMethodMap") @NonNull InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext, /* @InputConnectionInspector.missingMethods */ final int missingMethods, @@ -3642,6 +3647,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return false; } + @GuardedBy("mMethodMap") void buildInputMethodListLocked(boolean resetDefaultEnabledIme) { if (DEBUG) { Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java index f4238f21f47c..42c836eab7d7 100644 --- a/services/core/java/com/android/server/ServiceWatcher.java +++ b/services/core/java/com/android/server/ServiceWatcher.java @@ -199,6 +199,7 @@ public class ServiceWatcher implements ServiceConnection { * bound. * @returns {@code true} if a valid package was found to bind to. */ + @GuardedBy("mLock") private boolean bindBestPackageLocked(String justCheckThisPackage, boolean forceRebind) { Intent intent = new Intent(mAction); if (justCheckThisPackage != null) { @@ -273,6 +274,7 @@ public class ServiceWatcher implements ServiceConnection { return true; } + @GuardedBy("mLock") private void unbindLocked() { ComponentName component; component = mBoundComponent; @@ -287,6 +289,7 @@ public class ServiceWatcher implements ServiceConnection { } } + @GuardedBy("mLock") private void bindToPackageLocked(ComponentName component, int version, int userId) { Intent intent = new Intent(mAction); intent.setComponent(component); diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 84b93e36c602..1a0068de6852 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -809,6 +809,7 @@ class StorageManagerService extends IStorageManager.Stub } } + @GuardedBy("mLock") private void addInternalVolumeLocked() { // Create a stub volume that represents internal storage final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL, @@ -1109,6 +1110,7 @@ class StorageManagerService extends IStorageManager.Stub } }; + @GuardedBy("mLock") private void onDiskScannedLocked(DiskInfo disk) { int volumeCount = 0; for (int i = 0; i < mVolumes.size(); i++) { @@ -1134,6 +1136,7 @@ class StorageManagerService extends IStorageManager.Stub mCallbacks.notifyDiskScanned(disk, volumeCount); } + @GuardedBy("mLock") private void onVolumeCreatedLocked(VolumeInfo vol) { if (mPms.isOnlyCoreApps()) { Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId()); @@ -1209,6 +1212,7 @@ class StorageManagerService extends IStorageManager.Stub return true; } + @GuardedBy("mLock") private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) { // Remember that we saw this volume so we're ready to accept user // metadata, or so we can annoy them when a private volume is ejected @@ -1299,6 +1303,7 @@ class StorageManagerService extends IStorageManager.Stub } } + @GuardedBy("mLock") private void onMoveStatusLocked(int status) { if (mMoveCallback == null) { Slog.w(TAG, "Odd, status but no move requested"); @@ -1515,6 +1520,7 @@ class StorageManagerService extends IStorageManager.Stub } } + @GuardedBy("mLock") private void readSettingsLocked() { mRecords.clear(); mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); @@ -1559,6 +1565,7 @@ class StorageManagerService extends IStorageManager.Stub } } + @GuardedBy("mLock") private void writeSettingsLocked() { FileOutputStream fos = null; try { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index cee1ff97030f..2aa5589a9c12 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3292,6 +3292,7 @@ public class ActivityManagerService extends IActivityManager.Stub * Update AMS states when an activity is resumed. This should only be called by * {@link ActivityStack#setResumedActivityLocked} when an activity is resumed. */ + @GuardedBy("this") void setResumedActivityUncheckLocked(ActivityRecord r, String reason) { final TaskRecord task = r.getTask(); if (task.isActivityTypeStandard()) { @@ -3817,6 +3818,7 @@ public class ActivityManagerService extends IActivityManager.Stub info.className = entryPoint; info.packageName = "android"; info.seInfoUser = SELinuxUtil.COMPLETE_STR; + info.targetSdkVersion = Build.VERSION.SDK_INT; ProcessRecord proc = startProcessLocked(processName, info /* info */, false /* knownToBeDead */, 0 /* intentFlags */, "" /* hostingType */, null /* hostingName */, true /* allowWhileBooting */, true /* isolated */, @@ -3826,6 +3828,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, @@ -3836,6 +3839,7 @@ public class ActivityManagerService extends IActivityManager.Stub null /* crashHandler */); } + @GuardedBy("this") final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, @@ -3952,6 +3956,7 @@ public class ActivityManagerService extends IActivityManager.Stub return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0; } + @GuardedBy("this") private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) { startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */); @@ -3960,6 +3965,7 @@ public class ActivityManagerService extends IActivityManager.Stub /** * @return {@code true} if process start is successful, false otherwise. */ + @GuardedBy("this") private final boolean startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride) { if (app.pendingStart) { @@ -4084,9 +4090,9 @@ public class ActivityManagerService extends IActivityManager.Stub runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES; } - if (app.info.isAllowedToUseHiddenApi() || app.instr != null) { - // This app is allowed to use undocumented and private APIs or is - // being instrumented. Set up its runtime with the appropriate flag. + if (app.info.isAllowedToUseHiddenApi()) { + // This app is allowed to use undocumented and private APIs. Set + // up its runtime with the appropriate flag. runtimeFlags |= Zygote.DISABLE_HIDDEN_API_CHECKS; } @@ -5134,6 +5140,7 @@ public class ActivityManagerService extends IActivityManager.Stub .supportsLocalVoiceInteraction(); } + @GuardedBy("this") void onLocalVoiceInteractionStartedLocked(IBinder activity, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) { ActivityRecord activityToCallback = ActivityRecord.forTokenLocked(activity); @@ -5632,6 +5639,7 @@ public class ActivityManagerService extends IActivityManager.Stub * as a result of that process going away. Clears out all connections * to the process. */ + @GuardedBy("this") private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { int pid = app.pid; @@ -5778,10 +5786,12 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") final void appDiedLocked(ProcessRecord app) { appDiedLocked(app, app.pid, app.thread, false); } + @GuardedBy("this") final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread, boolean fromBinderDied) { // First check if this ProcessRecord is actually active for the pid. @@ -6239,6 +6249,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) { if (!mLaunchWarningShown) { mLaunchWarningShown = true; @@ -6665,6 +6676,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") void closeSystemDialogsLocked(String reason) { Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY @@ -6771,11 +6783,13 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") private void forceStopPackageLocked(final String packageName, int uid, String reason) { forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false, false, true, false, false, UserHandle.getUserId(uid), reason); } + @GuardedBy("this") private void finishForceStopPackageLocked(final String packageName, int uid) { Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED, Uri.fromParts("package", packageName, null)); @@ -6791,6 +6805,7 @@ public class ActivityManagerService extends IActivityManager.Stub } + @GuardedBy("this") private final boolean killPackageProcessesLocked(String packageName, int appId, int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit, boolean evenPersistent, String reason) { @@ -6962,6 +6977,7 @@ public class ActivityManagerService extends IActivityManager.Stub return didSomething; } + @GuardedBy("this") final boolean forceStopPackageLocked(String packageName, int appId, boolean callerWillRestart, boolean purgeCache, boolean doit, boolean evenPersistent, boolean uninstalling, int userId, String reason) { @@ -7173,6 +7189,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart, boolean allowRestart, String reason) { final String name = app.processName; @@ -7218,7 +7235,7 @@ public class ActivityManagerService extends IActivityManager.Stub handleAppDiedLocked(app, willRestart, allowRestart); if (willRestart) { removeLruProcessLocked(app); - addAppLocked(app.info, null, false, null /* ABI override */, app.instr); + addAppLocked(app.info, null, false, null /* ABI override */); } } else { mRemovedProcesses.add(app); @@ -7227,6 +7244,7 @@ public class ActivityManagerService extends IActivityManager.Stub return needRestart; } + @GuardedBy("this") private final void processContentProviderPublishTimedOutLocked(ProcessRecord app) { cleanupAppInLaunchingProvidersLocked(app, true); removeProcessLocked(app, false, true, "timeout publishing content providers"); @@ -7287,6 +7305,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") private final boolean attachApplicationLocked(IApplicationThread thread, int pid, int callingUid, long startSeq) { @@ -9140,6 +9159,7 @@ public class ActivityManagerService extends IActivityManager.Stub grantEphemeralAccess(userId, intent, targetAppId, ephemeralAppId); } + @GuardedBy("this") private UriPermission findUriPermissionLocked(int targetUid, GrantUri grantUri) { final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid); if (targetUris != null) { @@ -9148,6 +9168,7 @@ public class ActivityManagerService extends IActivityManager.Stub return null; } + @GuardedBy("this") private UriPermission findOrCreateUriPermissionLocked(String sourcePkg, String targetPkg, int targetUid, GrantUri grantUri) { ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid); @@ -9165,6 +9186,7 @@ public class ActivityManagerService extends IActivityManager.Stub return perm; } + @GuardedBy("this") private final boolean checkUriPermissionLocked(GrantUri grantUri, int uid, final int modeFlags) { final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0; @@ -9235,6 +9257,7 @@ public class ActivityManagerService extends IActivityManager.Stub * If you already know the uid of the target, you can supply it in * lastTargetUid else set that to -1. */ + @GuardedBy("this") int checkGrantUriPermissionLocked(int callingUid, String targetPkg, GrantUri grantUri, final int modeFlags, int lastTargetUid) { if (!Intent.isAccessUriMode(modeFlags)) { @@ -9397,6 +9420,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg, GrantUri grantUri, final int modeFlags, UriPermissionOwner owner) { if (!Intent.isAccessUriMode(modeFlags)) { @@ -9426,6 +9450,7 @@ public class ActivityManagerService extends IActivityManager.Stub perm.grantModes(modeFlags, owner); } + @GuardedBy("this") void grantUriPermissionLocked(int callingUid, String targetPkg, GrantUri grantUri, final int modeFlags, UriPermissionOwner owner, int targetUserId) { if (targetPkg == null) { @@ -9477,6 +9502,7 @@ public class ActivityManagerService extends IActivityManager.Stub /** * Like checkGrantUriPermissionLocked, but takes an Intent. */ + @GuardedBy("this") NeededUriGrants checkGrantUriPermissionFromIntentLocked(int callingUid, String targetPkg, Intent intent, int mode, NeededUriGrants needed, int targetUserId) { if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, @@ -9563,6 +9589,7 @@ public class ActivityManagerService extends IActivityManager.Stub /** * Like grantUriPermissionUncheckedLocked, but takes an Intent. */ + @GuardedBy("this") void grantUriPermissionUncheckedFromIntentLocked(NeededUriGrants needed, UriPermissionOwner owner) { if (needed != null) { @@ -9574,6 +9601,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") void grantUriPermissionFromIntentLocked(int callingUid, String targetPkg, Intent intent, UriPermissionOwner owner, int targetUserId) { NeededUriGrants needed = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, @@ -9618,6 +9646,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") void removeUriPermissionIfNeededLocked(UriPermission perm) { if (perm.modeFlags == 0) { final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get( @@ -9634,6 +9663,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") private void revokeUriPermissionLocked(String targetPackage, int callingUid, GrantUri grantUri, final int modeFlags) { if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, @@ -9768,6 +9798,7 @@ public class ActivityManagerService extends IActivityManager.Stub * @param targetOnly When {@code true}, only remove permissions where the app is the target, * not source. */ + @GuardedBy("this") private void removeUriPermissionsForPackageLocked( String packageName, int userHandle, boolean persistable, boolean targetOnly) { if (userHandle == UserHandle.USER_ALL && packageName == null) { @@ -9954,6 +9985,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") private void readGrantedUriPermissionsLocked() { if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "readGrantedUriPermissions()"); @@ -10116,6 +10148,7 @@ public class ActivityManagerService extends IActivityManager.Stub * * @return if any mutations occured that require persisting. */ + @GuardedBy("this") private boolean maybePrunePersistedUriGrantsLocked(int uid) { final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid); if (perms == null) return false; @@ -12490,8 +12523,7 @@ public class ActivityManagerService extends IActivityManager.Stub .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList(); for (ApplicationInfo app : apps) { if (!"android".equals(app.packageName)) { - addAppLocked(app, null, false, null /* ABI override */, - null /* instrumentation */); + addAppLocked(app, null, false, null /* ABI override */); } } } catch (RemoteException ex) { @@ -12617,6 +12649,7 @@ public class ActivityManagerService extends IActivityManager.Stub // GLOBAL MANAGEMENT // ========================================================= + @GuardedBy("this") final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid) { String proc = customProcess != null ? customProcess : info.processName; @@ -12706,8 +12739,9 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated, - String abiOverride, ActiveInstrumentation instrumentation) { + String abiOverride) { ProcessRecord app; if (!isolated) { app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName, @@ -12736,9 +12770,6 @@ public class ActivityManagerService extends IActivityManager.Stub app.persistent = true; app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ; } - - app.instr = instrumentation; - if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) { mPersistentStartingProcesses.add(app); startProcessLocked(app, "added application", @@ -12825,6 +12856,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") void finishRunningVoiceLocked() { if (mRunningVoice != null) { mRunningVoice = null; @@ -12840,6 +12872,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") void updateSleepIfNeededLocked() { final boolean shouldSleep = !mStackSupervisor.hasAwakeDisplay(); final boolean wasSleeping = mSleeping; @@ -12944,6 +12977,7 @@ public class ActivityManagerService extends IActivityManager.Stub Binder.restoreCallingIdentity(origId); } + @GuardedBy("this") void startRunningVoiceLocked(IVoiceInteractionSession session, int targetUid) { Slog.d(TAG, "<<< startRunningVoiceLocked()"); mVoiceWakeLock.setWorkSource(new WorkSource(targetUid)); @@ -16179,6 +16213,7 @@ public class ActivityManagerService extends IActivityManager.Stub return false; } + @GuardedBy("this") void dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage, int dumpAppId) { boolean needSep = false; @@ -16632,6 +16667,7 @@ public class ActivityManagerService extends IActivityManager.Stub pw.println(" mForceBackgroundCheck=" + mForceBackgroundCheck); } + @GuardedBy("this") void writeProcessesToProtoLocked(ProtoOutputStream proto, String dumpPackage) { int numPers = 0; @@ -17459,6 +17495,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") void dumpPermissionsLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage) { boolean needSep = false; @@ -19531,6 +19568,7 @@ public class ActivityManagerService extends IActivityManager.Stub * @return Returns true if the given process has been restarted, so the * app that was passed in must remain on the process lists. */ + @GuardedBy("this") private final boolean cleanUpApplicationRecordLocked(ProcessRecord app, boolean restarting, boolean allowRestart, int index, boolean replacingPid) { if (index >= 0) { @@ -20620,6 +20658,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, @@ -21543,7 +21582,8 @@ public class ActivityManagerService extends IActivityManager.Stub mUsageStatsService.reportEvent(ii.targetPackage, userId, UsageEvents.Event.SYSTEM_INTERACTION); } - ProcessRecord app = addAppLocked(ai, defProcess, false, abiOverride, activeInstr); + ProcessRecord app = addAppLocked(ai, defProcess, false, abiOverride); + app.instr = activeInstr; activeInstr.mFinished = false; activeInstr.mRunningProcesses.add(app); if (!mActiveInstrumentation.contains(activeInstr)) { @@ -21609,6 +21649,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) { if (app.instr == null) { Slog.w(TAG, "finishInstrumentation called on non-instrumented: " + app); @@ -24007,6 +24048,7 @@ public class ActivityManagerService extends IActivityManager.Stub return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime()); } + @GuardedBy("this") final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground, boolean oomAdj) { if (isForeground != proc.foregroundServices) { @@ -24076,6 +24118,7 @@ public class ActivityManagerService extends IActivityManager.Stub * if necessary, or skip. * @return whether updateOomAdjLocked(app) was successful. */ + @GuardedBy("this") final boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll) { final ActivityRecord TOP_ACT = resumedAppLocked(); final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null; @@ -24100,6 +24143,7 @@ public class ActivityManagerService extends IActivityManager.Stub return success; } + @GuardedBy("this") final void updateOomAdjLocked() { final ActivityRecord TOP_ACT = resumedAppLocked(); final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null; @@ -24820,6 +24864,7 @@ public class ActivityManagerService extends IActivityManager.Stub /** * Whitelists {@code targetUid} to temporarily bypass Power Save mode. */ + @GuardedBy("this") void tempWhitelistForPendingIntentLocked(int callerPid, int callerUid, int targetUid, long duration, String tag) { if (DEBUG_WHITELISTS) { @@ -24852,6 +24897,7 @@ public class ActivityManagerService extends IActivityManager.Stub /** * Whitelists {@code targetUid} to temporarily bypass Power Save mode. */ + @GuardedBy("this") void tempWhitelistUidLocked(int targetUid, long duration, String tag) { mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag)); setUidTempWhitelistStateLocked(targetUid, true); @@ -24891,6 +24937,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) { boolean changed = false; for (int i=mActiveUids.size()-1; i>=0; i--) { @@ -24905,6 +24952,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @GuardedBy("this") final void setUidTempWhitelistStateLocked(int uid, boolean onWhitelist) { boolean changed = false; final UidRecord uidRec = mActiveUids.get(uid); @@ -24942,7 +24990,7 @@ public class ActivityManagerService extends IActivityManager.Stub mRemovedProcesses.remove(i); if (app.persistent) { - addAppLocked(app.info, null, false, null /* ABI override */, app.instr); + addAppLocked(app.info, null, false, null /* ABI override */); } } } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index cae0d2bc5dd9..4bb18e2b0f01 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -133,11 +133,16 @@ import android.app.ActivityOptions; import android.app.PendingIntent; import android.app.PictureInPictureParams; import android.app.ResultInfo; +import android.app.servertransaction.ActivityLifecycleItem; +import android.app.servertransaction.ActivityRelaunchItem; +import android.app.servertransaction.ClientTransaction; +import android.app.servertransaction.ClientTransactionItem; import android.app.servertransaction.MoveToDisplayItem; import android.app.servertransaction.MultiWindowModeChangeItem; import android.app.servertransaction.NewIntentItem; import android.app.servertransaction.PauseActivityItem; import android.app.servertransaction.PipModeChangeItem; +import android.app.servertransaction.ResumeActivityItem; import android.app.servertransaction.WindowVisibilityItem; import android.app.servertransaction.ActivityConfigurationChangeItem; import android.content.ComponentName; @@ -2370,6 +2375,15 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo setLastReportedConfiguration(service.getGlobalConfiguration(), newMergedOverrideConfig); + if (state == INITIALIZING) { + // No need to relaunch or schedule new config for activity that hasn't been launched + // yet. We do, however, return after applying the config to activity record, so that + // it will use it for launch transaction. + if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, + "Skipping config check for initializing activity: " + this); + return true; + } + if (changes == 0 && !forceNewConfig) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Configuration no differences in " + this); @@ -2559,12 +2573,23 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo + " callers=" + Debug.getCallers(6)); forceNewConfig = false; mStackSupervisor.activityRelaunchingLocked(this); - app.thread.scheduleRelaunchActivity(appToken, pendingResults, pendingNewIntents, - configChangeFlags, !andResume, - new Configuration(service.getGlobalConfiguration()), - new Configuration(getMergedOverrideConfiguration()), preserveWindow); + final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults, + pendingNewIntents, configChangeFlags, + new MergedConfiguration(service.getGlobalConfiguration(), + getMergedOverrideConfiguration()), + preserveWindow); + final ActivityLifecycleItem lifecycleItem; + if (andResume) { + lifecycleItem = ResumeActivityItem.obtain(service.isNextTransitionForward()); + } else { + lifecycleItem = PauseActivityItem.obtain(); + } + final ClientTransaction transaction = ClientTransaction.obtain(app.thread, appToken); + transaction.addCallback(callbackItem); + transaction.setLifecycleStateRequest(lifecycleItem); + service.mLifecycleManager.scheduleTransaction(transaction); // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only - // pass in 'andResume' if this activity is currently resumed, which implies we aren't + // request resume if this activity is currently resumed, which implies we aren't // sleeping. } catch (RemoteException e) { if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index ab2dc36d66d0..f3deb8dc5164 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -138,6 +138,7 @@ import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import android.view.Display; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractor; import com.android.internal.os.BatteryStatsImpl; @@ -2211,6 +2212,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * Use {@link ActivityStackSupervisor#resumeFocusedStackTopActivityLocked} to resume the * right activity for the current system state. */ + @GuardedBy("mService") boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { if (mStackSupervisor.inResumeTopActivity) { // Don't even start recursing. @@ -2250,6 +2252,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.mRecentTasks.add(r.getTask()); } + @GuardedBy("mService") private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { if (!mService.mBooting && !mService.mBooted) { // Not ready yet! diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index a0f31cd213b7..831f89a1bdfa 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -166,6 +166,7 @@ import android.util.proto.ProtoOutputStream; import android.view.Display; import android.view.RemoteAnimationAdapter; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.ReferrerIntent; import com.android.internal.os.logging.MetricsLoggerWrapper; @@ -1508,6 +1509,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list"); } + // TODO(lifecycler): Resume or pause requests are done as part of launch transaction, + // so updating the state should be done accordingly. if (andResume && readyToResume()) { // As part of the process of launching, ActivityThread also performs // a resume. @@ -1858,6 +1861,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D * Called when the frontmost task is idle. * @return the state of mService.mBooting before this was called. */ + @GuardedBy("mService") private boolean checkFinishBootingLocked() { final boolean booting = mService.mBooting; boolean enableScreen = false; @@ -1873,6 +1877,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } // Checked. + @GuardedBy("mService") final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, boolean processPausingActivities, Configuration config) { if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token); diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 927b72ceb37e..ef82f36fa79f 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -182,6 +182,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { mExecutorService.shutdownNow(); } + @GuardedBy("this") private Future<?> scheduleSyncLocked(String reason, int flags) { if (mExecutorService.isShutdown()) { return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown")); @@ -248,6 +249,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { } }; + @GuardedBy("mWorkerLock") private void updateExternalStatsLocked(final String reason, int updateFlags) { // We will request data from external processes asynchronously, and wait on a timeout. SynchronousResultReceiver wifiReceiver = null; @@ -372,6 +374,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { return null; } + @GuardedBy("mWorkerLock") private WifiActivityEnergyInfo extractDeltaLocked(WifiActivityEnergyInfo latest) { final long timePeriodMs = latest.mTimestamp - mLastInfo.mTimestamp; final long lastScanMs = mLastInfo.mControllerScanTimeMs; diff --git a/services/core/java/com/android/server/am/PersistentConnection.java b/services/core/java/com/android/server/am/PersistentConnection.java index 52eaca10cb4d..c5edb26892f8 100644 --- a/services/core/java/com/android/server/am/PersistentConnection.java +++ b/services/core/java/com/android/server/am/PersistentConnection.java @@ -220,6 +220,7 @@ public abstract class PersistentConnection<T> { } } + @GuardedBy("mLock") public final void bindInnerLocked(boolean resetBackoff) { unscheduleRebindLocked(); @@ -260,6 +261,7 @@ public abstract class PersistentConnection<T> { } } + @GuardedBy("mLock") private void cleanUpConnectionLocked() { mIsConnected = false; mService = null; @@ -276,6 +278,7 @@ public abstract class PersistentConnection<T> { } } + @GuardedBy("mLock") private final void unbindLocked() { unscheduleRebindLocked(); @@ -289,11 +292,13 @@ public abstract class PersistentConnection<T> { cleanUpConnectionLocked(); } + @GuardedBy("mLock") void unscheduleRebindLocked() { injectRemoveCallbacks(mBindForBackoffRunnable); mRebindScheduled = false; } + @GuardedBy("mLock") void scheduleRebindLocked() { unbindLocked(); diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java index edf565abd7df..c10d81b96cbc 100644 --- a/services/core/java/com/android/server/am/ProcessStatsService.java +++ b/services/core/java/com/android/server/am/ProcessStatsService.java @@ -135,6 +135,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { return mMemFactorLowered; } + @GuardedBy("mAm") public boolean setMemFactorLocked(int memFactor, boolean screenOn, long now) { mMemFactorLowered = memFactor < mLastMemOnlyState; mLastMemOnlyState = memFactor; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 8635cff7ecf9..e95608f16203 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -285,7 +285,7 @@ public class AudioService extends IAudioService.Stub private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2]; /** Maximum volume index values for audio streams */ - private static int[] MAX_STREAM_VOLUME = new int[] { + protected static int[] MAX_STREAM_VOLUME = new int[] { 5, // STREAM_VOICE_CALL 7, // STREAM_SYSTEM 7, // STREAM_RING @@ -300,7 +300,7 @@ public class AudioService extends IAudioService.Stub }; /** Minimum volume index values for audio streams */ - private static int[] MIN_STREAM_VOLUME = new int[] { + protected static int[] MIN_STREAM_VOLUME = new int[] { 1, // STREAM_VOICE_CALL 0, // STREAM_SYSTEM 0, // STREAM_RING @@ -1410,7 +1410,7 @@ public class AudioService extends IAudioService.Stub Binder.getCallingUid()); } - private void adjustStreamVolume(int streamType, int direction, int flags, + protected void adjustStreamVolume(int streamType, int direction, int flags, String callingPackage, String caller, int uid) { if (mUseFixedVolume) { return; diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index 1ee0548a5bf7..c3f020ade635 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -1116,6 +1116,7 @@ public final class ContentService extends IContentService.Stub { return (pi != null) ? pi.packageName : null; } + @GuardedBy("mCache") private ArrayMap<Pair<String, Uri>, Bundle> findOrCreateCacheLocked(int userId, String providerPackageName) { ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>> userCache = mCache.get(userId); @@ -1131,6 +1132,7 @@ public final class ContentService extends IContentService.Stub { return packageCache; } + @GuardedBy("mCache") private void invalidateCacheLocked(int userId, String providerPackageName, Uri uri) { ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>> userCache = mCache.get(userId); if (userCache == null) return; diff --git a/services/core/java/com/android/server/content/SyncLogger.java b/services/core/java/com/android/server/content/SyncLogger.java index 75c01819a9ea..20aec7e4ae29 100644 --- a/services/core/java/com/android/server/content/SyncLogger.java +++ b/services/core/java/com/android/server/content/SyncLogger.java @@ -194,6 +194,7 @@ public class SyncLogger { } } + @GuardedBy("mLock") private void openLogLocked(long now) { // If we already have a log file opened and the date has't changed, just use it. final long day = now % DateUtils.DAY_IN_MILLIS; @@ -219,6 +220,7 @@ public class SyncLogger { } } + @GuardedBy("mLock") private void closeCurrentLogLocked() { IoUtils.closeQuietly(mLogWriter); mLogWriter = null; diff --git a/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java b/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java index 0976a22f5e13..b0cde2dd65ae 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java @@ -202,6 +202,7 @@ class FingerprintsUserState { } } + @GuardedBy("this") private void readStateSyncLocked() { FileInputStream in; if (!mFile.exists()) { @@ -226,6 +227,7 @@ class FingerprintsUserState { } } + @GuardedBy("this") private void parseStateLocked(XmlPullParser parser) throws IOException, XmlPullParserException { final int outerDepth = parser.getDepth(); @@ -243,6 +245,7 @@ class FingerprintsUserState { } } + @GuardedBy("this") private void parseFingerprintsLocked(XmlPullParser parser) throws IOException, XmlPullParserException { diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 1e09383db56d..de0f29851da5 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -1299,6 +1299,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { /** * Return external input devices. */ + @GuardedBy("mLock") List<HdmiDeviceInfo> getSafeExternalInputsLocked() { return mSafeExternalInputs; } @@ -1421,6 +1422,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } } + @GuardedBy("mLock") List<HdmiDeviceInfo> getSafeCecDevicesLocked() { ArrayList<HdmiDeviceInfo> infoList = new ArrayList<>(); for (HdmiDeviceInfo info : mSafeAllDeviceInfos) { diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 3d079ccb0cad..b06dba9f9627 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -1097,6 +1097,7 @@ public final class HdmiControlService extends SystemService { } } + @GuardedBy("mLock") private List<HdmiDeviceInfo> getMhlDevicesLocked() { return mMhlDevices; } diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java index 37b39907e976..4988974e95db 100644 --- a/services/core/java/com/android/server/job/JobServiceContext.java +++ b/services/core/java/com/android/server/job/JobServiceContext.java @@ -295,10 +295,12 @@ public final class JobServiceContext implements ServiceConnection { } /** Called externally when a job that was scheduled for execution should be cancelled. */ + @GuardedBy("mLock") void cancelExecutingJobLocked(int reason, String debugReason) { doCancelLocked(reason, debugReason); } + @GuardedBy("mLock") void preemptExecutingJobLocked() { doCancelLocked(JobParameters.REASON_PREEMPT, "cancelled due to preemption"); } @@ -319,6 +321,7 @@ public final class JobServiceContext implements ServiceConnection { return mTimeoutElapsed; } + @GuardedBy("mLock") boolean timeoutIfExecutingLocked(String pkgName, int userId, boolean matchJobId, int jobId, String reason) { final JobStatus executing = getRunningJobLocked(); @@ -512,6 +515,7 @@ public final class JobServiceContext implements ServiceConnection { } } + @GuardedBy("mLock") void doServiceBoundLocked() { removeOpTimeOutLocked(); handleServiceBoundLocked(); @@ -531,6 +535,7 @@ public final class JobServiceContext implements ServiceConnection { } } + @GuardedBy("mLock") void doCallbackLocked(boolean reschedule, String reason) { if (DEBUG) { Slog.d(TAG, "doCallback of : " + mRunningJob @@ -550,6 +555,7 @@ public final class JobServiceContext implements ServiceConnection { } } + @GuardedBy("mLock") void doCancelLocked(int arg1, String debugReason) { if (mVerb == VERB_FINISHED) { if (DEBUG) { @@ -567,6 +573,7 @@ public final class JobServiceContext implements ServiceConnection { } /** Start the job on the service. */ + @GuardedBy("mLock") private void handleServiceBoundLocked() { if (DEBUG) { Slog.d(TAG, "handleServiceBound for " + getRunningJobNameLocked()); @@ -605,6 +612,7 @@ public final class JobServiceContext implements ServiceConnection { * _EXECUTING -> Error * _STOPPING -> Error */ + @GuardedBy("mLock") private void handleStartedLocked(boolean workOngoing) { switch (mVerb) { case VERB_STARTING: @@ -637,6 +645,7 @@ public final class JobServiceContext implements ServiceConnection { * _STARTING -> Error * _PENDING -> Error */ + @GuardedBy("mLock") private void handleFinishedLocked(boolean reschedule, String reason) { switch (mVerb) { case VERB_EXECUTING: @@ -659,6 +668,7 @@ public final class JobServiceContext implements ServiceConnection { * in the message queue. * _ENDING -> No point in doing anything here, so we ignore. */ + @GuardedBy("mLock") private void handleCancelLocked(String reason) { if (JobSchedulerService.DEBUG) { Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " " @@ -683,6 +693,7 @@ public final class JobServiceContext implements ServiceConnection { } /** Process MSG_TIMEOUT here. */ + @GuardedBy("mLock") private void handleOpTimeoutLocked() { switch (mVerb) { case VERB_BINDING: @@ -722,6 +733,7 @@ public final class JobServiceContext implements ServiceConnection { * Already running, need to stop. Will switch {@link #mVerb} from VERB_EXECUTING -> * VERB_STOPPING. */ + @GuardedBy("mLock") private void sendStopMessageLocked(String reason) { removeOpTimeOutLocked(); if (mVerb != VERB_EXECUTING) { @@ -747,6 +759,7 @@ public final class JobServiceContext implements ServiceConnection { * or from acknowledging the stop message we sent. Either way, we're done tracking it and * we want to clean up internally. */ + @GuardedBy("mLock") private void closeAndCleanupJobLocked(boolean reschedule, String reason) { final JobStatus completedJob; if (mVerb == VERB_FINISHED) { diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java index 13873e476894..77e813e086ce 100644 --- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java +++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java @@ -92,6 +92,7 @@ public final class ConnectivityController extends StateController implements mNetPolicyManager.registerListener(mNetPolicyListener); } + @GuardedBy("mLock") @Override public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) { if (jobStatus.hasConnectivityConstraint()) { @@ -101,6 +102,7 @@ public final class ConnectivityController extends StateController implements } } + @GuardedBy("mLock") @Override public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) { @@ -325,6 +327,7 @@ public final class ConnectivityController extends StateController implements } }; + @GuardedBy("mLock") @Override public void dumpControllerStateLocked(PrintWriter pw, int filterUid) { pw.print("Connectivity: connected="); @@ -348,6 +351,7 @@ public final class ConnectivityController extends StateController implements } } + @GuardedBy("mLock") @Override public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) { final long token = proto.start(fieldId); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index e71572483cca..6deff3652944 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -2236,9 +2236,10 @@ public class LockSettingsService extends ILockSettings.Stub { * This happens during a normal migration case when the user currently has password. * * 2. credentialhash == null and credential == null - * A new SP blob and a new SID will be created, while the user has no credentials. + * A new SP blob and will be created, while the user has no credentials. * This can happens when we are activating an escrow token on a unsecured device, during * which we want to create the SP structure with an empty user credential. + * This could also happen during an untrusted reset to clear password. * * 3. credentialhash == null and credential != null * This is the untrusted credential reset, OR the user sets a new lockscreen password @@ -2250,16 +2251,8 @@ public class LockSettingsService extends ILockSettings.Stub { String credential, int credentialType, int requestedQuality, int userId) throws RemoteException { Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId); - // Load from the cache or a make a new one - AuthenticationToken auth = mSpCache.get(userId); - if (auth != null) { - // If the synthetic password has been cached, we can only be in case 3., described - // above, for an untrusted credential reset so a new SID is still needed. - mSpManager.newSidForUser(getGateKeeperService(), auth, userId); - } else { - auth = mSpManager.newSyntheticPasswordAndSid(getGateKeeperService(), - credentialHash, credential, userId); - } + final AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid( + getGateKeeperService(), credentialHash, credential, userId); onAuthTokenKnownForUser(userId, auth); if (auth == null) { Slog.wtf(TAG, "initializeSyntheticPasswordLocked returns null auth token"); @@ -2473,36 +2466,41 @@ public class LockSettingsService extends ILockSettings.Stub { : "pattern")); } + boolean untrustedReset = false; if (auth != null) { - // We are performing a trusted credential change i.e. a correct existing credential - // is provided - setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, requestedQuality, - userId); - mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId); onAuthTokenKnownForUser(userId, auth); } else if (response != null && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) { - // We are performing an untrusted credential change i.e. by DevicePolicyManager. - // So provision a new SP and SID. This would invalidate existing escrow tokens. - // Still support this for now but this flow will be removed in the next release. + // We are performing an untrusted credential change, by DevicePolicyManager or other + // internal callers that don't provide the existing credential Slog.w(TAG, "Untrusted credential change invoked"); - - if (mSpCache.get(userId) == null) { - throw new IllegalStateException( - "Untrusted credential reset not possible without cached SP"); - } - - initializeSyntheticPasswordLocked(null, credential, credentialType, requestedQuality, - userId); - synchronizeUnifiedWorkChallengeForProfiles(userId, null); - mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId); - - notifyActivePasswordMetricsAvailable(credential, userId); + // Try to get a cached auth token, so we can keep SP unchanged. + auth = mSpCache.get(userId); + untrustedReset = true; } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ { Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " + (response != null ? "rate limit exceeded" : "failed")); return; } + + if (auth != null) { + if (untrustedReset) { + // Force change the current SID to mantain existing behaviour that an untrusted + // reset leads to a change of SID. If the untrusted reset is for clearing the + // current password, the nuking of the SID will be done in + // setLockCredentialWithAuthTokenLocked next + mSpManager.newSidForUser(getGateKeeperService(), auth, userId); + } + setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, requestedQuality, + userId); + mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId); + } else { + throw new IllegalStateException( + "Untrusted credential reset not possible without cached SP"); + // Could call initializeSyntheticPasswordLocked(null, credential, credentialType, + // requestedQuality, userId) instead if we still allow untrusted reset that changes + // synthetic password. That would invalidate existing escrow tokens though. + } mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId); } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java index 662ffc814390..dee24c7c0450 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java @@ -44,6 +44,7 @@ import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; +import java.security.cert.CertPath; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -176,8 +177,17 @@ public class KeySyncTask implements Runnable { return; } - PublicKey publicKey = mRecoverableKeyStoreDb.getRecoveryServicePublicKey(mUserId, + PublicKey publicKey; + CertPath certPath = mRecoverableKeyStoreDb.getRecoveryServiceCertPath(mUserId, recoveryAgentUid); + if (certPath != null) { + Log.d(TAG, "Using the public key in stored CertPath for syncing"); + publicKey = certPath.getCertificates().get(0).getPublicKey(); + } else { + Log.d(TAG, "Using the stored raw public key for syncing"); + publicKey = mRecoverableKeyStoreDb.getRecoveryServicePublicKey(mUserId, + recoveryAgentUid); + } if (publicKey == null) { Log.w(TAG, "Not initialized for KeySync: no public key set. Cancelling task."); return; diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java index 33e767fe1a8f..9f822688a8c0 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java @@ -23,16 +23,15 @@ import static android.security.keystore.RecoveryController.ERROR_NO_SNAPSHOT_PEN import static android.security.keystore.RecoveryController.ERROR_SERVICE_INTERNAL_ERROR; import static android.security.keystore.RecoveryController.ERROR_SESSION_EXPIRED; +import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.PendingIntent; import android.content.Context; -import android.Manifest; import android.os.Binder; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.UserHandle; - import android.security.keystore.recovery.KeyChainProtectionParams; import android.security.keystore.recovery.KeyChainSnapshot; import android.security.keystore.recovery.RecoveryController; @@ -43,6 +42,10 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.HexDump; import com.android.server.locksettings.recoverablekeystore.storage.ApplicationKeyStorage; +import com.android.server.locksettings.recoverablekeystore.certificate.CertParsingException; +import com.android.server.locksettings.recoverablekeystore.certificate.CertValidationException; +import com.android.server.locksettings.recoverablekeystore.certificate.CertXml; +import com.android.server.locksettings.recoverablekeystore.certificate.TrustedRootCert; import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb; import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage; import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage; @@ -52,8 +55,10 @@ import java.security.KeyFactory; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; import java.security.UnrecoverableKeyException; +import java.security.cert.CertPath; +import java.security.cert.CertificateEncodingException; +import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; import java.util.HashMap; @@ -152,18 +157,67 @@ public class RecoverableKeyStoreManager { } public void initRecoveryService( - @NonNull String rootCertificateAlias, @NonNull byte[] signedPublicKeyList) + @NonNull String rootCertificateAlias, @NonNull byte[] recoveryServiceCertFile) throws RemoteException { checkRecoverKeyStorePermission(); int userId = UserHandle.getCallingUserId(); int uid = Binder.getCallingUid(); - // TODO: open /system/etc/security/... cert file, and check the signature on the public keys - PublicKey publicKey; + + // TODO: Check the public-key signature on the whole file before parsing it + + CertXml certXml; + try { + certXml = CertXml.parse(recoveryServiceCertFile); + } catch (CertParsingException e) { + // TODO: Do not use raw key bytes anymore once the other components are updated + Log.d(TAG, "Failed to parse the cert file", e); + PublicKey publicKey = parseEcPublicKey(recoveryServiceCertFile); + if (mDatabase.setRecoveryServicePublicKey(userId, uid, publicKey) > 0) { + mDatabase.setShouldCreateSnapshot(userId, uid, true); + } + return; + } + + // Check serial number + long newSerial = certXml.getSerial(); + Long oldSerial = mDatabase.getRecoveryServiceCertSerial(userId, uid); + if (oldSerial != null && oldSerial >= newSerial) { + if (oldSerial == newSerial) { + Log.i(TAG, "The cert file serial number is the same, so skip updating."); + } else { + Log.e(TAG, "The cert file serial number is older than the one in database."); + } + return; + } + Log.i(TAG, "Updating the certificate with the new serial number " + newSerial); + + CertPath certPath; + try { + Log.d(TAG, "Getting and validating a random endpoint certificate"); + certPath = certXml.getRandomEndpointCert(TrustedRootCert.TRUSTED_ROOT_CERT); + } catch (CertValidationException e) { + Log.e(TAG, "Invalid endpoint cert", e); + throw new ServiceSpecificException( + ERROR_BAD_CERTIFICATE_FORMAT, "Failed to validate certificate."); + } + try { + Log.d(TAG, "Saving the randomly chosen endpoint certificate to database"); + if (mDatabase.setRecoveryServiceCertPath(userId, uid, certPath) > 0) { + mDatabase.setRecoveryServiceCertSerial(userId, uid, newSerial); + mDatabase.setShouldCreateSnapshot(userId, uid, true); + } + } catch (CertificateEncodingException e) { + Log.e(TAG, "Failed to encode CertPath", e); + throw new ServiceSpecificException( + ERROR_BAD_CERTIFICATE_FORMAT, "Failed to encode CertPath."); + } + } + + private PublicKey parseEcPublicKey(@NonNull byte[] bytes) throws ServiceSpecificException { try { KeyFactory kf = KeyFactory.getInstance("EC"); - // TODO: Randomly choose a key from the list -- right now we just use the whole input - X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(signedPublicKeyList); - publicKey = kf.generatePublic(pkSpec); + X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(bytes); + return kf.generatePublic(pkSpec); } catch (NoSuchAlgorithmException e) { Log.wtf(TAG, "EC algorithm not available. AOSP must support this.", e); throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage()); @@ -171,10 +225,6 @@ public class RecoverableKeyStoreManager { throw new ServiceSpecificException( ERROR_BAD_CERTIFICATE_FORMAT, "Not a valid X509 certificate."); } - long updatedRows = mDatabase.setRecoveryServicePublicKey(userId, uid, publicKey); - if (updatedRows > 0) { - mDatabase.setShouldCreateSnapshot(userId, uid, true); - } } /** diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java index fea6733dd1f5..09ec5ad1d5dd 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java @@ -68,7 +68,7 @@ import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** Utility functions related to parsing and validating public-key certificates. */ -final class CertUtils { +public final class CertUtils { private static final String CERT_FORMAT = "X.509"; private static final String CERT_PATH_ALG = "PKIX"; @@ -217,7 +217,7 @@ final class CertUtils { * @return the decoding decoding result * @throws CertParsingException if the input string is not a properly base64-encoded string */ - static byte[] decodeBase64(String str) throws CertParsingException { + public static byte[] decodeBase64(String str) throws CertParsingException { try { return Base64.getDecoder().decode(str); } catch (IllegalArgumentException e) { diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/TrustedRootCert.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/TrustedRootCert.java new file mode 100644 index 000000000000..7195d628e4bd --- /dev/null +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/TrustedRootCert.java @@ -0,0 +1,74 @@ +/* + * 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.locksettings.recoverablekeystore.certificate; + +import java.security.cert.X509Certificate; + +/** + * Holds the X509 certificate of the trusted root CA cert for the recoverable key store service. + * + * TODO: Read the certificate from a PEM file directly and remove this class. + */ +public final class TrustedRootCert { + + private static final String TRUSTED_ROOT_CERT_BASE64 = "" + + "MIIFJjCCAw6gAwIBAgIJAIobXsJlzhNdMA0GCSqGSIb3DQEBDQUAMCAxHjAcBgNV" + + "BAMMFUdvb2dsZSBDcnlwdEF1dGhWYXVsdDAeFw0xODAyMDIxOTM5MTRaFw0zODAx" + + "MjgxOTM5MTRaMCAxHjAcBgNVBAMMFUdvb2dsZSBDcnlwdEF1dGhWYXVsdDCCAiIw" + + "DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2OT5i40/H7LINg/lq/0G0hR65P" + + "Q4Mud3OnuVt6UIYV2T18+v6qW1yJd5FcnND/ZKPau4aUAYklqJuSVjOXQD0BjgS2" + + "98Xa4dSn8Ci1rUR+5tdmrxqbYUdT2ZvJIUMMR6fRoqi+LlAbKECrV+zYQTyLU68w" + + "V66hQpAButjJKiZzkXjmKLfJ5IWrNEn17XM988rk6qAQn/BYCCQGf3rQuJeksGmA" + + "N1lJOwNYxmWUyouVwqwZthNEWqTuEyBFMkAT+99PXW7oVDc7oU5cevuihxQWNTYq" + + "viGB8cck6RW3cmqrDSaJF/E+N0cXFKyYC7FDcggt6k3UrxNKTuySdDEa8+2RTQqU" + + "Y9npxBlQE+x9Ig56OI1BG3bSBsGdPgjpyHadZeh2tgk+oqlGsSsum24YxaxuSysT" + + "Qfcu/XhyfUXavfmGrBOXerTzIl5oBh/F5aHTV85M2tYEG0qsPPvSpZAWtdJ/2rca" + + "OxvhwOL+leZKr8McjXVR00lBsRuKXX4nTUMwya09CO3QHFPFZtZvqjy2HaMOnVLQ" + + "I6b6dHEfmsHybzVOe3yPEoFQSU9UhUdmi71kwwoanPD3j9fJHmXTx4PzYYBRf1ZE" + + "o+uPgMPk7CDKQFZLjnR40z1uzu3O8aZ3AKZzP+j7T4XQKJLQLmllKtPgLgNdJyib" + + "2Glg7QhXH/jBTL6hAgMBAAGjYzBhMB0GA1UdDgQWBBSbZfrqOYH54EJpkdKMZjMc" + + "z/Hp+DAfBgNVHSMEGDAWgBSbZfrqOYH54EJpkdKMZjMcz/Hp+DAPBgNVHRMBAf8E" + + "BTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQ0FAAOCAgEAKh9nm/vW" + + "glMWp3vcCwWwJW286ecREDlI+CjGh5h+f2N4QRrXd/tKE3qQJWCqGx8sFfIUjmI7" + + "KYdsC2gyQ2cA2zl0w7pB2QkuqE6zVbnh1D17Hwl19IMyAakFaM9ad4/EoH7oQmqX" + + "nF/f5QXGZw4kf1HcgKgoCHWXjqR8MqHOcXR8n6WFqxjzJf1jxzi6Yo2dZ7PJbnE6" + + "+kHIJuiCpiHL75v5g1HM41gT3ddFFSrn88ThNPWItT5Z8WpFjryVzank2Yt02LLl" + + "WqZg9IC375QULc5B58NMnaiVJIDJQ8zoNgj1yaxqtUMnJX570lotO2OXe4ec9aCQ" + + "DIJ84YLM/qStFdeZ9416E80dchskbDG04GuVJKlzWjxAQNMRFhyaPUSBTLLg+kwP" + + "t9+AMmc+A7xjtFQLZ9fBYHOBsndJOmeSQeYeckl+z/1WQf7DdwXn/yijon7mxz4z" + + "cCczfKwTJTwBh3wR5SQr2vQm7qaXM87qxF8PCAZrdZaw5I80QwkgTj0WTZ2/GdSw" + + "d3o5SyzzBAjpwtG+4bO/BD9h9wlTsHpT6yWOZs4OYAKU5ykQrncI8OyavMggArh3" + + "/oM58v0orUWINtIc2hBlka36PhATYQiLf+AiWKnwhCaaHExoYKfQlMtXBodNvOK8" + + "xqx69x05q/qbHKEcTHrsss630vxrp1niXvA="; + + /** + * The X509 certificate of the trusted root CA cert for the recoverable key store service. + * + * TODO: Change it to the production certificate root CA before the final launch. + */ + public static final X509Certificate TRUSTED_ROOT_CERT; + + static { + try { + TRUSTED_ROOT_CERT = CertUtils.decodeCert( + CertUtils.decodeBase64(TRUSTED_ROOT_CERT_BASE64)); + } catch (CertParsingException e) { + // Should not happen + throw new RuntimeException(e); + } + } +} diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java index b96208d66b01..89ddb6c9eb30 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java @@ -31,9 +31,14 @@ import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKe import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry; import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry; +import java.io.ByteArrayInputStream; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; +import java.security.cert.CertPath; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; @@ -53,6 +58,7 @@ public class RecoverableKeyStoreDb { private static final String TAG = "RecoverableKeyStoreDb"; private static final int IDLE_TIMEOUT_SECONDS = 30; private static final int LAST_SYNCED_AT_UNSYNCED = -1; + private static final String CERT_PATH_ENCODING = "PkiPath"; private final RecoverableKeyStoreDbHelper mKeyStoreDbHelper; @@ -361,6 +367,79 @@ public class RecoverableKeyStoreDb { } /** + * Returns the serial number of the XML file containing certificates of the recovery service. + * + * @param userId The userId of the profile the application is running under. + * @param uid The uid of the application who initializes the local recovery components. + * @return The value that were previously set, or null if there's none. + * + * @hide + */ + @Nullable + public Long getRecoveryServiceCertSerial(int userId, int uid) { + return getLong(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL); + } + + /** + * Records the serial number of the XML file containing certificates of the recovery service. + * + * @param userId The userId of the profile the application is running under. + * @param uid The uid of the application who initializes the local recovery components. + * @param serial The serial number contained in the XML file for recovery service certificates. + * @return The primary key of the inserted row, or -1 if failed. + * + * @hide + */ + public long setRecoveryServiceCertSerial(int userId, int uid, long serial) { + return setLong(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL, serial); + } + + /** + * Returns the {@code CertPath} of the recovery service. + * + * @param userId The userId of the profile the application is running under. + * @param uid The uid of the application who initializes the local recovery components. + * @return The value that were previously set, or null if there's none. + * + * @hide + */ + @Nullable + public CertPath getRecoveryServiceCertPath(int userId, int uid) { + byte[] bytes = getBytes(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH); + if (bytes == null) { + return null; + } + try { + return decodeCertPath(bytes); + } catch (CertificateException e) { + Log.wtf(TAG, + String.format(Locale.US, + "Recovery service CertPath entry cannot be decoded for " + + "userId=%d uid=%d.", + userId, uid), e); + return null; + } + } + + /** + * Sets the {@code CertPath} of the recovery service. + * + * @param userId The userId of the profile the application is running under. + * @param uid The uid of the application who initializes the local recovery components. + * @param certPath The certificate path of the recovery service. + * @return The primary key of the inserted row, or -1 if failed. + * @hide + */ + public long setRecoveryServiceCertPath(int userId, int uid, CertPath certPath) throws + CertificateEncodingException { + if (certPath.getCertificates().size() == 0) { + throw new CertificateEncodingException("No certificate contained in the cert path."); + } + return setBytes(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH, + certPath.getEncoded(CERT_PATH_ENCODING)); + } + + /** * Returns the list of recovery agents initialized for given {@code userId} * @param userId The userId of the profile the application is running under. * @return The list of recovery agents @@ -515,48 +594,6 @@ public class RecoverableKeyStoreDb { } /** - * Returns the first (and only?) public key for {@code userId}. - * - * @param userId The userId of the profile whose keys are to be synced. - * @return The public key, or null if none exists. - */ - @Nullable - public PublicKey getRecoveryServicePublicKey(int userId) { - SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase(); - - String[] projection = { RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY }; - String selection = - RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ?"; - String[] selectionArguments = { Integer.toString(userId) }; - - try ( - Cursor cursor = db.query( - RecoveryServiceMetadataEntry.TABLE_NAME, - projection, - selection, - selectionArguments, - /*groupBy=*/ null, - /*having=*/ null, - /*orderBy=*/ null) - ) { - if (cursor.getCount() < 1) { - return null; - } - - cursor.moveToFirst(); - byte[] keyBytes = cursor.getBlob(cursor.getColumnIndexOrThrow( - RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY)); - - try { - return decodeX509Key(keyBytes); - } catch (InvalidKeySpecException e) { - Log.wtf(TAG, "Could not decode public key for " + userId); - return null; - } - } - } - - /** * Updates the counterId * * @param userId The userId of the profile the application is running under. @@ -585,7 +622,6 @@ public class RecoverableKeyStoreDb { return getLong(userId, uid, RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID); } - /** * Updates the server parameters given by the application initializing the local recovery * components. @@ -869,4 +905,16 @@ public class RecoverableKeyStoreDb { throw new RuntimeException(e); } } + + @Nullable + private static CertPath decodeCertPath(byte[] bytes) throws CertificateException { + CertificateFactory certFactory; + try { + certFactory = CertificateFactory.getInstance("X.509"); + } catch (CertificateException e) { + // Should not happen, as X.509 is mandatory for all providers. + throw new RuntimeException(e); + } + return certFactory.generateCertPath(new ByteArrayInputStream(bytes), CERT_PATH_ENCODING); + } } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java index 4ee282b6115e..1cb5d91be3ba 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java @@ -104,9 +104,10 @@ class RecoverableKeyStoreDbContract { static final String COLUMN_NAME_UID = "uid"; /** - * Version of the latest recovery snapshot + * Version of the latest recovery snapshot. */ static final String COLUMN_NAME_SNAPSHOT_VERSION = "snapshot_version"; + /** * Flag to generate new snapshot. */ @@ -118,6 +119,16 @@ class RecoverableKeyStoreDbContract { static final String COLUMN_NAME_PUBLIC_KEY = "public_key"; /** + * The certificate path of the recovery service. + */ + static final String COLUMN_NAME_CERT_PATH = "cert_path"; + + /** + * The serial number contained in the certificate XML file of the recovery service. + */ + static final String COLUMN_NAME_CERT_SERIAL = "cert_serial"; + + /** * Secret types used for end-to-end encryption. */ static final String COLUMN_NAME_SECRET_TYPES = "secret_types"; diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java index 79fd496ad11c..8a89f2d4faa9 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java @@ -19,6 +19,7 @@ package com.android.server.locksettings.recoverablekeystore.storage; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry; import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry; @@ -28,7 +29,9 @@ import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKe * Helper for creating the recoverable key database. */ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper { - private static final int DATABASE_VERSION = 2; + private static final String TAG = "RecoverableKeyStoreDbHp"; + + static final int DATABASE_VERSION = 3; private static final String DATABASE_NAME = "recoverablekeystore.db"; private static final String SQL_CREATE_KEYS_ENTRY = @@ -59,6 +62,8 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper { + RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION + " INTEGER," + RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT + " INTEGER," + RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY + " BLOB," + + RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH + " BLOB," + + RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL + " INTEGER," + RecoveryServiceMetadataEntry.COLUMN_NAME_SECRET_TYPES + " TEXT," + RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID + " INTEGER," + RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMS + " BLOB," @@ -88,9 +93,39 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - db.execSQL(SQL_DELETE_KEYS_ENTRY); - db.execSQL(SQL_DELETE_USER_METADATA_ENTRY); - db.execSQL(SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY); - onCreate(db); + if (oldVersion < 2) { + db.execSQL(SQL_DELETE_KEYS_ENTRY); + db.execSQL(SQL_DELETE_USER_METADATA_ENTRY); + db.execSQL(SQL_DELETE_RECOVERY_SERVICE_METADATA_ENTRY); + onCreate(db); + return; + } + + if (oldVersion < 3) { + upgradeDbForVersion3(db); + } + } + + private void upgradeDbForVersion3(SQLiteDatabase db) { + // Add the two columns for cert path and cert serial number + addColumnToTable(db, RecoveryServiceMetadataEntry.TABLE_NAME, + RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH, "BLOB", /*defaultStr=*/ null); + addColumnToTable(db, RecoveryServiceMetadataEntry.TABLE_NAME, + RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL, "INTEGER", /*defaultStr=*/ + null); + } + + private static void addColumnToTable( + SQLiteDatabase db, String tableName, String column, String columnType, + String defaultStr) { + Log.d(TAG, "Adding column " + column + " to " + tableName + "."); + + String alterStr = "ALTER TABLE " + tableName + " ADD COLUMN " + column + " " + columnType; + if (defaultStr != null && !defaultStr.isEmpty()) { + alterStr += " DEFAULT " + defaultStr; + } + + db.execSQL(alterStr + ";"); } } + diff --git a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java index 7881a952eab9..648c782a7d1e 100644 --- a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java +++ b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java @@ -289,6 +289,7 @@ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { } } + @GuardedBy("mLock") private void sendAudioPlayerActiveStateChangedMessageLocked( final AudioPlaybackConfiguration config, final boolean isRemoved) { for (MessageHandler messageHandler : mListenerMap.values()) { diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index a17dd122f760..f34662909a85 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -4678,10 +4678,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return subId; } + @GuardedBy("mNetworkPoliciesSecondLock") private int getSubIdLocked(Network network) { return mNetIdToSubId.get(network.netId, INVALID_SUBSCRIPTION_ID); } + @GuardedBy("mNetworkPoliciesSecondLock") private SubscriptionPlan getPrimarySubscriptionPlanLocked(int subId) { final SubscriptionPlan[] plans = mSubscriptionPlans.get(subId); return ArrayUtils.isEmpty(plans) ? null : plans[0]; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index bfc150e1a9b0..76c4db134036 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -405,6 +405,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags); } + @GuardedBy("mStatsLock") private void shutdownLocked() { mContext.unregisterReceiver(mTetherReceiver); mContext.unregisterReceiver(mPollReceiver); @@ -431,6 +432,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mSystemReady = false; } + @GuardedBy("mStatsLock") private void maybeUpgradeLegacyStatsLocked() { File file; try { @@ -909,6 +911,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * reflect current {@link #mPersistThreshold} value. Always defers to * {@link Global} values when defined. */ + @GuardedBy("mStatsLock") private void updatePersistThresholdsLocked() { mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold)); mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold)); @@ -1029,6 +1032,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * are active on a single {@code iface}, they are combined under a single * {@link NetworkIdentitySet}. */ + @GuardedBy("mStatsLock") private void updateIfacesLocked(Network[] defaultNetworks) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1128,6 +1132,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return ident; } + @GuardedBy("mStatsLock") private void recordSnapshotLocked(long currentTime) throws RemoteException { // snapshot and record current counters; read UID stats first to // avoid over counting dev stats. @@ -1163,6 +1168,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Bootstrap initial stats snapshot, usually during {@link #systemReady()} * so we have baseline values without double-counting. */ + @GuardedBy("mStatsLock") private void bootstrapStatsLocked() { final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); @@ -1197,6 +1203,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Periodic poll operation, reading current statistics and recording into * {@link NetworkStatsHistory}. */ + @GuardedBy("mStatsLock") private void performPollLocked(int flags) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")"); @@ -1258,6 +1265,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * Sample recent statistics summary into {@link EventLog}. */ + @GuardedBy("mStatsLock") private void performSampleLocked() { // TODO: migrate trustedtime fixes to separate binary log events final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1; @@ -1295,6 +1303,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * Clean up {@link #mUidRecorder} after UID is removed. */ + @GuardedBy("mStatsLock") private void removeUidsLocked(int... uids) { if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids)); @@ -1313,6 +1322,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * Clean up {@link #mUidRecorder} after user is removed. */ + @GuardedBy("mStatsLock") private void removeUserLocked(int userId) { if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId); @@ -1434,6 +1444,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + @GuardedBy("mStatsLock") private void dumpProtoLocked(FileDescriptor fd) { final ProtoOutputStream proto = new ProtoOutputStream(fd); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index ada002c0c5b0..3800017f0a08 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -686,6 +686,7 @@ public class NotificationManagerService extends SystemService { sbn.getId(), Notification.FLAG_AUTO_CANCEL, Notification.FLAG_FOREGROUND_SERVICE, false, r.getUserId(), REASON_CLICK, null); + reportUserInteraction(r); } } @@ -706,7 +707,7 @@ public class NotificationManagerService extends SystemService { .setSubtype(actionIndex)); EventLogTags.writeNotificationActionClicked(key, actionIndex, r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now)); - // TODO: Log action click via UsageStats. + reportUserInteraction(r); } } @@ -827,6 +828,7 @@ public class NotificationManagerService extends SystemService { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { r.recordDirectReplied(); + reportUserInteraction(r); } } } @@ -1758,6 +1760,10 @@ public class NotificationManagerService extends SystemService { return INotificationManager.Stub.asInterface(mService); } + /** + * Report to usage stats that the notification was seen. + * @param r notification record + */ protected void reportSeen(NotificationRecord r) { final int userId = r.sbn.getUserId(); mAppUsageStats.reportEvent(r.sbn.getPackageName(), @@ -1766,6 +1772,17 @@ public class NotificationManagerService extends SystemService { UsageEvents.Event.NOTIFICATION_SEEN); } + /** + * Report to usage stats that the notification was clicked. + * @param r notification record + */ + protected void reportUserInteraction(NotificationRecord r) { + final int userId = r.sbn.getUserId(); + mAppUsageStats.reportEvent(r.sbn.getPackageName(), + userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId, + UsageEvents.Event.USER_INTERACTION); + } + @VisibleForTesting NotificationManagerInternal getInternalService() { return mInternalService; @@ -3909,6 +3926,7 @@ public class NotificationManagerService extends SystemService { return true; } + @GuardedBy("mNotificationLock") protected int getNotificationCountLocked(String pkg, int userId, int excludedId, String excludedTag) { int count = 0; diff --git a/services/core/java/com/android/server/pm/InstantAppResolverConnection.java b/services/core/java/com/android/server/pm/InstantAppResolverConnection.java index a9ee41162ae1..98f421ecf2b8 100644 --- a/services/core/java/com/android/server/pm/InstantAppResolverConnection.java +++ b/services/core/java/com/android/server/pm/InstantAppResolverConnection.java @@ -141,6 +141,7 @@ final class InstantAppResolverConnection implements DeathRecipient { } } + @GuardedBy("mLock") private void waitForBindLocked(String token) throws TimeoutException, InterruptedException { final long startMillis = SystemClock.uptimeMillis(); while (mBindState != STATE_IDLE) { @@ -250,6 +251,7 @@ final class InstantAppResolverConnection implements DeathRecipient { } } + @GuardedBy("mLock") private void handleBinderDiedLocked() { if (mRemoteInstance != null) { try { diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 59f9dae0619a..0b32d1a5d69b 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -226,6 +226,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } } + @GuardedBy("mSessions") private void reconcileStagesLocked(String volumeUuid, boolean isEphemeral) { final File stagingDir = buildStagingDir(volumeUuid, isEphemeral); final ArraySet<File> unclaimedStages = newArraySet( @@ -283,6 +284,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } } + @GuardedBy("mSessions") private void readSessionsLocked() { if (LOGD) Slog.v(TAG, "readSessionsLocked()"); @@ -340,6 +342,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } } + @GuardedBy("mSessions") private void addHistoricalSessionLocked(PackageInstallerSession session) { CharArrayWriter writer = new CharArrayWriter(); IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); @@ -352,6 +355,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { mHistoricalSessionsByInstaller.get(installerUid) + 1); } + @GuardedBy("mSessions") private void writeSessionsLocked() { if (LOGD) Slog.v(TAG, "writeSessionsLocked()"); @@ -612,6 +616,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } } + @GuardedBy("mSessions") private int allocateSessionIdLocked() { int n = 0; int sessionId; diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 3dd5a3415e35..9c692816aa6e 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -318,6 +318,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { /** * @return {@code true} iff the installing is app an device owner or affiliated profile owner. */ + @GuardedBy("mLock") private boolean isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked() { DevicePolicyManagerInternal dpmi = LocalServices.getService(DevicePolicyManagerInternal.class); @@ -334,6 +335,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * * @return {@code true} iff we need to ask to confirm the permissions? */ + @GuardedBy("mLock") private boolean needToAskForPermissionsLocked() { if (mPermissionsManuallyAccepted) { return false; @@ -456,6 +458,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + @GuardedBy("mLock") private void assertPreparedAndNotSealedLocked(String cookie) { assertPreparedAndNotCommittedOrDestroyedLocked(cookie); if (mSealed) { @@ -463,6 +466,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + @GuardedBy("mLock") private void assertPreparedAndNotCommittedOrDestroyedLocked(String cookie) { assertPreparedAndNotDestroyedLocked(cookie); if (mCommitted) { @@ -470,6 +474,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + @GuardedBy("mLock") private void assertPreparedAndNotDestroyedLocked(String cookie) { if (!mPrepared) { throw new IllegalStateException(cookie + " before prepared"); @@ -484,6 +489,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * might point at an ASEC mount point, which is why we delay path resolution * until someone actively works with the session. */ + @GuardedBy("mLock") private File resolveStageDirLocked() throws IOException { if (mResolvedStageDir == null) { if (stageDir != null) { @@ -516,6 +522,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + @GuardedBy("mLock") private void computeProgressLocked(boolean forcePublish) { mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f) + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f); @@ -728,6 +735,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * Check if the caller is the owner of this session. Otherwise throw a * {@link SecurityException}. */ + @GuardedBy("mLock") private void assertCallerIsOwnerOrRootLocked() { final int callingUid = Binder.getCallingUid(); if (callingUid != Process.ROOT_UID && callingUid != mInstallerUid) { @@ -738,6 +746,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { /** * If anybody is reading or writing data of the session, throw an {@link SecurityException}. */ + @GuardedBy("mLock") private void assertNoWriteFileTransfersOpenLocked() { // Verify that all writers are hands-off for (RevocableFileDescriptor fd : mFds) { @@ -820,6 +829,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * @throws PackageManagerException if the session was sealed but something went wrong. If the * session was sealed this is the only possible exception. */ + @GuardedBy("mLock") private void sealAndValidateLocked() throws PackageManagerException, IOException { assertNoWriteFileTransfersOpenLocked(); assertPreparedAndNotDestroyedLocked("sealing of session"); @@ -901,6 +911,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mCallback.onSessionSealedBlocking(this); } + @GuardedBy("mLock") private void commitLocked() throws PackageManagerException { if (mDestroyed) { @@ -1016,6 +1027,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * Note that upgrade compatibility is still performed by * {@link PackageManagerService}. */ + @GuardedBy("mLock") private void validateInstallLocked(@Nullable PackageInfo pkgInfo) throws PackageManagerException { mPackageName = null; @@ -1228,6 +1240,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + @GuardedBy("mLock") private void assertApkConsistentLocked(String tag, ApkLite apk) throws PackageManagerException { if (!mPackageName.equals(apk.packageName)) { @@ -1511,6 +1524,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + @GuardedBy("mLock") private void dumpLocked(IndentingPrintWriter pw) { pw.println("Session " + sessionId + ":"); pw.increaseIndent(); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 2816bbd36b0b..384b074e4c2f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -797,6 +797,7 @@ public class PackageManagerService extends IPackageManager.Stub return overlayPackages; } + @GuardedBy("mInstallLock") final String[] getStaticOverlayPathsLocked(Collection<PackageParser.Package> allPackages, String targetPackageName, String targetPath) { if ("android".equals(targetPackageName)) { @@ -9015,6 +9016,7 @@ public class PackageManagerService extends IPackageManager.Stub } } + @GuardedBy("mPackages") private void notifyPackageUseLocked(String packageName, int reason) { final PackageParser.Package p = mPackages.get(packageName); if (p == null) { @@ -10625,8 +10627,6 @@ public class PackageManagerService extends IPackageManager.Stub ~ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE; pkg.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; - // clear protected broadcasts - pkg.protectedBroadcasts = null; // cap permission priorities if (pkg.permissionGroups != null && pkg.permissionGroups.size() > 0) { for (int i = pkg.permissionGroups.size() - 1; i >= 0; --i) { @@ -10635,6 +10635,8 @@ public class PackageManagerService extends IPackageManager.Stub } } if ((scanFlags & SCAN_AS_PRIVILEGED) == 0) { + // clear protected broadcasts + pkg.protectedBroadcasts = null; // ignore export request for single user receivers if (pkg.receivers != null) { for (int i = pkg.receivers.size() - 1; i >= 0; --i) { @@ -13954,6 +13956,7 @@ public class PackageManagerService extends IPackageManager.Stub } } + @GuardedBy("mPackages") private boolean canSuspendPackageForUserLocked(String packageName, int userId) { if (isPackageDeviceAdmin(packageName, userId)) { Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName @@ -16610,6 +16613,12 @@ public class PackageManagerService extends IPackageManager.Stub if (userId != UserHandle.USER_ALL) { ps.setInstalled(true, userId); ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName); + } else { + for (int currentUserId : sUserManager.getUserIds()) { + ps.setInstalled(true, currentUserId); + ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, currentUserId, + installerPackageName); + } } // When replacing an existing package, preserve the original install reason for all diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index a85d6d838045..034fd2390a8c 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -530,6 +530,7 @@ public class ShortcutService extends IShortcutService.Stub { return processState <= PROCESS_STATE_FOREGROUND_THRESHOLD; } + @GuardedBy("mLock") boolean isUidForegroundLocked(int uid) { if (uid == Process.SYSTEM_UID) { // IUidObserver doesn't report the state of SYSTEM, but it always has bound services, @@ -545,6 +546,7 @@ public class ShortcutService extends IShortcutService.Stub { return isProcessStateForeground(mActivityManagerInternal.getUidProcessState(uid)); } + @GuardedBy("mLock") long getUidLastForegroundElapsedTimeLocked(int uid) { return mUidLastForegroundElapsedTime.get(uid); } @@ -638,6 +640,7 @@ public class ShortcutService extends IShortcutService.Stub { } } + @GuardedBy("mLock") private void unloadUserLocked(int userId) { if (DEBUG) { Slog.d(TAG, "unloadUserLocked: user=" + userId); @@ -864,6 +867,7 @@ public class ShortcutService extends IShortcutService.Stub { writeAttr(out, name, intent.toUri(/* flags =*/ 0)); } + @GuardedBy("mLock") @VisibleForTesting void saveBaseStateLocked() { final AtomicFile file = getBaseStateFile(); @@ -896,6 +900,7 @@ public class ShortcutService extends IShortcutService.Stub { } } + @GuardedBy("mLock") private void loadBaseStateLocked() { mRawLastResetTime = 0; @@ -948,6 +953,7 @@ public class ShortcutService extends IShortcutService.Stub { return new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES); } + @GuardedBy("mLock") private void saveUserLocked(@UserIdInt int userId) { final File path = getUserFile(userId); if (DEBUG) { @@ -974,6 +980,7 @@ public class ShortcutService extends IShortcutService.Stub { } } + @GuardedBy("mLock") private void saveUserInternalLocked(@UserIdInt int userId, OutputStream os, boolean forBackup) throws IOException, XmlPullParserException { @@ -1107,12 +1114,14 @@ public class ShortcutService extends IShortcutService.Stub { } /** Return the last reset time. */ + @GuardedBy("mLock") long getLastResetTimeLocked() { updateTimesLocked(); return mRawLastResetTime; } /** Return the next reset time. */ + @GuardedBy("mLock") long getNextResetTimeLocked() { updateTimesLocked(); return mRawLastResetTime + mResetInterval; @@ -1125,6 +1134,7 @@ public class ShortcutService extends IShortcutService.Stub { /** * Update the last reset time. */ + @GuardedBy("mLock") private void updateTimesLocked() { final long now = injectCurrentTimeMillis(); @@ -1220,6 +1230,7 @@ public class ShortcutService extends IShortcutService.Stub { return ret; } + @GuardedBy("mLock") void forEachLoadedUserLocked(@NonNull Consumer<ShortcutUser> c) { for (int i = mUsers.size() - 1; i >= 0; i--) { c.accept(mUsers.valueAt(i)); @@ -1279,6 +1290,7 @@ public class ShortcutService extends IShortcutService.Stub { * {@link ShortcutBitmapSaver#waitForAllSavesLocked()} to make sure there's no pending bitmap * saves are going on. */ + @GuardedBy("mLock") private void cleanupDanglingBitmapDirectoriesLocked(@UserIdInt int userId) { if (DEBUG) { Slog.d(TAG, "cleanupDanglingBitmaps: userId=" + userId); @@ -2108,6 +2120,7 @@ public class ShortcutService extends IShortcutService.Stub { } } + @GuardedBy("mLock") private ParceledListSlice<ShortcutInfo> getShortcutsWithQueryLocked(@NonNull String packageName, @UserIdInt int userId, int cloneFlags, @NonNull Predicate<ShortcutInfo> query) { @@ -2418,6 +2431,7 @@ public class ShortcutService extends IShortcutService.Stub { * * This is called when an app is uninstalled, or an app gets "clear data"ed. */ + @GuardedBy("mLock") @VisibleForTesting void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId, boolean appStillExists) { @@ -2508,6 +2522,7 @@ public class ShortcutService extends IShortcutService.Stub { return setReturnedByServer(ret); } + @GuardedBy("ShortcutService.this.mLock") private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage, @Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince, @Nullable ComponentName componentName, int queryFlags, @@ -2579,6 +2594,7 @@ public class ShortcutService extends IShortcutService.Stub { } } + @GuardedBy("ShortcutService.this.mLock") private ShortcutInfo getShortcutInfoLocked( int launcherUserId, @NonNull String callingPackage, @NonNull String packageName, @NonNull String shortcutId, int userId, @@ -2940,6 +2956,7 @@ public class ShortcutService extends IShortcutService.Stub { verifyStates(); } + @GuardedBy("mLock") private void rescanUpdatedPackagesLocked(@UserIdInt int userId, long lastScanTime) { final ShortcutUser user = getUserShortcutsLocked(userId); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index b53d83b1291c..a0577b15736b 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1547,6 +1547,7 @@ public class UserManagerService extends IUserManager.Stub { return result; } + @GuardedBy("mRestrictionsLock") private EnforcingUser getEnforcingUserLocked(@UserIdInt int userId) { int source = mDeviceOwnerUserId == userId ? UserManager.RESTRICTION_SOURCE_DEVICE_OWNER : UserManager.RESTRICTION_SOURCE_PROFILE_OWNER; @@ -2896,6 +2897,7 @@ public class UserManagerService extends IUserManager.Stub { } } + @GuardedBy("mUsersLock") @VisibleForTesting void addRemovingUserIdLocked(int userId) { // We remember deleted user IDs to prevent them from being @@ -3405,6 +3407,7 @@ public class UserManagerService extends IUserManager.Stub { return nextId; } + @GuardedBy("mUsersLock") private int scanNextAvailableIdLocked() { for (int i = MIN_USER_ID; i < MAX_USER_ID; i++) { if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) { diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 08f8bbd20af6..3f8a1e8a6af1 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1210,6 +1210,7 @@ Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages)); return false; } + @GuardedBy("mLock") private void grantRuntimePermissionsGrantedToDisabledPackageLocked( PackageParser.Package pkg, int callingUid, PermissionCallback callback) { if (pkg.parentPackage == null) { @@ -1499,6 +1500,7 @@ Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages)); } } + @GuardedBy("mLock") private int[] revokeUnusedSharedUserPermissionsLocked( SharedUserSetting suSetting, int[] allUserIds) { // Collect all used permissions in the UID diff --git a/services/core/java/com/android/server/pm/permission/PermissionSettings.java b/services/core/java/com/android/server/pm/permission/PermissionSettings.java index f6c4990c3294..b3f2833a52f1 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionSettings.java +++ b/services/core/java/com/android/server/pm/permission/PermissionSettings.java @@ -201,34 +201,42 @@ public class PermissionSettings { } } + @GuardedBy("mLock") @Nullable BasePermission getPermissionLocked(@NonNull String permName) { return mPermissions.get(permName); } + @GuardedBy("mLock") @Nullable BasePermission getPermissionTreeLocked(@NonNull String permName) { return mPermissionTrees.get(permName); } + @GuardedBy("mLock") void putPermissionLocked(@NonNull String permName, @NonNull BasePermission permission) { mPermissions.put(permName, permission); } + @GuardedBy("mLock") void putPermissionTreeLocked(@NonNull String permName, @NonNull BasePermission permission) { mPermissionTrees.put(permName, permission); } + @GuardedBy("mLock") void removePermissionLocked(@NonNull String permName) { mPermissions.remove(permName); } + @GuardedBy("mLock") void removePermissionTreeLocked(@NonNull String permName) { mPermissionTrees.remove(permName); } + @GuardedBy("mLock") @NonNull Collection<BasePermission> getAllPermissionsLocked() { return mPermissions.values(); } + @GuardedBy("mLock") @NonNull Collection<BasePermission> getAllPermissionTreesLocked() { return mPermissionTrees.values(); } diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java index 847c90a08c5c..08dc97e7dd63 100644 --- a/services/core/java/com/android/server/power/BatterySaverPolicy.java +++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java @@ -306,6 +306,7 @@ public class BatterySaverPolicy extends ContentObserver { } } + @GuardedBy("mLock") @VisibleForTesting void updateConstantsLocked(final String setting, final String deviceSpecificSetting) { mSettings = setting; diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 1bb85c4426e1..38dc820e5b88 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -120,9 +120,6 @@ public final class PowerManagerService extends SystemService private static final boolean DEBUG = false; private static final boolean DEBUG_SPEW = DEBUG && true; - // if DEBUG_WIRELESS=true, plays wireless charging animation w/ sound on every plug + unplug - private static final boolean DEBUG_WIRELESS = false; - // Message: Sent when a user activity timeout occurs to update the power state. private static final int MSG_USER_ACTIVITY_TIMEOUT = 1; // Message: Sent when the device enters or exits a dreaming or dozing state. @@ -1743,14 +1740,15 @@ public final class PowerManagerService extends SystemService userActivityNoUpdateLocked( now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID); - // Tell the notifier whether wireless charging has started so that - // it can provide feedback to the user. - if (dockedOnWirelessCharger || DEBUG_WIRELESS) { - mNotifier.onWirelessChargingStarted(mBatteryLevel); - } else if (mIsPowered && !wasPowered - && (mPlugType == BatteryManager.BATTERY_PLUGGED_AC - || mPlugType == BatteryManager.BATTERY_PLUGGED_USB)) { - mNotifier.onWiredChargingStarted(); + // only play charging sounds if boot is completed so charging sounds don't play + // with potential notification sounds + if (mBootCompleted) { + if (mIsPowered && !BatteryManager.isPlugWired(oldPlugType) + && BatteryManager.isPlugWired(mPlugType)) { + mNotifier.onWiredChargingStarted(); + } else if (dockedOnWirelessCharger) { + mNotifier.onWirelessChargingStarted(mBatteryLevel); + } } } diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java index 671d7a67af1c..37df94fee207 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java @@ -285,6 +285,7 @@ public class BatterySavingStats { } } + @GuardedBy("mLock") private void transitionStateLocked(int newState) { if (mCurrentState == newState) { return; @@ -298,6 +299,7 @@ public class BatterySavingStats { mMetricsLoggerHelper.transitionState(newState, now, batteryLevel, batteryPercent); } + @GuardedBy("mLock") private void endLastStateLocked(long now, int batteryLevel, int batteryPercent) { if (mCurrentState < 0) { return; @@ -338,6 +340,7 @@ public class BatterySavingStats { } + @GuardedBy("mLock") private void startNewStateLocked(int newState, long now, int batteryLevel, int batteryPercent) { if (DEBUG) { Slog.d(TAG, "New state: " + stateToString(newState)); diff --git a/services/core/java/com/android/server/power/batterysaver/FileUpdater.java b/services/core/java/com/android/server/power/batterysaver/FileUpdater.java index e0ab9e93a8a6..c08b610ccd2d 100644 --- a/services/core/java/com/android/server/power/batterysaver/FileUpdater.java +++ b/services/core/java/com/android/server/power/batterysaver/FileUpdater.java @@ -306,6 +306,7 @@ public class FileUpdater { } } + @GuardedBy("mLock") private void saveDefaultValuesLocked() { final AtomicFile file = new AtomicFile(injectDefaultValuesFilename()); @@ -334,6 +335,7 @@ public class FileUpdater { } } + @GuardedBy("mLock") @VisibleForTesting boolean loadDefaultValuesLocked() { final AtomicFile file = new AtomicFile(injectDefaultValuesFilename()); diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index a82b55949cb9..ef6067a73716 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -85,7 +85,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity"; static final String TAG = "StatsCompanionService"; - static final boolean DEBUG = true; + static final boolean DEBUG = false; public static final int CODE_DATA_BROADCAST = 1; public static final int CODE_SUBSCRIBER_BROADCAST = 1; @@ -211,6 +211,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } // Assumes that sStatsdLock is held. + @GuardedBy("sStatsdLock") private final void informAllUidsLocked(Context context) throws RemoteException { UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); PackageManager pm = context.getPackageManager(); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 7c170aee92fa..343fb91eec53 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -321,7 +321,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub { public void showChargingAnimation(int batteryLevel) { if (mBar != null) { try { - mBar.showChargingAnimation(batteryLevel); + mBar.showWirelessChargingAnimation(batteryLevel); } catch (RemoteException ex){ } } diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java index 853c7eb51b84..0ac853b030e1 100644 --- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java +++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java @@ -22,7 +22,6 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Binder; -import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; @@ -43,7 +42,6 @@ import com.android.server.SystemService; import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; /** * A manager for TextClassifier services. @@ -54,9 +52,6 @@ public final class TextClassificationManagerService extends ITextClassifierServi private static final String LOG_TAG = "TextClassificationManagerService"; - // How long after the last interaction with the service we would unbind - private static final long TIMEOUT_IDLE_BIND_MILLIS = TimeUnit.MINUTES.toMillis(1); - public static final class Lifecycle extends SystemService { private final TextClassificationManagerService mManagerService; @@ -79,10 +74,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi } private final Context mContext; - private final Handler mHandler; private final Intent mServiceIntent; private final ServiceConnection mConnection; - private final Runnable mUnbind; private final Object mLock; @GuardedBy("mLock") private final Queue<PendingRequest> mPendingRequests; @@ -94,7 +87,6 @@ public final class TextClassificationManagerService extends ITextClassifierServi private TextClassificationManagerService(Context context) { mContext = Preconditions.checkNotNull(context); - mHandler = new Handler(); mServiceIntent = new Intent(TextClassifierService.SERVICE_INTERFACE) .setComponent(TextClassifierService.getServiceComponentName(mContext)); mConnection = new ServiceConnection() { @@ -131,7 +123,6 @@ public final class TextClassificationManagerService extends ITextClassifierServi } }; mPendingRequests = new LinkedList<>(); - mUnbind = this::unbind; mLock = new Object(); } @@ -152,7 +143,6 @@ public final class TextClassificationManagerService extends ITextClassifierServi if (isBoundLocked()) { mService.onSuggestSelection( text, selectionStartIndex, selectionEndIndex, options, callback); - scheduleUnbindLocked(); } else { final Callable<Void> request = () -> { onSuggestSelection( @@ -184,7 +174,6 @@ public final class TextClassificationManagerService extends ITextClassifierServi synchronized (mLock) { if (isBoundLocked()) { mService.onClassifyText(text, startIndex, endIndex, options, callback); - scheduleUnbindLocked(); } else { final Callable<Void> request = () -> { onClassifyText(text, startIndex, endIndex, options, callback); @@ -213,7 +202,6 @@ public final class TextClassificationManagerService extends ITextClassifierServi synchronized (mLock) { if (isBoundLocked()) { mService.onGenerateLinks(text, options, callback); - scheduleUnbindLocked(); } else { final Callable<Void> request = () -> { onGenerateLinks(text, options, callback); @@ -270,27 +258,6 @@ public final class TextClassificationManagerService extends ITextClassifierServi mBinding = binding; } - private void unbind() { - synchronized (mLock) { - if (!isBoundLocked()) { - return; - } - - Slog.d(LOG_TAG, "Unbinding from " + mServiceIntent.getComponent()); - mContext.unbindService(mConnection); - - synchronized (mLock) { - mService = null; - } - } - } - - @GuardedBy("mLock") - private void scheduleUnbindLocked() { - mHandler.removeCallbacks(mUnbind); - mHandler.postDelayed(mUnbind, TIMEOUT_IDLE_BIND_MILLIS); - } - @GuardedBy("mLock") private void enqueueRequestLocked( Callable<Void> request, Callable<Void> onServiceFailure, IBinder binder) { diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java index dc62cc89c14d..1b2f9542df11 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java @@ -151,6 +151,7 @@ class SurfaceAnimationRunner { } } + @GuardedBy("mLock") private void startPendingAnimationsLocked() { for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { startAnimationLocked(mPendingAnimations.valueAt(i)); @@ -158,6 +159,7 @@ class SurfaceAnimationRunner { mPendingAnimations.clear(); } + @GuardedBy("mLock") private void startAnimationLocked(RunningAnimation a) { final ValueAnimator anim = mAnimatorFactory.makeAnimator(); diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java index 7b047a80d572..621bee7d17e0 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java @@ -281,11 +281,13 @@ class TaskSnapshotPersister { mSnapshot = snapshot; } + @GuardedBy("mLock") @Override void onQueuedLocked() { mStoreQueueItems.offer(this); } + @GuardedBy("mLock") @Override void onDequeuedLocked() { mStoreQueueItems.remove(this); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 240e7fd8e9b0..b6712c097e23 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -265,7 +265,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // This is a non-system overlay window that is currently force hidden. private boolean mForceHideNonSystemOverlayWindow; boolean mAppFreezing; - boolean mHidden; // Used to determine if to show child windows. + boolean mHidden = true; // Used to determine if to show child windows. boolean mWallpaperVisible; // for wallpaper, what was last vis report? private boolean mDragResizing; private boolean mDragResizingChangeReported = true; @@ -4505,13 +4505,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (!mAnimatingExit && mAppDied) { mIsDimming = true; dimmer.dimAbove(getPendingTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW); - } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isVisibleNow() - && !mWinAnimator.mLastHidden) { + } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isVisibleNow() && !mHidden) { // Only show a dim behind when the following is satisfied: // 1. The window has the flag FLAG_DIM_BEHIND // 2. The WindowToken is not hidden so dims aren't shown when the window is exiting. // 3. The WS is considered visible according to the isVisible() method - // 4. The WSA is not hidden. + // 4. The WS is not hidden. mIsDimming = true; dimmer.dimBelow(getPendingTransaction(), this, mAttrs.dimAmount); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java index 60f204dd4bbc..0c0ce8dd5174 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java @@ -193,6 +193,7 @@ public class DeviceAdminServiceController { } } + @GuardedBy("mLock") private void disconnectServiceOnUserLocked(int userId, @NonNull String actionForLog) { final DevicePolicyServiceConnection conn = mConnections.get(userId); if (conn != null) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 95e71edb68d9..875334413b5a 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -10226,6 +10226,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mInjector.registerContentObserver(mDefaultImeChanged, false, this, UserHandle.USER_ALL); } + @GuardedBy("DevicePolicyManagerService.this") private void addPendingChangeByOwnerLocked(int userId) { mUserIdsWithPendingChangesByOwner.add(userId); } diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java index 7d9736ed3fe5..d19043223416 100644 --- a/services/net/java/android/net/apf/ApfFilter.java +++ b/services/net/java/android/net/apf/ApfFilter.java @@ -1068,6 +1068,7 @@ public class ApfFilter { mLastInstallEvent.flags = ApfProgramEvent.flagsFor(mIPv4Address != null, mMulticastFilter); } + @GuardedBy("this") private void logApfProgramEventLocked(long now) { if (mLastInstallEvent == null) { return; diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java index 49a1e79fd71e..8fbc01ea4493 100644 --- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java +++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java @@ -268,6 +268,7 @@ public class RouterAdvertisementDaemon { mUnicastResponder = null; } + @GuardedBy("mLock") private void assembleRaLocked() { final ByteBuffer ra = ByteBuffer.wrap(mRA); ra.order(ByteOrder.BIG_ENDIAN); diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java index ba5dde04897f..c1c32c28cb6b 100644 --- a/services/print/java/com/android/server/print/RemotePrintSpooler.java +++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java @@ -596,6 +596,7 @@ final class RemotePrintSpooler { } } + @GuardedBy("mLock") private void bindLocked() throws TimeoutException, InterruptedException { while (mIsBinding) { mLock.wait(); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java index ce5ee138cc3d..e40e3a42ee53 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java @@ -275,7 +275,7 @@ public class KeySyncTaskTest { } @Test - public void run_sendsEncryptedKeysIfAvailableToSync() throws Exception { + public void run_sendsEncryptedKeysIfAvailableToSync_withRawPublicKey() throws Exception { mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); @@ -323,6 +323,26 @@ public class KeySyncTaskTest { } @Test + public void run_sendsEncryptedKeysIfAvailableToSync_withCertPath() throws Exception { + mRecoverableKeyStoreDb.setRecoveryServiceCertPath( + TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TestData.CERT_PATH_1); + mRecoverableKeyStoreDb.setServerParams( + TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE); + when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); + addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); + + mKeySyncTask.run(); + + KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); + verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID); + List<WrappedApplicationKey> applicationKeys = keyChainSnapshot.getWrappedApplicationKeys(); + assertThat(applicationKeys).hasSize(1); + assertThat(keyChainSnapshot.getTrustedHardwarePublicKey()) + .isEqualTo(SecureBox.encodePublicKey( + TestData.CERT_PATH_1.getCertificates().get(0).getPublicKey())); + } + + @Test public void run_setsCorrectSnapshotVersion() throws Exception { mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java index 2343deec020b..a523b86f3b0b 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java @@ -238,15 +238,81 @@ public class RecoverableKeyStoreManagerTest { } @Test - public void initRecoveryService_updatesShouldCreateSnapshot() throws Exception { + public void initRecoveryService_succeeds() throws Exception { + int uid = Binder.getCallingUid(); + int userId = UserHandle.getCallingUserId(); + long certSerial = 1000L; + mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false); + + mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, + TestData.getCertXmlWithSerial(certSerial)); + + assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue(); + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isEqualTo( + TestData.CERT_PATH_1); + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isEqualTo( + certSerial); + assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull(); + } + + @Test + public void initRecoveryService_updatesWithLargerSerial() throws Exception { + int uid = Binder.getCallingUid(); + int userId = UserHandle.getCallingUserId(); + long certSerial = 1000L; + + mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, + TestData.getCertXmlWithSerial(certSerial)); + mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, + TestData.getCertXmlWithSerial(certSerial + 1)); + + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)) + .isEqualTo(certSerial + 1); + } + + @Test + public void initRecoveryService_ignoresSmallerSerial() throws Exception { + int uid = Binder.getCallingUid(); + int userId = UserHandle.getCallingUserId(); + long certSerial = 1000L; + + mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, + TestData.getCertXmlWithSerial(certSerial)); + mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, + TestData.getCertXmlWithSerial(certSerial - 1)); + + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)) + .isEqualTo(certSerial); + } + + @Test + public void initRecoveryService_ignoresTheSameSerial() throws Exception { + int uid = Binder.getCallingUid(); + int userId = UserHandle.getCallingUserId(); + long certSerial = 1000L; + + mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, + TestData.getCertXmlWithSerial(certSerial)); + mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false); + mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, + TestData.getCertXmlWithSerial(certSerial)); + + // If the second update succeeds, getShouldCreateSnapshot() will return true. + assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse(); + } + + @Test + public void initRecoveryService_succeedsWithRawPublicKey() throws Exception { int uid = Binder.getCallingUid(); int userId = UserHandle.getCallingUserId(); - // Sync is not needed. mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false); mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS, TEST_PUBLIC_KEY); assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue(); + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isNull(); + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isNull(); + assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNotNull(); } @Test @@ -344,26 +410,6 @@ public class RecoverableKeyStoreManagerTest { } @Test - public void startRecoverySession_throwsIfBadKey() throws Exception { - try { - mRecoverableKeyStoreManager.startRecoverySession( - TEST_SESSION_ID, - getUtf8Bytes("0"), - TEST_VAULT_PARAMS, - TEST_VAULT_CHALLENGE, - ImmutableList.of( - new KeyChainProtectionParams( - TYPE_LOCKSCREEN, - UI_FORMAT_PASSWORD, - KeyDerivationParams.createSha256Params(TEST_SALT), - TEST_SECRET))); - fail("should have thrown"); - } catch (ServiceSpecificException e) { - assertEquals("Not a valid X509 key", e.getMessage()); - } - } - - @Test public void startRecoverySession_throwsIfPublicKeysMismatch() throws Exception { byte[] vaultParams = TEST_VAULT_PARAMS.clone(); vaultParams[1] ^= (byte) 1; // Flip 1 bit diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestData.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestData.java new file mode 100644 index 000000000000..0e4f91b20ae2 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestData.java @@ -0,0 +1,202 @@ +package com.android.server.locksettings.recoverablekeystore; + +import com.android.server.locksettings.recoverablekeystore.certificate.CertUtils; + +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.security.cert.CertPath; +import java.security.cert.CertificateFactory; + +public final class TestData { + + private static final String CERT_PATH_ENCODING = "PkiPath"; + + private static final String CERT_PATH_1_BASE64 = "" + + "MIIIPzCCBS8wggMXoAMCAQICAhAAMA0GCSqGSIb3DQEBCwUAMCAxHjAcBgNVBAMM" + + "FUdvb2dsZSBDcnlwdEF1dGhWYXVsdDAeFw0xODAyMDMwMDQyMDNaFw0yODAyMDEw" + + "MDQyMDNaMC0xKzApBgNVBAMMIkdvb2dsZSBDcnlwdEF1dGhWYXVsdCBJbnRlcm1l" + + "ZGlhdGUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDckHib0X6rQyDq" + + "k4519b5du0OrCPk30XXKwz+Hz5y4cGZaWKGcHOHWS2X9YApRzO00/EbvFkWVUTVG" + + "27wJ54V+C3HHSOAUWHhEgfFWvvHwfn9HTDx1BEk79aQqJ7DuJ06Sn/WOiMtKVAT5" + + "6Mi8mekBxpMOrdZqwlcLrUVsZxEHsw5/ceZu4cSWzc7SzlnbNK1cCgyRDGqWf6Gp" + + "3hGE86kUOtM1i95RgUIpw+w/z0wxpF6kIyQTjK+KjiYH/RBOJIEcm6sSWZlMotKL" + + "Sn2lhf+XL8yUxExIHTosfeb077QWW4w2BB2NZM4wPAO3w4aw33FNigDQc2SQYmnU" + + "EYmIcD8kx77+JWCgCxBJc2zTHXtBxWuXAQ+iegt8RO+QD97pd6XKM9xPsAOkcWLp" + + "79o+AJol4P5fwvgYM69mM4lwH12v86RI4aptPQOag0KDIHXyKbjaQyAgv30l4KkD" + + "pf2uWODhOOTwNbVPYUm3sYUlhBcbyhTk8YqN9sPU4QAao5sKTAYZgB/mlheQypTU" + + "wyvqz6bRzGehVB3ltP9gCyKdI04VXEUuUBWk3STyV2REQen5/LKAns6v11Cz22Zr" + + "EdCvNLgetnyV7CJsOa/wD/GiUWL2Ta7pzshi9ahJqrrcNPRbAzOLcNKZkFexhzPp" + + "onuo/pNrcaRda1frepXxVkmbsgOULwIDAQABo2YwZDAdBgNVHQ4EFgQUd6md2hCP" + + "lmf3VkEX5FfDxKBLbaAwHwYDVR0jBBgwFoAUm2X66jmB+eBCaZHSjGYzHM/x6fgw" + + "EgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL" + + "BQADggIBAFgShhuW+WVTowN080PLf0TWPlHACHHUPghf7rFGxgUjJypCloE84Beg" + + "3ROpP5l19CDqZ9OyPzA1z6VAzeGXyFhZvby7G2tZDBRP/v0u8pnSAdC5F8l8Vh2Y" + + "GdgE3sZD25vpdBi7P0Ef6LYQetOJXn86PqgmgW1F6lzxDjKCsi9kpeU0AWwDdOVg" + + "748wku50o8UEzsVwxzFd9toGlge/nn3FH5J7EuGzAlFwToHqpwTVEegaAd0l9mr5" + + "+rS7Urd3X80BHDqCBcXE7Uqbtzw5Y+lmowMCnW0kFN02dC9dLt2c9IxC+9sPIA5e" + + "TkrZBkrkTVRGLj2r29j7nC9m5VaKcBqcLZDWy8pRna8yaZprgNdE8d/WTY9nVsic" + + "09N8zNF5Q0bhhWa3QonlB9XW5ZqDguiclvn+5TtREzSAtSOyxM+gfG3l0wjOywIk" + + "1aFa52RaqAWPL67KOM6G3vKNpMnW5hrmHrijuKxiarGIoZfkZMR5ijK0uFgv3/p6" + + "NHL/YQBaHJJhkKet5ThiPxwW9+1k/ZcXVeY26Xh+22Gp/8to7ZW8guPPiN1hfpD+" + + "7f1IdSmHDrsZQQ7bfzV0bppsyNNB7e2Ecyw+GQny27nytBLJDGdRBurbwQvzppQO" + + "6Qmlk0rfCszh7bGCoCQNxXmuDsQ5BC+pQUqJplTqds1smyi29xs3MIIDCDCB8aAD" + + "AgECAgYBYVkuU0cwDQYJKoZIhvcNAQELBQAwLTErMCkGA1UEAwwiR29vZ2xlIENy" + + "eXB0QXV0aFZhdWx0IEludGVybWVkaWF0ZTAeFw0xODAyMDIwMTAxMDNaFw0yMDAy" + + "MDMwMTAxMDNaMCkxJzAlBgNVBAMTHkdvb2dsZSBDcnlwdEF1dGhWYXVsdCBJbnN0" + + "YW5jZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLgAERiYHfButJT+htocB40B" + + "tDr2jdxh0EZJlQ8QhpMkZuA/0t/zeSAdkVWw5b16izJ9JVOi/KVl4b0hRH54Uvow" + + "DQYJKoZIhvcNAQELBQADggIBAJ3PM4GNTNYzMr8E/IGsWZkLx9ARAALqBXz7As59" + + "F8y5UcLMqkXD/ewOfBZgF5VzjlAePyE/wSw0wc3xzvrDVVDiZaMBW1DVtSlbn25q" + + "00m00mmcUeyyMc7vuRkPoDshIMQTc8+U3yyYsVScSV+B4TvSx6wPZ9FpwnSPjVPD" + + "2GkqeMTWszuxNVEWq0wmm0K5lMaX0hfiak+4/IZxOPPGIg2py1KLA/H2gdyeqyJR" + + "cAsyEkfwLlushR5T9abSiPsIRcYoX8Ck8Lt+gQ7RCMefnm8CoOBKIfcjuV4PGOoe" + + "Xrq57VR5SsOeT07bL+D7B+mohYFI1v2G3WClAE8XgM3q8NoFFvaYmoi0+UcTduil" + + "47qvozjdNmjRAgu5j6vMKXEdG5Rqsja8hy0LG1hwfnR0gNiwcZ5Le3GyFnwH1Igq" + + "vsGOUM0ohnDUAU0zJY7nG0QYrDYe5/QPRNhWDpYkwHDiqcG28wIQCOTPAZHU2EoS" + + "KjSqEG2l0S5JPcor2BEde9ikSkcmK8foxlOHIdFn+n7RNF3bSEfKn1IOuXoqPidm" + + "eBQLevqG8KTy/C9CHqlaCNlpbIA9h+WVfsjm2s6JXBu0YbcfoIbJAmSuZVeqB/+Z" + + "Vvpfiad/jQWzY49fRnsSmV7VveTFPGtJxC89EadbMAinMZo+72u59319RqN5wsP2" + + "Zus8"; + private static String CERT_PATH_2_BASE64 = "" + + "MIIFMzCCBS8wggMXoAMCAQICAhAAMA0GCSqGSIb3DQEBCwUAMCAxHjAcBgNVBAMM" + + "FUdvb2dsZSBDcnlwdEF1dGhWYXVsdDAeFw0xODAyMDMwMDQyMDNaFw0yODAyMDEw" + + "MDQyMDNaMC0xKzApBgNVBAMMIkdvb2dsZSBDcnlwdEF1dGhWYXVsdCBJbnRlcm1l" + + "ZGlhdGUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDckHib0X6rQyDq" + + "k4519b5du0OrCPk30XXKwz+Hz5y4cGZaWKGcHOHWS2X9YApRzO00/EbvFkWVUTVG" + + "27wJ54V+C3HHSOAUWHhEgfFWvvHwfn9HTDx1BEk79aQqJ7DuJ06Sn/WOiMtKVAT5" + + "6Mi8mekBxpMOrdZqwlcLrUVsZxEHsw5/ceZu4cSWzc7SzlnbNK1cCgyRDGqWf6Gp" + + "3hGE86kUOtM1i95RgUIpw+w/z0wxpF6kIyQTjK+KjiYH/RBOJIEcm6sSWZlMotKL" + + "Sn2lhf+XL8yUxExIHTosfeb077QWW4w2BB2NZM4wPAO3w4aw33FNigDQc2SQYmnU" + + "EYmIcD8kx77+JWCgCxBJc2zTHXtBxWuXAQ+iegt8RO+QD97pd6XKM9xPsAOkcWLp" + + "79o+AJol4P5fwvgYM69mM4lwH12v86RI4aptPQOag0KDIHXyKbjaQyAgv30l4KkD" + + "pf2uWODhOOTwNbVPYUm3sYUlhBcbyhTk8YqN9sPU4QAao5sKTAYZgB/mlheQypTU" + + "wyvqz6bRzGehVB3ltP9gCyKdI04VXEUuUBWk3STyV2REQen5/LKAns6v11Cz22Zr" + + "EdCvNLgetnyV7CJsOa/wD/GiUWL2Ta7pzshi9ahJqrrcNPRbAzOLcNKZkFexhzPp" + + "onuo/pNrcaRda1frepXxVkmbsgOULwIDAQABo2YwZDAdBgNVHQ4EFgQUd6md2hCP" + + "lmf3VkEX5FfDxKBLbaAwHwYDVR0jBBgwFoAUm2X66jmB+eBCaZHSjGYzHM/x6fgw" + + "EgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL" + + "BQADggIBAFgShhuW+WVTowN080PLf0TWPlHACHHUPghf7rFGxgUjJypCloE84Beg" + + "3ROpP5l19CDqZ9OyPzA1z6VAzeGXyFhZvby7G2tZDBRP/v0u8pnSAdC5F8l8Vh2Y" + + "GdgE3sZD25vpdBi7P0Ef6LYQetOJXn86PqgmgW1F6lzxDjKCsi9kpeU0AWwDdOVg" + + "748wku50o8UEzsVwxzFd9toGlge/nn3FH5J7EuGzAlFwToHqpwTVEegaAd0l9mr5" + + "+rS7Urd3X80BHDqCBcXE7Uqbtzw5Y+lmowMCnW0kFN02dC9dLt2c9IxC+9sPIA5e" + + "TkrZBkrkTVRGLj2r29j7nC9m5VaKcBqcLZDWy8pRna8yaZprgNdE8d/WTY9nVsic" + + "09N8zNF5Q0bhhWa3QonlB9XW5ZqDguiclvn+5TtREzSAtSOyxM+gfG3l0wjOywIk" + + "1aFa52RaqAWPL67KOM6G3vKNpMnW5hrmHrijuKxiarGIoZfkZMR5ijK0uFgv3/p6" + + "NHL/YQBaHJJhkKet5ThiPxwW9+1k/ZcXVeY26Xh+22Gp/8to7ZW8guPPiN1hfpD+" + + "7f1IdSmHDrsZQQ7bfzV0bppsyNNB7e2Ecyw+GQny27nytBLJDGdRBurbwQvzppQO" + + "6Qmlk0rfCszh7bGCoCQNxXmuDsQ5BC+pQUqJplTqds1smyi29xs3"; + + private static final String THM_CERT_XML_BEFORE_SERIAL = "" + + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + "<certificates>\n" + + " <metadata>\n" + + " <serial>\n"; + private static final String THM_CERT_XML_AFTER_SERIAL = "" + + " </serial>\n" + + " <creation-time>\n" + + " 1515697631\n" + + " </creation-time>\n" + + " <refresh-interval>\n" + + " 2592000\n" + + " </refresh-interval>\n" + + " <previous>\n" + + " <serial>\n" + + " 0\n" + + " </serial>\n" + + " <hash>\n" + + " 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=\n" + + " </hash>\n" + + " </previous>\n" + + " </metadata>\n" + + " <intermediates>\n" + + " <cert>\n" + + " MIIFLzCCAxegAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UEAwwVR29v\n" + + " Z2xlIENyeXB0QXV0aFZhdWx0MB4XDTE4MDIwMzAwNDIwM1oXDTI4MDIwMTAwNDIw\n" + + " M1owLTErMCkGA1UEAwwiR29vZ2xlIENyeXB0QXV0aFZhdWx0IEludGVybWVkaWF0\n" + + " ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANyQeJvRfqtDIOqTjnX1\n" + + " vl27Q6sI+TfRdcrDP4fPnLhwZlpYoZwc4dZLZf1gClHM7TT8Ru8WRZVRNUbbvAnn\n" + + " hX4LccdI4BRYeESB8Va+8fB+f0dMPHUESTv1pConsO4nTpKf9Y6Iy0pUBPnoyLyZ\n" + + " 6QHGkw6t1mrCVwutRWxnEQezDn9x5m7hxJbNztLOWds0rVwKDJEMapZ/oaneEYTz\n" + + " qRQ60zWL3lGBQinD7D/PTDGkXqQjJBOMr4qOJgf9EE4kgRybqxJZmUyi0otKfaWF\n" + + " /5cvzJTETEgdOix95vTvtBZbjDYEHY1kzjA8A7fDhrDfcU2KANBzZJBiadQRiYhw\n" + + " PyTHvv4lYKALEElzbNMde0HFa5cBD6J6C3xE75AP3ul3pcoz3E+wA6RxYunv2j4A\n" + + " miXg/l/C+Bgzr2YziXAfXa/zpEjhqm09A5qDQoMgdfIpuNpDICC/fSXgqQOl/a5Y\n" + + " 4OE45PA1tU9hSbexhSWEFxvKFOTxio32w9ThABqjmwpMBhmAH+aWF5DKlNTDK+rP\n" + + " ptHMZ6FUHeW0/2ALIp0jThVcRS5QFaTdJPJXZERB6fn8soCezq/XULPbZmsR0K80\n" + + " uB62fJXsImw5r/AP8aJRYvZNrunOyGL1qEmqutw09FsDM4tw0pmQV7GHM+mie6j+\n" + + " k2txpF1rV+t6lfFWSZuyA5QvAgMBAAGjZjBkMB0GA1UdDgQWBBR3qZ3aEI+WZ/dW\n" + + " QRfkV8PEoEttoDAfBgNVHSMEGDAWgBSbZfrqOYH54EJpkdKMZjMcz/Hp+DASBgNV\n" + + " HRMBAf8ECDAGAQH/AgEBMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOC\n" + + " AgEAWBKGG5b5ZVOjA3TzQ8t/RNY+UcAIcdQ+CF/usUbGBSMnKkKWgTzgF6DdE6k/\n" + + " mXX0IOpn07I/MDXPpUDN4ZfIWFm9vLsba1kMFE/+/S7ymdIB0LkXyXxWHZgZ2ATe\n" + + " xkPbm+l0GLs/QR/othB604lefzo+qCaBbUXqXPEOMoKyL2Sl5TQBbAN05WDvjzCS\n" + + " 7nSjxQTOxXDHMV322gaWB7+efcUfknsS4bMCUXBOgeqnBNUR6BoB3SX2avn6tLtS\n" + + " t3dfzQEcOoIFxcTtSpu3PDlj6WajAwKdbSQU3TZ0L10u3Zz0jEL72w8gDl5OStkG\n" + + " SuRNVEYuPavb2PucL2blVopwGpwtkNbLylGdrzJpmmuA10Tx39ZNj2dWyJzT03zM\n" + + " 0XlDRuGFZrdCieUH1dblmoOC6JyW+f7lO1ETNIC1I7LEz6B8beXTCM7LAiTVoVrn\n" + + " ZFqoBY8vrso4zobe8o2kydbmGuYeuKO4rGJqsYihl+RkxHmKMrS4WC/f+no0cv9h\n" + + " AFockmGQp63lOGI/HBb37WT9lxdV5jbpeH7bYan/y2jtlbyC48+I3WF+kP7t/Uh1\n" + + " KYcOuxlBDtt/NXRummzI00Ht7YRzLD4ZCfLbufK0EskMZ1EG6tvBC/OmlA7pCaWT\n" + + " St8KzOHtsYKgJA3Fea4OxDkEL6lBSommVOp2zWybKLb3Gzc=\n" + + " </cert>\n" + + " </intermediates>\n" + + " <endpoints>\n" + + " <cert>\n" + + " MIIDCDCB8aADAgECAgYBYVkuU0cwDQYJKoZIhvcNAQELBQAwLTErMCkGA1UEAwwi\n" + + " R29vZ2xlIENyeXB0QXV0aFZhdWx0IEludGVybWVkaWF0ZTAeFw0xODAyMDIwMTAx\n" + + " MDNaFw0yMDAyMDMwMTAxMDNaMCkxJzAlBgNVBAMTHkdvb2dsZSBDcnlwdEF1dGhW\n" + + " YXVsdCBJbnN0YW5jZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLgAERiYHfBu\n" + + " tJT+htocB40BtDr2jdxh0EZJlQ8QhpMkZuA/0t/zeSAdkVWw5b16izJ9JVOi/KVl\n" + + " 4b0hRH54UvowDQYJKoZIhvcNAQELBQADggIBAJ3PM4GNTNYzMr8E/IGsWZkLx9AR\n" + + " AALqBXz7As59F8y5UcLMqkXD/ewOfBZgF5VzjlAePyE/wSw0wc3xzvrDVVDiZaMB\n" + + " W1DVtSlbn25q00m00mmcUeyyMc7vuRkPoDshIMQTc8+U3yyYsVScSV+B4TvSx6wP\n" + + " Z9FpwnSPjVPD2GkqeMTWszuxNVEWq0wmm0K5lMaX0hfiak+4/IZxOPPGIg2py1KL\n" + + " A/H2gdyeqyJRcAsyEkfwLlushR5T9abSiPsIRcYoX8Ck8Lt+gQ7RCMefnm8CoOBK\n" + + " IfcjuV4PGOoeXrq57VR5SsOeT07bL+D7B+mohYFI1v2G3WClAE8XgM3q8NoFFvaY\n" + + " moi0+UcTduil47qvozjdNmjRAgu5j6vMKXEdG5Rqsja8hy0LG1hwfnR0gNiwcZ5L\n" + + " e3GyFnwH1IgqvsGOUM0ohnDUAU0zJY7nG0QYrDYe5/QPRNhWDpYkwHDiqcG28wIQ\n" + + " COTPAZHU2EoSKjSqEG2l0S5JPcor2BEde9ikSkcmK8foxlOHIdFn+n7RNF3bSEfK\n" + + " n1IOuXoqPidmeBQLevqG8KTy/C9CHqlaCNlpbIA9h+WVfsjm2s6JXBu0YbcfoIbJ\n" + + " AmSuZVeqB/+ZVvpfiad/jQWzY49fRnsSmV7VveTFPGtJxC89EadbMAinMZo+72u5\n" + + " 9319RqN5wsP2Zus8\n" + + " </cert>\n" + + " </endpoints>\n" + + "</certificates>\n"; + + public static byte[] getCertPath1Bytes() { + try { + return CertUtils.decodeBase64(CERT_PATH_1_BASE64); + } catch (Exception e){ + throw new RuntimeException(e); + } + } + + public static byte[] getCertPath2Bytes() { + try { + return CertUtils.decodeBase64(CERT_PATH_2_BASE64); + } catch (Exception e){ + throw new RuntimeException(e); + } + } + + public static final CertPath CERT_PATH_1; + public static final CertPath CERT_PATH_2; + + static { + try { + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + CERT_PATH_1 = certFactory.generateCertPath( + new ByteArrayInputStream(getCertPath1Bytes()), CERT_PATH_ENCODING); + CERT_PATH_2 = certFactory.generateCertPath( + new ByteArrayInputStream(getCertPath2Bytes()), CERT_PATH_ENCODING); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static byte[] getCertXmlWithSerial(long serial) { + String xml = THM_CERT_XML_BEFORE_SERIAL + serial + THM_CERT_XML_AFTER_SERIAL; + return xml.getBytes(StandardCharsets.UTF_8); + } +} diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java new file mode 100644 index 000000000000..37482a37003c --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java @@ -0,0 +1,179 @@ +/* + * 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.locksettings.recoverablekeystore.storage; + +import static com.google.common.truth.Truth.assertThat; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import android.content.ContentValues; +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.KeysEntry; +import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.RecoveryServiceMetadataEntry; +import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDbContract.UserMetadataEntry; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RecoverableKeyStoreDbHelperTest { + + private static final long TEST_USER_ID = 10L; + private static final long TEST_UID = 60001L; + private static final String TEST_ALIAS = "test-alias"; + private static final byte[] TEST_NONCE = "test-nonce".getBytes(UTF_8); + private static final byte[] TEST_WRAPPED_KEY = "test-wrapped-key".getBytes(UTF_8); + private static final long TEST_GENERATION_ID = 13L; + private static final long TEST_LAST_SYNCED_AT = 1517990732000L; + private static final int TEST_RECOVERY_STATUS = 3; + private static final int TEST_PLATFORM_KEY_GENERATION_ID = 11; + private static final int TEST_SNAPSHOT_VERSION = 31; + private static final int TEST_SHOULD_CREATE_SNAPSHOT = 1; + private static final byte[] TEST_PUBLIC_KEY = "test-public-key".getBytes(UTF_8); + private static final String TEST_SECRET_TYPES = "test-secret-types"; + private static final long TEST_COUNTER_ID = -3981205205038476415L; + private static final byte[] TEST_SERVER_PARAMS = "test-server-params".getBytes(UTF_8); + private static final byte[] TEST_CERT_PATH = "test-cert-path".getBytes(UTF_8); + private static final long TEST_CERT_SERIAL = 1000L; + + private static final String SQL_CREATE_V2_TABLE_KEYS = + "CREATE TABLE " + KeysEntry.TABLE_NAME + "( " + + KeysEntry._ID + " INTEGER PRIMARY KEY," + + KeysEntry.COLUMN_NAME_USER_ID + " INTEGER," + + KeysEntry.COLUMN_NAME_UID + " INTEGER," + + KeysEntry.COLUMN_NAME_ALIAS + " TEXT," + + KeysEntry.COLUMN_NAME_NONCE + " BLOB," + + KeysEntry.COLUMN_NAME_WRAPPED_KEY + " BLOB," + + KeysEntry.COLUMN_NAME_GENERATION_ID + " INTEGER," + + KeysEntry.COLUMN_NAME_LAST_SYNCED_AT + " INTEGER," + + KeysEntry.COLUMN_NAME_RECOVERY_STATUS + " INTEGER," + + "UNIQUE(" + KeysEntry.COLUMN_NAME_UID + "," + + KeysEntry.COLUMN_NAME_ALIAS + "))"; + + private static final String SQL_CREATE_V2_TABLE_USER_METADATA = + "CREATE TABLE " + UserMetadataEntry.TABLE_NAME + "( " + + UserMetadataEntry._ID + " INTEGER PRIMARY KEY," + + UserMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER UNIQUE," + + UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID + " INTEGER)"; + + private static final String SQL_CREATE_V2_TABLE_RECOVERY_SERVICE_METADATA = + "CREATE TABLE " + RecoveryServiceMetadataEntry.TABLE_NAME + " (" + + RecoveryServiceMetadataEntry._ID + " INTEGER PRIMARY KEY," + + RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER," + + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + " INTEGER," + + RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION + " INTEGER," + + RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT + " INTEGER," + + RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY + " BLOB," + + RecoveryServiceMetadataEntry.COLUMN_NAME_SECRET_TYPES + " TEXT," + + RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID + " INTEGER," + + RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMS + " BLOB," + + "UNIQUE(" + + RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + "," + + RecoveryServiceMetadataEntry.COLUMN_NAME_UID + "))"; + + private SQLiteDatabase mDatabase; + private RecoverableKeyStoreDbHelper mDatabaseHelper; + + @Before + public void setUp() throws Exception { + Context context = InstrumentationRegistry.getTargetContext(); + mDatabaseHelper = new RecoverableKeyStoreDbHelper(context); + mDatabase = SQLiteDatabase.create(null); + } + + @After + public void tearDown() throws Exception { + mDatabase.close(); + } + + private void createV2Tables() throws Exception { + mDatabase.execSQL(SQL_CREATE_V2_TABLE_KEYS); + mDatabase.execSQL(SQL_CREATE_V2_TABLE_USER_METADATA); + mDatabase.execSQL(SQL_CREATE_V2_TABLE_RECOVERY_SERVICE_METADATA); + } + + @Test + public void onCreate() throws Exception { + mDatabaseHelper.onCreate(mDatabase); + checkAllColumns(); + } + + @Test + public void onUpgrade_beforeV2() throws Exception { + mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 1, + RecoverableKeyStoreDbHelper.DATABASE_VERSION); + checkAllColumns(); + } + + @Test + public void onUpgrade_fromV2() throws Exception { + createV2Tables(); + mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 2, + RecoverableKeyStoreDbHelper.DATABASE_VERSION); + checkAllColumns(); + } + + private void checkAllColumns() throws Exception { + // Check the table containing encrypted application keys + ContentValues values = new ContentValues(); + values.put(KeysEntry.COLUMN_NAME_USER_ID, TEST_USER_ID); + values.put(KeysEntry.COLUMN_NAME_UID, TEST_UID); + values.put(KeysEntry.COLUMN_NAME_ALIAS, TEST_ALIAS); + values.put(KeysEntry.COLUMN_NAME_NONCE, TEST_NONCE); + values.put(KeysEntry.COLUMN_NAME_WRAPPED_KEY, TEST_WRAPPED_KEY); + values.put(KeysEntry.COLUMN_NAME_GENERATION_ID, TEST_GENERATION_ID); + values.put(KeysEntry.COLUMN_NAME_LAST_SYNCED_AT, TEST_LAST_SYNCED_AT); + values.put(KeysEntry.COLUMN_NAME_RECOVERY_STATUS, TEST_RECOVERY_STATUS); + assertThat(mDatabase.insert(KeysEntry.TABLE_NAME, /*nullColumnHack=*/ null, values)) + .isGreaterThan(-1L); + + // Check the table about user metadata + values = new ContentValues(); + values.put(UserMetadataEntry.COLUMN_NAME_USER_ID, TEST_USER_ID); + values.put(UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID, + TEST_PLATFORM_KEY_GENERATION_ID); + assertThat(mDatabase.insert(UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values)) + .isGreaterThan(-1L); + + // Check the table about recovery service metadata + values = new ContentValues(); + values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID, TEST_USER_ID); + values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_UID, TEST_UID); + values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SNAPSHOT_VERSION, + TEST_SNAPSHOT_VERSION); + values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SHOULD_CREATE_SNAPSHOT, + TEST_SHOULD_CREATE_SNAPSHOT); + values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_PUBLIC_KEY, TEST_PUBLIC_KEY); + values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SECRET_TYPES, TEST_SECRET_TYPES); + values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_COUNTER_ID, TEST_COUNTER_ID); + values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_SERVER_PARAMS, TEST_SERVER_PARAMS); + values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH, TEST_CERT_PATH); + values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL, TEST_CERT_SERIAL); + assertThat( + mDatabase.insert(RecoveryServiceMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, + values)) + .isGreaterThan(-1L); + } +} diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java index 097d2141d9e0..1c5bcd498f5c 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java @@ -32,6 +32,8 @@ import android.security.keystore.RecoveryController; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; + +import com.android.server.locksettings.recoverablekeystore.TestData; import com.android.server.locksettings.recoverablekeystore.WrappedKey; import java.io.File; @@ -370,6 +372,57 @@ public class RecoverableKeyStoreDbTest { pubkey); } + public void setRecoveryServiceCertPath_replaceOldValue() throws Exception { + int userId = 12; + int uid = 10009; + mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TestData.CERT_PATH_1); + mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TestData.CERT_PATH_2); + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isEqualTo( + TestData.CERT_PATH_2); + } + + @Test + public void getRecoveryServiceCertPath_returnsNullIfNoValue() throws Exception { + int userId = 12; + int uid = 10009; + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isNull(); + } + + @Test + public void getRecoveryServiceCertPath_returnsInsertedValue() throws Exception { + int userId = 12; + int uid = 10009; + mRecoverableKeyStoreDb.setRecoveryServiceCertPath(userId, uid, TestData.CERT_PATH_1); + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertPath(userId, uid)).isEqualTo( + TestData.CERT_PATH_1); + } + + @Test + public void setRecoveryServiceCertSerial_replaceOldValue() throws Exception { + int userId = 12; + int uid = 10009; + + mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, 1L); + mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, 3L); + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isEqualTo(3L); + } + + @Test + public void getRecoveryServiceCertSerial_returnsNullIfNoValue() throws Exception { + int userId = 12; + int uid = 10009; + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isNull(); + } + + @Test + public void getRecoveryServiceCertSerial_returnsInsertedValue() throws Exception { + int userId = 12; + int uid = 10009; + mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid, 1234L); + assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid)).isEqualTo( + 1234L); + } + @Test public void getRecoveryAgents_returnsUidIfSet() throws Exception { int userId = 12; @@ -493,17 +546,6 @@ public class RecoverableKeyStoreDbTest { } @Test - public void getRecoveryServicePublicKey_returnsFirstKey() throws Exception { - int userId = 68; - int uid = 12904; - PublicKey publicKey = genRandomPublicKey(); - - mRecoverableKeyStoreDb.setRecoveryServicePublicKey(userId, uid, publicKey); - - assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId)).isEqualTo(publicKey); - } - - @Test public void setServerParams_replaceOldValue() throws Exception { int userId = 12; int uid = 10009; diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java index 2284bbbbf3ac..63ac4af47207 100644 --- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java @@ -28,6 +28,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static com.android.server.wm.WindowContainer.POSITION_TOP; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -38,7 +39,6 @@ import org.junit.runner.RunWith; import android.annotation.SuppressLint; import android.content.res.Configuration; import android.graphics.Path; -import android.graphics.Point; import android.graphics.Rect; import android.os.SystemClock; import android.platform.test.annotations.Presubmit; @@ -166,6 +166,7 @@ public class DisplayContentTests extends WindowTestsBase { assertTrue(appWin.canBeImeTarget()); WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */); assertEquals(appWin, imeTarget); + appWin.mHidden = false; // Verify that an child window can be an ime target. final WindowState childWin = createWindow(appWin, diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java index 6a4710bb06a4..4d41718e4da0 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java @@ -36,6 +36,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -57,15 +58,17 @@ public class WindowStateTests extends WindowTestsBase { final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1"); final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2"); - assertFalse(parentWindow.mHidden); + // parentWindow is initially set to hidden. + assertTrue(parentWindow.mHidden); + assertFalse(parentWindow.isParentWindowHidden()); + assertTrue(child1.isParentWindowHidden()); + assertTrue(child2.isParentWindowHidden()); + + parentWindow.mHidden = false; assertFalse(parentWindow.isParentWindowHidden()); assertFalse(child1.isParentWindowHidden()); assertFalse(child2.isParentWindowHidden()); - parentWindow.mHidden = true; - assertFalse(parentWindow.isParentWindowHidden()); - assertTrue(child1.isParentWindowHidden()); - assertTrue(child2.isParentWindowHidden()); } @Test diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index d6f61cd12765..7b2c040db5ab 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -188,6 +188,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { protected void reportSeen(NotificationRecord r) { return; } + + @Override + protected void reportUserInteraction(NotificationRecord r) { + return; + } } @Before diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java index cc21199edfd9..32db7526f3c0 100644 --- a/services/usage/java/com/android/server/usage/AppStandbyController.java +++ b/services/usage/java/com/android/server/usage/AppStandbyController.java @@ -177,6 +177,12 @@ public class AppStandbyController { long mAppIdleParoleDurationMillis; long[] mAppStandbyScreenThresholds = SCREEN_TIME_THRESHOLDS; long[] mAppStandbyElapsedThresholds = ELAPSED_TIME_THRESHOLDS; + /** Minimum time a strong usage event should keep the bucket elevated. */ + long mStrongUsageTimeoutMillis; + /** Minimum time a notification seen event should keep the bucket elevated. */ + long mNotificationSeenTimeoutMillis; + /** Minimum time a system update event should keep the buckets elevated. */ + long mSystemUpdateUsageTimeoutMillis; volatile boolean mAppIdleEnabled; boolean mAppIdleTempParoled; @@ -330,7 +336,7 @@ public class AppStandbyController { synchronized (mAppIdleLock) { AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId, STANDBY_BUCKET_ACTIVE, elapsedRealtime, - elapsedRealtime + 2 * ONE_HOUR); + elapsedRealtime + mStrongUsageTimeoutMillis); maybeInformListeners(packageName, userId, elapsedRealtime, appUsage.currentBucket, false); } @@ -539,6 +545,7 @@ public class AppStandbyController { } } + @GuardedBy("mAppIdleLock") @StandbyBuckets int getBucketForLocked(String packageName, int userId, long elapsedRealtime) { int bucketIndex = mAppIdleHistory.getThresholdIndex(packageName, userId, @@ -627,11 +634,11 @@ public class AppStandbyController { if (event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN) { mAppIdleHistory.reportUsage(appHistory, event.mPackage, STANDBY_BUCKET_WORKING_SET, - elapsedRealtime, elapsedRealtime + 2 * ONE_HOUR); + elapsedRealtime, elapsedRealtime + mNotificationSeenTimeoutMillis); } else { mAppIdleHistory.reportUsage(event.mPackage, userId, STANDBY_BUCKET_ACTIVE, - elapsedRealtime, elapsedRealtime + 2 * ONE_HOUR); + elapsedRealtime, elapsedRealtime + mStrongUsageTimeoutMillis); } final boolean userStartedInteracting = @@ -1113,10 +1120,10 @@ public class AppStandbyController { final PackageInfo pi = packages.get(i); String packageName = pi.packageName; if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) { - // Mark app as used for 4 hours. After that it can timeout to whatever the + // Mark app as used for 2 hours. After that it can timeout to whatever the // past usage pattern was. mAppIdleHistory.reportUsage(packageName, userId, STANDBY_BUCKET_ACTIVE, 0, - elapsedRealtime + 4 * ONE_HOUR); + elapsedRealtime + mSystemUpdateUsageTimeoutMillis); } } } @@ -1395,6 +1402,12 @@ public class AppStandbyController { private static final String KEY_PAROLE_DURATION = "parole_duration"; private static final String KEY_SCREEN_TIME_THRESHOLDS = "screen_thresholds"; private static final String KEY_ELAPSED_TIME_THRESHOLDS = "elapsed_thresholds"; + private static final String KEY_STRONG_USAGE_HOLD_DURATION = "strong_usage_duration"; + private static final String KEY_NOTIFICATION_SEEN_HOLD_DURATION = + "notification_seen_duration"; + private static final String KEY_SYSTEM_UPDATE_HOLD_DURATION = + "system_update_usage_duration"; + private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -1455,7 +1468,15 @@ public class AppStandbyController { ELAPSED_TIME_THRESHOLDS); mCheckIdleIntervalMillis = Math.min(mAppStandbyElapsedThresholds[1] / 4, COMPRESS_TIME ? ONE_MINUTE : 4 * 60 * ONE_MINUTE); // 4 hours - + mStrongUsageTimeoutMillis = mParser.getDurationMillis + (KEY_STRONG_USAGE_HOLD_DURATION, + COMPRESS_TIME ? ONE_MINUTE : 1 * ONE_HOUR); + mNotificationSeenTimeoutMillis = mParser.getDurationMillis + (KEY_NOTIFICATION_SEEN_HOLD_DURATION, + COMPRESS_TIME ? 12 * ONE_MINUTE : 12 * ONE_HOUR); + mSystemUpdateUsageTimeoutMillis = mParser.getDurationMillis + (KEY_SYSTEM_UPDATE_HOLD_DURATION, + COMPRESS_TIME ? 2 * ONE_MINUTE : 2 * ONE_HOUR); } } diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java index 4b2d9b9adbbb..43f189b26dfa 100644 --- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java @@ -314,6 +314,7 @@ class UsbProfileGroupSettingsManager { * Upgrade any single-user settings from {@link #sSingleUserSettingsFile}. * Should only by called by owner. */ + @GuardedBy("mLock") private void upgradeSingleUserLocked() { if (sSingleUserSettingsFile.exists()) { mDevicePreferenceMap.clear(); @@ -347,6 +348,7 @@ class UsbProfileGroupSettingsManager { } } + @GuardedBy("mLock") private void readSettingsLocked() { if (DEBUG) Slog.v(TAG, "readSettingsLocked()"); @@ -386,6 +388,7 @@ class UsbProfileGroupSettingsManager { * <p>In the uncommon case that the system crashes in between the scheduling and the write the * update is lost.</p> */ + @GuardedBy("mLock") private void scheduleWriteSettingsLocked() { if (mIsWriteSettingsScheduled) { return; @@ -869,6 +872,7 @@ class UsbProfileGroupSettingsManager { return null; } + @GuardedBy("mLock") private boolean clearCompatibleMatchesLocked(@NonNull UserPackage userPackage, @NonNull DeviceFilter filter) { ArrayList<DeviceFilter> keysToRemove = new ArrayList<>(); @@ -892,6 +896,7 @@ class UsbProfileGroupSettingsManager { return !keysToRemove.isEmpty(); } + @GuardedBy("mLock") private boolean clearCompatibleMatchesLocked(@NonNull UserPackage userPackage, @NonNull AccessoryFilter filter) { ArrayList<AccessoryFilter> keysToRemove = new ArrayList<>(); @@ -915,6 +920,7 @@ class UsbProfileGroupSettingsManager { return !keysToRemove.isEmpty(); } + @GuardedBy("mLock") private boolean handlePackageAddedLocked(UserPackage userPackage, ActivityInfo aInfo, String metaDataName) { XmlResourceParser parser = null; diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index 1edc46967495..c1a75912425a 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -236,6 +236,7 @@ public class UsbService extends IUsbManager.Stub { * * @return Iff the caller is in the current user's profile group */ + @GuardedBy("mLock") private boolean isCallerInCurrentUserProfileGroupLocked() { int userIdInt = UserHandle.getCallingUserId(); diff --git a/tests/JankBench/Android.mk b/tests/JankBench/Android.mk index 12568a09e71e..291ba78758b4 100644 --- a/tests/JankBench/Android.mk +++ b/tests/JankBench/Android.mk @@ -19,7 +19,7 @@ LOCAL_RESOURCE_DIR := \ LOCAL_STATIC_ANDROID_LIBRARIES := \ - android-support-design \ + $(ANDROID_SUPPORT_DESIGN_TARGETS) \ android-support-v4 \ android-support-v7-appcompat \ android-support-v7-cardview \ diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk index 60327e5cb2a4..c8e6c2091d8f 100644 --- a/tests/UiBench/Android.mk +++ b/tests/UiBench/Android.mk @@ -15,7 +15,7 @@ LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_USE_AAPT2 := true LOCAL_STATIC_ANDROID_LIBRARIES := \ - android-support-design \ + $(ANDROID_SUPPORT_DESIGN_TARGETS) \ android-support-v4 \ android-support-v7-appcompat \ android-support-v7-cardview \ diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index c9e272c32eae..1afd283a430a 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -1446,6 +1446,13 @@ class LinkCommand { ContainerReaderEntry* entry; ContainerReader reader(input_stream.get()); + + if (reader.HadError()) { + context_->GetDiagnostics()->Error(DiagMessage(src) + << "failed to read file: " << reader.GetError()); + return false; + } + while ((entry = reader.Next()) != nullptr) { if (entry->Type() == ContainerEntryType::kResTable) { pb::ResourceTable pb_table; diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java index 3fb4fae2f6af..bdbc149a0a42 100644 --- a/wifi/java/android/net/wifi/RttManager.java +++ b/wifi/java/android/net/wifi/RttManager.java @@ -12,6 +12,7 @@ import android.net.wifi.rtt.RangingRequest; import android.net.wifi.rtt.RangingResult; import android.net.wifi.rtt.RangingResultCallback; import android.net.wifi.rtt.WifiRttManager; +import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; @@ -23,6 +24,7 @@ import java.util.List; /** @hide */ @SystemApi +@Deprecated @SystemService(Context.WIFI_RTT_SERVICE) public class RttManager { @@ -180,6 +182,7 @@ public class RttManager { /** * This class describe the RTT capability of the Hardware */ + @Deprecated public static class RttCapabilities implements Parcelable { /** @deprecated It is not supported*/ @Deprecated @@ -313,12 +316,16 @@ public class RttManager { }; } + /** + * This method is deprecated. Please use the {@link WifiRttManager} API. + */ @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) public RttCapabilities getRttCapabilities() { return mRttCapabilities; } /** specifies parameters for RTT request */ + @Deprecated public static class RttParams { /** * type of destination device being ranged @@ -501,6 +508,7 @@ public class RttManager { } /** pseudo-private class used to parcel arguments */ + @Deprecated public static class ParcelableRttParams implements Parcelable { @NonNull @@ -588,12 +596,14 @@ public class RttManager { }; } + @Deprecated public static class WifiInformationElement { /** Information Element ID 0xFF means element is invalid. */ public byte id; public byte[] data; } /** specifies RTT results */ + @Deprecated public static class RttResult { /** mac address of the device being ranged. */ public String bssid; @@ -745,6 +755,7 @@ public class RttManager { /** pseudo-private class used to parcel results. */ + @Deprecated public static class ParcelableRttResults implements Parcelable { public RttResult mResults[]; @@ -910,7 +921,7 @@ public class RttManager { }; } - + @Deprecated public static interface RttListener { public void onSuccess(RttResult[] results); public void onFailure(int reason, String description); @@ -919,6 +930,9 @@ public class RttManager { /** * Request to start an RTT ranging + * <p> + * This method is deprecated. Please use the + * {@link WifiRttManager#startRanging(RangingRequest, RangingResultCallback, Handler)} API. * * @param params -- RTT request Parameters * @param listener -- Call back to inform RTT result @@ -990,6 +1004,10 @@ public class RttManager { } } + /** + * This method is deprecated and performs no function. Please use the {@link WifiRttManager} + * API. + */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void stopRanging(RttListener listener) { Log.e(TAG, "stopRanging: unsupported operation - nop"); @@ -1004,6 +1022,7 @@ public class RttManager { * The client can freely destroy or reuse the callback after {@link RttManager#disableResponder} * is called. */ + @Deprecated public abstract static class ResponderCallback { /** Callback when responder is enabled. */ public abstract void onResponderEnabled(ResponderConfig config); @@ -1019,6 +1038,10 @@ public class RttManager { * Note calling this method with the same callback when the responder is already enabled won't * change the responder state, a cached {@link ResponderConfig} from the last enabling will be * returned through the callback. + * <p> + * This method is deprecated and will throw an {@link UnsupportedOperationException} + * exception. Please use the {@link WifiRttManager} API to perform a Wi-Fi Aware peer-to-peer + * ranging. * * @param callback Callback for responder enabling/disabling result. * @throws IllegalArgumentException If {@code callback} is null. @@ -1035,6 +1058,10 @@ public class RttManager { * <p> * Calling this method when responder isn't enabled won't have any effect. The callback can be * reused for enabling responder after this method is called. + * <p> + * This method is deprecated and will throw an {@link UnsupportedOperationException} + * exception. Please use the {@link WifiRttManager} API to perform a Wi-Fi Aware peer-to-peer + * ranging. * * @param callback The same callback used for enabling responder. * @throws IllegalArgumentException If {@code callback} is null. @@ -1051,6 +1078,7 @@ public class RttManager { * * @see ScanResult */ + @Deprecated public static class ResponderConfig implements Parcelable { // TODO: make all fields final once we can get mac address from responder HAL APIs. |